Skip to content

Commit 68b5116

Browse files
authored
Implement trace_propagation_targets for propagator (#4460)
1 parent c21525e commit 68b5116

File tree

2 files changed

+89
-12
lines changed

2 files changed

+89
-12
lines changed

sentry_sdk/opentelemetry/propagator.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
SpanContext,
2121
TraceFlags,
2222
)
23+
from opentelemetry.semconv.trace import SpanAttributes
2324

25+
import sentry_sdk
2426
from sentry_sdk.consts import (
2527
BAGGAGE_HEADER_NAME,
2628
SENTRY_TRACE_HEADER_NAME,
@@ -30,7 +32,11 @@
3032
SENTRY_TRACE_KEY,
3133
SENTRY_SCOPES_KEY,
3234
)
33-
from sentry_sdk.tracing_utils import Baggage, extract_sentrytrace_data
35+
from sentry_sdk.tracing_utils import (
36+
Baggage,
37+
extract_sentrytrace_data,
38+
should_propagate_trace,
39+
)
3440

3541
from typing import TYPE_CHECKING
3642

@@ -89,18 +95,23 @@ def extract(self, carrier, context=None, getter=default_getter):
8995

9096
def inject(self, carrier, context=None, setter=default_setter):
9197
# type: (CarrierT, Optional[Context], Setter[CarrierT]) -> None
92-
if context is None:
93-
context = get_current()
94-
9598
scopes = get_value(SENTRY_SCOPES_KEY, context)
96-
if scopes:
97-
scopes = cast("tuple[scope.PotelScope, scope.PotelScope]", scopes)
98-
(current_scope, _) = scopes
99-
100-
# TODO-neel-potel check trace_propagation_targets
101-
# TODO-neel-potel test propagator works with twp
102-
for key, value in current_scope.iter_trace_propagation_headers():
103-
setter.set(carrier, key, value)
99+
if not scopes:
100+
return
101+
102+
scopes = cast("tuple[scope.PotelScope, scope.PotelScope]", scopes)
103+
(current_scope, _) = scopes
104+
105+
span = current_scope.span
106+
if span:
107+
span_url = span.get_attribute(SpanAttributes.HTTP_URL)
108+
if span_url and not should_propagate_trace(
109+
sentry_sdk.get_client(), span_url
110+
):
111+
return
112+
113+
for key, value in current_scope.iter_trace_propagation_headers():
114+
setter.set(carrier, key, value)
104115

105116
@property
106117
def fields(self):

tests/opentelemetry/test_propagator.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
from opentelemetry.trace.propagation import get_current_span
66
from opentelemetry.propagators.textmap import DefaultSetter
7+
from opentelemetry.semconv.trace import SpanAttributes
78

89
import sentry_sdk
10+
from sentry_sdk.consts import MATCH_ALL
911
from sentry_sdk.opentelemetry.consts import (
1012
SENTRY_BAGGAGE_KEY,
1113
SENTRY_TRACE_KEY,
@@ -208,3 +210,67 @@ def test_inject_head_sdk(sentry_init):
208210
assert carrier["baggage"] == SortedBaggage(
209211
expected_baggage.format(trace_id=span.trace_id)
210212
)
213+
214+
215+
@pytest.mark.parametrize(
216+
"trace_propagation_targets,url,trace_propagated",
217+
[
218+
# No targets - should not propagate
219+
([], "https://example.com/api/users", False),
220+
(None, "https://example.com/api/users", False),
221+
# MATCH_ALL - should propagate
222+
([MATCH_ALL], "https://example.com/api/users", True),
223+
# Exact match - should propagate
224+
(["https://example.com"], "https://example.com/api/users", True),
225+
(["https://example.com/"], "https://example.com/api/users", True),
226+
# No match - should not propagate
227+
(["https://example.com"], "https://other-domain.com/api/users", False),
228+
(["https://example.com/"], "https://other-domain.com/api/users", False),
229+
# Regex patterns
230+
(
231+
["https://example.com", r"https?:\/\/[\w\-]+(\.[\w\-]+)+\.net"],
232+
"https://good.example.net/api",
233+
True,
234+
),
235+
(
236+
["https://example.com", r"https?:\/\/[\w\-]+(\.[\w\-]+)+\.net"],
237+
"https://example.net/api",
238+
False,
239+
),
240+
# HTTP vs HTTPS
241+
(["https://example.com"], "http://example.com/api/users", False),
242+
(["http://example.com"], "https://example.com/api/users", False),
243+
# Path matching
244+
(["https://example.com/api"], "https://example.com/api/users", True),
245+
(["https://example.com/api"], "https://example.com/other/path", False),
246+
],
247+
)
248+
def test_propagator_trace_propagation_targets(
249+
sentry_init,
250+
trace_propagation_targets,
251+
url,
252+
trace_propagated,
253+
):
254+
"""Test that the propagator respects trace_propagation_targets for HTTP spans."""
255+
sentry_init(
256+
trace_propagation_targets=trace_propagation_targets,
257+
traces_sample_rate=1.0,
258+
)
259+
260+
carrier = {}
261+
setter = DefaultSetter()
262+
263+
# Create a real HTTP span with the test URL
264+
with sentry_sdk.start_span(name="http.client") as span:
265+
span.set_attribute(SpanAttributes.HTTP_METHOD, "GET")
266+
span.set_attribute(SpanAttributes.HTTP_URL, url)
267+
268+
# Test the propagator
269+
SentryPropagator().inject(carrier, setter=setter)
270+
271+
if trace_propagated:
272+
assert "sentry-trace" in carrier
273+
assert "baggage" in carrier
274+
else:
275+
assert "sentry-trace" not in carrier
276+
assert "baggage" not in carrier

0 commit comments

Comments
 (0)