telemetry_rust/middleware/aws/instrumentation.rs
1use aws_types::request_id::RequestId;
2use std::{error::Error, future::Future};
3
4use super::{AwsSpan, AwsSpanBuilder};
5use crate::future::{InstrumentedFuture, InstrumentedFutureContext};
6
7impl<T, E> InstrumentedFutureContext<Result<T, E>> for AwsSpan
8where
9 T: RequestId,
10 E: RequestId + Error,
11{
12 fn on_result(self, result: &Result<T, E>) {
13 self.end(result);
14 }
15}
16
17/// Trait for instrumenting AWS futures with automatic span management.
18///
19/// This trait provides a convenient way to wrap AWS SDK futures with OpenTelemetry
20/// instrumentation, automatically handling span creation, error recording, and cleanup.
21///
22/// # Example
23///
24/// ```rust
25/// use aws_sdk_dynamodb::{Client as DynamoClient, types::AttributeValue};
26/// use telemetry_rust::middleware::aws::{AwsInstrument, DynamodbSpanBuilder};
27///
28/// async fn query_table() {
29/// let config = aws_config::load_from_env().await;
30/// let dynamo_client = DynamoClient::new(&config);
31/// let res = dynamo_client
32/// .query()
33/// .table_name("table_name")
34/// .index_name("my_index")
35/// .key_condition_expression("PK = :pk")
36/// .expression_attribute_values(":pk", AttributeValue::S("Test".to_string()))
37/// .send()
38/// .instrument(DynamodbSpanBuilder::get_item("table_name"))
39/// .await;
40/// println!("DynamoDB response: {res:#?}");
41/// }
42/// ```
43pub trait AwsInstrument<T, E, F>
44where
45 T: RequestId,
46 E: RequestId + Error,
47 F: Future<Output = Result<T, E>>,
48{
49 /// Instruments the future with an AWS span.
50 ///
51 /// Creates an instrumented future that will automatically start a span when polled
52 /// and properly handle the result when the future completes.
53 ///
54 /// # Arguments
55 ///
56 /// * `span` - A span builder or span to use for instrumentation
57 ///
58 /// # Returns
59 ///
60 /// An instrumented future that will record AWS operation details
61 fn instrument<'a>(
62 self,
63 span: impl Into<AwsSpanBuilder<'a>>,
64 ) -> InstrumentedFuture<F, AwsSpan>;
65}
66
67impl<T, E, F> AwsInstrument<T, E, F> for F
68where
69 T: RequestId,
70 E: RequestId + Error,
71 F: Future<Output = Result<T, E>>,
72{
73 fn instrument<'a>(
74 self,
75 span: impl Into<AwsSpanBuilder<'a>>,
76 ) -> InstrumentedFuture<F, AwsSpan> {
77 let span = span.into().start();
78 InstrumentedFuture::new(self, span)
79 }
80}