1 + | /*
|
2 + | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 + | * SPDX-License-Identifier: Apache-2.0
|
4 + | */
|
5 + |
|
6 + | use aws_config::Region;
|
7 + | use aws_credential_types::Credentials;
|
8 + | use aws_runtime::user_agent::test_util::assert_ua_contains_metric_values;
|
9 + | use aws_sdk_dynamodb::config::Builder;
|
10 + | use aws_smithy_observability::TelemetryProvider;
|
11 + | use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient};
|
12 + | use aws_smithy_types::body::SdkBody;
|
13 + | use std::sync::Arc;
|
14 + |
|
15 + | fn test_client(
|
16 + | update_builder: fn(Builder) -> Builder,
|
17 + | ) -> (aws_sdk_dynamodb::Client, StaticReplayClient) {
|
18 + | let http_client = StaticReplayClient::new(vec![ReplayEvent::new(
|
19 + | http::Request::builder()
|
20 + | .uri("https://dynamodb.us-east-1.amazonaws.com/")
|
21 + | .body(SdkBody::empty())
|
22 + | .unwrap(),
|
23 + | http::Response::builder()
|
24 + | .status(200)
|
25 + | .body(SdkBody::from(r#"{"TableNames":[]}"#))
|
26 + | .unwrap(),
|
27 + | )]);
|
28 + |
|
29 + | let config = update_builder(
|
30 + | aws_sdk_dynamodb::Config::builder()
|
31 + | .credentials_provider(Credentials::for_tests())
|
32 + | .region(Region::from_static("us-east-1"))
|
33 + | .http_client(http_client.clone()),
|
34 + | )
|
35 + | .build();
|
36 + |
|
37 + | (aws_sdk_dynamodb::Client::from_conf(config), http_client)
|
38 + | }
|
39 + |
|
40 + | async fn call_operation(client: aws_sdk_dynamodb::Client) {
|
41 + | let _ = client.list_tables().send().await;
|
42 + | }
|
43 + |
|
44 + | #[tokio::test]
|
45 + | async fn observability_metrics_in_user_agent() {
|
46 + | // Test case 1: No telemetry provider configured (default noop)
|
47 + | {
|
48 + | let (client, rx) = test_client(std::convert::identity);
|
49 + | call_operation(client).await;
|
50 + | let req = rx.expect_request().expect("request");
|
51 + | let user_agent = req.headers().get("x-amz-user-agent").unwrap();
|
52 + |
|
53 + | // Should NOT contain observability metrics when using noop provider
|
54 + | let ua_str = user_agent.to_str().unwrap();
|
55 + | assert!(!ua_str.contains("m/4")); // OBSERVABILITY_OTEL_METRICS = "4"
|
56 + | }
|
57 + |
|
58 + | // Test case 2: OpenTelemetry metrics provider configured
|
59 + | {
|
60 + | use aws_smithy_observability_otel::meter::OtelMeterProvider;
|
61 + | use opentelemetry_sdk::metrics::{PeriodicReader, SdkMeterProvider};
|
62 + | use opentelemetry_sdk::runtime::Tokio;
|
63 + | use opentelemetry_sdk::testing::metrics::InMemoryMetricExporter;
|
64 + |
|
65 + | // Create OTel meter provider
|
66 + | let exporter = InMemoryMetricExporter::default();
|
67 + | let reader = PeriodicReader::builder(exporter.clone(), Tokio).build();
|
68 + | let otel_mp = SdkMeterProvider::builder().with_reader(reader).build();
|
69 + | let sdk_mp = Arc::new(OtelMeterProvider::new(otel_mp));
|
70 + | let sdk_tp = TelemetryProvider::builder().meter_provider(sdk_mp).build();
|
71 + |
|
72 + | // Set global telemetry provider
|
73 + | aws_smithy_observability::global::set_telemetry_provider(sdk_tp).unwrap();
|
74 + |
|
75 + | let (client, rx) = test_client(std::convert::identity);
|
76 + | call_operation(client).await;
|
77 + | let req = rx.expect_request().expect("request");
|
78 + | let user_agent = req.headers().get("x-amz-user-agent").unwrap();
|
79 + |
|
80 + | // Should contain OBSERVABILITY_OTEL_METRICS metric
|
81 + | assert_ua_contains_metric_values(user_agent.to_str().unwrap(), &["4"]);
|
82 + |
|
83 + | // Reset to noop for other tests
|
84 + | aws_smithy_observability::global::set_telemetry_provider(TelemetryProvider::noop())
|
85 + | .unwrap();
|
86 + | }
|
87 + | }
|