AWS SDK

AWS SDK

rev. b6dc1d298ba698070286e6838abdd213fcbce093 (ignoring whitespace)

Files changed:

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/Cargo.toml

@@ -26,26 +85,93 @@
   46     46   
   47     47   
[dependencies.aws-smithy-eventstream]
   48     48   
path = "../aws-smithy-eventstream"
   49     49   
optional = true
   50     50   
version = "0.60.14"
   51     51   
   52     52   
[dependencies.aws-smithy-http]
   53     53   
path = "../aws-smithy-http"
   54     54   
version = "0.62.6"
   55     55   
          56  +
[dependencies.aws-smithy-observability]
          57  +
path = "../aws-smithy-observability"
          58  +
version = "0.1.5"
          59  +
          60  +
[dependencies.aws-smithy-observability-otel]
          61  +
path = "../aws-smithy-observability-otel"
          62  +
version = "0.1.3"
          63  +
   56     64   
[dependencies.aws-smithy-runtime]
   57     65   
path = "../aws-smithy-runtime"
   58     66   
features = ["client"]
   59     67   
version = "1.9.5"
   60     68   
   61     69   
[dependencies.aws-smithy-runtime-api]
   62     70   
path = "../aws-smithy-runtime-api"
   63     71   
features = ["client"]
   64     72   
version = "1.9.3"
   65     73   

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/endpoint_override.rs

@@ -0,1 +0,159 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Endpoint override detection for business metrics tracking
           7  +
           8  +
use aws_smithy_runtime_api::box_error::BoxError;
           9  +
use aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextRef;
          10  +
use aws_smithy_runtime_api::client::interceptors::Intercept;
          11  +
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
          12  +
use aws_smithy_runtime_api::client::runtime_plugin::RuntimePlugin;
          13  +
use aws_smithy_types::config_bag::{ConfigBag, FrozenLayer, Layer};
          14  +
          15  +
use crate::sdk_feature::AwsSdkFeature;
          16  +
          17  +
/// Interceptor that detects custom endpoint URLs for business metrics
          18  +
///
          19  +
/// This interceptor checks at runtime if a `StaticUriEndpointResolver` is configured,
          20  +
/// which indicates that `.endpoint_url()` was called. When detected, it stores the
          21  +
/// `AwsSdkFeature::EndpointOverride` feature flag for business metrics tracking.
          22  +
#[derive(Debug, Default)]
          23  +
#[non_exhaustive]
          24  +
pub struct EndpointOverrideInterceptor;
          25  +
          26  +
impl EndpointOverrideInterceptor {
          27  +
    /// Creates a new EndpointOverrideInterceptor
          28  +
    pub fn new() -> Self {
          29  +
        Self
          30  +
    }
          31  +
}
          32  +
          33  +
impl Intercept for EndpointOverrideInterceptor {
          34  +
    fn name(&self) -> &'static str {
          35  +
        "EndpointOverrideInterceptor"
          36  +
    }
          37  +
          38  +
    fn read_after_serialization(
          39  +
        &self,
          40  +
        _context: &BeforeTransmitInterceptorContextRef<'_>,
          41  +
        runtime_components: &RuntimeComponents,
          42  +
        cfg: &mut ConfigBag,
          43  +
    ) -> Result<(), BoxError> {
          44  +
        // Check if the endpoint resolver is a StaticUriEndpointResolver
          45  +
        // This indicates that .endpoint_url() was called
          46  +
        let resolver = runtime_components.endpoint_resolver();
          47  +
          48  +
        // Check the resolver's debug string to see if it's StaticUriEndpointResolver
          49  +
        let debug_str = format!("{resolver:?}");
          50  +
          51  +
        if debug_str.contains("StaticUriEndpointResolver") {
          52  +
            // Store in interceptor_state
          53  +
            cfg.interceptor_state()
          54  +
                .store_append(AwsSdkFeature::EndpointOverride);
          55  +
        }
          56  +
          57  +
        Ok(())
          58  +
    }
          59  +
}
          60  +
          61  +
/// Runtime plugin that detects when a custom endpoint URL has been configured
          62  +
/// and tracks it for business metrics.
          63  +
///
          64  +
/// This plugin is created by the codegen decorator when a user explicitly
          65  +
/// sets an endpoint URL via `.endpoint_url()`. It stores the
          66  +
/// `AwsSdkFeature::EndpointOverride` feature flag in the ConfigBag for
          67  +
/// business metrics tracking.
          68  +
#[derive(Debug, Default)]
          69  +
#[non_exhaustive]
          70  +
pub struct EndpointOverrideRuntimePlugin {
          71  +
    config: Option<FrozenLayer>,
          72  +
}
          73  +
          74  +
impl EndpointOverrideRuntimePlugin {
          75  +
    /// Creates a new `EndpointOverrideRuntimePlugin` with the given config layer
          76  +
    pub fn new(config: Option<FrozenLayer>) -> Self {
          77  +
        Self { config }
          78  +
    }
          79  +
          80  +
    /// Creates a new `EndpointOverrideRuntimePlugin` and marks that endpoint override is enabled
          81  +
    pub fn new_with_feature_flag() -> Self {
          82  +
        let mut layer = Layer::new("endpoint_override");
          83  +
        layer.store_append(AwsSdkFeature::EndpointOverride);
          84  +
        Self {
          85  +
            config: Some(layer.freeze()),
          86  +
        }
          87  +
    }
          88  +
}
          89  +
          90  +
impl RuntimePlugin for EndpointOverrideRuntimePlugin {
          91  +
    fn config(&self) -> Option<FrozenLayer> {
          92  +
        self.config.clone()
          93  +
    }
          94  +
}
          95  +
          96  +
#[cfg(test)]
          97  +
