Skip to content

Commit f7ec13c

Browse files
vcjanalandonxjames
andauthored
Track observability business metric (metric 7) (#4420)
## Motivation and Context Implements business metric tracking for observability providers per SEP User Agent 2.1 specification. The metric '7' (ObservabilityOtelMetrics) must be tracked when users configure OpenTelemetry metrics providers to help AWS understand observability usage patterns. ## Description This PR adds a new ObservabilityMetricDecorator that tracks the observability metric when OpenTelemetry metrics providers are configured through the global telemetry provider. ## Implementation The decorator registers an ObservabilityFeatureTrackerInterceptor that runs during request execution. It checks the global telemetry provider and uses type downcasting to detect if an OtelMeterProvider is configured: - Checks global telemetry provider via `aws_smithy_observability::global::get_telemetry_provider()` - Uses `downcast_ref::<OtelMeterProvider>()` for reliable type detection - Adds `as_any()` method to `ProvideMeter` trait to enable downcasting - Stores metric in interceptor state when OTel provider is detected When an OpenTelemetry metrics provider is configured, the metric is tracked in the User-Agent header. ## Checklist - [x] I have updated CHANGELOG.next.toml if I made changes to the smithy-rs codegen or runtime crates - [x] I have updated CHANGELOG.next.toml if I made changes to the AWS SDK, generated SDK code, or SDK runtime crates Note: This is a draft PR for review. The implementation successfully tracks OpenTelemetry metrics provider usage, which covers the SEP requirements for metric 7. --------- Co-authored-by: Landon James <[email protected]>
1 parent 4c75f22 commit f7ec13c

File tree

23 files changed

+250
-12
lines changed

23 files changed

+250
-12
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
applies_to: ["client"]
3+
authors: ["vcjana"]
4+
references: []
5+
breaking: false
6+
new_feature: false
7+
bug_fix: false
8+
---
9+
Add support for tracking observability business metrics (OBSERVABILITY_TRACING, OBSERVABILITY_OTEL_TRACING, OBSERVABILITY_OTEL_METRICS) in User-Agent headers when telemetry providers are configured.

aws/codegen-aws-sdk/src/main/kotlin/software/amazon/smithy/rustsdk/AwsCodegenDecorator.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ val DECORATORS: List<ClientCodegenDecorator> =
4646
CredentialsProviderDecorator(),
4747
RegionDecorator(),
4848
RequireEndpointRules(),
49+
ObservabilityMetricDecorator(),
4950
EndpointOverrideMetricDecorator(),
5051
UserAgentDecorator(),
5152
SigV4AuthDecorator(),
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.rustsdk
7+
8+
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
9+
import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator
10+
import software.amazon.smithy.rust.codegen.client.smithy.generators.ServiceRuntimePluginCustomization
11+
import software.amazon.smithy.rust.codegen.client.smithy.generators.ServiceRuntimePluginSection
12+
import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency
13+
import software.amazon.smithy.rust.codegen.core.rustlang.Visibility
14+
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
15+
import software.amazon.smithy.rust.codegen.core.rustlang.writable
16+
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
17+
18+
/**
19+
* Decorator that tracks observability business metrics when tracing/metrics providers are configured.
20+
*/
21+
class ObservabilityMetricDecorator : ClientCodegenDecorator {
22+
override val name: String = "ObservabilityMetric"
23+
override val order: Byte = 0
24+
25+
override fun serviceRuntimePluginCustomizations(
26+
codegenContext: ClientCodegenContext,
27+
baseCustomizations: List<ServiceRuntimePluginCustomization>,
28+
): List<ServiceRuntimePluginCustomization> =
29+
baseCustomizations + listOf(ObservabilityFeatureTrackerInterceptor(codegenContext))
30+
}
31+
32+
private class ObservabilityFeatureTrackerInterceptor(private val codegenContext: ClientCodegenContext) :
33+
ServiceRuntimePluginCustomization() {
34+
override fun section(section: ServiceRuntimePluginSection) =
35+
writable {
36+
if (section is ServiceRuntimePluginSection.RegisterRuntimeComponents) {
37+
section.registerInterceptor(this) {
38+
val runtimeConfig = codegenContext.runtimeConfig
39+
rustTemplate(
40+
"#{Interceptor}",
41+
"Interceptor" to
42+
RuntimeType.forInlineDependency(
43+
InlineAwsDependency.forRustFile(
44+
"observability_feature",
45+
Visibility.PRIVATE,
46+
CargoDependency.smithyObservability(runtimeConfig),
47+
),
48+
).resolve("ObservabilityFeatureTrackerInterceptor"),
49+
)
50+
}
51+
}
52+
}
53+
}

aws/rust-runtime/Cargo.lock

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aws/rust-runtime/aws-inlineable/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ aws-types = { path = "../aws-types" }
2323
aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async", features = ["rt-tokio"] }
2424
aws-smithy-checksums = { path = "../../../rust-runtime/aws-smithy-checksums" }
2525
aws-smithy-http = { path = "../../../rust-runtime/aws-smithy-http" }
26+
aws-smithy-observability = { path = "../../../rust-runtime/aws-smithy-observability" }
2627
aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime", features = ["client"] }
2728
aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] }
2829
aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types", features = ["http-body-0-4-x"] }

