Skip to content

Commit de7e58b

Browse files
authored
Profiler sampling context (#3840)
1 parent c54ebed commit de7e58b

File tree

4 files changed

+46
-16
lines changed

4 files changed

+46
-16
lines changed

sentry_sdk/integrations/opentelemetry/sampler.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from typing import TYPE_CHECKING
1818

1919
if TYPE_CHECKING:
20-
from typing import Optional, Sequence, Union
20+
from typing import Any, Optional, Sequence, Union
2121
from opentelemetry.context import Context
2222
from opentelemetry.trace import Link, SpanKind
2323
from opentelemetry.trace.span import SpanContext
@@ -152,15 +152,9 @@ def should_sample(
152152
has_traces_sampler = callable(client.options.get("traces_sampler"))
153153

154154
if is_root_span and has_traces_sampler:
155-
sampling_context = {
156-
"transaction_context": {
157-
"name": name,
158-
"op": attributes.get(SentrySpanAttribute.OP),
159-
"source": attributes.get(SentrySpanAttribute.SOURCE),
160-
},
161-
"parent_sampled": get_parent_sampled(parent_span_context, trace_id),
162-
}
163-
sampling_context.update(attributes)
155+
sampling_context = create_sampling_context(
156+
name, attributes, parent_span_context, trace_id
157+
)
164158
sample_rate = client.options["traces_sampler"](sampling_context)
165159
else:
166160
# Check if there is a parent with a sampling decision
@@ -193,3 +187,19 @@ def should_sample(
193187

194188
def get_description(self) -> str:
195189
return self.__class__.__name__
190+
191+
192+
def create_sampling_context(name, attributes, parent_span_context, trace_id):
193+
# type: (str, Attributes, SpanContext, str) -> dict[str, Any]
194+
sampling_context = {
195+
"transaction_context": {
196+
"name": name,
197+
"op": attributes.get(SentrySpanAttribute.OP),
198+
"source": attributes.get(SentrySpanAttribute.SOURCE),
199+
},
200+
"parent_sampled": get_parent_sampled(parent_span_context, trace_id),
201+
}
202+
203+
sampling_context.update(attributes)
204+
205+
return sampling_context

sentry_sdk/integrations/opentelemetry/span_processor.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
get_profiler_id,
2121
)
2222
from sentry_sdk.profiler.transaction_profiler import Profile
23+
from sentry_sdk.integrations.opentelemetry.sampler import create_sampling_context
2324
from sentry_sdk.integrations.opentelemetry.utils import (
2425
is_sentry_span,
2526
convert_from_otel_timestamp,
@@ -126,8 +127,10 @@ def _start_profile(self, span):
126127
# unix timestamp that is on span.start_time
127128
# setting it to 0 means the profiler will internally measure time on start
128129
profile = Profile(sampled, 0)
129-
# TODO-neel-potel sampling context??
130-
profile._set_initial_sampling_decision(sampling_context={})
130+
sampling_context = create_sampling_context(
131+
span.name, span.attributes, span.parent, span.context.trace_id
132+
)
133+
profile._set_initial_sampling_decision(sampling_context)
131134
profile.__enter__()
132135
set_sentry_meta(span, "profile", profile)
133136

sentry_sdk/tracing_utils.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
from typing import Generator
3434
from typing import Optional
3535
from typing import Union
36-
3736
from types import FrameType
3837

3938

@@ -731,6 +730,3 @@ def get_current_span(scope=None):
731730
LOW_QUALITY_TRANSACTION_SOURCES,
732731
SENTRY_TRACE_HEADER_NAME,
733732
)
734-
735-
if TYPE_CHECKING:
736-
from sentry_sdk.tracing import Span

tests/tracing/test_sampling.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,24 @@ def test_records_lost_event_only_if_traces_sampler_enabled(
307307

308308
# Use Counter because order of calls does not matter
309309
assert Counter(record_lost_event_calls) == Counter(expected_record_lost_event_calls)
310+
311+
312+
@pytest.mark.parametrize("parent_sampling_decision", [True, False])
313+
def test_profiles_sampler_gets_sampling_context(sentry_init, parent_sampling_decision):
314+
def dummy_profiles_sampler(sampling_context):
315+
assert sampling_context["transaction_context"] == {
316+
"name": "dogpark",
317+
"op": "op",
318+
"source": "custom",
319+
}
320+
assert sampling_context["parent_sampled"] == parent_sampling_decision
321+
return 1.0
322+
323+
sentry_init(traces_sample_rate=1.0, profiles_sampler=dummy_profiles_sampler)
324+
325+
sentry_trace = "12312012123120121231201212312012-1121201211212012-{}".format(
326+
int(parent_sampling_decision)
327+
)
328+
with sentry_sdk.continue_trace({"sentry-trace": sentry_trace}):
329+
with sentry_sdk.start_span(name="dogpark", op="op"):
330+
pass

0 commit comments

Comments
 (0)