Migrate from 2.x to 3.x
Learn about migrating from sentry-python 2.x to 3.x
Python SDK 3.0 pre-release
Version 3.0 of the Sentry Python SDK is currently in pre-release. If you feel like giving it a spin, check out our most recent releases. Your feedback at this stage is invaluable, so please let us know about your experience, whether positive or negative, on GitHub or on Discord: How did the migration go? Did you encounter any issues? Is everything working as expected?
This guide describes the common patterns involved in migrating to version 3.x of the sentry-python SDK. For the full list of changes, check out the detailed migration guide in the repository.
Sentry Python SDK 3.x only supports Python 3.7 and higher. If you're on an older Python version, you'll need to stay on an older version of the SDK:
- Python 2.7-3.5: SDK
1.x - Python 3.6: SDK
2.x
The enable_tracing option was removed. Use traces_sample_rate directly, or configure a traces_sampler for more fine-grained control over which spans should be sampled.
sentry_sdk.init(
- enable_tracing=True,
+ traces_sample_rate=1.0,
)
The deprecated propagate_traces option was removed. Use trace_propagation_targets instead.
sentry_sdk.init(
# don't propagate trace info downstream
- propagate_traces=False,
+ trace_propagation_targets=[],
)
Note that this only affects the global SDK option. The propagate_traces option of the Celery integration remains unchanged.
The profiles_sample_rate and profiler_mode options previously nested under _experiments have been removed. They're replaced by top-level options of the same name:
sentry_sdk.init(
- _experiments={
- "profiles_sample_rate": 1.0,
- "profiler_mode": "thread",
- },
+ profiles_sample_rate=1.0,
+ profiler_mode="thread",
)
The enable_logs and before_send_log options previously nested under _experiments have been removed. They're replaced by top-level options of the same name:
def my_before_send_log(log, hint):
...
sentry_sdk.init(
- _experiments={
- "enable_logs": True,
- "before_send_log": my_before_send_log,
- },
+ enable_logs=True,
+ before_send_log=my_before_send_log,
)
add_attachment() is now a part of the top-level level API and should be imported and used directly from sentry_sdk.
import sentry_sdk
- scope = sentry_sdk.get_current_scope()
- scope.add_attachment(bytes=b"Hello World!", filename="attachment.txt")
+ sentry_sdk.add_attachment(bytes=b"Hello World!", filename="attachment.txt")
Using sentry_sdk.add_attachment() directly also makes sure the attachment is added to the correct scope internally.
Tracing in the Sentry Python SDK 3.x is powered by OpenTelemetry in the background, which also means we're moving away from the Sentry-specific concept of transactions and towards a span-only future. sentry_sdk.start_transaction() is now deprecated in favor of sentry_sdk.start_span().
- with sentry_sdk.start_transaction():
+ with sentry_sdk.start_span():
...
If you start a span, it will automatically become the child of the currently active span. If you want to create a span that should instead start its own trace, use the new_trace() context manager.
with sentry_sdk.start_span(name="parent"):
with sentry_sdk.start_span(name="child-of-parent"):
with sentry_sdk.new_trace():
# The first span started in this context manager will become
# a new transaction (root span) with its own trace
with sentry_sdk.start_span(name="new-parent"):
with sentry_sdk.start_span(name="child-of-new-parent"):
...
Any spans without a parent span will become transactions by default. If you want to avoid promoting a span without a parent to a transaction, you can pass the only_as_child_span=True keyword argument to sentry_sdk.start_span().
sentry_sdk.start_transaction() and sentry_sdk.start_span() no longer take the following arguments: trace_id, baggage, span_id, parent_span_id, custom_sampling_context (see below). Use sentry_sdk.continue_trace() for propagating trace data.
sentry_sdk.continue_trace() no longer returns a Transaction and is now a context manager. To continue a trace from headers or environment variables, start a new span inside sentry_sdk.continue_trace():
- transaction = sentry_sdk.continue_trace({...})
- with sentry_sdk.start_transaction(transaction=transaction):
- ...
+ with sentry_sdk.continue_trace({...}):
+ with sentry_sdk.start_span():
+ ...
The functions continue_from_headers, continue_from_environ and from_traceparent have been removed. Use the sentry_sdk.continue_trace() context manager instead.
In OpenTelemetry, there is no concept of separate categories of data on a span: everything is simply a span attribute. This is a concept the Sentry SDK is also adopting. We deprecated set_data() and added a new span method called set_attribute():
with sentry_sdk.start_span(...) as span:
- span.set_data("my_attribute", "my_value")
+ span.set_attribute("my_attribute", "my_value")
You can also set attributes directly when creating the span. This has the advantage that these initial attributes will be accessible in the sampling context in your traces_sampler/profiles_sampler (see also the Sampling section).
with sentry_sdk.start_span(attributes={"my_attribute": "my_value"}):
...
Span attribute type restrictions
There are important type restrictions to consider when setting attributes on a span via span.set_attribute() and start_span(attributes={...}). The keys must be non-empty strings and the values can only be several primitive types (excluding None) or a list of a single primitive type. See the OpenTelemetry specification for details.
Note that since the SDK is now exclusively using span attributes, this restriction applies to other ways of setting data on a span as well like span.set_data(), span.set_measurement(), span.set_context().
It's no longer possible to change the sampling decision of a span by setting span.sampled directly after the span has been created. Use either a custom traces_sampler (preferred) or the sampled argument to start_span() for determining whether a span should be sampled.
with sentry_sdk.start_span(sampled=True) as span:
...
Sampling non-root spans
Both traces_sampler and the sampled argument will only influence whether root spans (transactions) are sampled. They can't be used for sampling child spans.
The sampling_context argument of traces_sampler and profiles_sampler has changed considerably for spans coming from our auto-instrumented integrations. As a consequence of using OpenTelemetry under the hood, spans can only carry specific, primitive types of data. This prevents us from making custom objects, for example, the Request object for several web frameworks, accessible on the span.
The ability to set custom_sampling_context on start_transaction was removed. If there is custom data that you want to have accessible in the sampling_context of a traces_sampler or profiles_sampler, set it on the span via the attributes argument, as all span attributes are now included in the sampling_context by default:
- with start_transaction(custom_sampling_context={"custom_attribute": "custom_value"}):
+ with start_span(attributes={"custom_attribute": "custom_value"}) as span:
# custom_attribute will now be accessible in the sampling context
# of your traces_sampler/profiles_sampler
...
Span attribute type restrictions
As mentioned above, span attribute keys must be non-empty strings and values can only be several primitive types (excluding None) or a list of a single primitive type. See the OpenTelemetry specification for details.
We've updated how we handle ExceptionGroups. You will now get more data if ExceptionGroups appear in chained exceptions. As an indirect consequence, you might notice a change in how issues are grouped in Sentry.
Additional integrations will now be activated automatically if the SDK detects the respective package is installed: Ariadne, ARQ, asyncpg, Chalice, clickhouse-driver, GQL, Graphene, huey, Loguru, PyMongo, Quart, Starlite, Strawberry. You can opt-out of specific integrations with the disabled_integrations option.
We no longer support Django older than 2.0, trytond older than 5.0, and Falcon older than 3.0.
The logging integration, which implements out-of-the-box support for the Python standard library logging framework, doesn't capture error logs as events anymore by default. The original behavior can still be achieved by providing a custom event_level to the LoggingIntegration:
sentry_sdk.init(
integrations=[
# capture error, critical, exception logs
# and send them to Sentry as errors
LoggingIntegration(event_level="ERROR"),
],
)
The parameter propagate_hub has been removed from ThreadingIntegration. Use the new propagate_scope parameter instead. (If you had ThreadingIntegration(propagate_hub=True), you can remove the parameter.)
The query being executed is now available under the db.query.text span attribute (only if send_default_pii is True).
The PyMongo integration no longer sets tags automatically. The data is still accessible via span attributes.
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.
In Redis pipeline spans, there is no span["data"]["redis.commands"] that contains a dictionary {"count": 3, "first_ten": ["cmd1", "cmd2", ...]}. Instead, there is span["data"]["redis.commands.count"] (containing 3) and span["data"]["redis.commands.first_ten"] (containing ["cmd1", "cmd2", ...]).
The set_measurement() API was removed. You can set custom attributes on the span instead with set_attribute().
The auto_session_tracking() context manager was removed. Use track_session() instead.
Setting Scope.user directly is no longer supported. Use Scope.set_user() instead.
The sentry_sdk.metrics API doesn't exist anymore in SDK 3.x as the metrics beta has come to an end. The associated experimental options enable_metrics, before_emit_metric and metric_code_locations have been removed as well.
There is no concept of a hub anymore and all APIs and attributes that were connected to hubs have been removed.
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").