Skip to content

Commit 064ef08

Browse files
committed
Merge branch 'potel-base' into potel-base-run-all-tests
2 parents 1f1cd2a + f261f28 commit 064ef08

File tree

11 files changed

+103
-129
lines changed

11 files changed

+103
-129
lines changed

sentry_sdk/integrations/opentelemetry/integration.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def setup_once():
4444
"Use at your own risk."
4545
)
4646

47+
_setup_scope_context_management()
4748
_setup_sentry_tracing()
4849
_patch_readable_span()
4950
# _setup_instrumentors()
@@ -68,12 +69,15 @@ def sentry_patched_readable_span(self):
6869
Span._readable_span = sentry_patched_readable_span
6970

7071

71-
def _setup_sentry_tracing():
72+
def _setup_scope_context_management():
7273
# type: () -> None
7374
import opentelemetry.context
7475

7576
opentelemetry.context._RUNTIME_CONTEXT = SentryContextVarsRuntimeContext()
7677

78+
79+
def _setup_sentry_tracing():
80+
# type: () -> None
7781
provider = TracerProvider(sampler=SentrySampler())
7882
provider.add_span_processor(PotelSentrySpanProcessor())
7983
trace.set_tracer_provider(provider)

sentry_sdk/integrations/opentelemetry/sampler.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,14 @@ def get_parent_sampled(parent_context, trace_id):
3434
# Only inherit sample rate if `traceId` is the same
3535
if is_span_context_valid and parent_context.trace_id == trace_id:
3636
# this is getSamplingDecision in JS
37+
# if there was no sampling flag, defer the decision
38+
dsc_sampled = parent_context.trace_state.get(TRACESTATE_SAMPLED_KEY)
39+
if dsc_sampled == "deferred":
40+
return None
41+
3742
if parent_context.trace_flags.sampled is not None:
3843
return parent_context.trace_flags.sampled
3944

40-
dsc_sampled = parent_context.trace_state.get(TRACESTATE_SAMPLED_KEY)
4145
if dsc_sampled == "true":
4246
return True
4347
elif dsc_sampled == "false":
@@ -53,6 +57,8 @@ def dropped_result(parent_span_context, attributes, sample_rate=None):
5357

5458
if TRACESTATE_SAMPLED_KEY not in trace_state:
5559
trace_state = trace_state.add(TRACESTATE_SAMPLED_KEY, "false")
60+
elif trace_state.get(TRACESTATE_SAMPLED_KEY) == "deferred":
61+
trace_state = trace_state.update(TRACESTATE_SAMPLED_KEY, "false")
5662

5763
if sample_rate and TRACESTATE_SAMPLE_RATE_KEY not in trace_state:
5864
trace_state = trace_state.add(TRACESTATE_SAMPLE_RATE_KEY, str(sample_rate))
@@ -88,6 +94,9 @@ def sampled_result(span_context, attributes, sample_rate):
8894

8995
if TRACESTATE_SAMPLED_KEY not in trace_state:
9096
trace_state = trace_state.add(TRACESTATE_SAMPLED_KEY, "true")
97+
elif trace_state.get(TRACESTATE_SAMPLED_KEY) == "deferred":
98+
trace_state = trace_state.update(TRACESTATE_SAMPLED_KEY, "true")
99+
91100
if TRACESTATE_SAMPLE_RATE_KEY not in trace_state:
92101
trace_state = trace_state.add(TRACESTATE_SAMPLE_RATE_KEY, str(sample_rate))
93102

sentry_sdk/integrations/opentelemetry/scope.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
SpanContext,
77
NonRecordingSpan,
88
TraceFlags,
9+
TraceState,
910
use_span,
1011
)
1112

@@ -14,6 +15,7 @@
1415
SENTRY_FORK_ISOLATION_SCOPE_KEY,
1516
SENTRY_USE_CURRENT_SCOPE_KEY,
1617
SENTRY_USE_ISOLATION_SCOPE_KEY,
18+
TRACESTATE_SAMPLED_KEY,
1719
)
1820
from sentry_sdk.integrations.opentelemetry.utils import trace_state_from_baggage
1921
from sentry_sdk.scope import Scope, ScopeType
@@ -96,10 +98,15 @@ def _incoming_otel_span_context(self):
9698
else TraceFlags.DEFAULT
9799
)
98100

99-
# TODO-neel-potel do we need parent and sampled like JS?
100-
trace_state = None
101101
if self._propagation_context.baggage:
102102
trace_state = trace_state_from_baggage(self._propagation_context.baggage)
103+
else:
104+
trace_state = TraceState()
105+
106+
# for twp to work, we also need to consider deferred sampling when the sampling
107+
# flag is not present, so the above TraceFlags are not sufficient
108+
if self._propagation_context.parent_sampled is None:
109+
trace_state = trace_state.add(TRACESTATE_SAMPLED_KEY, "deferred")
103110

