Repository navigation
Next Python SDK major - #5005
sentrivana wants to merge 432 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 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
|
Coverage Results 📊✅ 55646 passed | ❌ 2 failed | ⏭️ 2872 skipped | Total: 58520 | Pass Rate: 95.09% | Execution Time: 151m 27s 📊 Comparison with Base Branch
➕ New Tests (2)View new tests
❌ Failed Tests
|
| File | Patch coverage | Changed executable lines |
|---|---|---|
| sentry_sdk/integrations/aws_lambda.py | 13.51% | 5/37 covered; missed: 166, 167, 177, 181, 185, 186, 188, 189, 190, 191, 200, 201, 203, 276, 280, 282, 285, 286, 290, 295, 296, 297, 298, 300, 302, 307, 388, 389, 393, 394, 409, 412; partial branches: 399, 406 |
| 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/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/tracing_utils.py | 73.33% | 33/45 covered; missed: 193, 194, 195, 200, 201, 202, 203, 205, 206, 207, 209, 211; partial branches: 152, 337 |
| 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: 330, 331, 332; partial branches: 168, 262, 329 |
| 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, 811; partial branches: 164, 550, 748 |
| 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.12% | 32/34 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 | 91.67% | 22/24 covered; missed: 414, 415; partial branches: 832 |
| 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: 763, 1485, 1527 |
| 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/huey.py | 100.00% | 16/16 covered; partial branches: 146, 150 |
| 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 | 94.59% | 35/37 covered; missed: 285, 652 |
| sentry_sdk/utils.py | 95.12% | 39/41 covered; missed: 1417, 1994 |
| sentry_sdk/api.py | 91.67% | 11/12 covered; missed: 178 |
| sentry_sdk/integrations/arq.py | 100.00% | 14/14 covered; partial branches: 173 |
| sentry_sdk/integrations/asyncio.py | 87.50% | 7/8 covered; missed: 164 |
| sentry_sdk/integrations/boto3/_services/sqs.py | 100.00% | 20/20 covered; partial branches: 35 |
| 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: 93 |
| 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/_types.py | 100.00% | 1/1 covered |
| sentry_sdk/ai/utils.py | 100.00% | 2/2 covered |
| sentry_sdk/consts.py | 100.00% | 30/30 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/beam.py | 100.00% | 7/7 covered |
| sentry_sdk/integrations/boto3/_client.py | 100.00% | 9/9 covered |
| sentry_sdk/integrations/boto3/_context.py | 100.00% | 1/1 covered |
| sentry_sdk/integrations/boto3/_instrumentation.py | 100.00% | 27/27 covered |
| sentry_sdk/integrations/boto3/_services/dynamodb.py | 100.00% | 10/10 covered |
| sentry_sdk/integrations/boto3/_services/kinesis.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% | 42/42 covered |
| sentry_sdk/integrations/boto3/_services/secretsmanager.py | 100.00% | 10/10 covered |
| sentry_sdk/integrations/boto3/_services/sns.py | 100.00% | 10/10 covered |
| sentry_sdk/integrations/boto3/_services/stepfunctions.py | 100.00% | 10/10 covered |
| sentry_sdk/integrations/boto3/consts.py | 100.00% | 1/1 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/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.26% 90.04% -0.22%
==========================================
Files 202 193 -9
Tracked lines 26660 20938 -5722
Branches 9926 7208 -2718
==========================================
- Hits 24063 18852 -5211
+ Misses 2597 2086 -511
+ Partials 1510 1234 -276Generated by Coverage Action
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
Bug Fixes 🐛Anthropic
Documentation 📚
Internal Changes 🔧
Other
🤖 This preview updates automatically when you update the PR. |
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".
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.
) Group the TracingTestClass tracing tests into a class whose setup/teardown restores the `static` and `class_` attributes that `functions_to_trace` patches. Resolves warnings like these https://github.com/getsentry/sentry-python/actions/runs/37602693189/job/112730646420#step:6:3739 Refs PY-2637 Refs #6949
The task factory tests build the Sentry wrapper coroutine but never run it, so it is garbage-collected unawaited. This surfaces as a "coroutine was never awaited" RuntimeWarning attributed to an unrelated later test (e.g. test_span_origin). Close the coroutine once the assertions are done. Fixes PY-2943 Fixes #7923
#7930) ### Description Expand boto3 instrumentation with resource identity attributes; new service-extensions (and tests) are added as well (mostly boilerplate, but will be filled in the future). - add `cloud.account.id` and `cloud.resource_id` (https://opentelemetry.io/docs/specs/semconv/resource/cloud/) attributes whenever a request contains a valid AWS ARN; these are extracted using the common helper `_get_aws_arn_attributes()` in `boto3/_utils.py`; the resource's AWS account is used here, not the caller's. It accepts multiple request params. since operations may expose the same resource under different names (the first matching ARN is used). - additionally, following service extensions are registered: DynamoDB, Kinesis, Lambda (file is called `lambda_.py` since it clashes with `lambda` keyword, open for suggestions on renaming it), Secrets Manager, SNS, SQS, and Step Functions. - for SQS, `cloud.account.id` is extracted from `QueueURL` when no ARN is available, e.g. `https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue` (https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-queue-message-identifiers.html) #### Issues Resolves #7929
### Description Remove whitespace from services whose `service_id` contain spaces; since span names are formed using `str(service_id)` they are incorrect: * `service_id = "API Gateway"` => `service_id= "API Gateway"` * `span_name = "API Gateway.GetRestApis"` => `span_name = "APIGateway.GetRestApis"` #### Issues Resolves #7954
…8005) We're not recording the correct reason if a event/error processor raises (should be `callback_error`). Closes https://linear.app/getsentry/issue/PY-2888/drop-events-if-a-processor-raises
### Description boto3 spans now use `sentry.op = rpc` instead of `http.client`. Service extensions can (and will in the future) provide a more specific op with `get_span_op()`, e.g. `db` for DynamoDB. ### Why - boto3 span represents an AWS api call, not an HTTP request; the HTTP request is already captured as the as the `http.client` child - JS already also defaults AWS SDK spans to `rpc` It also lets these spans use new name and description rules in sentry-conventions, e.g. (getsentry/sentry-conventions#714, #717), e.g. `Lambda.Invoke billing` instead of `POST https://lambda.…`
### Description Rename the boto3 span origin from `auto.http.boto3` to `auto.aws.boto3`, for every boto3 span including the streamed response body child, and removes the unused `get_span_origin()` method from `_ServiceExtension`. ### Why 1. `auto.http.boto3` describes the underlying transport/integration used; boto3 spans are AWS API calls, and (in the future) the ops will be changed from `http.client` => `rpc`, `db`, `queue.*`, `object.*`, so it doesn't really fit anymore. 2. JS does the same and uses `auto.aws.aws_sdk`. ### Other option The other option is to use `auto.rpc.boto3` as the default origin (since `aws` isn't technically part of the categories, even though JS uses it https://develop.sentry.dev/sdk/telemetry/traces/trace-origin/) and override it with the span's op for different services: - `db` => `auto.db.boto3` - `queue.*` => `auto.queue.boto3` - `object.* ` => `auto.object.boto3` - streamed body child has op `http.client.stream` => `auto.http.boto3`
### Description Move aws-lambda integraton into package; moved some constants that are now used across modules in `aws_lambda/consts.py`. Mainly done for ease of future development and diff-checks
### Description - use of f-strings instead `”...”.format()`. - move constants into `consts.py`. - add new attributes to `SPANDATA` (will be used in the next PR).
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
SDK3.0 label on GitHub so that you can follow along.Notable changes
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-basebranch, 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.