Skip to content

Next Python SDK major - #5005

Draft
sentrivana wants to merge 456 commits into
masterfrom
major/3.0
Draft

sentrivana wants to merge 456 commits into
masterfrom
major/3.0

Conversation

@sentrivana

@sentrivana sentrivana commented Oct 24, 2025 •

Copy link
Copy Markdown
Collaborator

We're preparing our next major on this branch.

The project is tracked in Linear. If you don't have access, we'll try to tag issues belonging to the project with the SDK 3.0 label on GitHub so that you can follow along.

Notable changes

  • Transaction-based tracing will be removed. Span streaming will be the default tracing model.
  • Python 3.6 support will be removed.

Context

You might have read this announcement about us discontinuing work on a 3.0. This is referring to the work done on the potel-base branch, which included two types of changes: a huge refactor of our tracing code on the one hand, and various unrelated changes, improvements and fixes on the other. We're dropping the huge refactor part, and only porting the rest, to a new branch and eventually a new 3.0 release.

@codecov

codecov Bot commented Oct 24, 2025 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.76%. Comparing base (14aff96) to head (d864ba0).
⚠️ Report is 4 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #5005       +/-   ##
===========================================
+ Coverage   70.55%   83.76%   +13.21%     
===========================================
  Files         180      180               
  Lines       18077    18080        +3     
  Branches     3008     3009        +1     
===========================================
+ Hits        12754    15145     +2391     
+ Misses       4432     1943     -2489     
- Partials      891      992      +101     
Files with missing lines Coverage Δ
sentry_sdk/integrations/__init__.py 88.42% <100.00%> (+0.37%) ⬆️

... and 61 files with indirect coverage changes

@github-actions

github-actions Bot commented Mar 19, 2026 •

Copy link
Copy Markdown
Contributor

Coverage Results 📊

✅ 57523 passed | ⏭️ 2979 skipped | Total: 60502 | Pass Rate: 95.08% | Execution Time: 159m 31s

All tests are passing successfully.

✅ Patch coverage is 88.78% (2849 of 3209 changed executable lines covered; target 80%).
Project statement coverage is 90.37% (up 0.05 percentage points from base (7ad4e1a) to head (e0a5492)).