aws/rust-runtime/aws-inlineable/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
#[allow(dead_code)]
2727
pub mod account_id_endpoint;
2828

29+
/// Supporting code for tracking observability features (tracing/metrics).
30+
#[allow(dead_code)]
31+
pub mod observability_feature;
32+
2933
/// Supporting code for the aws-chunked content encoding.
3034
pub mod aws_chunked;
3135

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
use aws_smithy_runtime::client::sdk_feature::SmithySdkFeature;
7+
use aws_smithy_runtime_api::{
8+
box_error::BoxError,
9+
client::interceptors::{context::BeforeSerializationInterceptorContextRef, Intercept},
10+
};
11+
use aws_smithy_types::config_bag::ConfigBag;
12+
13+
// Interceptor that tracks Smithy SDK features for observability (tracing/metrics).
14+
#[derive(Debug, Default)]
15+
pub(crate) struct ObservabilityFeatureTrackerInterceptor;
16+
17+
impl Intercept for ObservabilityFeatureTrackerInterceptor {
18+
fn name(&self) -> &'static str {
19+
"ObservabilityFeatureTrackerInterceptor"
20+
}
21+
22+
fn read_before_execution(
23+
&self,
24+
_context: &BeforeSerializationInterceptorContextRef<'_>,
25+
cfg: &mut ConfigBag,
26+
) -> Result<(), BoxError> {
27+
// Check if an OpenTelemetry meter provider is configured via the global provider
28+
if let Ok(telemetry_provider) = aws_smithy_observability::global::get_telemetry_provider() {
29+
let meter_provider = telemetry_provider.meter_provider();
30+
31+
// Use provider_name() to detect OpenTelemetry without importing the otel crate.
32+
if meter_provider.provider_name() == "AwsSmithyObservabilityOtelProvider" {
33+
cfg.interceptor_state()
34+
.store_append(SmithySdkFeature::ObservabilityOtelMetrics);
35+
}
36+
}
37+
38+
Ok(())
39+
}
40+
}

aws/rust-runtime/aws-runtime/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aws-runtime"
3-
version = "1.5.17"
3+
version = "1.5.18"
44
authors = ["AWS Rust SDK Team <[email protected]>"]
55
description = "Runtime support code for the AWS SDK. This crate isn't intended to be used directly."
66
edition = "2021"

aws/rust-runtime/aws-runtime/src/user_agent/metrics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ impl ProvideBusinessMetric for SmithySdkFeature {
210210
FlexibleChecksumsResWhenRequired => {
211211
Some(BusinessMetric::FlexibleChecksumsResWhenRequired)
212212
}
213+
ObservabilityOtelMetrics => Some(BusinessMetric::ObservabilityOtelMetrics),
213214
otherwise => {
214215
// This may occur if a customer upgrades only the `aws-smithy-runtime-api` crate
215216
// while continuing to use an outdated version of an SDK crate or the `aws-runtime`

aws/sdk/integration-tests/telemetry/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ publish = false
1212

1313
[dev-dependencies]
1414
aws-config = { path = "../../build/aws-sdk/sdk/aws-config", features = ["test-util", "behavior-version-latest"] }
15+
aws-runtime = { path = "../../build/aws-sdk/sdk/aws-runtime", features = ["test-util"] }
1516
aws-sdk-dynamodb = { path = "../../build/aws-sdk/sdk/dynamodb", features = ["test-util", "behavior-version-latest"] }
1617
aws-sdk-s3 = { path = "../../build/aws-sdk/sdk/s3", features = ["test-util", "behavior-version-latest"] }
1718
aws-smithy-observability = { path = "../../build/aws-sdk/sdk/aws-smithy-observability" }

0 commit comments

Comments
 (0)