Skip to content

Commit 46a632d

Browse files
cnschnantonpirker
andauthored
Propagate sentry-trace and baggage to huey tasks (#2792)
This PR enables passing `sentry-trace` and `baggage` headers to background tasks using the Huey task queue. This allows easily correlating what happens inside a background task with whatever transaction (e.g. a user request in a Django application) queued the task in the first place. Periodic tasks do not get these headers, because otherwise each execution of the periodic task would be tied to the same parent trace (the long-running worker process). --- Co-authored-by: Anton Pirker <[email protected]>
1 parent 461bd59 commit 46a632d

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

sentry_sdk/integrations/huey.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66
from sentry_sdk._compat import reraise
77
from sentry_sdk._types import TYPE_CHECKING
88
from sentry_sdk import Hub
9+
from sentry_sdk.api import continue_trace, get_baggage, get_traceparent
910
from sentry_sdk.consts import OP
1011
from sentry_sdk.hub import _should_send_default_pii
1112
from sentry_sdk.integrations import DidNotEnable, Integration
12-
from sentry_sdk.tracing import Transaction, TRANSACTION_SOURCE_TASK
13+
from sentry_sdk.tracing import (
14+
BAGGAGE_HEADER_NAME,
15+
SENTRY_TRACE_HEADER_NAME,
16+
TRANSACTION_SOURCE_TASK,
17+
)
1318
from sentry_sdk.utils import (
1419
capture_internal_exceptions,
1520
event_from_exception,
@@ -25,7 +30,7 @@
2530
F = TypeVar("F", bound=Callable[..., Any])
2631

2732
try:
28-
from huey.api import Huey, Result, ResultGroup, Task
33+
from huey.api import Huey, Result, ResultGroup, Task, PeriodicTask
2934
from huey.exceptions import CancelExecution, RetryTask, TaskLockedException
3035
except ImportError:
3136
raise DidNotEnable("Huey is not installed")
@@ -56,6 +61,14 @@ def _sentry_enqueue(self, task):
5661
return old_enqueue(self, task)
5762

5863
with hub.start_span(op=OP.QUEUE_SUBMIT_HUEY, description=task.name):
64+
if not isinstance(task, PeriodicTask):
65+
# Attach trace propagation data to task kwargs. We do
66+
# not do this for periodic tasks, as these don't
67+
# really have an originating transaction.
68+
task.kwargs["sentry_headers"] = {
69+
BAGGAGE_HEADER_NAME: get_baggage(),
70+
SENTRY_TRACE_HEADER_NAME: get_traceparent(),
71+
}
5972
return old_enqueue(self, task)
6073

6174
Huey.enqueue = _sentry_enqueue
@@ -145,12 +158,15 @@ def _sentry_execute(self, task, timestamp=None):
145158
scope.clear_breadcrumbs()
146159
scope.add_event_processor(_make_event_processor(task))
147160

148-
transaction = Transaction(
161+
sentry_headers = task.kwargs.pop("sentry_headers", None)
162+
163+
transaction = continue_trace(
164+
sentry_headers or {},
149165
name=task.name,
150-
status="ok",
151166
op=OP.QUEUE_TASK_HUEY,
152167
source=TRANSACTION_SOURCE_TASK,
153168
)
169+
transaction.set_status("ok")
154170

155171
if not getattr(task, "_sentry_is_patched", False):
156172
task.execute = _wrap_task_execute(task.execute)

tests/integrations/huey/test_huey.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,21 @@ def dummy_task():
172172
assert len(event["spans"])
173173
assert event["spans"][0]["op"] == "queue.submit.huey"
174174
assert event["spans"][0]["description"] == "different_task_name"
175+
176+
177+
def test_huey_propagate_trace(init_huey, capture_events):
178+
huey = init_huey()
179+
180+
events = capture_events()
181+
182+
@huey.task()
183+
def propagated_trace_task():
184+
pass
185+
186+
with start_transaction() as outer_transaction:
187+
execute_huey_task(huey, propagated_trace_task)
188+
189+
assert (
190+
events[0]["transaction"] == "propagated_trace_task"
191+
) # the "inner" transaction
192+
assert events[0]["contexts"]["trace"]["trace_id"] == outer_transaction.trace_id

0 commit comments

Comments
 (0)