Skip to content

Commit bae199d

Browse files
committed
Implement trace_propagation_targets for propagator
1 parent 6ad4031 commit bae199d

File tree

2 files changed

+90
-12
lines changed

2 files changed

+90
-12
lines changed

sentry_sdk/opentelemetry/propagator.py

Lines changed: 21 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,21 @@ 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(sentry_sdk.get_client(), span_url):
109+
return
110+
111+
for key, value in current_scope.iter_trace_propagation_headers():
112+
setter.set(carrier, key, value)
104113

105114
@property
106115
def fields(self):

tests/opentelemetry/test_propagator.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44

55
from opentelemetry.trace.propagation import get_current_span
66
from opentelemetry.propagators.textmap import DefaultSetter
7+
from opentelemetry.semconv.trace import SpanAttributes
8+
from opentelemetry.sdk.trace import ReadableSpan
9+
from opentelemetry.trace import SpanKind
710

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

0 commit comments

Comments
 (0)