feat(boto3): Add ServiceExtension class - #7536
Conversation
Codecov Results 📊✅ 132793 passed | ⏭️ 7220 skipped | Total: 140013 | Pass Rate: 94.84% | Execution Time: 461m 39s 📊 Comparison with Base Branch
All tests are passing successfully. ✅ Patch coverage is 97.67%. Project has 2563 uncovered lines. Files with missing lines (3)
Coverage diff@@ Coverage Diff @@
## master #PR +/-##
==========================================
- Coverage 90.37% 90.35% -0.02%
==========================================
Files 199 202 +3
Lines 26526 26551 +25
Branches 9866 9856 -10
==========================================
+ Hits 23971 23988 +17
- Misses 2555 2563 +8
- Partials 1495 1487 -8Generated by Codecov Action |
499dbcc to
d9609eb
Compare
d9609eb to
ea505d1
Compare
9068e22 to
b9071e2
Compare
b9071e2 to
787cd71
Compare
17d48a0 to
8ace874
Compare
82e40da to
2de4cfe
Compare
d8279cc to
d7727cd
Compare
| def get_span_config( | ||
| self, ctx: "AwsCallContext" | ||
| ) -> "Optional[Tuple[Optional[str], Optional[str]]]": | ||
| """Return an optional `(op, origin)` override for the client span.""" |
There was a problem hiding this comment.
To confirm, the op, origin here is referring to the values that would normally live in the sentry.op and sentry.origin span attributes?
There was a problem hiding this comment.
Yupp, I originally I had 2 separate hooks for sentry.op and sentry.origin; not sure why I changed it to a single one. I changed it back to 2 separate ones since it’s more clear.
| from typing import Dict, Optional, Tuple | ||
|
|
||
|
|
||
| # service modules are imported lazily. |
There was a problem hiding this comment.
I saw the comment about this in the pull request summary and was wondering - do we know why this happens?
Not sure if you've learned the background on this design choice as you've been making changes in this integration. 🤔
There was a problem hiding this comment.
I wanted to first discuss with someone on whether this was a good approach or not, but didn’t get the chance. The idea was that a specific service module (e.g. _services/s3.py) would only be loaded at the time it was needed (first client call that needs it).
This is probably not needed when there are only a few number of extensions (final target is ~9), but might improve performance if there are more and have a number of dependencies/are large? I’m really not sure about this, the gains would probably negligible compared to the variance in network calls…
I guess it’s easier to just start with a static map like this, what do you think?
from sentry_sdk.integrations.boto3._services.s3 import _S3Extension
_SERVICE_EXTENSIONS = {
“s3”: _S3Extension
}
def _resolve_service(service_name: str):
return _SERVICE_EXTENSIONS.get(service_name)There was a problem hiding this comment.
Yeah, I think the static map approach would be easier to start with, and if we see that we're starting to impact performance we can revisit this.
As an aside, I think we may take a harder look at our lazy-loading approach once Python 3.15 drops with the lazy keyword support
| with capture_internal_exceptions(): | ||
| attributes.update(service_ext.get_request_attributes(ctx)) | ||
|
|
||
| # Generic attributes take precedence over service-specific attributes. |
There was a problem hiding this comment.
I'm not sure I follow why we want this to happen. Could you provide some context on why we'd rather this than the other way around (service-specific overrides generic)?
There was a problem hiding this comment.
Not sure why I did this (maybe for future AWS services there might be overlap between attributes, but I doubt it). Even if there is overlap, I think you would want service-precedence or just decide for that specific attribute which one should be kept.
There was a problem hiding this comment.
I put it back that generic attributes are set first, service-specific ones are set later.
91c9bdb to
226f56a
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 226f56a. Configure here.
226f56a to
4d0bd32
Compare
- 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>
…t_span_origin()`
4d0bd32 to
2eef01e
Compare

Description
Adds service-extension support to
Boto3Integration. This keeps the generic Boto3 call lifecycle independent of individual AWS services._ServiceExtensioninterface for service-specific behavior through_get_span_config(),_get_request_attributes(), and_get_response_attributes(). This allows for custom span operations/origin, request attributes, and response/error attributes. A future method can also inject trace context into service-specific payload, e.g. SQS message attributes.sentry.kindis added to every boto3 span and defaults tosentry.kind="client"; service extensions can override this later, e.g. SQS/SNS sendsentry.kind="producer"or SQS receive usesentry.kind="consumer"/sentry.kind="client"Issues
Resolves #7477