def browser_timing_insertion(response, transaction): # No point continuing if header is empty. This can occur if # RUM is not enabled within the UI. It is assumed at this # point that if header is not empty, then footer will not be # empty. We don't want to generate the footer just yet as # want to do that as late as possible so that application # server time in footer is as accurate as possible. In # particular, if the response content is generated on demand # then the flattening of the response could take some time # and we want to track that. We thus generate footer below # at point of insertion. header = transaction.browser_timing_header() if not header: return response def html_to_be_inserted(): return six.b(header) + six.b(transaction.browser_timing_footer()) # Make sure we flatten any content first as it could be # stored as a list of strings in the response object. We # assign it back to the response object to avoid having # multiple copies of the string in memory at the same time # as we progress through steps below. result = insert_html_snippet(response.content, html_to_be_inserted) if result is not None: if transaction.settings.debug.log_autorum_middleware: _logger.debug( 'RUM insertion from Django middleware ' 'triggered. Bytes added was %r.', len(result) - len(response.content)) response.content = result if response.get('Content-Length', None): response['Content-Length'] = str(len(response.content)) return response
def browser_timing_middleware(request, response): # Don't do anything if receive a streaming response which # was introduced in Django 1.5. Need to avoid this as there # will be no 'content' attribute. Alternatively there may be # a 'content' attribute which flattens the stream, which if # we access, will break the streaming and/or buffer what is # potentially a very large response in memory contrary to # what user wanted by explicitly using a streaming response # object in the first place. To preserve streaming but still # do RUM insertion, need to move to a WSGI middleware and # deal with how to update the content length. if hasattr(response, 'streaming_content'): return response # Need to be running within a valid web transaction. transaction = current_transaction() if not transaction: return response # Only insert RUM JavaScript headers and footers if enabled # in configuration and not already likely inserted. if not transaction.settings.browser_monitoring.enabled: return response if transaction.autorum_disabled: return response if not django_settings.browser_monitoring.auto_instrument: return response if transaction.rum_header_generated: return response # Only possible if the content type is one of the allowed # values. Normally this is just text/html, but optionally # could be defined to be list of further types. For example # a user may want to also perform insertion for # 'application/xhtml+xml'. ctype = response.get('Content-Type', '').lower().split(';')[0] if ctype not in transaction.settings.browser_monitoring.content_type: return response # Don't risk it if content encoding already set. if response.has_header('Content-Encoding'): return response # Don't risk it if content is actually within an attachment. cdisposition = response.get('Content-Disposition', '').lower() if cdisposition.split(';')[0].strip().lower() == 'attachment': return response # No point continuing if header is empty. This can occur if # RUM is not enabled within the UI. It is assumed at this # point that if header is not empty, then footer will not be # empty. We don't want to generate the footer just yet as # want to do that as late as possible so that application # server time in footer is as accurate as possible. In # particular, if the response content is generated on demand # then the flattening of the response could take some time # and we want to track that. We thus generate footer below # at point of insertion. header = transaction.browser_timing_header() if not header: return response def html_to_be_inserted(): return six.b(header) + six.b(transaction.browser_timing_footer()) # Make sure we flatten any content first as it could be # stored as a list of strings in the response object. We # assign it back to the response object to avoid having # multiple copies of the string in memory at the same time # as we progress through steps below. result = insert_html_snippet(response.content, html_to_be_inserted) if result is not None: if transaction.settings.debug.log_autorum_middleware: _logger.debug('RUM insertion from Django middleware ' 'triggered. Bytes added was %r.', len(result) - len(response.content)) response.content = result response['Content-Length'] = str(len(response.content)) return response
def _nr_wrapper_Compress_after_request(wrapped, instance, args, kwargs): def _params(response, *args, **kwargs): return response response = _params(*args, **kwargs) # If the response has direct_passthrough flagged, then is # likely to be streaming a file or other large response. # Leave the response alone in this situation even though # it looked like flask_compress doesn't honour it. #if getattr(response, 'direct_passthrough', None): # return wrapped(*args, **kwargs) # Need to be running within a valid web transaction. transaction = current_transaction() if not transaction: return wrapped(*args, **kwargs) # Only insert RUM JavaScript headers and footers if enabled # in configuration and not already likely inserted. if not transaction.settings.browser_monitoring.enabled: return wrapped(*args, **kwargs) if transaction.autorum_disabled: return wrapped(*args, **kwargs) if not flask_compress_settings.browser_monitoring.auto_instrument: return wrapped(*args, **kwargs) if transaction.rum_header_generated: return wrapped(*args, **kwargs) # Only possible if the content type is one of the allowed # values. Normally this is just text/html, but optionally # could be defined to be list of further types. For example # a user may want to also perform insertion for # 'application/xhtml+xml'. ctype = response.mimetype.lower() if ctype not in transaction.settings.browser_monitoring.content_type: return wrapped(*args, **kwargs) # Don't risk it if content encoding already set. if 'Content-Encoding' in response.headers: return wrapped(*args, **kwargs) # Don't risk it if content is actually within an attachment. cdisposition = response.headers.get('Content-Disposition', '').lower() if cdisposition.split(';')[0].strip() == 'attachment': return wrapped(*args, **kwargs) # No point continuing if header is empty. This can occur if # RUM is not enabled within the UI. It is assumed at this # point that if header is not empty, then footer will not be # empty. We don't want to generate the footer just yet as # want to do that as late as possible so that application # server time in footer is as accurate as possible. In # particular, if the response content is generated on demand # then the flattening of the response could take some time # and we want to track that. We thus generate footer below # at point of insertion. header = transaction.browser_timing_header() if not header: return wrapped(*args, **kwargs) def html_to_be_inserted(): return six.b(header) + six.b(transaction.browser_timing_footer()) # Make sure we flatten any content first as it could be # stored as a list of strings in the response object. We # assign it back to the response object to avoid having # multiple copies of the string in memory at the same time # as we progress through steps below. result = insert_html_snippet(response.get_data(), html_to_be_inserted) if result is not None: if transaction.settings.debug.log_autorum_middleware: _logger.debug('RUM insertion from flask_compress ' 'triggered. Bytes added was %r.', len(result) - len(response.get_data())) response.set_data(result) response.headers['Content-Length'] = str(len(response.get_data())) return wrapped(*args, **kwargs)
def browser_timing_middleware(request, response): # Don't do anything if receive a streaming response which # was introduced in Django 1.5. Need to avoid this as there # will be no 'content' attribute. Alternatively there may be # a 'content' attribute which flattens the stream, which if # we access, will break the streaming and/or buffer what is # potentially a very large response in memory contrary to # what user wanted by explicitly using a streaming response # object in the first place. To preserve streaming but still # do RUM insertion, need to move to a WSGI middleware and # deal with how to update the content length. if hasattr(response, 'streaming_content'): return response # Need to be running within a valid web transaction. transaction = current_transaction() if not transaction: return response # Only insert RUM JavaScript headers and footers if enabled # in configuration and not already likely inserted. if not transaction.settings.browser_monitoring.enabled: return response if transaction.autorum_disabled: return response if not django_settings.browser_monitoring.auto_instrument: return response if transaction.rum_header_generated: return response # Only possible if the content type is one of the allowed # values. Normally this is just text/html, but optionally # could be defined to be list of further types. For example # a user may want to also perform insertion for # 'application/xhtml+xml'. ctype = response.get('Content-Type', '').lower().split(';')[0] if ctype not in transaction.settings.browser_monitoring.content_type: return response # Don't risk it if content encoding already set. if response.has_header('Content-Encoding'): return response # Don't risk it if content is actually within an attachment. cdisposition = response.get('Content-Disposition', '').lower() if cdisposition.split(';')[0].strip().lower() == 'attachment': return response # No point continuing if header is empty. This can occur if # RUM is not enabled within the UI. It is assumed at this # point that if header is not empty, then footer will not be # empty. We don't want to generate the footer just yet as # want to do that as late as possible so that application # server time in footer is as accurate as possible. In # particular, if the response content is generated on demand # then the flattening of the response could take some time # and we want to track that. We thus generate footer below # at point of insertion. header = transaction.browser_timing_header() if not header: return response def html_to_be_inserted(): return six.b(header) + six.b(transaction.browser_timing_footer()) # Make sure we flatten any content first as it could be # stored as a list of strings in the response object. We # assign it back to the response object to avoid having # multiple copies of the string in memory at the same time # as we progress through steps below. result = insert_html_snippet(response.content, html_to_be_inserted) if result is not None: if transaction.settings.debug.log_autorum_middleware: _logger.debug( 'RUM insertion from Django middleware ' 'triggered. Bytes added was %r.', len(result) - len(response.content)) response.content = result if response.get('Content-Length', None): response['Content-Length'] = str(len(response.content)) return response
def _nr_wrapper_Compress_after_request(wrapped, instance, args, kwargs): def _params(response, *args, **kwargs): return response response = _params(*args, **kwargs) # If the response has direct_passthrough flagged, then is # likely to be streaming a file or other large response. # Leave the response alone in this situation even though # it looked like flask_compress doesn't honour it. #if getattr(response, 'direct_passthrough', None): # return wrapped(*args, **kwargs) # Need to be running within a valid web transaction. transaction = current_transaction() if not transaction: return wrapped(*args, **kwargs) # Only insert RUM JavaScript headers and footers if enabled # in configuration and not already likely inserted. if not transaction.settings.browser_monitoring.enabled: return wrapped(*args, **kwargs) if transaction.autorum_disabled: return wrapped(*args, **kwargs) if not flask_compress_settings.browser_monitoring.auto_instrument: return wrapped(*args, **kwargs) if transaction.rum_header_generated: return wrapped(*args, **kwargs) # Only possible if the content type is one of the allowed # values. Normally this is just text/html, but optionally # could be defined to be list of further types. For example # a user may want to also perform insertion for # 'application/xhtml+xml'. ctype = response.mimetype.lower() if ctype not in transaction.settings.browser_monitoring.content_type: return wrapped(*args, **kwargs) # Don't risk it if content encoding already set. if 'Content-Encoding' in response.headers: return wrapped(*args, **kwargs) # Don't risk it if content is actually within an attachment. cdisposition = response.headers.get('Content-Disposition', '').lower() if cdisposition.split(';')[0].strip() == 'attachment': return wrapped(*args, **kwargs) # No point continuing if header is empty. This can occur if # RUM is not enabled within the UI. It is assumed at this # point that if header is not empty, then footer will not be # empty. We don't want to generate the footer just yet as # want to do that as late as possible so that application # server time in footer is as accurate as possible. In # particular, if the response content is generated on demand # then the flattening of the response could take some time # and we want to track that. We thus generate footer below # at point of insertion. header = transaction.browser_timing_header() if not header: return wrapped(*args, **kwargs) def html_to_be_inserted(): return six.b(header) + six.b(transaction.browser_timing_footer()) # Make sure we flatten any content first as it could be # stored as a list of strings in the response object. We # assign it back to the response object to avoid having # multiple copies of the string in memory at the same time # as we progress through steps below. result = insert_html_snippet(response.get_data(), html_to_be_inserted) if result is not None: if transaction.settings.debug.log_autorum_middleware: _logger.debug( 'RUM insertion from flask_compress ' 'triggered. Bytes added was %r.', len(result) - len(response.get_data())) response.set_data(result) response.headers['Content-Length'] = str(len(response.get_data())) return wrapped(*args, **kwargs)