Skip to content

Commit f726f75

Browse files
committed
Merge remote-tracking branch 'origin/potel-base' into potel-base-run-all-tests
2 parents 7bebf79 + cc4afcc commit f726f75

File tree

7 files changed

+103
-50
lines changed

7 files changed

+103
-50
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090

9191
- **New integration:** Add [OpenFeature](https://openfeature.dev/) feature flagging integration (#3648) by @cmanallen
9292

93-
For more information, see the documentation for the [OpenFeatureIntegration](https://docs.sentry.io/platforms/python/integrations/opoenfeature/).
93+
For more information, see the documentation for the [OpenFeatureIntegration](https://docs.sentry.io/platforms/python/integrations/openfeature/).
9494

9595
- Add LaunchDarkly and OpenFeature integration (#3648) by @cmanallen
9696
- Correct typo in a comment (#3726) by @szokeasaurusrex

sentry_sdk/integrations/celery/__init__.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import sys
2+
import warnings
3+
24
from collections.abc import Mapping
35
from functools import wraps
46

@@ -67,6 +69,11 @@ def __init__(
6769
exclude_beat_tasks=None,
6870
):
6971
# type: (bool, bool, Optional[List[str]]) -> None
72+
warnings.warn(
73+
"The `propagate_traces` parameter is deprecated. Please use `trace_propagation_targets` instead.",
74+
DeprecationWarning,
75+
stacklevel=2,
76+
)
7077
self.propagate_traces = propagate_traces
7178
self.monitor_beat_tasks = monitor_beat_tasks
7279
self.exclude_beat_tasks = exclude_beat_tasks
@@ -112,7 +119,6 @@ def _capture_exception(task, exc_info):
112119
return
113120

114121
if isinstance(exc_info[1], CELERY_CONTROL_FLOW_EXCEPTIONS):
115-
# ??? Doesn't map to anything
116122
_set_status("aborted")
117123
return
118124

@@ -276,6 +282,7 @@ def apply_async(*args, **kwargs):
276282
op=OP.QUEUE_SUBMIT_CELERY,
277283
name=task_name,
278284
origin=CeleryIntegration.origin,
285+
only_if_parent=True,
279286
)
280287
if not task_started_from_beat
281288
else NoOpMgr()
@@ -306,11 +313,13 @@ def _inner(*args, **kwargs):
306313
with isolation_scope() as scope:
307314
scope._name = "celery"
308315
scope.clear_breadcrumbs()
316+
scope.set_transaction_name(task.name, source=TRANSACTION_SOURCE_TASK)
309317
scope.add_event_processor(_make_event_processor(task, *args, **kwargs))
310318

311319
# Celery task objects are not a thing to be trusted. Even
312320
# something such as attribute access can fail.
313321
headers = args[3].get("headers") or {}
322+
314323
with sentry_sdk.continue_trace(headers):
315324
with sentry_sdk.start_span(
316325
op=OP.QUEUE_TASK_CELERY,
@@ -320,9 +329,13 @@ def _inner(*args, **kwargs):
320329
# for some reason, args[1] is a list if non-empty but a
321330
# tuple if empty
322331
attributes=_prepopulate_attributes(task, list(args[1]), args[2]),
323-
) as transaction:
324-
transaction.set_status(SPANSTATUS.OK)
325-
return f(*args, **kwargs)
332+
) as root_span:
333+
return_value = f(*args, **kwargs)
334+
335+
if root_span.status is None:
336+
root_span.set_status(SPANSTATUS.OK)
337+
338+
return return_value
326339

327340
return _inner # type: ignore
328341

@@ -359,6 +372,7 @@ def _inner(*args, **kwargs):
359372
op=OP.QUEUE_PROCESS,
360373
name=task.name,
361374
origin=CeleryIntegration.origin,
375+
only_if_parent=True,
362376
) as span:
363377
_set_messaging_destination_name(task, span)
364378

@@ -390,6 +404,7 @@ def _inner(*args, **kwargs):
390404
)
391405

392406
return f(*args, **kwargs)
407+
393408
except Exception:
394409
exc_info = sys.exc_info()
395410
with capture_internal_exceptions():

sentry_sdk/scope.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,11 @@ def iter_trace_propagation_headers(self, *args, **kwargs):
613613
"""
614614
client = self.get_client()
615615
if not client.options.get("propagate_traces"):
616+
warnings.warn(
617+
"The `propagate_traces` parameter is deprecated. Please use `trace_propagation_targets` instead.",
618+
DeprecationWarning,
619+
stacklevel=2,
620+
)
616621
return
617622

618623
span = kwargs.pop("span", None)

sentry_sdk/utils.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ def get_lines_from_file(
546546

547547
def get_source_context(
548548
frame, # type: FrameType
549-
tb_lineno, # type: int
549+
tb_lineno, # type: Optional[int]
550550
max_value_length=None, # type: Optional[int]
551551
):
552552
# type: (...) -> Tuple[List[Annotated[str]], Optional[Annotated[str]], List[Annotated[str]]]
@@ -562,11 +562,13 @@ def get_source_context(
562562
loader = frame.f_globals["__loader__"]
563563
except Exception:
564564
loader = None
565-
lineno = tb_lineno - 1
566-
if lineno is not None and abs_path:
565+
566+
if tb_lineno is not None and abs_path:
567+
lineno = tb_lineno - 1
567568
return get_lines_from_file(
568569
abs_path, lineno, max_value_length, loader=loader, module=module
569570
)
571+
570572
return [], None, []
571573

572574

tests/integrations/celery/test_celery.py

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
import pytest
66
from celery import Celery, VERSION
77
from celery.bin import worker
8+
from celery.app.task import Task
9+
from opentelemetry import trace as otel_trace, context
810

911
import sentry_sdk
10-
from sentry_sdk import start_span, get_current_span
12+
from sentry_sdk import get_current_span
1113
from sentry_sdk.integrations.celery import (
1214
CeleryIntegration,
1315
_wrap_task_run,
@@ -126,14 +128,14 @@ def dummy_task(x, y):
126128
foo = 42 # noqa
127129
return x / y
128130

129-
with start_span(op="unit test transaction") as transaction:
131+
with sentry_sdk.start_span(op="unit test transaction") as root_span:
130132
celery_invocation(dummy_task, 1, 2)
131133
_, expected_context = celery_invocation(dummy_task, 1, 0)
132134

133135
(_, error_event, _, _) = events
134136

135-
assert error_event["contexts"]["trace"]["trace_id"] == transaction.trace_id
136-
assert error_event["contexts"]["trace"]["span_id"] != transaction.span_id
137+
assert error_event["contexts"]["trace"]["trace_id"] == root_span.trace_id
138+
assert error_event["contexts"]["trace"]["span_id"] != root_span.span_id
137139
assert error_event["transaction"] == "dummy_task"
138140
assert "celery_task_id" in error_event["tags"]
139141
assert error_event["extra"]["celery-job"] == dict(
@@ -190,17 +192,14 @@ def test_transaction_events(capture_events, init_celery, celery_invocation, task
190192
def dummy_task(x, y):
191193
return x / y
192194

193-
# XXX: For some reason the first call does not get instrumented properly.
194-
celery_invocation(dummy_task, 1, 1)
195-
196195
events = capture_events()
197196

198-
with start_span(name="submission") as transaction:
197+
with sentry_sdk.start_span(name="submission") as root_span:
199198
celery_invocation(dummy_task, 1, 0 if task_fails else 1)
200199

201200
if task_fails:
202201
error_event = events.pop(0)
203-
assert error_event["contexts"]["trace"]["trace_id"] == transaction.trace_id
202+
assert error_event["contexts"]["trace"]["trace_id"] == root_span.trace_id
204203
assert error_event["exception"]["values"][0]["type"] == "ZeroDivisionError"
205204

206205
execution_event, submission_event = events
@@ -211,24 +210,21 @@ def dummy_task(x, y):
211210
assert submission_event["transaction_info"] == {"source": "custom"}
212211

213212
assert execution_event["type"] == submission_event["type"] == "transaction"
214-
assert execution_event["contexts"]["trace"]["trace_id"] == transaction.trace_id
215-
assert submission_event["contexts"]["trace"]["trace_id"] == transaction.trace_id
213+
assert execution_event["contexts"]["trace"]["trace_id"] == root_span.trace_id
214+
assert submission_event["contexts"]["trace"]["trace_id"] == root_span.trace_id
216215

217216
if task_fails:
218217
assert execution_event["contexts"]["trace"]["status"] == "internal_error"
219218
else:
220219
assert execution_event["contexts"]["trace"]["status"] == "ok"
221220

222221
assert len(execution_event["spans"]) == 1
223-
assert (
224-
execution_event["spans"][0].items()
225-
>= {
226-
"trace_id": str(transaction.trace_id),
227-
"same_process_as_parent": True,
222+
assert execution_event["spans"][0] == ApproxDict(
223+
{
224+
"trace_id": str(root_span.trace_id),
228225
"op": "queue.process",
229226
"description": "dummy_task",
230-
"data": ApproxDict(),
231-
}.items()
227+
}
232228
)
233229
assert submission_event["spans"] == [
234230
{
@@ -237,11 +233,14 @@ def dummy_task(x, y):
237233
"op": "queue.submit.celery",
238234
"origin": "auto.queue.celery",
239235
"parent_span_id": submission_event["contexts"]["trace"]["span_id"],
240-
"same_process_as_parent": True,
241236
"span_id": submission_event["spans"][0]["span_id"],
242237
"start_timestamp": submission_event["spans"][0]["start_timestamp"],
243238
"timestamp": submission_event["spans"][0]["timestamp"],
244-
"trace_id": str(transaction.trace_id),
239+
"trace_id": str(root_span.trace_id),
240+
"status": "ok",
241+
"tags": {
242+
"status": "ok",
243+
},
245244
}
246245
]
247246

@@ -268,14 +267,16 @@ def dummy_task():
268267

269268

270269
def test_simple_no_propagation(capture_events, init_celery):
271-
celery = init_celery(propagate_traces=False)
270+
with pytest.warns(DeprecationWarning):
271+
celery = init_celery(propagate_traces=False)
272+
272273
events = capture_events()
273274

274275
@celery.task(name="dummy_task")
275276
def dummy_task():
276277
1 / 0
277278

278-
with start_span(name="task") as root_span:
279+
with sentry_sdk.start_span(name="task") as root_span:
279280
dummy_task.delay()
280281

281282
(event,) = events
@@ -350,7 +351,7 @@ def dummy_task(self):
350351
runs.append(1)
351352
1 / 0
352353

353-
with start_span(name="submit_celery"):
354+
with sentry_sdk.start_span(name="submit_celery"):
354355
# Curious: Cannot use delay() here or py2.7-celery-4.2 crashes
355356
res = dummy_task.apply_async()
356357

@@ -445,7 +446,7 @@ def walk_dogs(x, y):
445446
walk_dogs, [["Maisey", "Charlie", "Bodhi", "Cory"], "Dog park round trip"], 1
446447
)
447448

448-
sampling_context = traces_sampler.call_args_list[1][0][0]
449+
sampling_context = traces_sampler.call_args_list[0][0][0]
449450
assert sampling_context["celery.job.task"] == "dog_walk"
450451
for i, arg in enumerate(args_kwargs["args"]):
451452
assert sampling_context[f"celery.job.args.{i}"] == str(arg)
@@ -469,7 +470,7 @@ def __call__(self, *args, **kwargs):
469470
def dummy_task(x, y):
470471
return x / y
471472

472-
with start_span(name="celery"):
473+
with sentry_sdk.start_span(name="celery"):
473474
celery_invocation(dummy_task, 1, 0)
474475

475476
assert not events
@@ -510,7 +511,7 @@ def test_baggage_propagation(init_celery):
510511
def dummy_task(self, x, y):
511512
return _get_headers(self)
512513

513-
with start_span(name="task") as root_span:
514+
with sentry_sdk.start_span(name="task") as root_span:
514515
result = dummy_task.apply_async(
515516
args=(1, 0),
516517
headers={"baggage": "custom=value"},
@@ -520,6 +521,7 @@ def dummy_task(self, x, y):
520521
[
521522
"sentry-release=abcdef",
522523
"sentry-trace_id={}".format(root_span.trace_id),
524+
"sentry-transaction=task",
523525
"sentry-environment=production",
524526
"sentry-sample_rate=1.0",
525527
"sentry-sampled=true",
@@ -533,30 +535,47 @@ def test_sentry_propagate_traces_override(init_celery):
533535
Test if the `sentry-propagate-traces` header given to `apply_async`
534536
overrides the `propagate_traces` parameter in the integration constructor.
535537
"""
536-
celery = init_celery(
537-
propagate_traces=True, traces_sample_rate=1.0, release="abcdef"
538-
)
538+
with pytest.warns(DeprecationWarning):
539+
celery = init_celery(
540+
propagate_traces=True, traces_sample_rate=1.0, release="abcdef"
541+
)
542+
543+
# Since we're applying the task inline eagerly,
544+
# we need to cleanup the otel context for this test.
545+
# and since we patch build_tracer, we need to do this before that runs...
546+
# TODO: the right way is to not test this inline
547+
original_apply = Task.apply
548+
549+
def cleaned_apply(*args, **kwargs):
550+
token = context.attach(otel_trace.set_span_in_context(otel_trace.INVALID_SPAN))
551+
rv = original_apply(*args, **kwargs)
552+
context.detach(token)
553+
return rv
554+
555+
Task.apply = cleaned_apply
539556

540557
@celery.task(name="dummy_task", bind=True)
541558
def dummy_task(self, message):
542559
trace_id = get_current_span().trace_id
543560
return trace_id
544561

545-
with start_span(name="task") as root_span:
546-
transaction_trace_id = root_span.trace_id
562+
with sentry_sdk.start_span(name="task") as root_span:
563+
root_span_trace_id = root_span.trace_id
547564

548565
# should propagate trace
549-
task_transaction_id = dummy_task.apply_async(
566+
task_trace_id = dummy_task.apply_async(
550567
args=("some message",),
551568
).get()
552-
assert transaction_trace_id == task_transaction_id
569+
assert root_span_trace_id == task_trace_id, "Trace should be propagated"
553570

554571
# should NOT propagate trace (overrides `propagate_traces` parameter in integration constructor)
555-
task_transaction_id = dummy_task.apply_async(
572+
task_trace_id = dummy_task.apply_async(
556573
args=("another message",),
557574
headers={"sentry-propagate-traces": False},
558575
).get()
559-
assert transaction_trace_id != task_transaction_id
576+
assert root_span_trace_id != task_trace_id, "Trace should NOT be propagated"
577+
578+
Task.apply = original_apply
560579

561580

562581
def test_apply_async_manually_span(sentry_init):
@@ -710,7 +729,7 @@ def publish(*args, **kwargs):
710729
@celery.task()
711730
def task(): ...
712731

713-
with start_span(name="task"):
732+
with sentry_sdk.start_span(name="task"):
714733
task.apply_async()
715734

716735
(event,) = events
@@ -773,7 +792,7 @@ def publish(*args, **kwargs):
773792
@celery.task()
774793
def task(): ...
775794

776-
with start_span(name="custom_transaction"):
795+
with sentry_sdk.start_span(name="custom_transaction"):
777796
task.apply_async()
778797

779798
(event,) = events

tests/tracing/test_integration_tests.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,20 @@ def test_continue_trace(
117117
assert message_payload["message"] == "hello"
118118

119119

120+
@pytest.mark.parametrize("sample_rate", [0.0, 1.0])
121+
def test_propagate_traces_deprecation_warning(sentry_init, sample_rate):
122+
sentry_init(traces_sample_rate=sample_rate, propagate_traces=False)
123+
124+
with start_transaction(name="hi"):
125+
with start_span() as old_span:
126+
with pytest.warns(DeprecationWarning):
127+
dict(
128+
sentry_sdk.get_current_scope().iter_trace_propagation_headers(
129+
old_span
130+
)
131+
)
132+
133+
120134
@pytest.mark.parametrize("sample_rate", [0.5, 1.0])
121135
def test_dynamic_sampling_head_sdk_creates_dsc(
122136
sentry_init,

0 commit comments

Comments
 (0)