Expand description
§telemetry-batteries
Batteries-included telemetry for Rust applications. Configure tracing, metrics, and error reporting with a single function call.
§Quick Start
#[tokio::main]
async fn main() -> eyre::Result<()> {
// Initialize from environment variables
let _guard = telemetry_batteries::init()?;
tracing::info!("Hello, telemetry!");
Ok(())
}The guard must be kept alive for the duration of your application. When dropped, it gracefully shuts down the telemetry providers.
init() also installs a global panic hook. Panics are logged with tracing::error
and structured fields like source, payload_type, location, thread, and
backtrace; normal panic unwind/abort behavior is unchanged.
For fatal top-level errors, opt into the same panic path:
use telemetry_batteries::TopLevelResultExt;
#[tokio::main]
async fn main() -> eyre::Result<()> {
let _guard = telemetry_batteries::init()?;
run().await.panic_on_top_level_error();
Ok(())
}
async fn run() -> eyre::Result<()> {
eyre::bail!("fatal startup error")
}§Configuration
Configuration is done via environment variables using presets:
§Presets
| Preset | Log Format | Log Output | Span Export | Use Case |
|---|---|---|---|---|
local | pretty | stdout | none | Local development |
datadog | datadog_json | stdout | Datadog Agent | Production with Datadog |
none | - | none | none | Disable telemetry |
§Environment Variables
| Variable | Values | Default |
|---|---|---|
TELEMETRY_PRESET | local, datadog, none | local |
TELEMETRY_SERVICE_NAME | string | required for datadog |
RUST_LOG or TELEMETRY_LOG_LEVEL | EnvFilter syntax | info |
TELEMETRY_LOG_FORMAT | pretty, json, compact, datadog_json | (from preset) |
TELEMETRY_DATADOG_ENDPOINT | url | http://localhost:8126 |
TELEMETRY_EYRE_MODE | color, json | color |
§Metrics Configuration
Metrics are configured independently from presets:
| Variable | Values | Default |
|---|---|---|
TELEMETRY_METRICS_BACKEND | prometheus, statsd, none | none |
TELEMETRY_PROMETHEUS_MODE | http, push | http |
TELEMETRY_PROMETHEUS_LISTEN | addr:port | 0.0.0.0:9090 |
TELEMETRY_PROMETHEUS_ENDPOINT | url | - |
TELEMETRY_PROMETHEUS_INTERVAL | seconds | 10 |
TELEMETRY_STATSD_HOST | string | localhost |
TELEMETRY_STATSD_PORT | u16 | 8125 |
TELEMETRY_STATSD_PREFIX | string | - |
§Programmatic Configuration
For more control, use the builder pattern:
use telemetry_batteries::{
TelemetryConfig, TelemetryPreset, LogFormat,
MetricsConfig, MetricsBackend, StatsdConfig,
};
#[tokio::main]
async fn main() -> eyre::Result<()> {
let config = TelemetryConfig::builder()
.preset(TelemetryPreset::Datadog)
.service_name("my-service".to_owned())
.log_format(LogFormat::Pretty) // Override preset's log format
.metrics(MetricsConfig::builder()
.backend(MetricsBackend::Statsd)
.statsd(StatsdConfig::builder()
.host("localhost".to_owned())
.port(8125)
.build())
.build())
.build();
let _guard = telemetry_batteries::init_with_config(config)?;
tracing::info!("Configured programmatically!");
Ok(())
}§Usage Examples
# Local development - pretty logs, no tracing
cargo run
# Datadog production
TELEMETRY_PRESET=datadog TELEMETRY_SERVICE_NAME=my-service cargo run
# Datadog with pretty logs for debugging
TELEMETRY_PRESET=datadog TELEMETRY_SERVICE_NAME=my-service TELEMETRY_LOG_FORMAT=pretty cargo run
# With Prometheus metrics
TELEMETRY_METRICS_BACKEND=prometheus cargo run§Distributed Tracing
For distributed tracing with Axum, enable the axum feature:
telemetry-batteries = { version = "0.4", features = ["axum"] }Then use the route-aware constructor:
use axum::{routing::get, Router};
use telemetry_batteries::tracing::middleware::TraceLayer;
let app = Router::new()
.route("/", get(handler))
.layer(TraceLayer::new_for_axum());The middleware automatically:
- Creates a span for each request
- Names the span from the HTTP method and matched route template
- Records the matched route as
http.route - Extracts trace context from incoming headers (e.g.,
traceparent) - Injects trace context into response headers
Use TraceLayer::new() for framework-neutral Tower services. A custom
low-cardinality route template can be supplied with with_route_extractor.
Custom span creation:
use telemetry_batteries::tracing::middleware::TraceLayer;
use tracing::info_span;
let layer = TraceLayer::new().with_make_span(|req| {
info_span!(
"http_request",
method = %req.method(),
path = %req.uri().path(),
)
});§Outgoing requests
Inject the current span’s trace context into an individual reqwest request:
use telemetry_batteries::tracing::reqwest::RequestBuilderExt;
let response = reqwest::Client::new()
.get("https://example.com")
.inject_trace_context()
.send()
.await?;For reqwest-middleware, enable the reqwest-middleware feature and attach
TraceContextMiddleware once to the client:
use telemetry_batteries::tracing::reqwest::middleware::TraceContextMiddleware;
let client = reqwest_middleware::ClientBuilder::new(reqwest::Client::new())
.with(TraceContextMiddleware::new())
.build();This integration propagates the current context but does not create client spans.
§Cargo Features
| Feature | Default | Description |
|---|---|---|
axum | No | Route-aware server tracing for Axum applications |
metrics-prometheus | Yes | Prometheus metrics exporter |
metrics-statsd | Yes | StatsD metrics exporter |
reqwest-middleware | No | Automatic outgoing trace-context propagation for reqwest-middleware clients |
rustls | Yes | TLS via rustls |
native-tls | No | TLS via native-tls |
§Examples
See the examples directory:
basic.rs- Minimal setup with environment variablesaxum_tracing.rs- Axum server with distributed trace propagation
Run the examples:
# Basic example with local preset
cargo run --example basic
# Basic example with Datadog
TELEMETRY_PRESET=datadog TELEMETRY_SERVICE_NAME=test cargo run --example basic
# Axum server with trace propagation
TELEMETRY_PRESET=datadog TELEMETRY_SERVICE_NAME=my-api cargo run --features axum --example axum_tracing§License
Unless otherwise specified, all code in this repository is dual-licensed under either:
- MIT License (LICENSE-MIT)
- Apache License, Version 2.0, with LLVM Exceptions (LICENSE-APACHE)
at your option. This means you may select the license you prefer to use.
Any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Re-exports§
pub use config::LogFormat;pub use config::MetricsBackend;pub use config::MetricsConfig;pub use config::PrometheusConfig;pub use config::PrometheusMode;pub use config::StatsdConfig;pub use config::TelemetryConfig;pub use config::TelemetryPreset;pub use opentelemetry;pub use tracing_opentelemetry;
Modules§
- config
- Configuration types for telemetry initialization.
- reexports
- Reexports of crates that appear in the public API.
- tracing
Structs§
- Telemetry
Guard - Guard that ensures telemetry is properly shut down when dropped.
Traits§
- TopLevel
Result Ext - Extension trait for turning fatal top-level
Resulterrors into panics.
Functions§
- init
- Initialize telemetry from environment variables.
- init_
with_ config - Initialize telemetry with the given configuration.