Skip to content

Commit 074299f

Browse files
committed
refactor utils
1 parent 8d293fd commit 074299f

File tree

4 files changed

+101
-66
lines changed

4 files changed

+101
-66
lines changed

ext/opentelemetry-ext-celery/setup.cfg

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ package_dir=
4040
packages=find_namespace:
4141
install_requires =
4242
opentelemetry-api == 0.10.dev0
43+
opentelemetry-instrumentation == 0.10.dev0
4344
celery ~= 4.0
4445

4546
[options.extras_require]

ext/opentelemetry-ext-celery/src/opentelemetry/ext/celery/__init__.py

+36-60
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,11 @@ def add(x, y):
5454
import logging
5555
import signal
5656

57-
from celery import registry, signals # pylint: disable=no-name-in-module
57+
from celery import signals # pylint: disable=no-name-in-module
5858

5959
from opentelemetry import trace
60-
from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor
61-
from opentelemetry.ext.celery.utils import (
62-
attach_span,
63-
detach_span,
64-
retrieve_span,
65-
retrieve_task_id,
66-
set_attributes_from_context,
67-
)
60+
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
61+
from opentelemetry.ext.celery import utils
6862
from opentelemetry.ext.celery.version import __version__
6963
from opentelemetry.trace.status import Status, StatusCanonicalCode
7064

@@ -110,58 +104,53 @@ def _uninstrument(self, **kwargs):
110104
signals.task_retry.disconnect(self._trace_retry)
111105

112106
def _trace_prerun(self, *args, **kwargs):
113-
task = kwargs.get("task")
114-
task_id = kwargs.get("task_id")
115-
logger.debug("prerun signal start task_id=%s", task_id)
107+
task = utils.signal_retrieve_task(kwargs)
108+
task_id = utils.signal_retrieve_task_id(kwargs)
109+
116110
if task is None or task_id is None:
117-
logger.debug(
118-
"Unable to extract the Task and the task_id. This version of Celery may not be supported."
119-
)
120111
return
121112

113+
logger.debug("prerun signal start task_id=%s", task_id)
114+
122115
span = self._tracer.start_span(task.name, kind=trace.SpanKind.CONSUMER)
123116

124117
activation = self._tracer.use_span(span, end_on_exit=True)
125118
activation.__enter__()
126-
attach_span(task, task_id, (span, activation))
119+
utils.attach_span(task, task_id, (span, activation))
127120

128121
@staticmethod
129122
def _trace_postrun(*args, **kwargs):
130-
task = kwargs.get("task")
131-
task_id = kwargs.get("task_id")
132-
logger.debug("postrun signal task_id=%s", task_id)
123+
task = utils.signal_retrieve_task(kwargs)
124+
task_id = utils.signal_retrieve_task_id(kwargs)
125+
133126
if task is None or task_id is None:
134-
logger.debug(
135-
"Unable to extract the Task and the task_id. This version of Celery may not be supported."
136-
)
137127
return
138128

129+
logger.debug("postrun signal task_id=%s", task_id)
130+
139131
# retrieve and finish the Span
140-
span, activation = retrieve_span(task, task_id)
132+
span, activation = utils.retrieve_span(task, task_id)
141133
if span is None:
142134
logger.warning("no existing span found for task_id=%s", task_id)
143135
return
144136

145137
# request context tags
146138
span.set_attribute(_TASK_TAG_KEY, _TASK_RUN)
147-
set_attributes_from_context(span, kwargs)
148-
set_attributes_from_context(span, task.request)
139+
utils.set_attributes_from_context(span, kwargs)
140+
utils.set_attributes_from_context(span, task.request)
149141
span.set_attribute(_TASK_NAME_KEY, task.name)
150142

151143
activation.__exit__(None, None, None)
152-
detach_span(task, task_id)
144+
utils.detach_span(task, task_id)
153145