Changed files with executable lines (143)
File Patch coverage Changed executable lines
sentry_sdk/integrations/aws_lambda/_handler.py 19.10% 17/89 covered; missed: 43, 45, 46, 59, 60, 62, 63, 65, 66, 67, 69, 70, 72, 76, 78, 79, 80, 81, 82, 83, 91, 95, 99, 107, 109, 112, 113, 115, 116, 117, 118, 119, 120, 121, 125, 126, 127, 131, 132, 133, 134, 135, 139, 140, 144, 145, 146, 147, 149, 154, 156, 168, 169, 170, 171, 172, 173, 174, 176, 190, 191, 192, 197, 198, 199, 200, 201, 205, 206, 208, 209, 211
sentry_sdk/integrations/aws_lambda/_runtime.py 22.00% 11/50 covered; missed: 23, 25, 26, 28, 29, 31, 32, 33, 37, 41, 42, 43, 47, 68, 70, 72, 76, 77, 78, 79, 82, 101, 102, 103, 104, 106, 109, 110, 112, 115, 117, 121, 122, 123, 124, 125, 126, 127, 138
sentry_sdk/integrations/aws_lambda/_request.py 69.86% 51/73 covered; missed: 19, 25, 27, 28, 29, 31, 32, 33, 35, 68, 76, 77, 78, 82, 83, 91, 92, 93, 97, 98, 101, 120; partial branches: 18, 22, 67, 75, 88, 90, 95, 96, 119
sentry_sdk/integrations/langchain.py 90.26% 139/154 covered; missed: 237, 274, 388, 405, 414, 492, 501, 507, 522, 528, 548, 591, 592, 598, 1244; partial branches: 236, 273, 285, 387, 404, 413, 491, 500, 506, 521, 527, 547
sentry_sdk/integrations/ray.py 33.33% 11/33 covered; missed: 92, 94, 95, 104, 105, 106, 107, 108, 109, 111, 130, 134, 135, 138, 139, 140, 141, 143, 160, 161, 162, 163; partial branches: 129
sentry_sdk/integrations/aws_lambda/init.py 36.36% 12/33 covered; missed: 24, 28, 29, 30, 34, 36, 37, 41, 43, 47, 49, 52, 53, 57, 62, 63, 64, 65, 67, 69, 74
sentry_sdk/integrations/mcp.py 93.55% 87/93 covered; missed: 279, 283, 355, 359, 403, 405; partial branches: 278, 282, 288, 354, 358, 366, 371, 386, 389, 393, 395, 398, 447, 449
sentry_sdk/integrations/anthropic.py 76.92% 30/39 covered; missed: 459, 461, 463, 467, 472, 695, 785, 994, 1096; partial branches: 471, 694, 784, 993, 1095
sentry_sdk/integrations/google_genai/init.py 80.65% 50/62 covered; missed: 76, 106, 139, 140, 142, 144, 170, 243, 262, 263, 264, 265; partial branches: 75, 242
sentry_sdk/integrations/socket.py 59.09% 13/22 covered; missed: 59, 96, 107, 108, 114, 115, 116, 117, 118; partial branches: 58, 68, 95, 105, 112
sentry_sdk/integrations/gcp.py 7.14% 1/14 covered; missed: 88, 89, 100, 104, 105, 131, 132, 134, 225, 226, 230, 231, 237
sentry_sdk/integrations/openai_agents/patches/runner.py 80.95% 34/42 covered; missed: 152, 173, 178, 179, 196, 201, 202, 203; partial branches: 151, 164, 169, 193
sentry_sdk/integrations/litestar.py 85.00% 34/40 covered; missed: 169, 184, 186, 204, 206, 272; partial branches: 168, 183, 185, 203, 205
sentry_sdk/integrations/asyncpg.py 86.21% 25/29 covered; missed: 216, 217, 244, 245; partial branches: 113, 212, 240, 247, 250
sentry_sdk/integrations/pydantic_ai/spans/ai_client.py 86.11% 31/36 covered; missed: 330, 331, 332, 333, 334; partial branches: 295, 300, 305, 323
sentry_sdk/integrations/mistral.py 92.31% 48/52 covered; missed: 321, 325, 441, 445; partial branches: 320, 324, 440, 444
sentry_sdk/integrations/openai_agents/spans/ai_client.py 87.10% 27/31 covered; missed: 227, 228, 239, 255; partial branches: 225, 230, 238, 254
sentry_sdk/integrations/otlp.py 87.10% 27/31 covered; missed: 154, 158, 180, 219; partial branches: 149, 153, 157, 174
sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py 100.00% 41/41 covered; partial branches: 65, 69, 77, 95, 103, 111, 113, 121
sentry_sdk/integrations/openai_agents/patches/agent_run.py 58.33% 7/12 covered; missed: 60, 225, 232, 254, 263; partial branches: 104, 182
sentry_sdk/integrations/quart.py 86.84% 33/38 covered; missed: 105, 107, 108, 148, 149; partial branches: 190, 200
sentry_sdk/integrations/aiohttp.py 95.45% 63/66 covered; missed: 331, 332, 333; partial branches: 169, 263, 330
sentry_sdk/integrations/asgi.py 86.49% 32/37 covered; missed: 244, 246, 248, 249, 254; partial branches: 230
sentry_sdk/integrations/django/init.py 94.92% 56/59 covered; missed: 805, 824, 900; partial branches: 590, 804, 823
sentry_sdk/integrations/openai.py 96.84% 92/95 covered; missed: 413, 524, 794; partial branches: 585, 604, 793
sentry_sdk/integrations/starlette.py 93.48% 43/46 covered; missed: 109, 165, 801; partial branches: 164, 540, 738
sentry_sdk/integrations/typesafe.py 90.00% 18/20 covered; missed: 265, 349; partial branches: 230, 264, 314, 348
sentry_sdk/integrations/sqlalchemy.py 86.67% 13/15 covered; missed: 169, 173; partial branches: 82, 150, 164
sentry_sdk/_init_implementation.py 89.47% 17/19 covered; missed: 21, 33; partial branches: 20, 32
sentry_sdk/integrations/aiomysql.py 100.00% 21/21 covered; partial branches: 98, 102, 146, 150
sentry_sdk/integrations/chalice.py 94.29% 33/35 covered; missed: 97, 141; partial branches: 96, 100
sentry_sdk/integrations/cohere.py 81.82% 18/22 covered; missed: 144, 149, 158, 260
sentry_sdk/integrations/django/caching.py 97.37% 37/38 covered; missed: 62; partial branches: 61, 81, 108
sentry_sdk/integrations/django/templates.py 77.78% 7/9 covered; missed: 58, 92; partial branches: 57, 91
sentry_sdk/integrations/django/views.py 84.62% 11/13 covered; missed: 25, 75; partial branches: 24, 74
sentry_sdk/integrations/langgraph.py 97.37% 37/38 covered; missed: 275; partial branches: 118, 137, 272
sentry_sdk/integrations/openai_agents/init.py 96.77% 30/31 covered; missed: 133; partial branches: 90, 116, 126
sentry_sdk/client.py 92.31% 24/26 covered; missed: 420, 421; partial branches: 838
sentry_sdk/integrations/boto3/_utils.py 95.00% 19/20 covered; missed: 33; partial branches: 32, 36
sentry_sdk/integrations/flask.py 66.67% 6/9 covered; missed: 48, 142, 143
sentry_sdk/integrations/google_genai/utils.py 88.46% 23/26 covered; missed: 711, 720, 909
sentry_sdk/integrations/grpc/aio/client.py 87.50% 14/16 covered; missed: 90, 93; partial branches: 89
sentry_sdk/integrations/grpc/client.py 85.71% 12/14 covered; missed: 64, 67; partial branches: 63
sentry_sdk/integrations/starlite.py 87.50% 14/16 covered; missed: 155, 247; partial branches: 154
sentry_sdk/scope.py 100.00% 66/66 covered; partial branches: 745, 1475, 1517
sentry_sdk/data_collection.py 83.33% 5/6 covered; missed: 260; partial branches: 259
sentry_sdk/integrations/celery/init.py 100.00% 37/37 covered; partial branches: 105, 365
sentry_sdk/integrations/django/asgi.py 90.00% 9/10 covered; missed: 181; partial branches: 180
sentry_sdk/integrations/django/middleware.py 80.00% 4/5 covered; missed: 80; partial branches: 79
sentry_sdk/integrations/django/transactions.py 71.43% 5/7 covered; missed: 16, 17
sentry_sdk/integrations/google_genai/streaming.py 84.62% 11/13 covered; missed: 115, 119
sentry_sdk/integrations/grpc/server.py 66.67% 4/6 covered; missed: 62, 63
sentry_sdk/integrations/huggingface_hub.py 93.33% 28/30 covered; missed: 232, 427
sentry_sdk/integrations/pure_eval.py 33.33% 1/3 covered; missed: 24, 30
sentry_sdk/integrations/pyramid.py 86.67% 13/15 covered; missed: 78, 79
sentry_sdk/integrations/pyreqwest.py 100.00% 19/19 covered; partial branches: 139, 163
sentry_sdk/integrations/redis/modules/queries.py 100.00% 10/10 covered; partial branches: 55, 58
sentry_sdk/integrations/strawberry.py 97.67% 42/43 covered; missed: 271; partial branches: 270
sentry_sdk/integrations/tornado.py 100.00% 46/46 covered; partial branches: 134, 136
sentry_sdk/traces.py 96.67% 58/60 covered; missed: 293, 678
sentry_sdk/tracing_utils.py 100.00% 29/29 covered; partial branches: 140, 292
sentry_sdk/utils.py 95.12% 39/41 covered; missed: 1401, 1970
sentry_sdk/api.py 91.67% 11/12 covered; missed: 178
sentry_sdk/integrations/arq.py 100.00% 14/14 covered; partial branches: 187
sentry_sdk/integrations/asyncio.py 87.50% 7/8 covered; missed: 164
sentry_sdk/integrations/boto3/_services/kinesis.py 100.00% 20/20 covered; partial branches: 21
sentry_sdk/integrations/boto3/_services/sqs.py 100.00% 20/20 covered; partial branches: 35
sentry_sdk/integrations/boto3/_services/stepfunctions.py 100.00% 38/38 covered; partial branches: 57
sentry_sdk/integrations/bottle.py 100.00% 11/11 covered; partial branches: 118
sentry_sdk/integrations/dramatiq.py 100.00% 17/17 covered; partial branches: 170
sentry_sdk/integrations/falcon.py 100.00% 15/15 covered; partial branches: 97
sentry_sdk/integrations/httpx.py 100.00% 40/40 covered; partial branches: 177
sentry_sdk/integrations/httpx2.py 100.00% 40/40 covered; partial branches: 177
sentry_sdk/integrations/litellm.py 100.00% 14/14 covered; partial branches: 124
sentry_sdk/integrations/logging.py 100.00% 29/29 covered; partial branches: 148
sentry_sdk/integrations/loguru.py 100.00% 14/14 covered; partial branches: 154
sentry_sdk/integrations/openai_agents/patches/error_tracing.py 100.00% 3/3 covered; partial branches: 58
sentry_sdk/integrations/pymongo.py 100.00% 24/24 covered; partial branches: 108
sentry_sdk/integrations/redis/utils.py 100.00% 7/7 covered; partial branches: 107
sentry_sdk/integrations/rq.py 100.00% 15/15 covered; partial branches: 124
sentry_sdk/integrations/sanic.py 100.00% 32/32 covered; partial branches: 186
sentry_sdk/integrations/threading.py 50.00% 1/2 covered; missed: 65
sentry_sdk/integrations/wsgi.py 100.00% 38/38 covered; partial branches: 429
sentry_sdk/profiler/continuous_profiler.py 50.00% 1/2 covered; missed: 84
sentry_sdk/_compat.py 100.00% 4/4 covered
sentry_sdk/_span_batcher.py 100.00% 11/11 covered
sentry_sdk/_types.py 100.00% 1/1 covered
sentry_sdk/ai/utils.py 100.00% 2/2 covered
sentry_sdk/consts.py 100.00% 76/76 covered
sentry_sdk/envelope.py 100.00% 1/1 covered
sentry_sdk/feature_flags.py 100.00% 3/3 covered
sentry_sdk/integrations/init.py 100.00% 3/3 covered
sentry_sdk/integrations/_asgi_common.py 100.00% 20/20 covered
sentry_sdk/integrations/_wsgi_common.py 100.00% 11/11 covered
sentry_sdk/integrations/ariadne.py 100.00% 9/9 covered
sentry_sdk/integrations/aws_lambda/consts.py 100.00% 5/5 covered
sentry_sdk/integrations/beam.py 100.00% 7/7 covered
sentry_sdk/integrations/boto3/_client.py 100.00% 12/12 covered
sentry_sdk/integrations/boto3/_context.py 100.00% 1/1 covered
sentry_sdk/integrations/boto3/_instrumentation.py 100.00% 28/28 covered
sentry_sdk/integrations/boto3/_services/dynamodb.py 100.00% 10/10 covered
sentry_sdk/integrations/boto3/services/lambda.py 100.00% 10/10 covered
sentry_sdk/integrations/boto3/_services/registry.py 100.00% 9/9 covered
sentry_sdk/integrations/boto3/_services/s3.py 100.00% 45/45 covered
sentry_sdk/integrations/boto3/_services/secretsmanager.py 100.00% 26/26 covered
sentry_sdk/integrations/boto3/_services/sns.py 100.00% 10/10 covered
sentry_sdk/integrations/boto3/consts.py 100.00% 2/2 covered
sentry_sdk/integrations/clickhouse_driver.py 100.00% 19/19 covered
sentry_sdk/integrations/dedupe.py 100.00% 5/5 covered
sentry_sdk/integrations/django/signals_handlers.py 100.00% 4/4 covered
sentry_sdk/integrations/django/tasks.py 100.00% 4/4 covered
sentry_sdk/integrations/executing.py 100.00% 1/1 covered
sentry_sdk/integrations/fastapi.py 100.00% 14/14 covered
sentry_sdk/integrations/gql.py 100.00% 3/3 covered
sentry_sdk/integrations/graphene.py 100.00% 12/12 covered
sentry_sdk/integrations/grpc/init.py 100.00% 2/2 covered
sentry_sdk/integrations/grpc/aio/server.py 100.00% 10/10 covered
sentry_sdk/integrations/huey.py 100.00% 16/16 covered
sentry_sdk/integrations/launchdarkly.py 100.00% 9/9 covered
sentry_sdk/integrations/openai_agents/patches/models.py 100.00% 9/9 covered
sentry_sdk/integrations/openai_agents/spans/init.py 100.00% 1/1 covered
sentry_sdk/integrations/openai_agents/spans/execute_tool.py 100.00% 8/8 covered
sentry_sdk/integrations/openai_agents/spans/invoke_agent.py 100.00% 8/8 covered
sentry_sdk/integrations/openai_agents/utils.py 100.00% 15/15 covered
sentry_sdk/integrations/openfeature.py 100.00% 5/5 covered
sentry_sdk/integrations/pydantic_ai/init.py 100.00% 46/46 covered
sentry_sdk/integrations/pydantic_ai/spans/init.py 100.00% 1/1 covered
sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py 100.00% 10/10 covered
sentry_sdk/integrations/pydantic_ai/spans/utils.py 100.00% 5/5 covered
sentry_sdk/integrations/pydantic_ai/utils.py 100.00% 10/10 covered
sentry_sdk/integrations/redis/init.py 100.00% 6/6 covered
sentry_sdk/integrations/redis/_async_common.py 100.00% 15/15 covered
sentry_sdk/integrations/redis/_sync_common.py 100.00% 9/9 covered
sentry_sdk/integrations/redis/modules/caches.py 100.00% 7/7 covered
sentry_sdk/integrations/redis/redis.py 100.00% 6/6 covered
sentry_sdk/integrations/rust_tracing.py 100.00% 12/12 covered
sentry_sdk/integrations/spark/spark_driver.py 100.00% 8/8 covered
sentry_sdk/integrations/statsig.py 100.00% 1/1 covered
sentry_sdk/integrations/stdlib.py 100.00% 32/32 covered
sentry_sdk/integrations/trytond.py 100.00% 11/11 covered
sentry_sdk/integrations/typer.py 100.00% 5/5 covered
sentry_sdk/integrations/unleash.py 100.00% 5/5 covered
sentry_sdk/transport.py 100.00% 3/3 covered
Coverage diff
@@            Coverage Diff             @@
##        master     #5005       +/-##
==========================================
+ Coverage    90.32%    90.37%    +0.05%
==========================================
  Files          203       198        -5
  Tracked lines     26872     21251     -5621
  Branches     10044      7360     -2684
