Skip to content

feat(boto3): Add S3 service extension - #7617

Draft
pabloDeputter wants to merge 72 commits into
pablo/add-boto3-service-extension-classfrom
pablo/add-boto3-s3-service
Draft

pabloDeputter wants to merge 72 commits into
pablo/add-boto3-service-extension-classfrom
pablo/add-boto3-s3-service

Conversation

@pabloDeputter

Copy link
Copy Markdown
Member

Description

  • add the following service-specific attributes:
    • aws.s3.bucket required in almost all s3 operations except list-buckets.
    • http.response.body.size which is the number of bytes in the payload.
  • add the following OTel attributes that are NOT yet in sentry-conventions:
    • aws.s3.copy_source
    • aws.s3.delete
    • aws.s3.key
    • aws.s3.part_number
    • aws.s3.upload_id
    • aws.s3.object_size (not in OTel) which is the total size of the s3 object itself.
      • extracted from ContentLength on GetObject and HeadObject responses; ObjectSize on GetObjectAttributes, and ContentLength on PutObject requests. For ranged GetObject or HeadObject calls, ContentLength is the used size.
  • more information where these parameters can be found/extracted from in https://opentelemetry.io/docs/specs/semconv/object-stores/s3/ & https://opentelemetry.io/docs/specs/semconv/registry/attributes/aws/#amazon-s3-attributes

Issues

Resolves #7576

@pabloDeputter
pabloDeputter changed the base branch from master to pablo/add-boto3-service-extension-class September 22, 2026 14:50
@pabloDeputter
pabloDeputter added this pull request to stack #7541 September 22, 2026 14:52
@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-service-extension-class branch from d8279cc to d7727cd Compare September 22, 2026 14:53
@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-s3-service branch from ca45d46 to 0c2873f Compare September 22, 2026 14:53
@pabloDeputter
pabloDeputter removed this pull request from stack #7541 September 22, 2026 14:57
@pabloDeputter
pabloDeputter added this pull request to stack #7618 September 22, 2026 14:57
@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Codecov Results 📊

✅ 132785 passed | ❌ 1 failed | ⏭️ 7220 skipped | Total: 140006 | Pass Rate: 94.84% | Execution Time: 452m 28s

📊 Comparison with Base Branch

Metric Change
Total Tests 📈 +621
Passed Tests 📈 +593
Failed Tests 📈 +1
Skipped Tests 📈 +27

➕ New Tests (1)

View new tests
  • test_cache_spans_item_size[True]
    • File: tests.integrations.django.test_cache_module
    • Status: ❌ Failing

❌ Failed Tests

test_cache_spans_item_size[True]

File: tests.integrations.django.test_cache_module
Suite: py3.12-django-v4.2.30
Error: tests/integrations/django/test_cache_module.py:763: in test_cache_spans_item_size assert not spans[0]["attributes"]["cache.hit"] E assert not True

Stack Trace
tests/integrations/django/test_cache_module.py:763: in test_cache_spans_item_size
    assert not spans[0]["attributes"]["cache.hit"]
E   assert not True

✅ Patch coverage is 83.12%. Project has 2569 uncovered lines.
✅ Project coverage is 90.35%. Comparing base (91c9bdb) to head (7c39a6c).

Files with missing lines (2)
File Patch % Lines
sentry_sdk/integrations/boto3/_services/s3.py 72.09% ⚠️ 12 Missing and 5 partials
sentry_sdk/integrations/boto3/_services/_attribute_extraction.py 93.75% ⚠️ 1 Missing and 1 partials
Coverage diff
@@            Coverage Diff             @@
##        master       #PR       +/-##
==========================================
+ Coverage    90.29%    90.35%    +0.06%
==========================================
  Files          195       204        +9
  Lines        26252     26625      +373
  Branches      9792      9882       +90
==========================================
+ Hits         23703     24056      +353
- Misses        2549      2569       +20
- Partials      1486      1493        +7

Generated by Codecov Action

@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-service-extension-class branch from d7727cd to c1249cb Compare September 29, 2026 08:34
@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-s3-service branch from 0c2873f to 70218f1 Compare September 29, 2026 08:34
Comment on lines +28 to +31
return {}

attributes = {}
for param, attribute, convert in specs:

@sentry-warden sentry-warden Bot Sep 29, 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.

PutObject object size is read from an absent response field

PutObject responses do not include Size, so this mapping leaves aws.s3.object_size unset. Extract ContentLength from the request params for PutObject, as the PR description specifies.

Evidence
  • _RESPONSE_OBJECT_SIZE_FIELDS maps PutObject to Size.
  • get_response_attributes() reads that field from the response and only sets aws.s3.object_size when it is an integer.
  • The S3 PutObject response has no Size; request extraction does not otherwise capture ContentLength.
Also found at 2 additional locations
  • sentry_sdk/integrations/boto3/_services/registry.py:15-15
  • sentry_sdk/integrations/boto3/_services/s3.py:28-31

Identified by Warden · code-review, find-bugs · F8T-EAX

Comment on lines +14 to +16
_SERVICE_EXTENSIONS: "Dict[str, Tuple[str, str]]" = {
"s3": ("sentry_sdk.integrations.boto3._services.s3", "_S3Extension"),
}

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.

