Skip to content

Commit 442e41b

Browse files
committed
Merge branch 'potel-base' into potel-base-run-all-tests
2 parents 6edf89e + 09b4a01 commit 442e41b

File tree

16 files changed

+116
-76
lines changed

16 files changed

+116
-76
lines changed

MIGRATION_GUIDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
1111
- The SDK now supports Python 3.7 and higher.
1212
- `sentry_sdk.start_span` now only takes keyword arguments.
1313
- `sentry_sdk.start_span` no longer takes an explicit `span` argument.
14+
- `sentry_sdk.start_span` no longer takes explicit `trace_id`, `span_id` or `parent_span_id` arguments.
1415
- The `Span()` constructor does not accept a `hub` parameter anymore.
1516
- `Span.finish()` does not accept a `hub` parameter anymore.
1617
- The `Profile()` constructor does not accept a `hub` parameter anymore.
@@ -19,11 +20,13 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
1920
- Redis integration: In Redis pipeline spans there is no `span["data"]["redis.commands"]` that contains a dict `{"count": 3, "first_ten": ["cmd1", "cmd2", ...]}` but instead `span["data"]["redis.commands.count"]` (containing `3`) and `span["data"]["redis.commands.first_ten"]` (containing `["cmd1", "cmd2", ...]`).
2021
- clickhouse-driver integration: The query is now available under the `db.query.text` span attribute (only if `send_default_pii` is `True`).
2122
- `sentry_sdk.init` now returns `None` instead of a context manager.
23+
- The `sampling_context` argument of `traces_sampler` now additionally contains all span attributes known at span start.
2224

2325
### Removed
2426

2527
- Spans no longer have a `description`. Use `name` instead.
2628
- Dropped support for Python 3.6.
29+
- The `custom_sampling_context` parameter of `start_transaction` has been removed. Use `attributes` instead to set key-value pairs of data that should be accessible in the traces sampler. Note that span attributes need to conform to the [OpenTelemetry specification](https://opentelemetry.io/docs/concepts/signals/traces/#attributes), meaning only certain types can be set as values.
2730
- The PyMongo integration no longer sets tags. The data is still accessible via span attributes.
2831
- The PyMongo integration doesn't set `operation_ids` anymore. The individual IDs (`operation_id`, `request_id`, `session_id`) are now accessible as separate span attributes.
2932
- `sentry_sdk.metrics` and associated metrics APIs have been removed as Sentry no longer accepts metrics data in this form. See https://sentry.zendesk.com/hc/en-us/articles/26369339769883-Upcoming-API-Changes-to-Metrics

sentry_sdk/api.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
ExcInfo,
4141
MeasurementUnit,
4242
LogLevelStr,
43-
SamplingContext,
4443
)
4544
from sentry_sdk.tracing import Span, TransactionKwargs
4645

@@ -239,12 +238,8 @@ def flush(
239238
return get_client().flush(timeout=timeout, callback=callback)
240239

241240

242-
def start_span(
243-
*,
244-
custom_sampling_context=None,
245-
**kwargs, # type: Any
246-
):
247-
# type: (...) -> POTelSpan
241+
def start_span(**kwargs):
242+
# type: (type.Any) -> POTelSpan
248243
"""
249244
Start and return a span.
250245
@@ -257,13 +252,11 @@ def start_span(
257252
of the `with` block. If not using context managers, call the `finish()`
258253
method.
259254
"""
260-
# TODO: Consider adding type hints to the method signature.
261-
return get_current_scope().start_span(custom_sampling_context, **kwargs)
255+
return get_current_scope().start_span(**kwargs)
262256

263257

264258
def start_transaction(
265259
transaction=None, # type: Optional[Transaction]
266-
custom_sampling_context=None, # type: Optional[SamplingContext]
267260
**kwargs, # type: Unpack[TransactionKwargs]
268261
):
269262
# type: (...) -> POTelSpan
@@ -295,14 +288,12 @@ def start_transaction(
295288
296289
:param transaction: The transaction to start. If omitted, we create and
297290
start a new transaction.
298-
:param custom_sampling_context: The transaction's custom sampling context.
299291
:param kwargs: Optional keyword arguments to be passed to the Transaction
300292
constructor. See :py:class:`sentry_sdk.tracing.Transaction` for
301293
available arguments.
302294
"""
303295
return start_span(
304296
span=transaction,
305-
custom_sampling_context=custom_sampling_context,
306297
**kwargs,
307298
)
308299

sentry_sdk/integrations/arq.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ async def _sentry_run_job(self, job_id, score):
104104
with sentry_sdk.isolation_scope() as scope:
105105
scope._name = "arq"
106106
scope.set_transaction_name(
107-
DEFAULT_TRANSACTION_NAME, source=TRANSACTION_SOURCE_TASK,
107+
DEFAULT_TRANSACTION_NAME,
108+
source=TRANSACTION_SOURCE_TASK,
108109
)
109110
scope.clear_breadcrumbs()
110111

sentry_sdk/integrations/opentelemetry/consts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ class SentrySpanAttribute:
3030
NAME = "sentry.name"
3131
SOURCE = "sentry.source"
3232
CONTEXT = "sentry.context"
33+
CUSTOM_SAMPLED = "sentry.custom_sampled" # used for saving start_span(sampled=X)

sentry_sdk/integrations/opentelemetry/sampler.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from typing import cast
33

44
from opentelemetry import trace
5-
65
from opentelemetry.sdk.trace.sampling import Sampler, SamplingResult, Decision
76
from opentelemetry.trace.span import TraceState
87

@@ -12,6 +11,7 @@
1211
from sentry_sdk.integrations.opentelemetry.consts import (
1312
TRACESTATE_SAMPLED_KEY,
1413
TRACESTATE_SAMPLE_RATE_KEY,
14+
SentrySpanAttribute,
1515
)
1616

1717
from typing import TYPE_CHECKING
@@ -114,28 +114,34 @@ def should_sample(
114114

115115
parent_span_context = trace.get_current_span(parent_context).get_span_context()
116116

117+
attributes = attributes or {}
118+
117119
# No tracing enabled, thus no sampling
118120
if not has_tracing_enabled(client.options):
119121
return dropped_result(parent_span_context, attributes)
120122

121-
sample_rate = None
123+
# Explicit sampled value provided at start_span
124+
if attributes.get(SentrySpanAttribute.CUSTOM_SAMPLED) is not None:
125+
sample_rate = float(attributes[SentrySpanAttribute.CUSTOM_SAMPLED])
126+
if sample_rate > 0:
127+
return sampled_result(parent_span_context, attributes, sample_rate)
128+
else:
129+
return dropped_result(parent_span_context, attributes)
122130

123-
# Check if sampled=True was passed to start_transaction
124-
# TODO-anton: Do we want to keep the start_transaction(sampled=True) thing?
131+
sample_rate = None
125132

126133
# Check if there is a traces_sampler
127134
# Traces_sampler is responsible to check parent sampled to have full transactions.
128135
has_traces_sampler = callable(client.options.get("traces_sampler"))
129136
if has_traces_sampler:
130-
# TODO-anton: Make proper sampling_context
131-
# TODO-neel-potel: Make proper sampling_context
132137
sampling_context = {
133138
"transaction_context": {
134139
"name": name,
140+
"op": attributes.get(SentrySpanAttribute.OP),
135141
},
136142
"parent_sampled": get_parent_sampled(parent_span_context, trace_id),
137143
}
138-
144+
sampling_context.update(attributes)
139145
sample_rate = client.options["traces_sampler"](sampling_context)
140146

141147
else:

sentry_sdk/integrations/opentelemetry/scope.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
from typing import Tuple, Optional, Generator, Dict, Any
2525
from typing_extensions import Unpack
2626

27-
from sentry_sdk._types import SamplingContext
2827
from sentry_sdk.tracing import TransactionKwargs
2928

3029

@@ -112,22 +111,31 @@ def _incoming_otel_span_context(self):
112111

113112
return span_context
114113

115-
def start_transaction(self, custom_sampling_context=None, **kwargs):
116-
# type: (Optional[SamplingContext], Unpack[TransactionKwargs]) -> POTelSpan
114+
def start_transaction(self, **kwargs):
115+
# type: (Unpack[TransactionKwargs]) -> POTelSpan
117116
"""
118117
.. deprecated:: 3.0.0
119118
This function is deprecated and will be removed in a future release.
120119
Use :py:meth:`sentry_sdk.start_span` instead.
121120
"""
122-
return self.start_span(custom_sampling_context=custom_sampling_context)
121+
return self.start_span(**kwargs)
123122

124-
def start_span(self, custom_sampling_context=None, **kwargs):
125-
# type: (Optional[SamplingContext], Any) -> POTelSpan
123+
def start_span(self, **kwargs):
124+
# type: (Any) -> POTelSpan
126125
return POTelSpan(**kwargs, scope=self)
127126

128127

129-
_INITIAL_CURRENT_SCOPE = PotelScope(ty=ScopeType.CURRENT)
130-
_INITIAL_ISOLATION_SCOPE = PotelScope(ty=ScopeType.ISOLATION)
128+
_INITIAL_CURRENT_SCOPE = None
129+
_INITIAL_ISOLATION_SCOPE = None
130+
131+
132+
def _setup_initial_scopes():
133+
global _INITIAL_CURRENT_SCOPE, _INITIAL_ISOLATION_SCOPE
134+
_INITIAL_CURRENT_SCOPE = PotelScope(ty=ScopeType.CURRENT)
135+
_INITIAL_ISOLATION_SCOPE = PotelScope(ty=ScopeType.ISOLATION)
136+
137+
138+
_setup_initial_scopes()
131139

132140

133141
@contextmanager

sentry_sdk/integrations/rq.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
from rq.job import Job
3434

35+
DEFAULT_TRANSACTION_NAME = "unknown RQ task"
36+
3537

3638
class RqIntegration(Integration):
3739
identifier = "rq"
@@ -55,22 +57,27 @@ def setup_once():
5557
def sentry_patched_perform_job(self, job, *args, **kwargs):
5658
# type: (Any, Job, *Queue, **Any) -> bool
5759
with sentry_sdk.new_scope() as scope:
60+
try:
61+
transaction_name = job.func_name or DEFAULT_TRANSACTION_NAME
62+
except AttributeError:
63+
transaction_name = DEFAULT_TRANSACTION_NAME
64+
65+
scope.set_transaction_name(
66+
transaction_name, source=TRANSACTION_SOURCE_TASK
67+
)
5868
scope.clear_breadcrumbs()
5969
scope.add_event_processor(_make_event_processor(weakref.ref(job)))
6070

6171
with sentry_sdk.continue_trace(
6272
job.meta.get("_sentry_trace_headers") or {}
6373
):
64-
with sentry_sdk.start_transaction(
74+
with sentry_sdk.start_span(
6575
op=OP.QUEUE_TASK_RQ,
66-
name="unknown RQ task",
76+
name=transaction_name,
6777
source=TRANSACTION_SOURCE_TASK,
6878
origin=RqIntegration.origin,
6979
custom_sampling_context={"rq_job": job},
70-
) as transaction:
71-
with capture_internal_exceptions():
72-
transaction.name = job.func_name
73-
80+
):
7481
rv = old_perform_job(self, job, *args, **kwargs)
7582

7683
if self.is_horse:
@@ -101,11 +108,9 @@ def sentry_patched_handle_exception(self, job, *exc_info, **kwargs):
101108
@ensure_integration_enabled(RqIntegration, old_enqueue_job)
102109
def sentry_patched_enqueue_job(self, job, **kwargs):
103110
# type: (Queue, Any, **Any) -> Any
104-
scope = sentry_sdk.get_current_scope()
105-
if scope.span is not None:
106-
job.meta["_sentry_trace_headers"] = dict(
107-
scope.iter_trace_propagation_headers()
108-
)
111+
job.meta["_sentry_trace_headers"] = dict(
112+
sentry_sdk.get_current_scope().iter_trace_propagation_headers()
113+
)
109114

110115
return old_enqueue_job(self, job, **kwargs)
111116

sentry_sdk/scope.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,11 @@ def get_traceparent(self, *args, **kwargs):
497497
client = self.get_client()
498498

499499
# If we have an active span, return traceparent from there
500-
if has_tracing_enabled(client.options) and self.span is not None:
500+
if (
501+
has_tracing_enabled(client.options)
502+
and self.span is not None
503+
and self.span.is_valid
504+
):
501505
return self.span.to_traceparent()
502506

503507
# If this scope has a propagation context, return traceparent from there
@@ -521,7 +525,11 @@ def get_baggage(self, *args, **kwargs):
521525
client = self.get_client()
522526

523527
# If we have an active span, return baggage from there
524-
if has_tracing_enabled(client.options) and self.span is not None:
528+
if (
529+
has_tracing_enabled(client.options)
530+
and self.span is not None
531+
and self.span.is_valid
532+
):
525533
return self.span.to_baggage()
526534

527535
# If this scope has a propagation context, return baggage from there
@@ -610,7 +618,7 @@ def iter_trace_propagation_headers(self, *args, **kwargs):
610618
span = kwargs.pop("span", None)
611619
span = span or self.span
612620

613-
if has_tracing_enabled(client.options) and span is not None:
621+
if has_tracing_enabled(client.options) and span is not None and span.is_valid:
614622
for header in span.iter_headers():
615623
yield header
616624
else:
@@ -946,9 +954,7 @@ def add_breadcrumb(self, crumb=None, hint=None, **kwargs):
946954
while len(self._breadcrumbs) > max_breadcrumbs:
947955
self._breadcrumbs.popleft()
948956

949-
def start_transaction(
950-
self, transaction=None, custom_sampling_context=None, **kwargs
951-
):
957+
def start_transaction(self, transaction=None, **kwargs):
952958
# type: (Optional[Transaction], Optional[SamplingContext], Unpack[TransactionKwargs]) -> Union[Transaction, NoOpSpan]
953959
"""
954960
Start and return a transaction.
@@ -974,7 +980,6 @@ def start_transaction(
974980
975981
:param transaction: The transaction to start. If omitted, we create and
976982
start a new transaction.
977-
:param custom_sampling_context: The transaction's custom sampling context.
978983
:param kwargs: Optional keyword arguments to be passed to the Transaction
979984
constructor. See :py:class:`sentry_sdk.tracing.Transaction` for
980985
available arguments.
@@ -985,8 +990,6 @@ def start_transaction(
985990

986991
try_autostart_continuous_profiler()
987992

988-
custom_sampling_context = custom_sampling_context or {}
989-
990993
# if we haven't been given a transaction, make one
991994
transaction = Transaction(**kwargs)
992995

@@ -996,7 +999,6 @@ def start_transaction(
996999
"transaction_context": transaction.to_json(),
9971000
"parent_sampled": transaction.parent_sampled,
9981001
}
999-
sampling_context.update(custom_sampling_context)
10001002
transaction._set_initial_sampling_decision(sampling_context=sampling_context)
10011003

10021004
if transaction.sampled:
@@ -1317,7 +1319,11 @@ def _apply_contexts_to_event(self, event, hint, options):
13171319

13181320
# Add "trace" context
13191321
if contexts.get("trace") is None:
1320-
if has_tracing_enabled(options) and self._span is not None:
1322+
if (
1323+
has_tracing_enabled(options)
1324+
and self._span is not None
1325+
and self._span.is_valid
1326+
):
13211327
contexts["trace"] = self._span.get_trace_context()
13221328
else:
13231329
contexts["trace"] = self.get_trace_context()

0 commit comments

Comments
 (0)