__init__.py (6648B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\beeline\middleware\django\__init__.py 2 import contextlib 3 import datetime 4 import beeline 5 from beeline.propagation import Request 6 from django.db import connections 7 8 class DjangoRequest(Request): 9 10 def __init__(self, request): 11 self._request = request 12 self._META = request.META 13 if beeline.get_beeline(): 14 beeline.get_beeline().log(request.META) 15 16 def header(self, key): 17 lookup_key = 'HTTP_' + key.upper().replace('-', '_') 18 return self._request.META.get(lookup_key) 19 20 def method(self): 21 return self._request.method 22 23 def scheme(self): 24 return self._request.scheme 25 26 def host(self): 27 return self._request.get_host() 28 29 def path(self): 30 return self._request.path 31 32 def query(self): 33 return self._request.META.get('QUERY_STRING') 34 35 def middleware_request(self): 36 return self._request 37 38 39 class HoneyDBWrapper(object): 40 41 def __call__(self, execute, sql, params, many, context): 42 if not beeline.get_beeline(): 43 return execute(sql, params, many, context) 44 vendor = context['connection'].vendor 45 trace_name = 'django_%s_query' % vendor 46 with beeline.tracer(trace_name): 47 beeline.add_context({'type': 'db', 48 'db.query': sql, 49 'db.query_args': params}) 50 try: 51 db_call_start = datetime.datetime.now() 52 result = execute(sql, params, many, context) 53 db_call_diff = datetime.datetime.now() - db_call_start 54 beeline.add_context_field('db.duration', db_call_diff.total_seconds() * 1000) 55 except Exception as e: 56 beeline.add_context_field('db.error', str(type(e))) 57 beeline.add_context_field('db.error_detail', beeline.internal.stringify_exception(e)) 58 raise 59 else: 60 return result 61 finally: 62 if vendor in ('postgresql', 'mysql'): 63 beeline.add_context({'db.last_insert_id': context['cursor'].cursor.lastrowid, 64 'db.rows_affected': context['cursor'].cursor.rowcount}) 65 66 67 class HoneyMiddlewareBase(object): 68 69 def __init__(self, get_response): 70 self.get_response = get_response 71 72 def __call__(self, request): 73 response = self.create_http_event(request) 74 return response 75 76 def get_context_from_request(self, request): 77 trace_name = 'django_http_%s' % request.method.lower() 78 return {'name': trace_name, 79 'type': 'http_server', 80 'request.host': request.get_host(), 81 'request.method': request.method, 82 'request.path': request.path, 83 'request.remote_addr': request.META.get('REMOTE_ADDR'), 84 'request.content_length': request.META.get('CONTENT_LENGTH', 0), 85 'request.user_agent': request.META.get('HTTP_USER_AGENT'), 86 'request.scheme': request.scheme, 87 'request.secure': request.is_secure(), 88 'request.query': request.GET.dict(), 89 'request.xhr': request.headers.get('x-requested-with') == 'XMLHttpRequest'} 90 91 def get_context_from_response(self, request, response): 92 return {'response.status_code': response.status_code} 93 94 def create_http_event(self, request): 95 if not beeline.get_beeline(): 96 return self.get_response(request) 97 dr = DjangoRequest(request) 98 request_context = self.get_context_from_request(request) 99 root_span = beeline.propagate_and_start_trace(request_context, dr) 100 response = self.get_response(request) 101 response_context = self.get_context_from_response(request, response) 102 beeline.add_context(response_context) 103 104 def wrap_streaming_content(content): 105 for chunk in content: 106 yield chunk 107 108 beeline.finish_trace(root_span) 109 110 if response.streaming: 111 response.streaming_content = wrap_streaming_content(response.streaming_content) 112 else: 113 beeline.finish_trace(root_span) 114 return response 115 116 def process_exception(self, request, exception): 117 if beeline.get_beeline(): 118 beeline.add_context_field('request.error_detail', beeline.internal.stringify_exception(exception)) 119 120 def process_view(self, request, view_func, view_args, view_kwargs): 121 if beeline.get_beeline(): 122 try: 123 beeline.add_context_field('django.view_func', view_func.__name__) 124 except AttributeError: 125 pass 126 127 try: 128 beeline.add_context_field('request.route', request.resolver_match.route) 129 except AttributeError: 130 pass 131 132 133 class HoneyMiddlewareHttp(HoneyMiddlewareBase): 134 pass 135 136 137 class HoneyMiddleware(HoneyMiddlewareBase): 138 139 def __call__(self, request): 140 try: 141 db_wrapper = HoneyDBWrapper() 142 with contextlib.ExitStack() as stack: 143 for connection in connections.all(): 144 stack.enter_context(connection.execute_wrapper(db_wrapper)) 145 146 response = self.create_http_event(request) 147 148 def wrap_streaming_content(content): 149 with contextlib.ExitStack() as stack: 150 for connection in connections.all(): 151 stack.enter_context(connection.execute_wrapper(db_wrapper)) 152 153 for chunk in content: 154 yield chunk 155 156 if response.streaming: 157 response.streaming_content = wrap_streaming_content(response.streaming_content) 158 except AttributeError: 159 response = self.create_http_event(request) 160 161 return response 162 163 164 class HoneyMiddlewareWithPOST(HoneyMiddleware): 165 166 def get_context_from_request(self, request): 167 trace_name = 'django_http_%s' % request.method.lower() 168 return {'name': trace_name, 169 'type': 'http_server', 170 'request.host': request.get_host(), 171 'request.method': request.method, 172 'request.path': request.path, 173 'request.remote_addr': request.META.get('REMOTE_ADDR'), 174 'request.content_length': request.META.get('CONTENT_LENGTH', 0), 175 'request.user_agent': request.META.get('HTTP_USER_AGENT'), 176 'request.scheme': request.scheme, 177 'request.secure': request.is_secure(), 178 'request.query': request.GET.dict(), 179 'request.xhr': request.headers.get('x-requested-with') == 'XMLHttpRequest', 180 'request.post': request.POST.dict()}