otel-bootstrap
One-call OpenTelemetry bootstrap for Rust services — traces, metrics, and logs over OTLP with sensible defaults.
The standard opentelemetry + opentelemetry-otlp + tracing-subscriber wiring is the same in every service. This crate does it once: call init_telemetry("my-service"), keep the handle alive, and drop it to flush.
Features
- One call to wire it all up — traces, metrics, and logs over OTLP,
tracing-subscriberconfigured, W3C TraceContext + Baggage propagators registered. - gRPC or HTTP/protobuf — select transport via cargo feature.
- Env-var configuration — follows the OpenTelemetry spec (
OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_SERVICE_NAME,OTEL_TRACES_SAMPLER, …). - Builder API — version, environment, sampler, custom meter setup, extra subscriber layers.
- Optional axum middleware —
OtelTraceLayerfor inbound HTTP trace propagation. - Optional
enduser.*span enrichment — emit the four canonicalenduser.*attributes from anapi-bones::OrganizationContexton every span. - Graceful shutdown — drop
TelemetryHandlesto flush and shut down both providers.
Quick start
[]
= "0.4"
= { = "1", = ["full"] }
use init_telemetry;
async
For more control, use the builder:
use Telemetry;
let _telemetry = builder
.version
.environment
.init?;
Cargo features
| Feature | Default | Description |
|---|---|---|
grpc |
✅ | OTLP/gRPC transport via tonic |
http |
❌ | OTLP/HTTP-protobuf transport via reqwest |
axum |
❌ | OtelTraceLayer for axum servers |
org-context |
❌ | enduser.* span enrichment from api-bones::OrganizationContext |
testing |
❌ | In-memory exporters for unit tests |
At least one of grpc or http must be enabled (enforced at compile time).
Configuration
| Variable | Default |
|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT |
http://localhost:4317 (gRPC) / http://localhost:4318 (HTTP) |
OTEL_EXPORTER_OTLP_PROTOCOL |
grpc |
OTEL_EXPORTER_OTLP_TIMEOUT |
10000 ms |
OTEL_SERVICE_NAME |
overridden by the service_name argument |
OTEL_TRACES_SAMPLER |
parentbased_always_on |
OTEL_TRACES_SAMPLER_ARG |
sampler-specific (e.g. ratio for traceidratio) |
Full reference: OTEL_TRACES_SAMPLER values.
Axum middleware
= { = "0.4", = ["axum"] }
use axum_layer;
let app = new
.route
.layer;
This layer reads the traceparent / tracestate headers, starts a server span, and propagates context to all child spans.
enduser.* span enrichment
= { = "0.4", = ["axum", "org-context"] }
use org_context_span_enricher_layer;
let app = new
.route
.layer;
Reads OrganizationContext from axum request extensions and records enduser.id, enduser.org_id, enduser.org_path, and enduser.principal_kind on the active span. Routes without a context are silently skipped.
Examples
basic_setup— minimal initshutdown_handling— explicit graceful flushcustom_config— builder API with version, environment, sampleraxum_org_context— axum +enduser.*enrichment
License
MIT — see LICENSE.