154146
def _trace_before_publish(self, *args, **kwargs):
155147
# The `Task` instance **does not** include any information about the current
156148
# execution, so it **must not** be used to retrieve `request` data.
157149
# pylint: disable=no-member
158-
task = registry.tasks.get(kwargs.get("sender"))
159-
task_id = retrieve_task_id(kwargs)
150+
task = utils.signal_retrieve_task_from_sender(kwargs)
151+
task_id = utils.signal_retrieve_task_id_from_message(kwargs)
160152

161153
if task is None or task_id is None:
162-
logger.debug(
163-
"Unable to extract the Task and the task_id. This version of Celery may not be supported."
164-
)
165154
return
166155

167156
span = self._tracer.start_span(task.name, kind=trace.SpanKind.PRODUCER)
@@ -170,44 +159,39 @@ def _trace_before_publish(self, *args, **kwargs):
170159
span.set_attribute(_TASK_TAG_KEY, _TASK_APPLY_ASYNC)
171160
span.set_attribute(_MESSAGE_ID_ATTRIBUTE_NAME, task_id)
172161
span.set_attribute(_TASK_NAME_KEY, task.name)
173-
set_attributes_from_context(span, kwargs)
162+
utils.set_attributes_from_context(span, kwargs)
174163

175164
activation = self._tracer.use_span(span, end_on_exit=True)
176165
activation.__enter__()
177-
attach_span(task, task_id, (span, activation), is_publish=True)
166+
utils.attach_span(task, task_id, (span, activation), is_publish=True)
178167

179168
@staticmethod
180169
def _trace_after_publish(*args, **kwargs):
181-
# pylint: disable=no-member
182-
task = registry.tasks.get(kwargs.get("sender"))
183-
task_id = retrieve_task_id(kwargs)
170+
task = utils.signal_retrieve_task_from_sender(kwargs)
171+
task_id = utils.signal_retrieve_task_id_from_message(kwargs)
172+
184173
if task is None or task_id is None:
185-
logger.debug(
186-
"Unable to extract the Task and the task_id. This version of Celery may not be supported."
187-
)
188174
return
189175

190176
# retrieve and finish the Span
191-
_, activation = retrieve_span(task, task_id, is_publish=True)
177+
_, activation = utils.retrieve_span(task, task_id, is_publish=True)
192178
if activation is None:
193179
logger.warning("no existing span found for task_id=%s", task_id)
194180
return
195181

196182
activation.__exit__(None, None, None)
197-
detach_span(task, task_id, is_publish=True)
183+
utils.detach_span(task, task_id, is_publish=True)
198184

199185
@staticmethod
200186
def _trace_failure(*args, **kwargs):
201-
task = kwargs.get("sender")
202-
task_id = kwargs.get("task_id")
187+
task = utils.signal_retrieve_task_from_sender(kwargs)
188+
task_id = utils.signal_retrieve_task_id(kwargs)
189+
203190
if task is None or task_id is None:
204-
logger.debug(
205-
"Unable to extract the Task and the task_id. This version of Celery may not be supported."
206-
)
207191
return
208192

209193
# retrieve and pass exception info to activation
210-
span, _ = retrieve_span(task, task_id)
194+
span, _ = utils.retrieve_span(task, task_id)
211195
if span is None:
212196
return
213197

@@ -226,22 +210,14 @@ def _trace_failure(*args, **kwargs):
226210

227211
@staticmethod
228212
def _trace_retry(*args, **kwargs):
229-
task = kwargs.get("sender")
230-
context = kwargs.get("request")
231-
if task is None or context is None:
232-
logger.debug(
233-
"Unable to extract the Task or the Context. This version of Celery may not be supported."
234-
)
235-
return
213+
task = utils.signal_retrieve_task_from_sender(kwargs)
214+
task_id = utils.signal_retrieve_task_id_from_request(kwargs)
215+
reason = utils.signal_retrieve_reason(kwargs)
236216

237-
reason = kwargs.get("reason")
238-
if not reason:
239-
logger.debug(
240-
"Unable to extract the retry reason. This version of Celery may not be supported."
241-
)
217+
if task is None or task_id is None or reason is None:
242218
return
243219

