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