Skip to content

Commit 2a1e6ed

Browse files
committed
opentelemetry-instrumentation-celery: don't detach a None token (open-telemetry#2927)
1 parent 1e952e2 commit 2a1e6ed

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3232
([#2901])(https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2901)
3333
- `opentelemetry-instrumentation-system-metrics` Update metric units to conform to UCUM conventions.
3434
([#2922](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2922))
35+
- `opentelemetry-instrumentation-celery` Don't detach context without a None token
36+
([#2927](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2927))
3537

3638
### Breaking changes
3739

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,10 @@ def _trace_postrun(self, *args, **kwargs):
213213
self.update_task_duration_time(task_id)
214214
labels = {"task": task.name, "worker": task.request.hostname}
215215
self._record_histograms(task_id, labels)
216-
context_api.detach(token)
216+
# if the process sending the task is not instrumented
217+
# there's no incoming context and no token to detach
218+
if token is not None:
219+
context_api.detach(token)
217220

218221
def _trace_before_publish(self, *args, **kwargs):
219222
task = utils.retrieve_task_from_sender(kwargs)

instrumentation/opentelemetry-instrumentation-celery/tests/test_tasks.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
import threading
1616
import time
1717

18+
from wrapt import wrap_function_wrapper
19+
1820
from opentelemetry import baggage, context
19-
from opentelemetry.instrumentation.celery import CeleryInstrumentor
21+
from opentelemetry.instrumentation.celery import CeleryInstrumentor, utils
22+
from opentelemetry.instrumentation.utils import unwrap
2023
from opentelemetry.semconv.trace import SpanAttributes
2124
from opentelemetry.test.test_base import TestBase
2225
from opentelemetry.trace import SpanKind, StatusCode
@@ -185,6 +188,40 @@ def test_baggage(self):
185188

186189
self.assertEqual(task.result, {"key": "value"})
187190

191+
def test_task_not_instrumented_does_not_raise(self):
192+
def _retrieve_context_wrapper_none_token(
193+
wrapped, instance, args, kwargs
194+
):
195+
ctx = wrapped(*args, **kwargs)
196+
if ctx is None:
197+
return ctx
198+
span, activation, _ = ctx
199+
return span, activation, None
200+
201+
wrap_function_wrapper(
202+
utils,
203+
"retrieve_context",
204+
_retrieve_context_wrapper_none_token,
205+
)
206+
207+
CeleryInstrumentor().instrument()
208+
209+
result = task_add.delay(1, 2)
210+
211+
timeout = time.time() + 60 * 1 # 1 minutes from now
212+
while not result.ready():
213+
if time.time() > timeout:
214+
break
215+
time.sleep(0.05)
216+
217+
spans = self.sorted_spans(self.memory_exporter.get_finished_spans())
218+
self.assertEqual(len(spans), 2)
219+
220+
# TODO: assert we don't have "TypeError: expected an instance of Token, got None" in logs
221+
self.assertTrue(result)
222+
223+
unwrap(utils, "retrieve_context")
224+
188225

189226
class TestCelerySignatureTask(TestBase):
190227
def setUp(self):

0 commit comments

Comments
 (0)