From 0680d183b4d9d081d1bdb3f4a9075fc00d2e44dc Mon Sep 17 00:00:00 2001 From: harryautomazione Date: Thu, 19 Mar 2026 14:45:11 +0100 Subject: [PATCH 1/3] docs: Document span filtering migration to span first --- MIGRATION_GUIDE.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 53396a37ba..6b7e56dcbf 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -190,3 +190,41 @@ Looking to upgrade from Sentry SDK 1.x to 2.x? Here's a comprehensive list of wh - Deprecated `sentry_sdk.transport.Transport.capture_event`. Please use `sentry_sdk.transport.Transport.capture_envelope`, instead. - Passing a function to `sentry_sdk.init`'s `transport` keyword argument has been deprecated. If you wish to provide a custom transport, please pass a `sentry_sdk.transport.Transport` instance or a subclass. - The parameter `propagate_hub` in `ThreadingIntegration()` was deprecated and renamed to `propagate_scope`. + +## Migrating Span Filtering to Span First + +If you are using the experimental **Span First** mode (also known as span streaming, enabled via `_experiments={"trace_lifecycle": "stream"}`), you might notice that individual spans are sent in real-time and do not pass together through `before_send_transaction`. + +To filter or ignore individual spans in Span First mode, you can use the experimental `ignore_spans` configuration option: + +```python +import sentry_sdk +import re + +sentry_sdk.init( + dsn="...", + traces_sample_rate=1.0, # Required for tracing + _experiments={ + "trace_lifecycle": "stream", + "ignore_spans": [ + "ignore_this_exact_name", # 1. Match by name (String) + re.compile(r"^GET /static/.*"), # 2. Match by name (Regex Range) + {"name": "ignore_by_name_dict"}, # 3. Match by name (Dict) + { # 4. Match by Span Attribute + "attributes": { + "http.status_code": 200, + } + } + ] + } +) +``` + +### Key Differences: +- **Before (Transaction Mode)**: You filtered child spans by mutating `event["spans"]` inside `before_send_transaction`. +- **After (Span First)**: You define rules up-front in `ignore_spans`. If a rule matches, a `NoOpStreamedSpan` is returned immediately resulting in no overhead. +- **Inheritance**: Any child span started with an ignored parent will automatically be ignored as well. + +> [!NOTE] +> `ignore_spans` is currently an experimental feature reading from `_experiments`. + From cd8189025173395f78a12a5d172a9704a2a4f859 Mon Sep 17 00:00:00 2001 From: harryautomazione Date: Thu, 19 Mar 2026 15:30:56 +0100 Subject: [PATCH 2/3] feat(db): Distinguish async vs sync database drivers with db.driver attribute --- sentry_sdk/integrations/asyncpg.py | 1 + sentry_sdk/integrations/sqlalchemy.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/sentry_sdk/integrations/asyncpg.py b/sentry_sdk/integrations/asyncpg.py index 7f3591154a..873d620361 100644 --- a/sentry_sdk/integrations/asyncpg.py +++ b/sentry_sdk/integrations/asyncpg.py @@ -192,6 +192,7 @@ async def _inner(*args: "Any", **kwargs: "Any") -> "T": def _set_db_data(span: "Span", conn: "Any") -> None: span.set_data(SPANDATA.DB_SYSTEM, "postgresql") + span.set_data("db.driver", "asyncpg") addr = conn._addr if addr: diff --git a/sentry_sdk/integrations/sqlalchemy.py b/sentry_sdk/integrations/sqlalchemy.py index 7d3ed95373..c29d5a84ab 100644 --- a/sentry_sdk/integrations/sqlalchemy.py +++ b/sentry_sdk/integrations/sqlalchemy.py @@ -137,6 +137,9 @@ def _set_db_data(span: "Span", conn: "Any") -> None: if db_system is not None: span.set_data(SPANDATA.DB_SYSTEM, db_system) + if hasattr(conn.engine, "dialect") and hasattr(conn.engine.dialect, "driver"): + span.set_data("db.driver", conn.engine.dialect.driver) + if conn.engine.url is None: return From 8c0ea16de1e8191d12f55c3c17ffbecdaad2db82 Mon Sep 17 00:00:00 2001 From: harryautomazione Date: Thu, 19 Mar 2026 16:30:47 +0100 Subject: [PATCH 3/3] fix(asyncpg): add db.driver to connect span and cleanup docs --- MIGRATION_GUIDE.md | 38 ------------------------------ sentry_sdk/integrations/asyncpg.py | 1 + 2 files changed, 1 insertion(+), 38 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 6b7e56dcbf..53396a37ba 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -190,41 +190,3 @@ Looking to upgrade from Sentry SDK 1.x to 2.x? Here's a comprehensive list of wh - Deprecated `sentry_sdk.transport.Transport.capture_event`. Please use `sentry_sdk.transport.Transport.capture_envelope`, instead. - Passing a function to `sentry_sdk.init`'s `transport` keyword argument has been deprecated. If you wish to provide a custom transport, please pass a `sentry_sdk.transport.Transport` instance or a subclass. - The parameter `propagate_hub` in `ThreadingIntegration()` was deprecated and renamed to `propagate_scope`. - -## Migrating Span Filtering to Span First - -If you are using the experimental **Span First** mode (also known as span streaming, enabled via `_experiments={"trace_lifecycle": "stream"}`), you might notice that individual spans are sent in real-time and do not pass together through `before_send_transaction`. - -To filter or ignore individual spans in Span First mode, you can use the experimental `ignore_spans` configuration option: - -```python -import sentry_sdk -import re - -sentry_sdk.init( - dsn="...", - traces_sample_rate=1.0, # Required for tracing - _experiments={ - "trace_lifecycle": "stream", - "ignore_spans": [ - "ignore_this_exact_name", # 1. Match by name (String) - re.compile(r"^GET /static/.*"), # 2. Match by name (Regex Range) - {"name": "ignore_by_name_dict"}, # 3. Match by name (Dict) - { # 4. Match by Span Attribute - "attributes": { - "http.status_code": 200, - } - } - ] - } -) -``` - -### Key Differences: -- **Before (Transaction Mode)**: You filtered child spans by mutating `event["spans"]` inside `before_send_transaction`. -- **After (Span First)**: You define rules up-front in `ignore_spans`. If a rule matches, a `NoOpStreamedSpan` is returned immediately resulting in no overhead. -- **Inheritance**: Any child span started with an ignored parent will automatically be ignored as well. - -> [!NOTE] -> `ignore_spans` is currently an experimental feature reading from `_experiments`. - diff --git a/sentry_sdk/integrations/asyncpg.py b/sentry_sdk/integrations/asyncpg.py index 873d620361..fa042f955e 100644 --- a/sentry_sdk/integrations/asyncpg.py +++ b/sentry_sdk/integrations/asyncpg.py @@ -169,6 +169,7 @@ async def _inner(*args: "Any", **kwargs: "Any") -> "T": origin=AsyncPGIntegration.origin, ) as span: span.set_data(SPANDATA.DB_SYSTEM, "postgresql") + span.set_data("db.driver", "asyncpg") addr = kwargs.get("addr") if addr: try: