Skip to content

Commit f8f53b8

Browse files
Fixed Celery headers for Beat auto-instrumentation (#2102)
* Fixed celery headers for beat auto instrumentation --------- Co-authored-by: Ivana Kellyerova <[email protected]>
1 parent 041534d commit f8f53b8

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

sentry_sdk/integrations/celery.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ def apply_async(*args, **kwargs):
157157
# tracing tools (dd-trace-py) also employ this exact
158158
# workaround and we don't want to break them.
159159
kwarg_headers.setdefault("headers", {}).update(headers)
160+
161+
# Add the Sentry options potentially added in `sentry_apply_entry`
162+
# to the headers (done when auto-instrumenting Celery Beat tasks)
163+
for key, value in kwarg_headers.items():
164+
if key.startswith("sentry-"):
165+
kwarg_headers["headers"][key] = value
166+
160167
kwargs["headers"] = kwarg_headers
161168

162169
return f(*args, **kwargs)
@@ -431,7 +438,9 @@ def sentry_apply_entry(*args, **kwargs):
431438
)
432439
headers.update({"sentry-monitor-check-in-id": check_in_id})
433440

434-
schedule_entry.options.update(headers)
441+
# Set the Sentry configuration in the options of the ScheduleEntry.
442+
# Those will be picked up in `apply_async` and added to the headers.
443+
schedule_entry.options["headers"] = headers
435444
return original_apply_entry(*args, **kwargs)
436445

437446
Scheduler.apply_entry = sentry_apply_entry

tests/integrations/celery/test_celery.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
pytest.importorskip("celery")
66

77
from sentry_sdk import Hub, configure_scope, start_transaction
8-
from sentry_sdk.integrations.celery import CeleryIntegration
8+
from sentry_sdk.integrations.celery import CeleryIntegration, _get_headers
9+
910
from sentry_sdk._compat import text_type
1011

1112
from celery import Celery, VERSION
1213
from celery.bin import worker
14+
from celery.signals import task_success
1315

1416
try:
1517
from unittest import mock # python 3.3 and above
@@ -437,3 +439,29 @@ def dummy_task(x, y):
437439
celery_invocation(dummy_task, 1, 0)
438440

439441
assert not events
442+
443+
444+
def test_task_headers(celery):
445+
"""
446+
Test that the headers set in the Celery Beat auto-instrumentation are passed to the celery signal handlers
447+
"""
448+
sentry_crons_setup = {
449+
"sentry-monitor-slug": "some-slug",
450+
"sentry-monitor-config": {"some": "config"},
451+
"sentry-monitor-check-in-id": "123abc",
452+
}
453+
454+
@celery.task(name="dummy_task")
455+
def dummy_task(x, y):
456+
return x + y
457+
458+
def crons_task_success(sender, **kwargs):
459+
headers = _get_headers(sender)
460+
assert headers == sentry_crons_setup
461+
462+
task_success.connect(crons_task_success)
463+
464+
# This is how the Celery Beat auto-instrumentation starts a task
465+
# in the monkey patched version of `apply_async`
466+
# in `sentry_sdk/integrations/celery.py::_wrap_apply_async()`
467+
dummy_task.apply_async(args=(1, 0), headers=sentry_crons_setup)

0 commit comments

Comments
 (0)