provide-telemetry/rust
Structured logging + OpenTelemetry traces and metrics for Rust — feature
parity with the provide-telemetry
Python, TypeScript, and Go packages.
Install
Add to Cargo.toml:
[]
= { = "../rust" } # local workspace
# or once published:
# provide-telemetry = "0.3"
Requires Rust 1.81+.
Quick start
use ;
API reference
Setup
| Export | Description |
|---|---|
setup_telemetry() |
Idempotent init from environment variables. |
reconfigure_telemetry(overrides) |
Hot-reload sampling / backpressure / exporter policy. |
flush_telemetry() |
Drain every installed provider and leave them installed. |
adopt_global_providers(AdoptedProviders) |
Tell the facade the host installed live providers on the OTel globals, so emission routes through them. Rust cannot detect this for itself. |
shutdown_telemetry() |
Flush and shut down all providers. |
get_runtime_config() |
Inspect the applied config snapshot. |
get_runtime_status() |
Inspect provider state, fallback mode, last error. |
Logging
let logger = get_logger;
logger.debug;
logger.info;
logger.warn;
logger.error;
// Attach structured fields inline
logger.info_with;
// Attach DARS metadata (domain.action.resource.status)
use event;
let ev = event.expect;
logger.info_event;
Event names follow the DA(R)S pattern: event() accepts 3–4 dot-separated
segments; event_name() accepts 3–5 segments.
Tracing
use ;
trace;
Metrics
use ;
let reqs = counter;
reqs.add;
let lat = histogram;
lat.record;
let cpu = gauge;
cpu.set;
Context binding
use ;
use BTreeMap;
let mut fields = new;
fields.insert;
fields.insert;
bind_context;
// All log calls on this task/thread include these fields automatically.
clear_context;
Session correlation
use ;
bind_session_context;
let sid = get_session_id; // Some("sess-abc-123")
clear_session_context;
W3C trace propagation
use ;
// In an HTTP handler — extract incoming traceparent/tracestate.
let traceparent = headers.get.map;
let baggage = headers.get.map;
let pc = extract_w3c_context;
bind_propagation_context;
// ... handle request ...
clear_propagation_context;
PII sanitization
use ;
use json;
register_pii_rule;
let payload = json!;
let clean = sanitize_payload;
// clean["user"]["ssn"] == "***"
Built-in: redacts password, token, secret, authorization, api_key,
and similar keys by default.
Health snapshot
use get_health_snapshot;
let snap = get_health_snapshot;
println!;
Testing helpers
Configuration
All options come from environment variables:
| Env var | Default | Description |
|---|---|---|
PROVIDE_TELEMETRY_SERVICE_NAME |
provide-service |
Service identity |
PROVIDE_TELEMETRY_ENV |
dev |
Deployment environment |
PROVIDE_TELEMETRY_VERSION |
0.0.0 |
Service version |
PROVIDE_LOG_LEVEL |
INFO |
Log level: TRACE / DEBUG / INFO / WARN / ERROR |
PROVIDE_LOG_FORMAT |
console |
Output format: console / json / pretty |
PROVIDE_LOG_PRETTY_KEY_COLOR |
dim |
ANSI color name for keys in pretty format |
PROVIDE_LOG_PRETTY_VALUE_COLOR |
"" |
ANSI color name for values in pretty format |
PROVIDE_LOG_PRETTY_FIELDS |
"" |
Comma-separated field names to display in pretty format |
PROVIDE_TELEMETRY_STRICT_SCHEMA |
false |
Enforce DA(R)S event name format |
PROVIDE_TRACE_ENABLED |
true |
Enable tracing |
PROVIDE_TRACE_SAMPLE_RATE |
1.0 |
Trace sample rate [0.0, 1.0] |
PROVIDE_METRICS_ENABLED |
true |
Enable metrics |
PROVIDE_SAMPLING_LOGS_RATE |
1.0 |
Log sampling rate [0.0, 1.0] |
PROVIDE_BACKPRESSURE_LOGS_MAXSIZE |
1000 |
Max queued log events before backpressure |
PROVIDE_SECURITY_MAX_ATTR_VALUE_LENGTH |
1024 |
Truncate long field values at this byte count |
PROVIDE_SECURITY_MAX_ATTR_COUNT |
64 |
Maximum context attributes per log record |
PROVIDE_SECURITY_MAX_NESTING_DEPTH |
8 |
Maximum PII sanitization recursion depth |
OTEL_EXPORTER_OTLP_ENDPOINT |
— | OTLP base endpoint (e.g. http://localhost:4318) |
OTEL_EXPORTER_OTLP_HEADERS |
— | Percent-encoded key=value auth headers |
OTEL_METRIC_EXPORT_INTERVAL |
60000 |
Metrics push interval in milliseconds (--features otel) |
Cargo features
| Feature | Default | Description |
|---|---|---|
otel |
no | Real OTLP export for traces, metrics, and logs via opentelemetry-otlp (HTTP/protobuf). When off, the crate provides in-process fallback instrumentation (noop tracer, in-process metrics, stderr-only logs). |
otel-grpc |
no | Adds gRPC transport on top of otel. Requires tonic (heavier dep tree). |
OTLP export
When built with --features otel, setup_telemetry() installs real
TracerProvider, MeterProvider, and LoggerProvider backed by OTLP
HTTP/protobuf exporters. All three signals (traces, metrics, logs) are
emitted to the configured endpoint:
| Env Var | Example | Notes |
|---|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT |
http://localhost:4318 |
Shared base URL; per-signal paths (/v1/traces, /v1/metrics, /v1/logs) are appended automatically. |
OTEL_EXPORTER_OTLP_HEADERS |
Authorization=Basic%20dXNlcjpwYXNz |
Shared auth header (percent-encoded). |
OTEL_EXPORTER_OTLP_PROTOCOL |
http/protobuf |
Default. Also accepts http/json. grpc requires --features otel-grpc. |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT |
http://traces:4318/v1/traces |
Signal-specific override (used verbatim, no path appending). |
OTEL_METRIC_EXPORT_INTERVAL |
60000 |
Metrics push interval in milliseconds. |
Tokio runtime requirement: this crate depends on tokio (for
run_with_resilience retry/timeout logic) regardless of feature flags.
With --features otel the SDK's batch span processor and periodic metrics
reader additionally require an active multi-threaded runtime. Call
setup_telemetry() from within a #[tokio::main] function or an
explicit tokio::runtime::Builder runtime:
async
Architecture: consent, sampling, backpressure, and resilience
modules act as pre-filters. The OTel SDK sits behind them and handles
batching + OTLP network export only. When OTel is unconfigured or the
feature is off, the crate falls back gracefully to in-process
instrumentation (stderr logs, noop tracer, in-process counters).
Spec conformance
This crate implements every required: true symbol in
spec/telemetry-api.yaml, with names
converted to Rust snake_case per the spec's naming_conventions.rust rule.
Run the conformance validator:
Examples
The example suite covers the same numbered telemetry topics as Python, TypeScript, and Go, includes OpenObserve integration examples, and keeps the OTLP E2E client/server pair used by the cross-language verification flow.
Requirements
- Rust 1.81+
Coverage gate
Rust CI enforces zero uncovered project lines with cargo-llvm-cov.
The gate ignores Rust standard-library source paths only; missed lines in
rust/ fail the workflow. Locally:
RUST_TEST_THREADS=1
Performance gate
Hot-path benchmarks (benches/hot_path.rs) run on every CI push as the
performance-smoke job, comparing per-op measurements against
baselines/perf-rust.json for the runner's OS bucket. Locally:
make perf-rust. See docs/internal/quality-gates.md for
the gate's design (5x default tolerance, OS-tagged baselines) and how to
seed or refresh entries.
Mutation testing
Rust changes are gated by a complete all-feature cargo-mutants sweep with
a 100% kill requirement. Equivalent mutations must be narrowly documented in
rust/.cargo/mutants.toml or at the source site; the
gate does not permit surviving or timed-out behavioral mutants.
Re-run the sweep from rust/:
CARGO_BUILD_JOBS=1 NEXTEST_TEST_THREADS=1 CARGO_PROFILE_TEST_DEBUG=0 \
This uses the same memory-bounded compiler, test-runner, and mutation-worker
limits as each Rust mutation shard in
.github/workflows/ci-mutation.yml.
Sweep outputs land in rust/mutants.out/, including
outcomes.json, caught.txt, missed.txt, and per-mutant logs.
License
Apache-2.0. See LICENSE.