mod tests {
          98  +
    use super::*;
          99  +
    use crate::sdk_feature::AwsSdkFeature;
         100  +
         101  +
    #[test]
         102  +
    fn test_plugin_with_no_config() {
         103  +
        let plugin = EndpointOverrideRuntimePlugin::default();
         104  +
        assert!(plugin.config().is_none());
         105  +
    }
         106  +
         107  +
    #[test]
         108  +
    fn test_plugin_with_feature_flag() {
         109  +
        let plugin = EndpointOverrideRuntimePlugin::new_with_feature_flag();
         110  +
        let config = plugin.config().expect("config should be set");
         111  +
         112  +
        // Verify the feature flag is present in the config
         113  +
        let features: Vec<_> = config.load::<AwsSdkFeature>().cloned().collect();
         114  +
        assert_eq!(features.len(), 1);
         115  +
        assert_eq!(features[0], AwsSdkFeature::EndpointOverride);
         116  +
    }
         117  +
         118  +
    #[test]
         119  +
    fn test_interceptor_detects_static_uri_resolver() {
         120  +
        use aws_smithy_runtime::client::orchestrator::endpoints::StaticUriEndpointResolver;
         121  +
        use aws_smithy_runtime_api::client::endpoint::SharedEndpointResolver;
         122  +
        use aws_smithy_runtime_api::client::interceptors::context::{Input, InterceptorContext};
         123  +
        use aws_smithy_runtime_api::client::orchestrator::HttpRequest;
         124  +
        use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder;
         125  +
        use aws_smithy_types::config_bag::ConfigBag;
         126  +
         127  +
        // Create a StaticUriEndpointResolver
         128  +
        let endpoint_resolver = SharedEndpointResolver::new(StaticUriEndpointResolver::uri(
         129  +
            "https://custom.example.com",
         130  +
        ));
         131  +
         132  +
        let mut context = InterceptorContext::new(Input::doesnt_matter());
         133  +
        context.enter_serialization_phase();
         134  +
        context.set_request(HttpRequest::empty());
         135  +
        let _ = context.take_input();
         136  +
        context.enter_before_transmit_phase();
         137  +
         138  +
        let rc = RuntimeComponentsBuilder::for_tests()
         139  +
            .with_endpoint_resolver(Some(endpoint_resolver))
         140  +
            .build()
         141  +
            .unwrap();
         142  +
        let mut cfg = ConfigBag::base();
         143  +
         144  +
        let interceptor = EndpointOverrideInterceptor::new();
         145  +
        let ctx = Into::into(&context);
         146  +
        interceptor
         147  +
            .read_after_serialization(&ctx, &rc, &mut cfg)
         148  +
            .unwrap();
         149  +
         150  +
        // Verify the feature flag was set
         151  +
        let features: Vec<_> = cfg
         152  +
            .interceptor_state()
         153  +
            .load::<AwsSdkFeature>()
         154  +
            .cloned()
         155  +
            .collect();
         156  +
        assert_eq!(features.len(), 1, "Expected 1 feature, got: {:?}", features);
         157  +
        assert_eq!(features[0], AwsSdkFeature::EndpointOverride);
         158  +
    }
         159  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/lib.rs

@@ -1,1 +53,59 @@
   19     19   
/// Supporting code for authentication in the AWS SDK.
   20     20   
pub mod auth;
   21     21   
   22     22   
/// AWS-specific content-encoding tools
   23     23   
#[cfg(feature = "http-02x")]
   24     24   
pub mod content_encoding;
   25     25   
   26     26   
/// Supporting code for recursion detection in the AWS SDK.
   27     27   
pub mod recursion_detection;
   28     28   
          29  +
/// Supporting code for endpoint override detection in the AWS SDK.
          30  +
pub mod endpoint_override;
          31  +
          32  +
/// Supporting code for observability feature detection in the AWS SDK.
          33  +
pub mod observability_detection;
          34  +
   29     35   
/// Supporting code for user agent headers in the AWS SDK.
   30     36   
pub mod user_agent;
   31     37   
   32     38   
/// Supporting code for retry behavior specific to the AWS SDK.
   33     39   
pub mod retries;
   34     40   
   35     41   
/// Supporting code for invocation ID headers in the AWS SDK.
   36     42   
pub mod invocation_id;
   37     43   
   38     44   
/// Supporting code for request metadata headers in the AWS SDK.

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/observability_detection.rs

@@ -0,1 +0,177 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Observability feature detection for business metrics tracking
           7  +
//!
           8  +
//! This module provides an interceptor for detecting observability features in the AWS SDK:
           9  +
//!
          10  +
//! - [`crate::observability_detection::ObservabilityDetectionInterceptor`]: Detects observability features during
          11  +
//!   request processing and tracks them for business metrics in the User-Agent header.
          12  +
          13  +
use aws_smithy_observability_otel::meter::OtelMeterProvider;
          14  +
use aws_smithy_runtime::client::sdk_feature::SmithySdkFeature;
          15  +
use aws_smithy_runtime_api::box_error::BoxError;
          16  +
use aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextRef;
          17  +
use aws_smithy_runtime_api::client::interceptors::Intercept;
          18  +
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
          19  +
use aws_smithy_types::config_bag::ConfigBag;
          20  +
          21  +
/// Interceptor that detects when observability features are being used
          22  +
/// and tracks them for business metrics.
          23  +
#[derive(Debug, Default)]
          24  +
#[non_exhaustive]
          25  +
pub struct ObservabilityDetectionInterceptor;
          26  +
          27  +
impl ObservabilityDetectionInterceptor {
          28  +
    /// Creates a new `ObservabilityDetectionInterceptor`
          29  +
    pub fn new() -> Self {
          30  +
        Self
          31  +
    }
          32  +
}
          33  +
          34  +
impl Intercept for ObservabilityDetectionInterceptor {
          35  +
    fn name(&self) -> &'static str {
          36  +
        "ObservabilityDetectionInterceptor"
          37  +
    }
          38  +
          39  +
    fn read_before_signing(
          40  +
        &self,
          41  +
        _context: &BeforeTransmitInterceptorContextRef<'_>,
          42  +
        _runtime_components: &RuntimeComponents,
          43  +
        cfg: &mut ConfigBag,
          44  +
    ) -> Result<(), BoxError> {
          45  +
        // Try to get the global telemetry provider
          46  +
        if let Ok(provider) = aws_smithy_observability::global::get_telemetry_provider() {
          47  +
            // Use type-safe downcasting to detect OpenTelemetry meter provider
          48  +
            // This works with any ProvideMeter implementation and doesn't require
          49  +
            // implementation-specific boolean flags
          50  +
            if provider
          51  +
                .meter_provider()
          52  +
                .as_any()
          53  +
                .downcast_ref::<OtelMeterProvider>()
          54  +
                .is_some()
          55  +
            {
          56  +
                // Track that observability metrics are enabled
          57  +
                cfg.interceptor_state()
          58  +
                    .store_append(SmithySdkFeature::ObservabilityMetrics);
          59  +
            }
          60  +
        }
          61  +
          62  +
        Ok(())
          63  +
    }
          64  +
}
          65  +
          66  +
#[cfg(test)]
          67  +
