Skip to content

Commit da9c9a2

Browse files
committed
Unwrap ExceptionInfo and ExceptionWithTraceback
Instead of reporting the `ExceptionInfo` and `ExceptionWithTraceback` wrappers raised by Celery, report the exceptions that they wrap. This ensures that the exception in the OpenTelemetry span has a type and traceback that are meaningful and relevant to the developer.
1 parent a5ed4da commit da9c9a2

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
- `opentelemetry-instrumentation-celery` Unwrap Celery's `ExceptionInfo` errors and report the actual exception that was raised. ([#1863](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1863))
1011
- Instrument all httpx versions >= 0.18. ([#1748](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1748))
1112

1213
## Version 1.18.0/0.39b0 (2023-05-10)

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ def add(x, y):
6363
from typing import Collection, Iterable
6464

6565
from celery import signals # pylint: disable=no-name-in-module
66+
from billiard.einfo import ExceptionInfo
67+
68+
try:
69+
from billiard.einfo import ExceptionWithTraceback # pylint: disable=no-name-in-module
70+
except ImportError:
71+
ExceptionWithTraceback = None
6672

6773
from opentelemetry import trace
6874
from opentelemetry.instrumentation.celery import utils
@@ -256,6 +262,21 @@ def _trace_failure(*args, **kwargs):
256262
return
257263

258264
if ex is not None:
265+
# Unwrap the actual exception wrapped by billiard's
266+
# `ExceptionInfo` and `ExceptionWithTraceback`.
267+
if (
268+
isinstance(ex, ExceptionInfo)
269+
and ex.exception is not None
270+
):
271+
ex = ex.exception
272+
273+
if (
274+
ExceptionWithTraceback is not None
275+
and isinstance(ex, ExceptionWithTraceback)
276+
and ex.exc is not None
277+
):
278+
ex = ex.exc
279+
259280
status_kwargs["description"] = str(ex)
260281
span.record_exception(ex)
261282
span.set_status(Status(**status_kwargs))

tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ def fn_exception():
279279
assert len(span.events) == 1
280280
event = span.events[0]
281281
assert event.name == "exception"
282-
assert event.attributes[SpanAttributes.EXCEPTION_TYPE] == "ExceptionInfo"
282+
assert event.attributes[SpanAttributes.EXCEPTION_TYPE] == "Exception"
283283
assert SpanAttributes.EXCEPTION_MESSAGE in event.attributes
284284
assert (
285285
span.attributes.get(SpanAttributes.MESSAGING_MESSAGE_ID)

0 commit comments

Comments
 (0)