Skip to content

Commit d586149

Browse files
authored
Make sure each task that is started by Celery Beat has its own trace. (#2249)
When tasks are started by Celery Beat they should not inherit the trace from the starting code (which is Celery Beat) but get their own trace.
1 parent 093003f commit d586149

File tree

2 files changed

+40
-27
lines changed

2 files changed

+40
-27
lines changed

sentry_sdk/integrations/celery.py

+25-21
Original file line numberDiff line numberDiff line change
@@ -462,30 +462,34 @@ def sentry_apply_entry(*args, **kwargs):
462462
if match_regex_list(monitor_name, integration.exclude_beat_tasks):
463463
return original_apply_entry(*args, **kwargs)
464464

465-
monitor_config = _get_monitor_config(celery_schedule, app)
466-
467-
is_supported_schedule = bool(monitor_config)
468-
if is_supported_schedule:
469-
headers = schedule_entry.options.pop("headers", {})
470-
headers.update(
471-
{
472-
"sentry-monitor-slug": monitor_name,
473-
"sentry-monitor-config": monitor_config,
474-
}
475-
)
465+
with hub.configure_scope() as scope:
466+
# When tasks are started from Celery Beat, make sure each task has its own trace.
467+
scope.set_new_propagation_context()
468+
469+
monitor_config = _get_monitor_config(celery_schedule, app)
470+
471+
is_supported_schedule = bool(monitor_config)
472+
if is_supported_schedule:
473+
headers = schedule_entry.options.pop("headers", {})
474+
headers.update(
475+
{
476+
"sentry-monitor-slug": monitor_name,
477+
"sentry-monitor-config": monitor_config,
478+
}
479+
)
476480

477-
check_in_id = capture_checkin(
478-
monitor_slug=monitor_name,
479-
monitor_config=monitor_config,
480-
status=MonitorStatus.IN_PROGRESS,
481-
)
482-
headers.update({"sentry-monitor-check-in-id": check_in_id})
481+
check_in_id = capture_checkin(
482+
monitor_slug=monitor_name,
483+
monitor_config=monitor_config,
484+
status=MonitorStatus.IN_PROGRESS,
485+
)
486+
headers.update({"sentry-monitor-check-in-id": check_in_id})
483487

484-
# Set the Sentry configuration in the options of the ScheduleEntry.
485-
# Those will be picked up in `apply_async` and added to the headers.
486-
schedule_entry.options["headers"] = headers
488+
# Set the Sentry configuration in the options of the ScheduleEntry.
489+
# Those will be picked up in `apply_async` and added to the headers.
490+
schedule_entry.options["headers"] = headers
487491

488-
return original_apply_entry(*args, **kwargs)
492+
return original_apply_entry(*args, **kwargs)
489493

490494
Scheduler.apply_entry = sentry_apply_entry
491495

sentry_sdk/scope.py

+15-6
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,23 @@ def _create_new_propagation_context(self):
196196
"dynamic_sampling_context": None,
197197
}
198198

199+
def set_new_propagation_context(self):
200+
# type: () -> None
201+
"""
202+
Creates a new propagation context and sets it as `_propagation_context`. Overwriting existing one.
203+
"""
204+
self._propagation_context = self._create_new_propagation_context()
205+
logger.debug(
206+
"[Tracing] Create new propagation context: %s",
207+
self._propagation_context,
208+
)
209+
199210
def generate_propagation_context(self, incoming_data=None):
200211
# type: (Optional[Dict[str, str]]) -> None
201212
"""
202-
Populates `_propagation_context`. Either from `incoming_data` or with a new propagation context.
213+
Makes sure `_propagation_context` is set.
214+
If there is `incoming_data` overwrite existing `_propagation_context`.
215+
if there is no `incoming_data` create new `_propagation_context`, but do NOT overwrite if already existing.
203216
"""
204217
if incoming_data:
205218
context = self._extract_propagation_context(incoming_data)
@@ -212,11 +225,7 @@ def generate_propagation_context(self, incoming_data=None):
212225
)
213226

214227
if self._propagation_context is None:
215-
self._propagation_context = self._create_new_propagation_context()
216-
logger.debug(
217-
"[Tracing] Create new propagation context: %s",
218-
self._propagation_context,
219-
)
228+
self.set_new_propagation_context()
220229

221230
def get_dynamic_sampling_context(self):
222231
# type: () -> Optional[Dict[str, str]]

0 commit comments

Comments
 (0)