mod tests {
          68  +
    use super::*;
          69  +
    use crate::sdk_feature::AwsSdkFeature;
          70  +
    use aws_smithy_observability::TelemetryProvider;
          71  +
    use aws_smithy_runtime_api::client::interceptors::context::{Input, InterceptorContext};
          72  +
    use aws_smithy_runtime_api::client::orchestrator::HttpRequest;
          73  +
    use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder;
          74  +
    use aws_smithy_types::config_bag::ConfigBag;
          75  +
          76  +
    #[test]
          77  +
    fn test_detects_noop_provider() {
          78  +
        let mut context = InterceptorContext::new(Input::doesnt_matter());
          79  +
        context.enter_serialization_phase();
          80  +
        context.set_request(HttpRequest::empty());
          81  +
        let _ = context.take_input();
          82  +
        context.enter_before_transmit_phase();
          83  +
          84  +
        let rc = RuntimeComponentsBuilder::for_tests().build().unwrap();
          85  +
        let mut cfg = ConfigBag::base();
          86  +
          87  +
        // Set a noop provider (ignore error if already set by another test)
          88  +
        let _ = aws_smithy_observability::global::set_telemetry_provider(TelemetryProvider::noop());
          89  +
          90  +
        let interceptor = ObservabilityDetectionInterceptor::new();
          91  +
        let ctx = Into::into(&context);
          92  +
        interceptor
          93  +
            .read_before_signing(&ctx, &rc, &mut cfg)
          94  +
            .unwrap();
          95  +
          96  +
        // Should not track any features for noop provider since it doesn't downcast to OtelMeterProvider
          97  +
        let smithy_features: Vec<_> = cfg.load::<SmithySdkFeature>().collect();
          98  +
        assert_eq!(smithy_features.len(), 0);
          99  +
         100  +
        let aws_features: Vec<_> = cfg.load::<AwsSdkFeature>().collect();
         101  +
        assert_eq!(aws_features.len(), 0);
         102  +
    }
         103  +
         104  +
    #[test]
         105  +
    fn test_custom_provider_not_detected_as_otel() {
         106  +
        use aws_smithy_observability::meter::{Meter, ProvideMeter};
         107  +
        use aws_smithy_observability::noop::NoopMeterProvider;
         108  +
        use aws_smithy_observability::Attributes;
         109  +
        use std::sync::Arc;
         110  +
         111  +
        // Create a custom (non-OTel, non-noop) meter provider
         112  +
        // This simulates a user implementing their own metrics provider
         113  +
        #[derive(Debug)]
         114  +
        struct CustomMeterProvider {
         115  +
            inner: NoopMeterProvider,
         116  +
        }
         117  +
         118  +
        impl ProvideMeter for CustomMeterProvider {
         119  +
            fn get_meter(&self, scope: &'static str, attributes: Option<&Attributes>) -> Meter {
         120  +
                // Delegate to noop for simplicity, but this is a distinct type
         121  +
                self.inner.get_meter(scope, attributes)
         122  +
            }
         123  +
         124  +
            fn as_any(&self) -> &dyn std::any::Any {
         125  +
                self
         126  +
            }
         127  +
        }
         128  +
         129  +
        let mut context = InterceptorContext::new(Input::doesnt_matter());
         130  +
        context.enter_serialization_phase();
         131  +
        context.set_request(HttpRequest::empty());
         132  +
        let _ = context.take_input();
         133  +
        context.enter_before_transmit_phase();
         134  +
         135  +
        let rc = RuntimeComponentsBuilder::for_tests().build().unwrap();
         136  +
        let mut cfg = ConfigBag::base();
         137  +
         138  +
        // Set the custom provider
         139  +
        let custom_provider = Arc::new(CustomMeterProvider {
         140  +
            inner: NoopMeterProvider,
         141  +
        });
         142  +
        let telemetry_provider = TelemetryProvider::builder()
         143  +
            .meter_provider(custom_provider)
         144  +
            .build();
         145  +
        let _ = aws_smithy_observability::global::set_telemetry_provider(telemetry_provider);
         146  +
         147  +
        let interceptor = ObservabilityDetectionInterceptor::new();
         148  +
        let ctx = Into::into(&context);
         149  +
        interceptor
         150  +
            .read_before_signing(&ctx, &rc, &mut cfg)
         151  +
            .unwrap();
         152  +
         153  +
        // Should NOT track any features for custom provider since it doesn't downcast to OtelMeterProvider
         154  +
        // The new implementation only emits metrics when OTel is detected
         155  +
        let smithy_features: Vec<_> = cfg
         156  +
            .interceptor_state()
         157  +
            .load::<SmithySdkFeature>()
         158  +
            .cloned()
         159  +
            .collect();
         160  +
        assert!(
         161  +
            !smithy_features.iter().any(|f| *f == SmithySdkFeature::ObservabilityMetrics),
         162  +
            "Should not detect custom provider as having observability metrics (only OTel is tracked)"
         163  +
        );
         164  +
         165  +
        // Verify no AWS-specific features are tracked for custom provider
         166  +
        let aws_features: Vec<_> = cfg
         167  +
            .interceptor_state()
         168  +
            .load::<AwsSdkFeature>()
         169  +
            .cloned()
         170  +
            .collect();
         171  +
        assert_eq!(
         172  +
            aws_features.len(),
         173  +
            0,
         174  +
            "Should not track any AWS-specific features for custom provider"
         175  +
        );
         176  +
    }
         177  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/sdk_feature.rs

@@ -1,1 +31,33 @@
   17     17   
    /// An operation called with account ID mode set to disabled
   18     18   
    AccountIdModeDisabled,
   19     19   
    /// An operation called with account ID mode set to required
   20     20   
    AccountIdModeRequired,
   21     21   
    /// Indicates that an operation was called by the S3 Transfer Manager
   22     22   
    S3Transfer,
   23     23   
    /// Calling an SSO-OIDC operation as part of the SSO login flow, when using the OAuth2.0 device code grant
   24     24   
    SsoLoginDevice,
   25     25   
    /// Calling an SSO-OIDC operation as part of the SSO login flow, when using the OAuth2.0 authorization code grant
   26     26   
    SsoLoginAuth,
          27  +
    /// An operation called using a user provided endpoint URL
          28  +
    EndpointOverride,
   27     29   
}
   28     30   
   29     31   
impl Storable for AwsSdkFeature {
   30     32   
    type Storer = StoreAppend<Self>;
   31     33   
}

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/user_agent/interceptor.rs