==========================================
- Hits         24272     19205     -5067
+ Misses        2600      2046      -554
+ Partials      1520      1237      -283

Generated by Coverage Action

@github-actions

github-actions Bot commented Mar 19, 2026 •

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

⚪ None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

  • (logging) Separate ignore lists for events/breadcrumbs and sentry logs by sl0thentr0py in #5698

Bug Fixes 🐛

Anthropic

  • Set exception info on streaming span when applicable by alexander-alderman-webb in #5683
  • Patch AsyncStream.close() and AsyncMessageStream.close() to finish spans by alexander-alderman-webb in #5675
  • Patch Stream.close() and MessageStream.close() to finish spans by alexander-alderman-webb in #5674

Documentation 📚

  • Add note on AI PRs to CONTRIBUTING.md by sentrivana in #5696

Internal Changes 🔧

  • Add -latest alias for each integration test suite by sentrivana in #5706
  • Use date-based branch names for toxgen PRs by sentrivana in #5704
  • 🤖 Update test matrix with new releases (03/19) by github-actions in #5703
  • Add client report tests for span streaming by sentrivana in #5677

Other

  • Next Python SDK major by sentrivana in #5005
  • Update CHANGELOG.md by sentrivana in #5685

🤖 This preview updates automatically when you update the PR.

