awssdk-instrumentation
Out-of-the-box OpenTelemetry/X-Ray instrumentation for the AWS SDK for Rust, with first-class support for AWS Lambda.
About The Project
awssdk-instrumentation wires together three concerns that every instrumented AWS workload needs:
- SDK interceptors — automatically attach OpenTelemetry semantic-convention attributes to every AWS SDK call (DynamoDB, S3, SQS, and more via user-defined extractors).
- Lambda Tower layer — create a per-invocation span covering the handler, propagate the X-Ray trace context, track cold-starts, and flush the exporter after each invocation.
- Environment resource detection — detect whether the process is running on Lambda, ECS, EKS, or EC2 and populate the OTel
Resourceaccordingly.
The default feature set (tracing-backend + env-lambda + extract-dynamodb + export-xray) covers the most common Lambda workload with zero extra configuration.
Features
- Automatic OTel span enrichment for every AWS SDK call (region, operation, HTTP status, request ID, service-specific attributes)
- Per-invocation Lambda spans with X-Ray trace context propagation and cold-start tracking
- Built-in attribute extractors for DynamoDB, S3, and SQS
- Extensible extraction pipeline: register custom
AttributeExtractorimplementations or closure hooks filtered by service/operation - Auto-detection of AWS runtime environment (Lambda, ECS, EKS, EC2) for OTel
Resourcepopulation - X-Ray ID generation, propagation, and daemon export out of the box
make_lambda_runtime!macro for zero-boilerplate Lambda setup- Two backend options:
tracingecosystem integration (default) or direct OTel span management
Getting Started
Prerequisites
- Rust 1.85.0 or later
- An AWS SDK for Rust client (
aws-sdk-dynamodb,aws-sdk-s3, etc.) - For Lambda workloads:
tokio.
Installation
Add the crate to your Cargo.toml:
[]
= "0.1"
Or using cargo:
The default features (tracing-backend, env-lambda, extract-dynamodb, export-xray) are suitable for most Lambda + DynamoDB workloads. See Feature Flags to customise.
Usage
Re-exports. To minimise the dependencies you need to declare in your own
Cargo.toml, this crate re-exports every external crate that appears in its public API:aws-config,aws-smithy-runtime-api,aws-smithy-types,opentelemetry,opentelemetry_sdk,opentelemetry-semantic-conventions, plustracing/tracing-subscriber/tracing-opentelemetry(undertracing-backend),lambda_runtime(underenv-lambda), andopentelemetry-aws(underexport-xray). All are available viaawssdk_instrumentation::<crate>.You still need to add the following to your own
Cargo.toml:
- The
aws-sdk-*service crates you use (aws-sdk-dynamodb,aws-sdk-s3, …).tokio— the#[tokio::main]proc-macro emitted bymake_lambda_runtime!resolves thetokiocrate by absolute path (::tokio), so re-exporting would not help. Lambda functions in Rust needtokioanyway.serde_json(orserde) — for typical Lambda event types.
Quick Start — Lambda with DynamoDB
The make_lambda_runtime! macro generates main(), telemetry initialisation, SDK client singletons, and the Tower layer in a single call:
use ;
use Value;
// 1. Declare the handler.
async
// 2. One macro call generates main(), telemetry init, and the Tower layer.
// Client declarations produce OnceLock-backed singletons with the
// interceptor pre-attached.
make_lambda_runtime!;
Manual Setup
When you need more control over the telemetry stack, wire the pieces together yourself:
use Value;
use ;
async
async
Extending the Extraction Pipeline
For simple, scoped customisations — targeting a single service or operation — closure hooks are the most convenient approach:
use ;
use SpanWrite;
let mut interceptor = new;
// Add a custom attribute to every DynamoDB GetItem call.
interceptor.extractor.register_input_hook;
For more complex extraction logic — spanning multiple phases or services — implement the AttributeExtractor trait instead:
use ;
use SpanWrite;
use context;
;
let mut interceptor = new;
interceptor.extractor.register_attribute_extractor;
Contributions welcome: additional service extractors and extraction logic improvements are very welcome and likely to be merged quickly. See Contributing.
Feature Flags
Features are grouped by category. Items marked ✅ are enabled by default.
Backend
At least one backend must be enabled (enforced at compile time).
| Feature | Default | Description |
|---|---|---|
tracing-backend |
✅ | Writes span attributes via tracing::Span + tracing-opentelemetry. Integrates naturally with the tracing ecosystem. |
otel-backend |
Manages OTel spans directly without tracing. |
Environment Detection
| Feature | Default | Description |
|---|---|---|
env-lambda |
✅ | Lambda Tower layer, resource detector, make_lambda_runtime! macro. |
env-ecs |
ECS resource detector (reads container metadata endpoint). | |
env-eks |
EKS resource detector (reads Kubernetes service account + IMDSv2). | |
env-ec2 |
EC2 resource detector (reads IMDSv2). |
Service Attribute Extraction
| Feature | Default | Description |
|---|---|---|
extract-dynamodb |
✅ | DynamoDB OTel semantic-convention attributes (table name, consumed capacity, etc.). |
extract-s3 |
S3 OTel semantic-convention attributes (bucket name, key, etc.). | |
extract-sqs |
SQS OTel semantic-convention attributes (queue URL, message ID, etc.). |
Export
| Feature | Default | Description |
|---|---|---|
export-xray |
✅ | X-Ray ID generator, propagator, and daemon exporter via opentelemetry-aws. |
When export-xray is enabled, the opentelemetry_aws crate is re-exported at the crate root so you can access the X-Ray propagator and exporter types directly.
Configuration
X-Ray Annotations and Metadata
When export-xray is enabled, two environment variables control how span attributes are mapped to X-Ray segments:
| Variable | Effect |
|---|---|
XRAY_ANNOTATIONS |
Set to "all" to index every attribute as an X-Ray annotation, or to a space-separated list of attribute keys. |
XRAY_METADATA |
Set to "all" to include every attribute as X-Ray metadata, or to a space-separated list of attribute keys. |
Sampling Strategy
The default sampler is ParentBased(AlwaysOff) when env-lambda is enabled — Lambda controls sampling via the X-Ray trace header. Outside Lambda, the default is ParentBased(AlwaysOn).
Logging
Console logging is driven by the RUST_LOG environment variable (via tracing-subscriber's EnvFilter). Logs are emitted as structured JSON to stdout, suitable for CloudWatch Logs ingestion.
API Documentation
Full API documentation is available on docs.rs.
Minimum Supported Rust Version (MSRV)
This crate requires Rust 1.85.0 or later. The MSRV is verified in CI on every push.
FAQ
Can I use both backends at once?
Both tracing-backend and otel-backend can be enabled simultaneously — they compile side by side. However, DefaultInterceptor and DefaultTracingLayer always resolve to the tracing-backend types when both are active. The tracing-backend is recommended for most use cases.
Why is the default sampler AlwaysOff on Lambda?
On Lambda, the X-Ray service controls sampling via the _X_AMZN_TRACE_ID header injected into each invocation. The ParentBased(AlwaysOff) sampler means the crate respects the parent sampling decision from X-Ray and does not create additional root traces on its own.
How do I add extraction for a service not yet supported?
Implement the AttributeExtractor trait and register it on the interceptor's extractor field with register_attribute_extractor(). For simpler cases, use register_input_hook() (or the other register_*_hook methods) with a ServiceFilter to scope the hook to specific services or operations.
Do I need to add opentelemetry or tracing to my own Cargo.toml?
No — both are re-exported. Reach them via awssdk_instrumentation::opentelemetry and awssdk_instrumentation::tracing (the latter requires tracing-backend, which is on by default). The same applies to tracing-subscriber, tracing-opentelemetry, opentelemetry_sdk, and opentelemetry-semantic-conventions. If you prefer adding them as direct dependencies for shorter use paths, that works too.
Can I use this crate outside of Lambda?
Yes. The Lambda-specific functionality is behind the env-lambda feature flag. Disable it and use the interceptor directly with any AWS SDK client. The environment detectors (env-ecs, env-eks, env-ec2) populate the OTel Resource for other AWS compute environments.
Contributing
We welcome contributions! Please read our Contributing Guidelines before submitting pull requests.
License
Distributed under the MIT License. See LICENSE for more information.
Authors
- Jérémie RODON (@JeremieRodon)
— RustyServerless rustysl.com
Related Projects
- opentelemetry-rust — The OpenTelemetry SDK for Rust
- opentelemetry-rust-contrib — Community-maintained OTel exporters and propagators (X-Ray, etc.)
- aws-sdk-rust — The AWS SDK for Rust
- lambda_runtime — The Rust runtime for AWS Lambda
If you find this crate useful, please star the repository and share your feedback!