244-
span, _ = retrieve_span(task, context.id)
220+
span, _ = utils.retrieve_span(task, task_id)
245221
if span is None:
246222
return
247223

ext/opentelemetry-ext-celery/src/opentelemetry/ext/celery/utils.py

+63-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import logging
16+
17+
import celery
18+
19+
logger = logging.getLogger(__name__)
20+
1521
# Celery Context key
1622
CTX_KEY = "__otel_task_span"
1723

@@ -148,16 +154,69 @@ def retrieve_span(task, task_id, is_publish=False):
148154
return span_dict.get((task_id, is_publish), (None, None))
149155

150156

151-
def retrieve_task_id(context):
157+
def signal_retrieve_task(kwargs):
158+
task = kwargs.get("task")
159+
if task is None:
160+
logger.debug("Unable to retrieve task from signal arguments")
161+
return task
162+
163+
164+
def signal_retrieve_task_from_sender(kwargs):
165+
sender = kwargs.get("sender")
166+
if sender is None:
167+
logger.debug("Unable to retrieve the sender from signal arguments")
168+
return
169+
170+
# before and after publish signals sender is the task name
171+
# for retry and failure signals sender is the task object
172+
if isinstance(sender, str):
173+
sender = celery.registry.tasks.get(sender)
174+
if sender is None:
175+
logger.debug("Unable to retrieve the task from sender=%s", sender)
176+
return
177+
178+
return sender
179+
180+
181+
def signal_retrieve_task_id(kwargs):
182+
task_id = kwargs.get("task_id")
183+
if task_id is None:
184+
logger.debug("Unable to retrieve task_id from signal arguments")
185+
return task_id
186+
187+
188+
def signal_retrieve_task_id_from_request(kwargs):
189+
# retry signal does not include task_id as argument so use request argument
190+
request = kwargs.get("request")
191+
if request is None:
192+
logger.debug("Unable to retrieve the request from signal arguments")
193+
194+
task_id = getattr(request, "id")
195+
if task_id is None:
196+
logger.debug("Unable to retrieve the task_id from the request")
197+
198+
return task_id
199+
200+
201+
def signal_retrieve_task_id_from_message(kwargs):
152202
"""Helper to retrieve the `Task` identifier from the message `body`.
153203
This helper supports Protocol Version 1 and 2. The Protocol is well
154204
detailed in the official documentation:
155205
http://docs.celeryproject.org/en/latest/internals/protocol.html
156206
"""
157-
headers = context.get("headers")
158-
body = context.get("body")
159-
if headers is not None:
207+
headers = kwargs.get("headers")
208+
body = kwargs.get("body")
209+
if headers is not None and len(headers) > 0:
160210
# Protocol Version 2 (default from Celery 4.0)
161211
return headers.get("id")
162212
# Protocol Version 1
163213
return body.get("id")
214+
215+
216+
217+
218+
def signal_retrieve_reason(kwargs):
219+
reason = kwargs.get("reason")
220+
if not reason:
221+
logger.debug("Unable to retrieve the retry reason")
222+
return reason

tox.ini

+1-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ envlist =
144144
pypy3-test-ext-redis
145145

146146
; opentelemetry-ext-celery
147-
py3{4,5,6,7,8}-test-ext-celery
147+
py3{5,6,7,8}-test-ext-celery
148148
pypy3-test-ext-celery
149149

150150
; opentelemetry-ext-system-metrics
@@ -232,7 +232,6 @@ commands_pre =
232232

233233
getting-started: pip install -e {toxinidir}/opentelemetry-instrumentation -e {toxinidir}/ext/opentelemetry-ext-requests -e {toxinidir}/ext/opentelemetry-ext-wsgi -e {toxinidir}/ext/opentelemetry-ext-flask
234234

235-
celery: pip install {toxinidir}/opentelemetry-instrument
236235
celery: pip install {toxinidir}/ext/opentelemetry-ext-celery[test]
237236

238237
grpc: pip install {toxinidir}/ext/opentelemetry-ext-grpc[test]

0 commit comments

Comments
 (0)