telemetry-init
One-call observability bootstrap for Rust — the shared init pattern of the
WyattAu estate, wiring logs (tracing_subscriber), metrics
(metrics-kit), and traces (opentelemetry-otlp) in a single fallible
call instead of six hand-rolled dialects of the same 40–80 lines.
- One init, typed failure:
Telemetry::initreturnsTelemetryError; double initialization isAlreadyInitialized, never a panic. - Logs:
EnvFilterfrom the configured directive withRUST_LOGoverride, JSON by default (jsonfeature), human format for local dev. - Metrics: a lock-free
metrics-kit::Registrywith a cardinality budget, handed to you as anArc— no hidden globals. - Traces (
otlpfeature): OTLP/HTTP exporter wired as atracing-opentelemetrylayer withservice.name/service.versionresource attributes and parent-based ratio sampling. - Explicit shutdown, best-effort drop:
shutdown()is the guaranteed, idempotent flush path;Dropis a documented safety net. - No silent fallbacks:
LogFormat::Jsonwithout thejsonfeature is a configuration error. #![forbid(unsafe_code)],#![deny(missing_docs)], clippyunwrap_used/expect_used/panic/indexing_slicingdenied.
Install
[]
= "0.1"
Example
use ;
let telemetry = init?;
// Hot-path handles register through the handed-out Arc.
let requests = telemetry
.metrics
.counter?;
requests.inc;
assert!;
telemetry.shutdown?;
# Ok::
With traces enabled:
[]
= { = "0.1", = ["otlp"] }
let telemetry = init?;
Spans export over OTLP/HTTP (protobuf, batched); the endpoint is trusted infrastructure — point it at your collector, not the public internet.
The config surface
| Builder call | Default | Notes |
|---|---|---|
new("service-name") |
— | required; becomes service.name |
.version("1.2.3") |
"0.0.0" |
becomes service.version |
.log_level("info") |
"info" |
any env-filter directive; RUST_LOG wins |
.log_format(LogFormat::Json) |
Json |
Json needs the json feature |
.metrics_budget(8192) |
8192 |
series cardinality guard |
.otlp_endpoint("…") |
none | otlp feature; none = no traces |
.sample_rate(1.0) |
1.0 |
clamped to 0.0..=1.0 |
Feature flags
| Feature | Default | Description |
|---|---|---|
metrics |
yes | metrics-kit registry via Telemetry::metrics() |
json |
yes | JSON log format via tracing-subscriber/json |
otlp |
no | OTLP trace export (opentelemetry-otlp + tracing-opentelemetry) |
--no-default-features builds a logs-only bootstrap (choose
LogFormat::Pretty explicitly; Json errors without the feature).
Why not otelkit::init?
otelkit v2 exposes a whole-subscriber init: it installs its own global
subscriber and returns a flush guard, so it cannot compose as a layer inside
this crate's single subscriber — and its OTLP path ignores the log format and
RUST_LOG. telemetry-init wires opentelemetry-otlp +
tracing-opentelemetry directly to keep one code path for every feature
combination.
Testing note
The global subscriber is a once-per-process resource. All tests that call
Telemetry::init live in a single deterministic function
(tests/global_init.rs), so the default multi-threaded harness cannot race
double-init assertions.
Performance
Init is a startup cost, measured as a smoke benchmark
(benches/init_bench.rs, cargo bench): subscriber construction is
filter-parse + layer assembly, microseconds-class; the metrics hot path is
metrics-kit's lock-free recording (see its README for the measured numbers).
License
Licensed under either of Apache-2.0 or MIT at your option.