Comment thread sentry_sdk/consts.py
Comment thread sentry_sdk/integrations/otlp.py
Comment thread tests/integrations/django/asgi/test_asgi.py
Comment thread sentry_sdk/integrations/otlp.py
Comment thread tests/integrations/threading/test_threading.py Outdated
Comment thread sentry_sdk/integrations/launchdarkly.py Outdated
Comment thread sentry_sdk/scope.py Outdated
Comment thread sentry_sdk/integrations/trytond.py
Comment thread sentry_sdk/integrations/chalice.py
Comment thread sentry_sdk/integrations/openai_agents/__init__.py
Comment thread sentry_sdk/integrations/pydantic_ai/__init__.py
Comment thread sentry_sdk/integrations/spark/spark_driver.py
Comment thread tests/integrations/launchdarkly/test_launchdarkly.py
Comment thread sentry_sdk/integrations/__init__.py Outdated
Comment thread sentry_sdk/integrations/openai_agents/__init__.py
Comment thread sentry_sdk/integrations/starlette.py
sentrivana added a commit that referenced this pull request Aug 6, 2026
Fixes for things that the bots
[surfaced](#5005) on the
major branch:
- some version checks were too late (after patching)
- fix TrytondWSGI integration name/`_MIN_VERSIONS` entry mismatch

Also, changed the warning of the `DidNotEnable` message from "X not
installed" to "X not installed or incompatible".
Comment thread sentry_sdk/integrations/redis/modules/queries.py
Comment thread sentry_sdk/integrations/langchain.py
Comment thread sentry_sdk/spotlight.py
Comment thread sentry_sdk/spotlight.py
Comment thread sentry_sdk/integrations/otlp.py
Comment thread sentry_sdk/integrations/aiomysql.py
Comment thread sentry_sdk/integrations/aiomysql.py Outdated
Comment thread MIGRATION_GUIDE.md Outdated
Comment thread sentry_sdk/integrations/otlp.py
Comment thread sentry_sdk/integrations/pyramid.py Outdated
Comment thread sentry_sdk/integrations/strawberry.py Outdated
Comment thread tests/integrations/aiomysql/test_aiomysql.py
Comment thread tests/integrations/aiomysql/test_aiomysql.py
Comment thread tests/integrations/aiomysql/test_aiomysql.py
Comment thread sentry_sdk/integrations/stdlib.py Outdated
Comment thread sentry_sdk/integrations/stdlib.py Outdated
Comment thread sentry_sdk/integrations/__init__.py
Comment thread sentry_sdk/integrations/threading.py
Comment thread tests/integrations/bottle/test_bottle.py
Comment thread tests/integrations/httpx/test_httpx.py Outdated
sentrivana added a commit that referenced this pull request Aug 26, 2026
Originally raised by a bot
[here](#5005 (comment)):
the `parse_version` function parses version strings as is (e.g. 3.1
becomes `(3, 1)`). We use these parsed version tuples in integrations to
compare the installed version against the minimum (defined in
`integrations/__init__.py`). The minimum versions are often three-part,
e.g. `(3, 1, 0)`.

This means that we can mistakenly consider a valid version to be below
the minimum, because in pure tuple terms, `(3, 1) < (3, 1, 0)` is true.

This can also happen in reverse (package version has three parts, while
our min version boundary has two).

In this PR, we make the internal version comparison work as expected
regardless of mismatches in the length of the version strings/tuples.
Comment thread sentry_sdk/integrations/typer.py
Comment thread sentry_sdk/_init_implementation.py
Comment thread sentry_sdk/integrations/arq.py Outdated
Comment thread sentry_sdk/integrations/asgi.py Outdated
Comment thread sentry_sdk/integrations/strawberry.py Outdated
Comment thread sentry_sdk/integrations/redis/redis.py
Comment thread sentry_sdk/integrations/stdlib.py Outdated
Comment thread MIGRATION_GUIDE.md Outdated
Comment thread MIGRATION_GUIDE.md Outdated
Comment thread sentry_sdk/consts.py
Comment thread sentry_sdk/integrations/anthropic.py Outdated
Comment thread sentry_sdk/integrations/ray.py Outdated
Comment thread MIGRATION_GUIDE.md
Comment thread sentry_sdk/integrations/pymongo.py
Comment thread sentry_sdk/integrations/redis/_async_common.py Outdated
Comment thread sentry_sdk/transport.py
pabloDeputter and others added 6 commits October 16, 2026 14:56
### Description
- use of f-strings instead `”...”.format()`.
- move constants into `consts.py`.
- add new attributes to `SPANDATA` (will be used in the next PR).
### Description
Expand aws-lambda instrumentation with extra resource identity and
runtime metadata following OTel
(https://opentelemetry.io/docs/specs/semconv/faas/aws-lambda/).

Changes:
- add `sentry.kind=server`.
- add `cloud.account.id`, extracted from the invoked function ARN.
- `cloud.resource_id` is now normalized from the invoked function ARN;
keep the original value in `aws.lambda.invoked_arn` and replace an alias
with the resolved published version when the function is not `$LATEST`.
- `cloud.region` is now extracted from `AWS_REGION` env. var;
`faas.name` from `AWS_LAMBDA_FUNCTION_NAME`; `faas.version` from
`AWS_LAMBDA_FUNCTION_VERSION` following OTel
(https://opentelemetry.io/docs/specs/semconv/faas/aws-lambda/#resource-detector).
- refresh `sentry_sdk` on every test setup (for easier local testing so
runs don’t reuse old behavior from earlier implementation).
- add `capture_internal_exceptions()` around attribute extraction so
that a single failure does not affect the other instrumentation.


#### Issues
Resolves #7931
### Description
Adds the following attributes:
- `aws.secretsmanager.secret.arn` (OTel): from an ARN `SecretID`,
replaced by the response `ARN` (if available).
- `aws.secretsmanager.secret.name` (getsentry/sentry-conventions#716):
from response `Name` or the request `Name` or `SecretId`, else the ARN
without its random `-XXXXXX` suffix (in case of failed calls).

The actual secret values are never read.

#### Issues
Resolves #7574
## Description
Adds the following attributes:
- `aws.step_functions.state_machine.arn`, `*.activity.arn` (OTel) and
`*.execution.arn` (getsentry/sentry-conventions#672), from the request
and response.
- `aws.step_functions.state_machine.name` and `*.activity.name`
(getsentry/sentry-conventions#716), from `name` on create calls or from
the ARN without its version/alias qualifier.

Whenever `StartSyncExecution` returns a failed call (`FAILED` or
`TIMED_OUT`), `error.type` will be set to the respective value.


### Issues
Resolves #7478
### Description
Adds the following attribute:
- `aws.kinesis.stream_name` (OTel): from `StreamName`, else from the
stream in `StreamARN`, `ConsumerARN` or `ResourceARN`
(`…:stream/<name>[/consumer/…]`).

#### Issues
Resolves #7575
sentrivana and others added 5 commits October 21, 2026 13:37
Updated the changelog for the upcoming 3.0.0b1 release, highlighting notable changes, new features, and migration resources.
## Description

Adds span links as is specified in the [specs](https://develop.sentry.dev/sdk/telemetry/spans/#span-links): a span can reference other spans, e.g. in other traces, without making them its parent.

- `sentry_sdk.start_span(..., links=[...])`, `span.add_link(link)` and `span.add_links(links)`; with links being of the following format: `{"trace_id", "span_id", "sampled"?, "attributes"?}`
- span without links omits `links`
- `NoOpSpan` ignores links
- added to the migration guide as well
- [example](https://sentry-sdks.sentry.io/explore/traces/trace/8194b70609574447aa8732f24e1350a0/?mode=samples&node=span-bad54d1bc8cb9604&project=4511733153660928&source=traces&statsPeriod=24h&table=trace&timestamp=1792484175.113) in sentry-test

Related docs update can be found [here](getsentry/sentry-docs#20103).

## Why
An SQS/SNS consumer can receive a batch of records sent by several producers, each in its own trace. A span can only have one parent, so without links there's no way to connect the consumer each producer. With links the consumer span can point to each producer's trace.
Comment thread MIGRATION_GUIDE.md
Comment on lines +21 to +33
identity = aws_event.get("requestContext", {}).get("identity")
if identity is None:
return {}

user_info: "dict[str, Any]" = {}

user_arn = identity.get("userArn")
if user_arn is not None:
user_info["id"] = user_arn

ip = identity.get("sourceIp")
if ip is not None:
user_info["ip_address"] = ip

@sentry-warden sentry-warden Bot Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_get_user_from_event crashes on non-dict requestContext/identity

Use isinstance checks for requestContext and identity before calling .get — a null or non-dict value raises AttributeError; the handler invokes this outside capture_internal_exceptions and can fail the Lambda before user code runs, and the event processor path can drop the error event.

Evidence
  • _get_user_from_event does aws_event.get("requestContext", {}).get("identity"); if the requestContext key is present with value None (or another non-dict), the default {} is skipped and .get raises AttributeError.
  • After the identity is None guard, identity.get("userArn") / identity.get("sourceIp") still assume a mapping, so a non-dict identity also raises.
  • _handler.py calls _get_user_from_event(request_data) outside capture_internal_exceptions when data_collection["user_info"] is true (the default), so the exception aborts sentry_handler before the user handler runs.
  • The same helper runs inside the request event processor; Scope.run_event_processors treats a processor exception as a dropped event.
  • The same file already guards headers with isinstance(..., dict) (e.g. _get_url), but not requestContext/identity.

Identified by Warden · code-review, find-bugs · RSZ-TZN

Comment on lines +132 to +142
if "queryStringParameters" in request_data:
qs = request_data["queryStringParameters"]
if qs:
filtered_qs = _apply_key_value_collection_filtering(
items=qs,
behaviour=data_collection["url_query_params"],
)
if filtered_qs:
additional_attributes[SPANDATA.URL_QUERY] = urlencode(
filtered_qs
)

@sentry-warden sentry-warden Bot Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

queryStringParameters assumed to be a Mapping

Check isinstance(qs, Mapping) (or wrap in capture_internal_exceptions) before filtering: a truthy non-dict value makes _apply_key_value_collection_filtering call .items() and crash the invocation.

Evidence
  • The branch only checks if qs: then passes qs to _apply_key_value_collection_filtering(items=qs, ...).
  • That helper always does items.items() with no type guard.
  • Unlike headers (explicitly coerced to {} when not a dict for EventBridge), queryStringParameters has no isinstance check.
  • This path is outside capture_internal_exceptions, so a bad value aborts sentry_handler before the user handler runs.

Identified by Warden · find-bugs, code-review · FLN-MQ8

Comment thread sentry_sdk/integrations/aws_lambda/_runtime.py
from sentry_sdk.consts import SPANDATA
from sentry_sdk.traces import StreamedSpan
from sentry_sdk.tracing_utils import has_span_streaming_enabled
from sentry_sdk.traces import Span

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closing a Cohere chat stream leaves its Span active

If a consumer closes the returned chat_stream iterator before it is exhausted, GeneratorExit bypasses the except Exception handler and span.end() is skipped. Because the span was activated when chat_stream was called, the current scope can retain that unfinished span and use it as the parent for later spans.

Evidence
  • _wrap_chat starts an active span before returning the wrapped stream iterator.
  • new_iterator calls span.end() only after normal exhaustion; its cleanup handler catches Exception, not GeneratorExit.
  • There is no finally block, so closing a suspended iterator skips span.end().
  • Span._end() restores the previous scope span; without it, the scope can retain the unfinished span.
Also found at 2 additional locations
  • sentry_sdk/integrations/cohere.py:224-246
  • sentry_sdk/integrations/cohere.py:197-260

Identified by Warden · find-bugs · AZ7-GHE

Comment thread sentry_sdk/integrations/gql.py
Comment thread sentry_sdk/integrations/gql.py
Comment thread sentry_sdk/consts.py
sample_rate: float = 1.0,
send_default_pii: "Optional[bool]" = None,
data_collection: "Optional[DataCollectionUserOptions]" = None,
data_collection: "Optional[DataCollectionUserOptions]" = {},

@sentry-warden sentry-warden Bot Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data_collection typed Optional but None raises TypeError

Drop Optional from the annotation (or accept None in _resolve_data_collection); type checkers allow data_collection=None, but init will raise TypeError.

Evidence
  • ClientConstructor.__init__ types data_collection as Optional[DataCollectionUserOptions] with default {}.
  • DEFAULT_OPTIONS is built from these defaults via _get_default_options() / inspect.getfullargspec.
  • _resolve_data_collection() does isinstance(user_dc, dict) and raises TypeError for any non-dict, including None.
  • _get_options() always calls _resolve_data_collection(rv), so sentry_sdk.init(data_collection=None) fails at runtime despite the Optional type.

Identified by Warden · code-review, find-bugs · BW5-RFW

pabloDeputter and others added 10 commits October 27, 2026 17:16
### Description
S3 object operations now override default `rpc` op with `object.*`.
Other S3 operations, e.g. `ListBuckets`, stay on `rpc`.
…into-3.0

# Conflicts:
#	.github/workflows/test-integrations-agents.yml
#	.github/workflows/test-integrations-cloud.yml
#	scripts/populate_tox/config.py
#	scripts/populate_tox/package_dependencies.jsonl
#	scripts/populate_tox/releases.jsonl
#	scripts/populate_tox/tox.jinja
#	sentry_sdk/integrations/falcon.py
#	tests/integrations/falcon/test_falcon.py
#	tox.ini
### Description

Removes `with_metaclass()` from `sentry_sdk/_compat.py`. Nothing on
`major/3.0` uses it anymore.

It's a Python 2 / `six`-style helper for declaring a metaclass across
Python versions; on Python 3 you just write `class Foo(metaclass=Meta)`.
Its only caller was `class Hub(with_metaclass(HubMeta))` in
`sentry_sdk/hub.py`. #6919 ("Drop hub related code in new major")
deleted `Hub` and the import, but left the helper behind.

With the helper gone, the `TYPE_CHECKING` block in `_compat.py` (`Any`,
`TypeVar`, `T`) is unused too, so it's removed as well. `T` wasn't used
before this change either.

**Evidence**
- On `major/3.0`, `git grep with_metaclass` matches only the definition.
There are no callers in `sentry_sdk`, `tests`, `scripts` or `docs`.
- Nothing imports `T` or `Any` from `sentry_sdk._compat`.
- #6091 and #7421 (against `master`) proposed the same removal as part
of larger Python 2 cleanups. Both were closed without being merged, one
for inactivity. Neither raised an objection to this change. On `master`,
`Hub` still uses the helper, so this only applies to `major/3.0`.

`_compat` is a private module, so this doesn't touch the public API.

#### Issues
n/a

<!-- junior-request-attribution:start -->
via **Ivana Kellyer**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 -->

--

[View Junior
Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119)
[[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
…8154)

### Description

Removes the `PY37` flag from `sentry_sdk/_compat.py`, along with the
code paths that only ran when it was `False`. It also removes the
`nanosecond_time()` wrapper, which existed only to choose between those
paths.

`setup.py` sets `python_requires=">=3.7"`, so `PY37` is always `True` on
every supported interpreter, and the `tox.ini` matrix starts at py3.7.
That makes these branches unreachable:

- `nanosecond_time()` in `sentry_sdk/utils.py`: the
`int(time.perf_counter() * 1e9)` fallback is gone. Once only
`time.perf_counter_ns()` was left, the wrapper added nothing, so it's
removed as well. Its two call sites in `sentry_sdk/traces.py` (`Span`
start and end) now call `time.perf_counter_ns()` directly.
- `tests/test_gevent.py`: `compression_algo` always includes `"br"` now,
as it already did in practice.
- `tests/test_transport.py`: `elif PY37:` becomes `else:`, and the
pre-3.7 case list after it is removed. The cases that run on 3.7 are
unchanged.

`PY38`, `PY310` and `PY311` are still used, so they stay. This doesn't
depend on #8153; the two only touch different lines of `_compat.py` and
merge cleanly together.

`_compat` and `utils` are private modules, and nothing else in the repo
(including tests) references `nanosecond_time`. Runtime behavior doesn't
change on any supported Python version.

#### Issues
n/a

<!-- junior-request-attribution:start -->
via **Ivana Kellyer**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 -->

--

[View Junior
Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119)
[[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921)

<!-- junior-session-footer:end -->

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
### Description

Removes the private `_get_usage_attributes()` helper from
`sentry_sdk/tracing_utils.py`. Nothing on `major/3.0` calls it anymore.

It pulled `gen_ai.usage.*` token counts out of return values for the AI
Agents `@trace` templates added in #4676. #7457 ("Remove trace template,
trace_ignore_status_codes") deleted the template code that called it,
but left the helper behind.

**Evidence**
- On `major/3.0`, `git grep -w _get_usage_attributes` matches only the
definition. There are no callers in `sentry_sdk` or `tests`.
- No open PR touches it.

`_get_value()` is still imported by the LangChain integration, so it
stays.

On `master` the helper is still used, because the trace templates still
exist there. This change only applies to `major/3.0`.

#### Issues
n/a

<!-- junior-request-attribution:start -->
via **Ivana Kellyer**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 -->

--

[View Junior
Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119)
[[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
### Description

Removes the private `_ScopeManager` class from `sentry_sdk/scope.py`.
Nothing on `major/3.0` uses it anymore.

It was the context manager behind `push_scope()` and the `Hub` scope
helpers. #6919 ("Drop hub related code in new major") and #6944 ("Remove
`push_scope`, `configure_scope` in new major") removed those callers and
their imports, but left the class behind.

**Evidence**
- On `major/3.0`, `git grep -w _ScopeManager` matches only the class
definition in `sentry_sdk/` and `tests/`. The only other hits are
historical `CHANGELOG.md` and `MIGRATION_GUIDE.md` entries from 2.0
about it moving out of `sentry_sdk.hub`.
- No open PR touches it.

It's underscore-private and isn't exported, so this doesn't touch the
public API.

#### Issues
n/a

<!-- junior-request-attribution:start -->
via **Ivana Kellyer**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 -->

--

[View Junior
Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119)
[[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
### Description

Removes two helpers that only `EventScrubber` used:

- `iter_event_frames()` in `sentry_sdk/utils.py`
- `AnnotatedValue.substituted_because_contains_sensitive_data()` in
`sentry_sdk/_types.py`

#7772 ("Remove `EventScrubber` and the `event_scrubber` option") deleted
`sentry_sdk/scrubber.py`, which held the only call to each of them:
frame-vars scrubbing called `iter_event_frames(event)`, and denylisted
keys were replaced with
`AnnotatedValue.substituted_because_contains_sensitive_data()`. Both
helpers were left behind.

**Evidence**
- On `major/3.0`, `git grep -w` for each name matches only its
definition. There are no callers in `sentry_sdk`, `tests`, `scripts` or
`docs`.
- No open PR touches either one.

`iter_event_stacktraces()` (used by `handle_in_app`) and
`SENSITIVE_DATA_SUBSTITUTE` (used by the data-collection filtering and
several integrations) are still used, so they stay.

On `master`, `EventScrubber` still uses both helpers, so this only
applies to `major/3.0`. `iter_event_frames` could be imported from
`sentry_sdk.utils`, but it isn't documented anywhere, and `major/3.0` is
already a breaking release.

#### Issues
n/a

<!-- junior-request-attribution:start -->
via **Ivana Kellyer**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 -->

--

[View Junior
Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119)
[[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
### Description

Removes `AwsCallContext.service_id_hyphenized` from
`sentry_sdk/integrations/boto3/_context.py`. It's still computed on
every call (`service_id.hyphenize()`), but on `major/3.0` nothing reads
it.

It had two readers. One was the `aws.service_id` span tag, which #7261
("Drop tags auto-set by the SDK") removed. The other was the span name:
#7800 ("align span names with OTel conventions") switched that to
`ctx.service_id`, so the hyphenized value lost its last reader. This
removes the slot, the attribute and the `hyphenize()` call.

**Evidence**
- On `major/3.0`, `git grep -w service_id_hyphenized` matches only the
three lines in `_context.py` that set it up.
- The open boto3 extension PRs against `major/3.0` (#8117 SQS, #8137
Lambda) don't reference it.

On `master`, `service_id_hyphenized` is still used for the span name and
the tag, so this only applies to `major/3.0`.

#### Issues
n/a

<!-- junior-request-attribution:start -->
via **Ivana Kellyer**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 -->

--

[View Junior
Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119)
[[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
### Description

Removes `get_url_attributes_legacy()` from
`sentry_sdk/tracing_utils.py`. Nothing on `major/3.0` calls it anymore.

Its callers were the outgoing HTTP client integrations (pyreqwest,
httpx, httpx2). It handled their old `send_default_pii` behavior. When
#7698, #7819 and #7830 dropped `send_default_pii` support from those
integrations, each one removed its calls and switched to
`get_url_attributes()`. The legacy helper was left behind.

**Evidence**
- On `major/3.0`, `git grep -w get_url_attributes_legacy` matches only
the definition. There are no callers in `sentry_sdk`, `tests`, `scripts`
or `docs`.
- No open PR mentions it. The function doesn't exist on `master`, so a
future `master` → `major/3.0` merge can't bring it back.

`get_url_attributes()` and
`_apply_data_collection_filtering_to_query_string` are still used, so
they stay.

#### Issues
n/a

<!-- junior-request-attribution:start -->
via **Ivana Kellyer**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:slack%3AC0BTREZTS2Z%3A1793270559.842119 -->

--

[View Junior
Session](https://junior-prod.sentry.dev/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119)
[[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0BTREZTS2Z%3A1793270559.842119/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants