Skip to content

Conversation

@vcjana
Copy link
Contributor

@vcjana vcjana commented Nov 6, 2025

Motivation and Context

This PR implements business metrics tracking for observability and endpoint override features.

Description

This PR adds five new business metrics to track SDK feature usage:

Observability Metrics:

  • m/4: Observability tracing enabled
  • m/5: Observability metrics enabled
  • m/6: OpenTelemetry tracing integration
  • m/7: OpenTelemetry metrics integration

Endpoint Configuration Metrics:

  • m/N: Custom endpoint URL override detection

Testing

Integration tests added in aws/sdk/integration-tests/s3/tests/business_metrics.rs covering all seven metrics.

Checklist

  • For changes to the smithy-rs codegen or runtime crates, I have created a changelog entry Markdown file in the .changelog directory, specifying "client," "server," or both in the applies_to key.
  • For changes to the AWS SDK, generated SDK code, or SDK runtime crates, I have created a changelog entry Markdown file in the .changelog directory, specifying "aws-sdk-rust" in the applies_to key.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@vcjana vcjana force-pushed the feature-ids-implementation branch from c3c5ac1 to 21a98a3 Compare November 12, 2025 06:58
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@vcjana vcjana force-pushed the feature-ids-implementation branch from 1eb10a8 to 81ee539 Compare November 12, 2025 08:32
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@smithy-lang smithy-lang deleted a comment from github-actions bot Nov 12, 2025
@smithy-lang smithy-lang deleted a comment from github-actions bot Nov 12, 2025
@smithy-lang smithy-lang deleted a comment from github-actions bot Nov 12, 2025
@smithy-lang smithy-lang deleted a comment from github-actions bot Nov 12, 2025
Copy link
Contributor

@landonxjames landonxjames left a comment

Choose a reason for hiding this comment

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

Good start, would like to see some E2E tests ensuring that the observability and endpoint metrics actually make it in to the user-agent

}

@Test
fun `generated code includes endpoint override interceptor registration`() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This test doesn't quite test what the name suggests it does. It tests that it compiles, but it would compile just find if the EndpointOverride interceptor wasn't inserted at all. Same with the test below. I would try to write a test that actually ensures the interceptor is inserted, likely by making a request with an overridden endpoint and checking the user-agent on that request.

S3Transfer => Some(BusinessMetric::S3Transfer),
SsoLoginDevice => Some(BusinessMetric::SsoLoginDevice),
SsoLoginAuth => Some(BusinessMetric::SsoLoginAuth),
ObservabilityMetrics => Some(BusinessMetric::ObservabilityMetrics),
Copy link
Contributor

Choose a reason for hiding this comment

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

The Observability metrics should probably all be in SmithySdkFeature instead of AwsSdkFeature. Nothing about the observability interfaces is Aws specific.

cfg.interceptor_state()
.store_append(AwsSdkFeature::ObservabilityMetrics);

// PRAGMATIC APPROACH: Track tracing based on meter provider state
Copy link
Contributor

Choose a reason for hiding this comment

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

I would say we should probably just not emit this one since we don't actually support it, and it could be confusing.


// If using OpenTelemetry for metrics, likely using it for tracing too
cfg.interceptor_state()
.store_append(AwsSdkFeature::ObservabilityOtelTracing);
Copy link
Contributor

Choose a reason for hiding this comment

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

Same with this one, and this could be especially misleading since users can hook their tracing crate traces up to OTel.

}

// Note: We cannot easily test non-noop providers without creating a custom meter provider
// implementation, which would require exposing internal types. The noop test above
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this would require leaking any internal types? The OTel meter provider already exists so anything require to implement another one should already be pub. If something is missing we probably need to make it pub anyway so users can implement their own providers.

fn resolve_endpoint<'a>(&'a self, _params: &'a EndpointResolverParams) -> EndpointFuture<'a> {
EndpointFuture::ready(Ok(Endpoint::builder()
.url(self.endpoint.to_string())
.property("is_custom_endpoint", true)
Copy link
Contributor

Choose a reason for hiding this comment

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

This property name doesn't seem to be referenced anywhere else in this PR?

smithy.rs.runtime.crate.stable.version=1.1.7
# Version number to use for the generated unstable runtime crates
smithy.rs.runtime.crate.unstable.version=0.60.6
# Version number for aws-smithy-observability crate
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems unnecessary. How is it being used?

// Try to get the global telemetry provider
if let Ok(provider) = aws_smithy_observability::global::get_telemetry_provider() {
// Check if it's not a noop provider
if !provider.is_noop() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't quite enough information to know that the provider is our OTel impl. This just says it isn't the noop impl. But a user could implement the traits their self and provide a different implementation (say for the metrics crate), or we could provide another non-OTel impl in the future that would break this assumption.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the better approach here would be to use the as_any method you added to the ProvideMeter trait. Something along the lines of provider.as_any().downcast_ref::<OtelMeterProvider>() which returns an Option<&OtelMeterProvider> and then only emit the metric if it is Some(_). That would allow us to get rid of the is_otel and is_noop stuff and wouldn't break if users were using some third implementation.

Copy link
Contributor

Choose a reason for hiding this comment

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

The runtime plugin and the interceptor could probably just go in the same file to keep things together.

}

// Also load AWS SDK features from interceptor_state (where interceptors store them)
let aws_sdk_features_from_interceptor = cfg.interceptor_state().load::<AwsSdkFeature>();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the cfg.load::<AwsSdkFeature>() should capture all of the AwsSdkFeature in the cfg bag so it shouldn't be necessary to grab them from this single layer? I might be wrong about though, will have to check in the morning, but @ysaito1001 probably knows.

Copy link
Contributor

Choose a reason for hiding this comment

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

Correct, it's covered by the code above from line 144 to line 149. We can remove this newly added lines of code.

Copy link
Contributor

@ysaito1001 ysaito1001 left a comment

Choose a reason for hiding this comment

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

For the ENDPOINT_OVERRIDE feature, I'm struggling to understand the code change in this PR. That feature is tied to this service-specific endpoint URL implementation. This is how service specific endpoint is usually handled (example), but I don't see how EndpointOverrideDecorator tracks the feature accordingly?

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

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.

3 participants