104111
span_context = SpanContext(
105112
trace_id=int(self._propagation_context.trace_id, 16), # type: ignore

sentry_sdk/scope.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ def get_client(cls):
376376
This checks the current scope, the isolation scope and the global scope for a client.
377377
If no client is available a :py:class:`sentry_sdk.client.NonRecordingClient` is returned.
378378
"""
379-
current_scope = cls._get_current_scope()
379+
current_scope = cls.get_current_scope()
380380
try:
381381
client = current_scope.client
382382
except AttributeError:
@@ -385,7 +385,7 @@ def get_client(cls):
385385
if client is not None and client.is_active():
386386
return client
387387

388-
isolation_scope = cls._get_isolation_scope()
388+
isolation_scope = cls.get_isolation_scope()
389389
try:
390390
client = isolation_scope.client
391391
except AttributeError:

sentry_sdk/tracing.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,8 @@ def __exit__(self, ty, value, tb):
13111311
# type: (Optional[Any], Optional[Any], Optional[Any]) -> None
13121312
if value is not None:
13131313
self.set_status(SPANSTATUS.INTERNAL_ERROR)
1314+
else:
1315+
self.set_status(SPANSTATUS.OK)
13141316

13151317
self.finish()
13161318
context.detach(self._ctx_token)

tests/integrations/opentelemetry/test_compat.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def test_transaction_name_span_description_compat(
99

1010
events = capture_events()
1111

12-
with sentry_sdk.start_transaction(
12+
with sentry_sdk.start_span(
1313
name="trx-name",
1414
op="trx-op",
1515
) as trx:
@@ -33,13 +33,12 @@ def test_transaction_name_span_description_compat(
3333
assert spn.__class__.__name__ == "POTelSpan"
3434
assert spn.op == "span-op"
3535
assert spn.description == "span-desc"
36-
assert spn.name is None
36+
assert spn.name == "span-desc"
3737

3838
assert spn._otel_span is not None
3939
assert spn._otel_span.name == "span-desc"
4040
assert spn._otel_span.attributes["sentry.op"] == "span-op"
4141
assert spn._otel_span.attributes["sentry.description"] == "span-desc"
42-
assert "sentry.name" not in spn._otel_span.attributes
4342

4443
transaction = events[0]
4544
assert transaction["transaction"] == "trx-name"
@@ -53,4 +52,3 @@ def test_transaction_name_span_description_compat(
5352
assert span["op"] == "span-op"
5453
assert span["data"]["sentry.op"] == "span-op"
5554
assert span["data"]["sentry.description"] == "span-desc"
56-
assert "sentry.name" not in span["data"]

tests/integrations/opentelemetry/test_experimental.py

Lines changed: 0 additions & 47 deletions
This file was deleted.

tests/integrations/opentelemetry/test_potel.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import pytest
2-
32
from opentelemetry import trace
43

54
import sentry_sdk
5+
from tests.conftest import ApproxDict
66

77

88
tracer = trace.get_tracer(__name__)
@@ -43,7 +43,6 @@ def test_root_span_transaction_payload_started_with_otel_only(capture_envelopes)
4343
assert "span_id" in trace_context
4444
assert trace_context["origin"] == "manual"
4545
assert trace_context["op"] == "request"
46-
assert trace_context["status"] == "ok"
4746

4847
assert payload["spans"] == []
4948

@@ -63,7 +62,6 @@ def test_child_span_payload_started_with_otel_only(capture_envelopes):
6362
assert span["op"] == "db"
6463
assert span["description"] == "db"
6564
assert span["origin"] == "manual"
66-
assert span["status"] == "ok"
6765
assert span["span_id"] is not None
6866
assert span["trace_id"] == payload["contexts"]["trace"]["trace_id"]
6967
assert span["parent_span_id"] == payload["contexts"]["trace"]["span_id"]
@@ -222,8 +220,8 @@ def test_span_attributes_in_data_started_with_otel(capture_envelopes):
222220
(item,) = envelope.items
223221
payload = item.payload.json
224222

225-
assert payload["contexts"]["trace"]["data"] == {"foo": "bar", "baz": 42}
226-
assert payload["spans"][0]["data"] == {"abc": 99, "def": "moo"}
223+
assert payload["contexts"]["trace"]["data"] == ApproxDict({"foo": "bar", "baz": 42})
224+
assert payload["spans"][0]["data"] == ApproxDict({"abc": 99, "def": "moo"})
227225

228226

229227
def test_span_data_started_with_sentry(capture_envelopes):
@@ -238,18 +236,22 @@ def test_span_data_started_with_sentry(capture_envelopes):
238236
(item,) = envelope.items
239237
payload = item.payload.json
240238

241-
assert payload["contexts"]["trace"]["data"] == {
242-
"foo": "bar",
243-
"sentry.origin": "manual",
244-
"sentry.description": "request",
245-
"sentry.op": "http",
246-
}
247-
assert payload["spans"][0]["data"] == {
248-
"baz": 42,
249-
"sentry.origin": "manual",
250-
"sentry.description": "statement",
251-
"sentry.op": "db",
252-
}
239+
assert payload["contexts"]["trace"]["data"] == ApproxDict(
240+
{
241+
"foo": "bar",
242+
"sentry.origin": "manual",
243+
"sentry.description": "request",
244+
"sentry.op": "http",
245+
}
246+
)
247+
assert payload["spans"][0]["data"] == ApproxDict(
248+
{
249+
"baz": 42,
250+
"sentry.origin": "manual",
251+
"sentry.description": "statement",
252+
"sentry.op": "db",
253+
}
254+
)
253255

254256

255257
def test_transaction_tags_started_with_otel(capture_envelopes):

0 commit comments

Comments
 (0)