33
33
34
34
import logging
35
35
import threading
36
+ from types import FunctionType
37
+ from typing import Optional
36
38
37
39
from django .apps import apps
38
40
from django .conf import settings as django_settings
41
+ from django .http import HttpRequest , HttpResponse
39
42
40
43
import elasticapm
41
44
from elasticapm .conf import constants
@@ -114,10 +117,10 @@ def process_response_wrapper(wrapped, instance, args, kwargs):
114
117
response = wrapped (* args , ** kwargs )
115
118
try :
116
119
request , original_response = args
117
- # if there's no view_func on the request , and this middleware created
120
+ # if we haven't set the name in a view , and this middleware created
118
121
# a new response object, it's logged as the responsible transaction
119
122
# name
120
- if not hasattr (request , "_elasticapm_view_func" ) and response is not original_response :
123
+ if not getattr (request , "_elasticapm_name_set" , False ) and response is not original_response :
121
124
elasticapm .set_transaction_name (
122
125
build_name_with_http_method_prefix (get_name_from_middleware (wrapped , instance ), request )
123
126
)
@@ -159,25 +162,17 @@ def instrument_middlewares(self):
159
162
except ImportError :
160
163
client .logger .warning ("Can't instrument middleware %s" , middleware_path )
161
164
162
- def process_view (self , request , view_func , view_args , view_kwargs ):
163
- request ._elasticapm_view_func = view_func
165
+ def process_view (self , request : HttpRequest , view_func : FunctionType , view_args : list , view_kwargs : dict ):
166
+ elasticapm .set_transaction_name (self .get_transaction_name (request , view_func ), override = False )
167
+ request ._elasticapm_name_set = True
164
168
165
- def process_response (self , request , response ):
169
+ def process_response (self , request : HttpRequest , response : HttpResponse ):
166
170
if django_settings .DEBUG and not self .client .config .debug :
167
171
return response
168
172
try :
169
173
if hasattr (response , "status_code" ):
170
- transaction_name = None
171
- if self .client .config .django_transaction_name_from_route and hasattr (request .resolver_match , "route" ):
172
- r = request .resolver_match
173
- # if no route is defined (e.g. for the root URL), fall back on url_name and then function name
174
- transaction_name = r .route or r .url_name or get_name_from_func (r .func )
175
- elif getattr (request , "_elasticapm_view_func" , False ):
176
- transaction_name = get_name_from_func (request ._elasticapm_view_func )
177
- if transaction_name :
178
- transaction_name = build_name_with_http_method_prefix (transaction_name , request )
179
- elasticapm .set_transaction_name (transaction_name , override = False )
180
-
174
+ if not getattr (request , "_elasticapm_name_set" , False ):
175
+ elasticapm .set_transaction_name (self .get_transaction_name (request ), override = False )
181
176
elasticapm .set_context (
182
177
lambda : self .client .get_data_from_request (request , constants .TRANSACTION ), "request"
183
178
)
@@ -191,6 +186,18 @@ def process_response(self, request, response):
191
186
self .client .error_logger .error ("Exception during timing of request" , exc_info = True )
192
187
return response
193
188
189
+ def get_transaction_name (self , request : HttpRequest , view_func : Optional [FunctionType ] = None ) -> str :
190
+ transaction_name = ""
191
+ if self .client .config .django_transaction_name_from_route and hasattr (request .resolver_match , "route" ):
192
+ r = request .resolver_match
193
+ # if no route is defined (e.g. for the root URL), fall back on url_name and then function name
194
+ transaction_name = r .route or r .url_name or get_name_from_func (r .func )
195
+ elif view_func :
196
+ transaction_name = get_name_from_func (view_func )
197
+ if transaction_name :
198
+ transaction_name = build_name_with_http_method_prefix (transaction_name , request )
199
+ return transaction_name
200
+
194
201
195
202
class ErrorIdMiddleware (MiddlewareMixin ):
196
203
"""
0 commit comments