@@ -410,410 +440,473 @@
  430    430   
  431    431   
        let header = expect_header(&context, "user-agent");
  432    432   
        assert_eq!(AwsUserAgent::for_tests().ua_header(), header);
  433    433   
        assert!(!header.contains("unused"));
  434    434   
  435    435   
        assert_eq!(
  436    436   
            AwsUserAgent::for_tests().aws_ua_header(),
  437    437   
            expect_header(&context, "x-amz-user-agent")
  438    438   
        );
  439    439   
    }
         440  +
         441  +
    #[test]
         442  +
    fn test_cfg_load_captures_all_feature_layers() {
         443  +
        use crate::sdk_feature::AwsSdkFeature;
         444  +
         445  +
        // Create a ConfigBag with features in both base layer and interceptor_state
         446  +
        let mut base_layer = Layer::new("base");
         447  +
        base_layer.store_append(AwsSdkFeature::EndpointOverride);
         448  +
         449  +
        let mut config = ConfigBag::of_layers(vec![base_layer]);
         450  +
         451  +
        // Store a feature in interceptor_state (simulating what interceptors do)
         452  +
        config
         453  +
            .interceptor_state()
         454  +
            .store_append(AwsSdkFeature::SsoLoginDevice);
         455  +
         456  +
        // Verify that cfg.load() captures features from all layers
         457  +
        let all_features: Vec<&AwsSdkFeature> = config.load::<AwsSdkFeature>().collect();
         458  +
         459  +
        assert_eq!(
         460  +
            all_features.len(),
         461  +
            2,
         462  +
            "cfg.load() should capture features from all layers"
         463  +
        );
         464  +
        assert!(
         465  +
            all_features.contains(&&AwsSdkFeature::EndpointOverride),
         466  +
            "should contain feature from base layer"
         467  +
        );
         468  +
        assert!(
         469  +
            all_features.contains(&&AwsSdkFeature::SsoLoginDevice),
         470  +
            "should contain feature from interceptor_state"
         471  +
        );
         472  +
    }
  440    473   
}

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/user_agent/metrics.rs

@@ -183,183 +266,268 @@
  203    203   
            }
  204    204   
            FlexibleChecksumsReqWhenRequired => {
  205    205   
                Some(BusinessMetric::FlexibleChecksumsReqWhenRequired)
  206    206   
            }
  207    207   
            FlexibleChecksumsResWhenSupported => {
  208    208   
                Some(BusinessMetric::FlexibleChecksumsResWhenSupported)
  209    209   
            }
  210    210   
            FlexibleChecksumsResWhenRequired => {
  211    211   
                Some(BusinessMetric::FlexibleChecksumsResWhenRequired)
  212    212   
            }
         213  +
            ObservabilityMetrics => Some(BusinessMetric::ObservabilityMetrics),
  213    214   
            otherwise => {
  214    215   
                // This may occur if a customer upgrades only the `aws-smithy-runtime-api` crate
  215    216   
                // while continuing to use an outdated version of an SDK crate or the `aws-runtime`
  216    217   
                // crate.
  217    218   
                tracing::warn!(
  218    219   
                    "Attempted to provide `BusinessMetric` for `{otherwise:?}`, which is not recognized in the current version of the `aws-runtime` crate. \
  219    220   
                    Consider upgrading to the latest version to ensure that all tracked features are properly reported in your metrics."
  220    221   
                );
  221    222   
                None
  222    223   
            }
  223    224   
        }
  224    225   
    }
  225    226   
}
  226    227   
  227    228   
impl ProvideBusinessMetric for AwsSdkFeature {
  228    229   
    fn provide_business_metric(&self) -> Option<BusinessMetric> {
  229    230   
        use AwsSdkFeature::*;
  230    231   
        match self {
  231    232   
            AccountIdModePreferred => Some(BusinessMetric::AccountIdModePreferred),
  232    233   
            AccountIdModeDisabled => Some(BusinessMetric::AccountIdModeDisabled),
  233    234   
            AccountIdModeRequired => Some(BusinessMetric::AccountIdModeRequired),
  234    235   
            S3Transfer => Some(BusinessMetric::S3Transfer),
  235    236   
            SsoLoginDevice => Some(BusinessMetric::SsoLoginDevice),
  236    237   
            SsoLoginAuth => Some(BusinessMetric::SsoLoginAuth),
         238  +
            EndpointOverride => Some(BusinessMetric::EndpointOverride),
  237    239   
        }
  238    240   
    }
  239    241   
}
  240    242   
  241    243   
impl ProvideBusinessMetric for AwsCredentialFeature {
  242    244   
    fn provide_business_metric(&self) -> Option<BusinessMetric> {
  243    245   
        use AwsCredentialFeature::*;
  244    246   
        match self {
  245    247   
            ResolvedAccountId => Some(BusinessMetric::ResolvedAccountId),
  246    248   
            CredentialsCode => Some(BusinessMetric::CredentialsCode),
@@ -387,389 +417,494 @@
  407    409   
  408    410   
        let csv = "A10BCE";
  409    411   
        assert_eq!("A10BC", drop_unfinished_metrics_to_fit(csv, 5));
  410    412   
  411    413   
        let csv = "A";
  412    414   
        assert_eq!("A", drop_unfinished_metrics_to_fit(csv, 5));
  413    415   
  414    416   
        let csv = "A,B";
  415    417   
        assert_eq!("A,B", drop_unfinished_metrics_to_fit(csv, 5));
  416    418   
    }
         419  +
         420  +
    #[test]
         421  +
    fn test_aws_sdk_feature_mappings() {
         422  +
        use crate::sdk_feature::AwsSdkFeature;
         423  +
        use crate::user_agent::metrics::ProvideBusinessMetric;
         424  +
         425  +
        // Test SsoLoginDevice mapping
         426  +
        assert_eq!(
         427  +
            AwsSdkFeature::SsoLoginDevice.provide_business_metric(),
         428  +
            Some(BusinessMetric::SsoLoginDevice)
         429  +
        );
         430  +
         431  +
        // Test SsoLoginAuth mapping
         432  +
        assert_eq!(
         433  +
            AwsSdkFeature::SsoLoginAuth.provide_business_metric(),
         434  +
            Some(BusinessMetric::SsoLoginAuth)
         435  +
        );
         436  +
         437  +
        // Test EndpointOverride mapping
         438  +
        assert_eq!(
         439  +
            AwsSdkFeature::EndpointOverride.provide_business_metric(),
         440  +
            Some(BusinessMetric::EndpointOverride)
         441  +
        );
         442  +
    }
         443  +
         444  +
    #[test]
         445  +
    fn test_smithy_sdk_feature_observability_mappings() {
         446  +
        use crate::user_agent::metrics::ProvideBusinessMetric;
         447  +
        use aws_smithy_runtime::client::sdk_feature::SmithySdkFeature;
         448  +
         449  +
        // Test ObservabilityMetrics mapping
         450  +
        assert_eq!(
         451  +
            SmithySdkFeature::ObservabilityMetrics.provide_business_metric(),
         452  +
            Some(BusinessMetric::ObservabilityMetrics)
         453  +
        );
         454  +
    }
         455  +
         456  +
    #[test]
         457  +
    fn test_metric_id_values() {
         458  +
        // Test that metric IDs match the expected values from FEATURES.md specification
         459  +
         460  +
        // SSO Login metrics
         461  +
        assert_eq!(
         462  +
            FEATURE_ID_TO_METRIC_VALUE.get(&BusinessMetric::SsoLoginDevice),
         463  +
            Some(&"1".into())
         464  +
        );
         465  +
        assert_eq!(
         466  +
            FEATURE_ID_TO_METRIC_VALUE.get(&BusinessMetric::SsoLoginAuth),
         467  +
            Some(&"2".into())
         468  +
        );
         469  +
         470  +
        // Observability metrics
         471  +
        assert_eq!(
         472  +
            FEATURE_ID_TO_METRIC_VALUE.get(&BusinessMetric::ObservabilityTracing),
         473  +
            Some(&"4".into())
         474  +
        );
         475  +
        assert_eq!(
         476  +
            FEATURE_ID_TO_METRIC_VALUE.get(&BusinessMetric::ObservabilityMetrics),
         477  +
            Some(&"5".into())
         478  +
        );
         479  +
        assert_eq!(
         480  +
            FEATURE_ID_TO_METRIC_VALUE.get(&BusinessMetric::ObservabilityOtelTracing),
         481  +
            Some(&"6".into())
         482  +
        );
         483  +
        assert_eq!(
         484  +
            FEATURE_ID_TO_METRIC_VALUE.get(&BusinessMetric::ObservabilityOtelMetrics),
         485  +
            Some(&"7".into())
         486  +
        );
         487  +
         488  +
        // Endpoint Override metric
         489  +
        assert_eq!(
         490  +
            FEATURE_ID_TO_METRIC_VALUE.get(&BusinessMetric::EndpointOverride),
         491  +
            Some(&"N".into())
         492  +
        );
         493  +
    }
  417    494   
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability-otel/src/meter.rs

@@ -259,259 +318,322 @@
  279    279   
            Ok(_) => Ok(()),
  280    280   
            Err(err) => Err(ObservabilityError::new(ErrorKind::Other, err)),
  281    281   
        }
  282    282   
    }
  283    283   
}
  284    284   
  285    285   
