@@ -64,6 +64,26 @@ def task_info(instance, *args, **kwargs):
64
64
return task_name , task_source
65
65
66
66
67
+ # def create_DT_headers_and_attach(wrapped, transaction):
68
+ # try:
69
+ # request = wrapped and wrapped.request_stack and wrapped.request_stack.top
70
+ # original_headers = getattr(request, "headers", None) or vars(request)
71
+ # dt_headers = MessageTrace.generate_request_headers(transaction)
72
+ # if dt_headers:
73
+ # if not original_headers:
74
+ # wrapped.request.headers = dict(dt_headers)
75
+ # else:
76
+ # dt_headers.update(original_headers)
77
+ # wrapped.request.headers = dt_headers = dict(dt_headers)
78
+ # # original_headers.update(dict(dt_headers))
79
+ # # wrapped.request.headers = original_headers
80
+
81
+ # except Exception:
82
+ # pass
83
+
84
+ # return wrapped
85
+
86
+
67
87
def wrap_task_call (wrapped , instance , args , kwargs ):
68
88
transaction = current_transaction (active_only = False )
69
89
@@ -104,22 +124,23 @@ def wrap_task_call(wrapped, instance, args, kwargs):
104
124
try :
105
125
# Headers on earlier versions of Celery may end up as attributes
106
126
# on the request context instead of as custom headers. Handle this
107
- # by defaulting to using vars() if headers is not available
108
- request = wrapped .request
127
+ # by defaulting to using `vars()` if headers is not available
128
+
129
+ # If there is no request, the request property will return
130
+ # a new instance of `celery.Context()` instead of `None`, so
131
+ # this will be handled by accessing the request_stack directly.
132
+ request = wrapped and wrapped .request_stack and wrapped .request_stack .top
109
133
headers = getattr (request , "headers" , None ) or vars (request )
110
134
111
135
settings = transaction .settings
112
136
if headers is not None and settings is not None :
113
137
if settings .distributed_tracing .enabled :
138
+ # Generate DT headers if they do not already exist in the incoming request
114
139
if not transaction .accept_distributed_trace_headers (headers , transport_type = "AMQP" ):
115
140
try :
116
141
dt_headers = MessageTrace .generate_request_headers (transaction )
117
142
if dt_headers :
118
- if not headers :
119
- wrapped .request .headers = dict (dt_headers )
120
- else :
121
- headers .update (dict (dt_headers ))
122
- wrapped .request .headers = headers
143
+ headers .update (dict (dt_headers ))
123
144
except Exception :
124
145
pass
125
146
elif transaction .settings .cross_application_tracer .enabled :
@@ -143,7 +164,6 @@ def run(self, *args, **kwargs):
143
164
task = bound_args .get ("task" , None )
144
165
145
166
task = TaskWrapper (task , wrap_task_call )
146
- task .__module__ = wrapped .__module__ # Ensure module is set for monkeypatching detection
147
167
bound_args ["task" ] = task
148
168
149
169
return wrapped (** bound_args )
@@ -193,22 +213,23 @@ def wrapper(wrapped, instance, args, kwargs):
193
213
try :
194
214
# Headers on earlier versions of Celery may end up as attributes
195
215
# on the request context instead of as custom headers. Handle this
196
- # by defaulting to using vars() if headers is not available
197
- request = instance .request
216
+ # by defaulting to using `vars()` if headers is not available
217
+
218
+ # If there is no request, the request property will return
219
+ # a new instance of `celery.Context()` instead of `None`, so
220
+ # this will be handled by accessing the request_stack directly.
221
+ request = instance and instance .request_stack and instance .request_stack .top
198
222
headers = getattr (request , "headers" , None ) or vars (request )
199
223
200
224
settings = transaction .settings
201
225
if headers is not None and settings is not None :
202
226
if settings .distributed_tracing .enabled :
227
+ # Generate DT headers if they do not already exist in the incoming request
203
228
if not transaction .accept_distributed_trace_headers (headers , transport_type = "AMQP" ):
204
229
try :
205
230
dt_headers = MessageTrace .generate_request_headers (transaction )
206
231
if dt_headers :
207
- if not headers :
208
- instance .request .headers = dict (dt_headers )
209
- else :
210
- headers .update (dict (dt_headers ))
211
- instance .request .headers = headers
232
+ headers .update (dict (dt_headers ))
212
233
except Exception :
213
234
pass
214
235
elif transaction .settings .cross_application_tracer .enabled :
@@ -238,7 +259,7 @@ def wrapper(wrapped, instance, args, kwargs):
238
259
# Celery has included a monkey-patching provision which did not perform this
239
260
# optimization on functions that were monkey-patched. Unfortunately, our
240
261
# wrappers are too transparent for celery to detect that they've even been
241
- # monky -patched. To circumvent this, we set the __module__ of our wrapped task
262
+ # monkey -patched. To circumvent this, we set the __module__ of our wrapped task
242
263
# to this file which causes celery to properly detect that it has been patched.
243
264
#
244
265
# For versions of celery 2.5.3 to 2.5.5
@@ -252,7 +273,6 @@ def run(self, *args, **kwargs):
252
273
return self .__call__ (* args , ** kwargs )
253
274
254
275
wrapped_task = TaskWrapper (wrapped , wrapper )
255
- # Reset __module__ to be less transparent so celery detects our monkey-patching
256
276
wrapped_task .__module__ = CeleryTaskWrapper .__module__
257
277
258
278
return wrapped_task
@@ -262,7 +282,7 @@ def instrument_celery_local(module):
262
282
if hasattr (module , "Proxy" ):
263
283
# This is used in the case where the function is
264
284
# called directly on the Proxy object (rather than
265
- # using " delay" or " apply_async" )
285
+ # using ` delay` or ` apply_async` )
266
286
module .Proxy .__call__ = CeleryTaskWrapper (module .Proxy .__call__ )
267
287
268
288
0 commit comments