Skip to content

Conversation

@rite7sh
Copy link
Contributor

@rite7sh rite7sh commented Jan 10, 2026

Fixes #4040

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

  • Added a new unit test test_presigned_url_is_traced
  • Verified that a span named botocore.presigned_url is emitted when
    botocore.signers.RequestSigner.generate_presigned_url is invoked
    (e.g. via rds.generate_db_auth_token)

To reproduce:

pytest instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py -k presigned

@rite7sh
Copy link
Contributor Author

rite7sh commented Jan 11, 2026

Hey @xrmx , this PR implements tracing for RequestSigner.generate_presigned_url (incl. RDS IAM auth) as discussed in #4040.
Would love your review when you have a moment, thanks :)

@xrmx xrmx moved this to Ready for review in @xrmx's Python PR digest Jan 13, 2026
wrapped(*args, **kwargs)

try:
original = instance.generate_presigned_url
Copy link
Contributor

Choose a reason for hiding this comment

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

We should be using hasattr or getattr here.

Comment on lines 187 to 191
wrap_function_wrapper(
"botocore.signers",
"RequestSigner.__init__",
self._patched_signer_init,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we not just do:

Suggested change
wrap_function_wrapper(
"botocore.signers",
"RequestSigner.__init__",
self._patched_signer_init,
)
wrap_function_wrapper(
"botocore.signers",
"RequestSigner.generate_presigned_url",
self._patched_generate_presigned_url,
)

tracer = get_tracer(__name__, __version__, self.tracer_provider)

with tracer.start_as_current_span("botocore.presigned_url") as span:
try:
Copy link
Contributor

Choose a reason for hiding this comment

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

This try-catch is unnecessary.

except Exception:
pass

return wrapped(*args, **kwargs)
Copy link
Contributor

Choose a reason for hiding this comment

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

You're just doing a direct pass through with this wrapper. I'd imagine we'd at least want to know the operation name and maybe the expiration time and region name.

@rite7sh
Copy link
Contributor Author

rite7sh commented Jan 13, 2026

gosh that makes sense :')
I’ll update this to wrap RequestSigner.generate_presigned_url directly, remove the try/except, and use getattr instead.
I’ll also add a few useful span attributes (like operation, expiry, region, etc.) so it’s not just a pass-through span. Will push a follow-up shortly.

@rite7sh
Copy link
Contributor Author

rite7sh commented Jan 14, 2026

@herin049 Addressed the review comments and pushed an update, hope this looks good now.

if not is_instrumentation_enabled():
return wrapped(*args, **kwargs)

tracer = get_tracer(__name__, __version__, self.tracer_provider)
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to make sure that the schema version is set. It should be set to _AwsSdkExtension.tracer_schema_version(). I would personally externalize this into another function _get_default_tracer on the current class.

Comment on lines 372 to 374
operation = kwargs.get("ClientMethod")
if operation:
span.set_attribute("aws.operation", operation)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit

Suggested change
operation = kwargs.get("ClientMethod")
if operation:
span.set_attribute("aws.operation", operation)
if operation := kwargs.get("ClientMethod"):
span.set_attribute("aws.operation", operation)

Comment on lines 382 to 384
region = getattr(instance, "_region_name", None)
if region:
span.set_attribute("aws.region", region)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
region = getattr(instance, "_region_name", None)
if region:
span.set_attribute("aws.region", region)
if region := getattr(instance, "_region_name", None):
span.set_attribute("aws.region", region)

# Region
region = getattr(instance, "_region_name", None)
if region:
span.set_attribute("aws.region", region)
Copy link
Contributor

Choose a reason for hiding this comment

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

Make sure to use the dedicated Span attributes in semconv, or create dedicated constants for these.

DBUsername="testuser",
)

self.assertIsNotNone(token)
Copy link
Contributor

Choose a reason for hiding this comment

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

We should add assertions to check that the newly added Span attributes are present in the resulting Spans.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hello @herin049 , I’ve updated the PR based on your suggestion and reworked the presigned URL spans to use the stable rpc.* semconv attributes with an explicit schema URL.
I also adjusted the tests to reflect the schema handling, and the full botocore test suite is passing now.
Please let me know if this matches what you had in mind or if anything should be tweaked further, happy to update. Thank you :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Hey @rite7sh thanks for making these changes. Apologies, I should have been more explicit. We do not want use anything with SpanAttribute.* there are deprecated. I simply meant that we should be using constants from the semconv incubating package instead of directly providing strings wherever possible. Also, we should avoid duplicating our tracer schema version if possible, we already have it defined in _AwsSdkExtension.tracer_schema_version()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@herin049 its all good, I have updated the PR based on the review.Presigned URL spans now use stable semconv + schema handling, and I added a small follow-up commit to clean up imports/formatting after running ruff.
All botocore tests are passing locally. ping me if something feels off, Thanks for the review.

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

Labels

None yet

Projects

Status: Ready for review

Development

Successfully merging this pull request may close these issues.

Instrument botocore.signers.RequestSigner.generate_presigned_url

2 participants