impl ProvideMeter for OtelMeterProvider {
  286    286   
    fn get_meter(&self, scope: &'static str, _attributes: Option<&Attributes>) -> Meter {
  287    287   
        Meter::new(Arc::new(MeterWrap(self.meter_provider.meter(scope))))
  288    288   
    }
         289  +
         290  +
    fn as_any(&self) -> &dyn std::any::Any {
         291  +
        self
         292  +
    }
  289    293   
}
  290    294   
  291    295   
#[cfg(test)]
  292    296   
mod tests {
  293    297   
  294    298   
    use std::sync::Arc;
  295    299   
  296    300   
    use aws_smithy_observability::instruments::AsyncMeasure;
  297    301   
    use aws_smithy_observability::{AttributeValue, Attributes, TelemetryProvider};
  298    302   
    use opentelemetry_sdk::metrics::{

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability/src/lib.rs

@@ -1,1 +31,32 @@
   18     18   
// libraries update this with detailed usage docs and examples
   19     19   
   20     20   
mod attributes;
   21     21   
pub use attributes::{AttributeValue, Attributes};
   22     22   
mod context;
   23     23   
pub use context::{Context, ContextManager, Scope};
   24     24   
mod error;
   25     25   
pub use error::{ErrorKind, GlobalTelemetryProviderError, ObservabilityError};
   26     26   
pub mod global;
   27     27   
pub mod meter;
   28         -
mod noop;
          28  +
#[doc(hidden)]
          29  +
pub mod noop;
   29     30   
mod provider;
   30     31   
pub use provider::{TelemetryProvider, TelemetryProviderBuilder};
   31     32   
pub mod instruments;

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability/src/meter.rs

@@ -1,1 +49,78 @@
    7      7   
//! real time.
    8      8   
    9      9   
use crate::instruments::{
   10     10   
    AsyncInstrumentBuilder, AsyncMeasure, Histogram, InstrumentBuilder, MonotonicCounter,
   11     11   
    UpDownCounter,
   12     12   
};
   13     13   
use crate::{attributes::Attributes, instruments::ProvideInstrument};
   14     14   
use std::{borrow::Cow, fmt::Debug, sync::Arc};
   15     15   
   16     16   
/// Provides named instances of [Meter].
   17         -
pub trait ProvideMeter: Send + Sync + Debug {
          17  +
pub trait ProvideMeter: Send + Sync + Debug + 'static {
   18     18   
    /// Get or create a named [Meter].
   19     19   
    fn get_meter(&self, scope: &'static str, attributes: Option<&Attributes>) -> Meter;
          20  +
          21  +
    /// Downcast to `Any` for type inspection.
          22  +
    ///
          23  +
    /// This method enables runtime type checking via downcasting to concrete types.
          24  +
    ///
          25  +
    /// Implementations must return `self` to enable proper downcasting:
          26  +
    ///
          27  +
    /// ```ignore
          28  +
    /// impl ProvideMeter for MyProvider {
          29  +
    ///     fn as_any(&self) -> &dyn std::any::Any {
          30  +
    ///         self
          31  +
    ///     }
          32  +
    /// }
          33  +
    /// ```
          34  +
    ///
          35  +
    /// # Example Usage
          36  +
    ///
          37  +
    /// ```ignore
          38  +
    /// use aws_smithy_observability::meter::ProvideMeter;
          39  +
    /// use aws_smithy_observability_otel::meter::OtelMeterProvider;
          40  +
    ///
          41  +
    /// fn check_provider_type(provider: &dyn ProvideMeter) {
          42  +
    ///     // Downcast to check if this is an OpenTelemetry provider
          43  +
    ///     if provider.as_any().downcast_ref::<OtelMeterProvider>().is_some() {
          44  +
    ///         println!("This is an OpenTelemetry provider");
          45  +
    ///     }
          46  +
    /// }
          47  +
    /// ```
          48  +
    fn as_any(&self) -> &dyn std::any::Any;
   20     49   
}
   21     50   
   22     51   
/// The entry point to creating instruments. A grouping of related metrics.
   23     52   
#[derive(Clone)]
   24     53   
pub struct Meter {
   25     54   
    pub(crate) instrument_provider: Arc<dyn ProvideInstrument + Send + Sync>,
   26     55   
}
   27     56   
   28     57   
impl Meter {
   29     58   
    /// Create a new [Meter] from an [ProvideInstrument]
@@ -69,98 +0,204 @@
   89    118   
    }
   90    119   
   91    120   
    /// Create a new [Histogram].
   92    121   
    pub fn create_histogram(
   93    122   
        &self,
   94    123   
        name: impl Into<Cow<'static, str>>,
   95    124   
    ) -> InstrumentBuilder<'_, Arc<dyn Histogram>> {
   96    125   
        InstrumentBuilder::new(self, name.into())
   97    126   
    }
   98    127   
}
         128  +
         129  +
#[cfg(test)]
         130  +
mod tests {
         131  +
    use super::*;
         132  +
    use crate::noop::NoopMeterProvider;
         133  +
         134  +
    #[test]
         135  +
    fn test_as_any_downcasting_works() {
         136  +
        // Create a noop provider
         137  +
        let provider = NoopMeterProvider;
         138  +
         139  +
        // Convert to trait object
         140  +
        let provider_dyn: &dyn ProvideMeter = &provider;
         141  +
         142  +
        // Test that downcasting works when as_any() is properly implemented
         143  +
        let downcast_result = provider_dyn.as_any().downcast_ref::<NoopMeterProvider>();
         144  +
        assert!(
         145  +
            downcast_result.is_some(),
         146  +
            "Downcasting should succeed when as_any() returns self"
         147  +
        );
         148  +
    }
         149  +
         150  +
    /// Custom meter provider for testing extensibility.
         151  +
    ///
         152  +
    /// This demonstrates that users can create their own meter provider implementations
         153  +
    /// and that all required types are publicly accessible.
         154  +
    #[derive(Debug)]
         155  +
    struct CustomMeterProvider;
         156  +
         157  +
    impl ProvideMeter for CustomMeterProvider {
         158  +
        fn get_meter(&self, _scope: &'static str, _attributes: Option<&Attributes>) -> Meter {
         159  +
            // Create a meter using NoopMeterProvider's implementation
         160  +
            // This demonstrates that users can compose their own providers
         161  +
            let noop_provider = NoopMeterProvider;
         162  +
            noop_provider.get_meter(_scope, _attributes)
         163  +
        }
         164  +
         165  +
        fn as_any(&self) -> &dyn std::any::Any {
         166  +
            self
         167  +
        }
         168  +
    }
         169  +
         170  +
    #[test]
         171  +
    fn test_custom_provider_extensibility() {
         172  +
        // Create a custom provider
         173  +
        let custom = CustomMeterProvider;
         174  +
        let provider_ref: &dyn ProvideMeter = &custom;
         175  +
         176  +
        // Verify custom provider doesn't downcast to NoopMeterProvider
         177  +
        assert!(
         178  +
            provider_ref
         179  +
                .as_any()
         180  +
                .downcast_ref::<NoopMeterProvider>()
         181  +
                .is_none(),
         182  +
            "Custom provider should not downcast to NoopMeterProvider"
         183  +
        );
         184  +
         185  +
        // Verify custom provider downcasts to its own type
         186  +
        assert!(
         187  +
            provider_ref
         188  +
                .as_any()
         189  +
                .downcast_ref::<CustomMeterProvider>()
         190  +
                .is_some(),
         191  +
            "Custom provider should downcast to CustomMeterProvider"
         192  +
        );
         193  +
         194  +
        // Verify the provider can create meters (demonstrates all required types are accessible)
         195  +
        let meter = custom.get_meter("test_scope", None);
         196  +
         197  +
        // Verify we can create instruments from the meter
         198  +
        let _counter = meter.create_monotonic_counter("test_counter").build();
         199  +
        let _histogram = meter.create_histogram("test_histogram").build();
         200  +
        let _up_down = meter.create_up_down_counter("test_up_down").build();
         201  +
         202  +
        // If we got here, all required types are publicly accessible
         203  +
    }
         204  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-observability/src/noop.rs

@@ -1,1 +56,63 @@
   11     11   
use crate::instruments::{
   12     12   
    AsyncInstrumentBuilder, AsyncMeasure, Histogram, InstrumentBuilder, MonotonicCounter,
   13     13   
    ProvideInstrument, UpDownCounter,
   14     14   
};
   15     15   
use crate::{
   16     16   
    attributes::Attributes,
   17     17   
    context::Context,
   18     18   
    meter::{Meter, ProvideMeter},
   19     19   
};
   20     20   
          21  +
/// A no-op implementation of [`ProvideMeter`] that creates no-op meters.
          22  +
///
          23  +
/// This provider is useful for testing or when observability is disabled.
   21     24   
#[derive(Debug)]
   22         -
pub(crate) struct NoopMeterProvider;
          25  +
pub struct NoopMeterProvider;
   23     26   
impl ProvideMeter for NoopMeterProvider {
   24     27   
    fn get_meter(&self, _scope: &'static str, _attributes: Option<&Attributes>) -> Meter {
   25     28   
        Meter::new(Arc::new(NoopMeter))
   26     29   
    }
          30  +
          31  +
    fn as_any(&self) -> &dyn std::any::Any {
          32  +
        self
          33  +
    }
   27     34   
}
   28     35   
   29     36   
#[derive(Debug)]
   30     37   
pub(crate) struct NoopMeter;
   31     38   
impl ProvideInstrument for NoopMeter {
   32     39   
    fn create_gauge(
   33     40   
        &self,
   34     41   
        _builder: AsyncInstrumentBuilder<'_, Arc<dyn AsyncMeasure<Value = f64>>, f64>,
   35     42   
    ) -> Arc<dyn AsyncMeasure<Value = f64>> {
   36     43   
        Arc::new(NoopAsyncMeasurement(PhantomData::<f64>))

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/sdk_feature.rs

@@ -1,1 +30,31 @@
   16     16   
    RetryModeAdaptive,
   17     17   
    FlexibleChecksumsReqCrc32,
   18     18   
    FlexibleChecksumsReqCrc32c,
   19     19   
    FlexibleChecksumsReqCrc64,
   20     20   
    FlexibleChecksumsReqSha1,
   21     21   
    FlexibleChecksumsReqSha256,
   22     22   
    FlexibleChecksumsReqWhenSupported,
   23     23   
    FlexibleChecksumsReqWhenRequired,
   24     24   
    FlexibleChecksumsResWhenSupported,
   25     25   
    FlexibleChecksumsResWhenRequired,
          26  +
    ObservabilityMetrics,
   26     27   
}
   27     28   
   28     29   
impl Storable for SmithySdkFeature {
   29     30   
    type Storer = StoreAppend<Self>;
   30     31   
}

tmp-codegen-diff/aws-sdk/sdk/bedrockruntime/src/config.rs

@@ -1340,1340 +1399,1400 @@
 1360   1360   
            use crate::config::endpoint::ResolveEndpoint;
 1361   1361   
            crate::config::endpoint::DefaultResolver::new().into_shared_resolver()
 1362   1362   
        }));
 1363   1363   
        runtime_components.push_interceptor(::aws_smithy_runtime::client::http::connection_poisoning::ConnectionPoisoningInterceptor::new());
 1364   1364   
        runtime_components.push_retry_classifier(::aws_smithy_runtime::client::retries::classifiers::HttpStatusCodeClassifier::default());
 1365   1365   
        runtime_components.push_interceptor(crate::sdk_feature_tracker::retry_mode::RetryModeFeatureTrackerInterceptor::new());
 1366   1366   
        runtime_components.push_interceptor(::aws_runtime::service_clock_skew::ServiceClockSkewInterceptor::new());
 1367   1367   
        runtime_components.push_interceptor(::aws_runtime::request_info::RequestInfoInterceptor::new());
 1368   1368   
        runtime_components.push_interceptor(::aws_runtime::user_agent::UserAgentInterceptor::new());
 1369   1369   
        runtime_components.push_interceptor(::aws_runtime::invocation_id::InvocationIdInterceptor::new());
        1370  +
        runtime_components.push_interceptor(::aws_runtime::observability_detection::ObservabilityDetectionInterceptor::new());
 1370   1371   
        runtime_components.push_interceptor(::aws_runtime::recursion_detection::RecursionDetectionInterceptor::new());
 1371   1372   
        runtime_components.push_auth_scheme(::aws_smithy_runtime_api::client::auth::SharedAuthScheme::new(
 1372   1373   
            ::aws_runtime::auth::sigv4::SigV4AuthScheme::new(),
 1373   1374   
        ));
 1374   1375   
        Self { config, runtime_components }
 1375   1376   
    }
 1376   1377   
}
 1377   1378   
 1378   1379   