S3 attribute extraction is not covered by tests

Please add tests that assert the new S3 request and response attributes, including the operation-specific object-size and response-body-size behavior. The existing S3 tests do not verify these fields, so regressions in the new extraction logic could go undetected.

Evidence
  • _S3Extension.get_request_attributes extracts S3 request fields and handles CompleteMultipartUpload object size.
  • _S3Extension.get_response_attributes has operation-specific logic for response body size and object size, including ranged HeadObject calls.
  • The boto3 tests do not assert SPANDATA.AWS_S3_* or HTTP_RESPONSE_BODY_SIZE; existing ApproxDict assertions allow additional attributes without checking them.
Also found at 1 additional location
  • sentry_sdk/integrations/boto3/_services/s3.py:64-109

Identified by Warden · code-review · VBM-G26

# the appropriate type.
# https://opentelemetry.io/docs/specs/semconv/object-stores/s3/
("Bucket", SPANDATA.AWS_S3_BUCKET, _as_string),
("CopySource", SPANDATA.AWS_S3_COPY_SOURCE, _as_string),

@sentry-warden sentry-warden Bot Sep 29, 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.

CopySource dict form silently drops aws.s3.copy_source

Boto3 often passes CopySource as a dict (Bucket/Key/VersionId); _as_string rejects that and omits aws.s3.copy_source—normalize dicts to the bucket/key string form.

Evidence
  • _REQUEST_ATTRIBUTES converts CopySource with _as_string.
  • _as_string only accepts non-empty str values and returns None for dicts.
  • Boto3 documents CopySource as str or dict; dict form is common for copy_object/copy_from, so the attribute is dropped on a frequent path.
Also found at 1 additional location
  • sentry_sdk/integrations/boto3/_services/registry.py:15-15

Identified by Warden · code-review, find-bugs · 8LX-QYJ

Comment on lines +85 to +107

if operation_name in _RESPONSE_BODY_SIZE_OPERATIONS:
# `ContentLength` is the size of the HTTP body returned, which may be a range.
content_length = _as_integer(response.get("ContentLength"))
if content_length is not None and content_length >= 0:
attributes[SPANDATA.HTTP_RESPONSE_BODY_SIZE] = content_length

# these fields report the total S3 object size, not the HTTP body size.
object_size_field = _RESPONSE_OBJECT_SIZE_FIELDS.get(operation_name)
if object_size_field is not None:
object_size = _as_integer(response.get(object_size_field))
if object_size is not None and object_size >= 0:
attributes[SPANDATA.AWS_S3_OBJECT_SIZE] = object_size

if (
operation_name == "HeadObject"
and "Range" not in ctx.params
and "PartNumber" not in ctx.params
):
# an un-ranged `HEAD` has no body, so `ContentLength` is the object size.
object_size = _as_integer(response.get("ContentLength"))
if object_size is not None and object_size >= 0:
attributes[SPANDATA.AWS_S3_OBJECT_SIZE] = object_size

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.

Non-ranged GetObject never sets aws.s3.object_size

Un-ranged GetObject only sets http.response.body.size from ContentLength; mirror the HeadObject guard so full-object gets also set aws.s3.object_size.

Evidence
  • For GetObject, ContentLength is only written to SPANDATA.HTTP_RESPONSE_BODY_SIZE.
  • aws.s3.object_size from ContentLength is set only for un-ranged HeadObject (Range/PartNumber absent).
  • GetObject is not in _RESPONSE_OBJECT_SIZE_FIELDS and has no equivalent un-ranged branch.
  • PR intent: object size from ContentLength on GetObject and HeadObject responses when not a range.

Identified by Warden · find-bugs · 6BP-LMY

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.

Fix attempt detected (commit 85a8895)

The S3 response-attribute code adds an un-ranged HeadObject object-size branch, but still only records ContentLength for GetObject as the HTTP body size, so the reported issue persists.

The original issue appears unresolved. Please review and try again.

Evaluated by Warden

@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-service-extension-class branch from 5c6b2b0 to 5e335b5 Compare September 30, 2026 09:21
@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-s3-service branch 2 times, most recently from 2fdaa4b to 85a8895 Compare September 30, 2026 12:04
@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-service-extension-class branch from 5e335b5 to 70414fe Compare September 30, 2026 12:04
@pabloDeputter
pabloDeputter removed this pull request from stack #7618 September 30, 2026 12:05
@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-s3-service branch from 85a8895 to a0c0e25 Compare September 30, 2026 13:31
@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-service-extension-class branch from 70414fe to 0a53853 Compare September 30, 2026 13:31
pabloDeputter and others added 26 commits September 30, 2026 16:04
- otherwise service-specific spans with different origins would be skipped (e.g. DynamoDB)
ref(boto3): improve docstring for `get_request_attributes()`

Co-authored-by: Erica Pisani <hey@ericapisani.dev>
@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-s3-service branch from a0c0e25 to 7c39a6c Compare September 30, 2026 14:05
@pabloDeputter
pabloDeputter force-pushed the pablo/add-boto3-service-extension-class branch 3 times, most recently from 226f56a to 4d0bd32 Compare September 30, 2026 15:50

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(boto3): Add S3 service extension

1 participant