| Crates.io | opentelemetry-xray |
| lib.rs | opentelemetry-xray |
| version | 0.1.5 |
| created_at | 2025-02-10 02:13:23.494351+00 |
| updated_at | 2025-05-31 06:37:18.386806+00 |
| description | A library for AWS X‑Ray distributed tracing using OpenTelemetry. |
| homepage | |
| repository | https://github.com/cosmicmind/opentelemetry-xray |
| max_upload_size | |
| id | 1549504 |
| size | 72,796 |
opentelemetry-xray is a Rust library that provides a flexible interface for AWS X‑Ray distributed tracing using OpenTelemetry. It simplifies the integration of AWS X‑Ray with your applications by setting up a global tracer provider, mapping tracing contexts into AWS X‑Ray–compatible formats, and supporting rich span information such as annotations, metadata, exceptions, and HTTP context.
traceparent header into the AWS X‑Ray header (x-amzn-trace-id).tracing crate for structured logging and span management.annotation.) for filtering and searching.metadata. prefix).exception.type and exception.message).http.request.method and http.response.status).Note: In these examples we show keys as dot‑separated (e.g.
annotation.otel.kind) without extra quotation marks. In your actual Rust code, if a field name isn't a valid identifier (because it includes a period), you may need to use a string literal (for example,"annotation.otel.kind" = "server")—the important part is that the exported key appears asannotation.otel.kind(and similarly forhttp.request,http.response, etc).
Add the following to your Cargo.toml:
[dependencies]
opentelemetry-xray = "0.1.5"
opentelemetry = { version = "0.29.0", features = ["trace"] }
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "json"] }
Initialize your telemetry and create a span enriched with annotations, metadata, and exception details:
use opentelemetry_xray::{Telemetry, TelemetryConfig};
use tracing::{info_span, error, Instrument};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = TelemetryConfig {
service_name: "my-service".into(),
service_version: env!("CARGO_PKG_VERSION").into(),
deployment_env: "production".into(),
log_level: "info".into(),
};
// Initialize the propagator, tracer provider, and subscriber.
let telemetry = Telemetry::init(config)?;
// Create a span with enriched attributes. In these examples, we conceptually use keys like:
// annotation.user_id, metadata.request_id, http.request.method, etc.
let span = info_span!(
main_operation,
annotation.user_id = 42,
metadata.request_id = "abc123",
// HTTP-related attributes:
http.request.method = "GET",
http.request.url = "https://example.com/api"
);
async {
if let Err(e) = do_something().await {
// Record exception details:
error!(
exception.type = "OperationError",
exception.message = %e,
"Operation failed"
);
}
}
.instrument(span)
.await;
telemetry.shutdown();
Ok(())
}
async fn do_something() -> Result<(), &'static str> {
Err("Something went wrong")
}
Annotations are meant to be indexed and are useful for filtering and searching in AWS X‑Ray. Specify annotation attributes using the annotation. prefix:
use tracing::info_span;
let span = info_span!(
processing_order,
annotation.order_id = 1001,
annotation.priority = "high"
);
Metadata provides additional context but is not indexed. Use the metadata. prefix:
let span = info_span!(
user_session,
metadata.session_id = "xyz789",
metadata.user_agent = "Mozilla/5.0"
);
When errors occur, capture detailed error information by using the exception. prefix:
use tracing::error;
let err = "Null Pointer Exception";
error!(
exception.type = "NullPointerException",
exception.message = err,
"An error occurred"
);
Extract incoming trace contexts from HTTP requests and create spans enriched with HTTP attributes:
use axum::{Router, routing::get};
use tower_http::trace::TraceLayer;
use opentelemetry_xray::{extract_headers, Telemetry};
use axum::http::Request;
use axum::body::Body;
async fn handler() {
// Your request handling logic.
}
async fn build_router() -> Router {
Router::new()
.route("/", get(handler))
.layer(
TraceLayer::new_for_http().make_span_with(|request: &Request<Body>| {
let span = tracing::info_span!(
http_request,
http.request.method = ?request.method(),
http.request.url = ?request.uri()
);
// Extract and set the incoming trace context:
let parent_context = extract_headers(request.headers());
span.set_parent(parent_context);
span
})
)
}
Inject the current trace context into outgoing HTTP requests so downstream services continue the distributed trace:
use reqwest::Client;
use http::HeaderMap;
use opentelemetry_xray::inject_headers;
async fn make_request(client: &Client, url: &str) -> Result<(), reqwest::Error> {
let mut headers = HeaderMap::new();
// Inject the current OpenTelemetry context (this converts the standard
// `traceparent` header to the AWS X‑Ray header, e.g. `x-amzn-trace-id`).
inject_headers(&mut headers);
client.get(url)
.headers(headers)
.send()
.await?;
Ok(())
}
Configure telemetry using the TelemetryConfig struct:
let config = TelemetryConfig {
service_name: "my-service".into(),
service_version: env!("CARGO_PKG_VERSION").into(),
deployment_env: "production".into(),
log_level: "info".into(),
};
Telemetry::init() for a standardized setup of the propagator, tracer provider, and subscriber.telemetry.shutdown() at application exit to ensure all spans are flushed.tracing macros (e.g., info_span!, error!) to create spans.annotation., metadata., http.request., exception.) to indicate the purpose of each attribute.extract_headers.inject_headers.Run the test suite:
cargo test
This project is licensed under the MIT License – see the LICENSE file for details.
Contributions are welcome! Please open an issue or submit a pull request with your improvements or bug fixes.
For issues and feature requests, please use the GitHub issue tracker.