impl ::aws_smithy_runtime_api::client::runtime_plugin::RuntimePlugin for ServiceRuntimePlugin {
 1379   1380   
    fn config(&self) -> ::std::option::Option<::aws_smithy_types::config_bag::FrozenLayer> {
@@ -1430,1431 +1489,1502 @@
 1450   1451   
pub use ::aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
 1451   1452   
pub use ::aws_smithy_types::config_bag::ConfigBag;
 1452   1453   
 1453   1454   
pub use ::aws_credential_types::Credentials;
 1454   1455   
 1455   1456   
impl From<&::aws_types::sdk_config::SdkConfig> for Builder {
 1456   1457   
    fn from(input: &::aws_types::sdk_config::SdkConfig) -> Self {
 1457   1458   
        let mut builder = Builder::default();
 1458   1459   
        builder.set_credentials_provider(input.credentials_provider());
 1459   1460   
        builder = builder.region(input.region().cloned());
        1461  +
        // Track endpoint override metric if endpoint URL is configured from any source
        1462  +
        let has_global_endpoint = input.endpoint_url().is_some();
        1463  +
        let has_service_specific_endpoint = input
        1464  +
            .service_config()
        1465  +
            .and_then(|conf| conf.load_config(service_config_key("Bedrock Runtime", "AWS_ENDPOINT_URL", "endpoint_url")))
        1466  +
            .is_some();
        1467  +
        1468  +
        if has_global_endpoint || has_service_specific_endpoint {
        1469  +
            builder.push_runtime_plugin(::aws_smithy_runtime_api::client::runtime_plugin::SharedRuntimePlugin::new(
        1470  +
                ::aws_runtime::endpoint_override::EndpointOverrideRuntimePlugin::new_with_feature_flag(),
        1471  +
            ));
        1472  +
        }
 1460   1473   
        builder.set_use_fips(input.use_fips());
 1461   1474   
        builder.set_use_dual_stack(input.use_dual_stack());
 1462   1475   
        if input.get_origin("endpoint_url").is_client_config() {
 1463   1476   
            builder.set_endpoint_url(input.endpoint_url().map(|s| s.to_string()));
 1464   1477   
        } else {
 1465   1478   
            builder.set_endpoint_url(
 1466   1479   
                input
 1467   1480   
                    .service_config()
 1468   1481   
                    .and_then(|conf| {
 1469   1482   
                        conf.load_config(service_config_key("Bedrock Runtime", "AWS_ENDPOINT_URL", "endpoint_url"))

tmp-codegen-diff/aws-sdk/sdk/cloudwatchlogs/src/config.rs

@@ -1291,1291 +1350,1351 @@
 1311   1311   
            use crate::config::endpoint::ResolveEndpoint;
 1312   1312   
            crate::config::endpoint::DefaultResolver::new().into_shared_resolver()
 1313   1313   
        }));
 1314   1314   
        runtime_components.push_interceptor(::aws_smithy_runtime::client::http::connection_poisoning::ConnectionPoisoningInterceptor::new());
 1315   1315   
        runtime_components.push_retry_classifier(::aws_smithy_runtime::client::retries::classifiers::HttpStatusCodeClassifier::default());
 1316   1316   
        runtime_components.push_interceptor(crate::sdk_feature_tracker::retry_mode::RetryModeFeatureTrackerInterceptor::new());
 1317   1317   
        runtime_components.push_interceptor(::aws_runtime::service_clock_skew::ServiceClockSkewInterceptor::new());
 1318   1318   
        runtime_components.push_interceptor(::aws_runtime::request_info::RequestInfoInterceptor::new());
 1319   1319   
        runtime_components.push_interceptor(::aws_runtime::user_agent::UserAgentInterceptor::new());
 1320   1320   
        runtime_components.push_interceptor(::aws_runtime::invocation_id::InvocationIdInterceptor::new());
        1321  +
        runtime_components.push_interceptor(::aws_runtime::observability_detection::ObservabilityDetectionInterceptor::new());
 1321   1322   
        runtime_components.push_interceptor(::aws_runtime::recursion_detection::RecursionDetectionInterceptor::new());
 1322   1323   
        runtime_components.push_auth_scheme(::aws_smithy_runtime_api::client::auth::SharedAuthScheme::new(
 1323   1324   
            ::aws_runtime::auth::sigv4::SigV4AuthScheme::new(),
 1324   1325   
        ));
 1325   1326   
        Self { config, runtime_components }
 1326   1327   
    }
 1327   1328   
}
 1328   1329   
 1329   1330   
impl ::aws_smithy_runtime_api::client::runtime_plugin::RuntimePlugin for ServiceRuntimePlugin {
 1330   1331   
    fn config(&self) -> ::std::option::Option<::aws_smithy_types::config_bag::FrozenLayer> {
@@ -1381,1382 +1440,1453 @@
 1401   1402   
pub use ::aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
 1402   1403   
pub use ::aws_smithy_types::config_bag::ConfigBag;
 1403   1404   
 1404   1405   
pub use ::aws_credential_types::Credentials;
 1405   1406   
 1406   1407   
impl From<&::aws_types::sdk_config::SdkConfig> for Builder {
 1407   1408   
    fn from(input: &::aws_types::sdk_config::SdkConfig) -> Self {
 1408   1409   
        let mut builder = Builder::default();
 1409   1410   
        builder.set_credentials_provider(input.credentials_provider());
 1410   1411   
        builder = builder.region(input.region().cloned());
        1412  +
        // Track endpoint override metric if endpoint URL is configured from any source
        1413  +
        let has_global_endpoint = input.endpoint_url().is_some();
        1414  +
        let has_service_specific_endpoint = input
        1415  +
            .service_config()
        1416  +
            .and_then(|conf| conf.load_config(service_config_key("CloudWatch Logs", "AWS_ENDPOINT_URL", "endpoint_url")))
        1417  +
            .is_some();
        1418  +
        1419  +
        if has_global_endpoint || has_service_specific_endpoint {
        1420  +
            builder.push_runtime_plugin(::aws_smithy_runtime_api::client::runtime_plugin::SharedRuntimePlugin::new(
        1421  +
                ::aws_runtime::endpoint_override::EndpointOverrideRuntimePlugin::new_with_feature_flag(),
        1422  +
            ));
        1423  +
        }
 1411   1424   
        builder.set_use_fips(input.use_fips());
 1412   1425   
        builder.set_use_dual_stack(input.use_dual_stack());
 1413   1426   
        if input.get_origin("endpoint_url").is_client_config() {
 1414   1427   
            builder.set_endpoint_url(input.endpoint_url().map(|s| s.to_string()));
 1415   1428   
        } else {
 1416   1429   
            builder.set_endpoint_url(
 1417   1430   
                input
 1418   1431   
                    .service_config()
 1419   1432   
                    .and_then(|conf| {
 1420   1433   
                        conf.load_config(service_config_key("CloudWatch Logs", "AWS_ENDPOINT_URL", "endpoint_url"))

tmp-codegen-diff/aws-sdk/sdk/codecatalyst/src/config.rs

@@ -1292,1292 +1351,1352 @@
 1312   1312   
            use crate::config::endpoint::ResolveEndpoint;
 1313   1313   
            crate::config::endpoint::DefaultResolver::new().into_shared_resolver()
 1314   1314   
        }));
 1315   1315   
        runtime_components.push_interceptor(::aws_smithy_runtime::client::http::connection_poisoning::ConnectionPoisoningInterceptor::new());
 1316   1316   
        runtime_components.push_retry_classifier(::aws_smithy_runtime::client::retries::classifiers::HttpStatusCodeClassifier::default());
 1317   1317   
        runtime_components.push_interceptor(crate::sdk_feature_tracker::retry_mode::RetryModeFeatureTrackerInterceptor::new());
 1318   1318   
        runtime_components.push_interceptor(::aws_runtime::service_clock_skew::ServiceClockSkewInterceptor::new());
 1319   1319   
        runtime_components.push_interceptor(::aws_runtime::request_info::RequestInfoInterceptor::new());
 1320   1320   
        runtime_components.push_interceptor(::aws_runtime::user_agent::UserAgentInterceptor::new());
 1321   1321   
        runtime_components.push_interceptor(::aws_runtime::invocation_id::InvocationIdInterceptor::new());
        1322  +
        runtime_components.push_interceptor(::aws_runtime::observability_detection::ObservabilityDetectionInterceptor::new());
 1322   1323   
        runtime_components.push_interceptor(::aws_runtime::recursion_detection::RecursionDetectionInterceptor::new());
 1323   1324   
        Self { config, runtime_components }
 1324   1325   
    }
 1325   1326   
}
 1326   1327   
 1327   1328   
impl ::aws_smithy_runtime_api::client::runtime_plugin::RuntimePlugin for ServiceRuntimePlugin {
 1328   1329   
    fn config(&self) -> ::std::option::Option<::aws_smithy_types::config_bag::FrozenLayer> {
 1329   1330   
        self.config.clone()
 1330   1331   
    }
 1331   1332   
@@ -1370,1371 +1429,1442 @@
 1390   1391   
}
 1391   1392   
 1392   1393   
pub use ::aws_smithy_runtime::client::identity::IdentityCache;
 1393   1394   
pub use ::aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
 1394   1395   
pub use ::aws_smithy_types::config_bag::ConfigBag;
 1395   1396   
 1396   1397   
impl From<&::aws_types::sdk_config::SdkConfig> for Builder {
 1397   1398   
    fn from(input: &::aws_types::sdk_config::SdkConfig) -> Self {
 1398   1399   
        let mut builder = Builder::default();
 1399   1400   
        builder = builder.region(input.region().cloned());
        1401  +
        // Track endpoint override metric if endpoint URL is configured from any source
        1402  +
        let has_global_endpoint = input.endpoint_url().is_some();
        1403  +
        let has_service_specific_endpoint = input
        1404  +
            .service_config()
        1405  +
            .and_then(|conf| conf.load_config(service_config_key("CodeCatalyst", "AWS_ENDPOINT_URL", "endpoint_url")))
        1406  +
            .is_some();
        1407  +
        1408  +
        if has_global_endpoint || has_service_specific_endpoint {
        1409  +
            builder.push_runtime_plugin(::aws_smithy_runtime_api::client::runtime_plugin::SharedRuntimePlugin::new(
        1410  +
                ::aws_runtime::endpoint_override::EndpointOverrideRuntimePlugin::new_with_feature_flag(),
        1411  +
            ));
        1412  +
        }
 1400   1413   
        builder.set_use_fips(input.use_fips());
 1401   1414   
        if input.get_origin("endpoint_url").is_client_config() {
 1402   1415   
            builder.set_endpoint_url(input.endpoint_url().map(|s| s.to_string()));
 1403   1416   
        } else {
 1404   1417   
            builder.set_endpoint_url(
 1405   1418   
                input
 1406   1419   
                    .service_config()
 1407   1420   
                    .and_then(|conf| {
 1408   1421   
                        conf.load_config(service_config_key("CodeCatalyst", "AWS_ENDPOINT_URL", "endpoint_url"))
 1409   1422   
                            .map(|it| it.parse().unwrap())