Observability
Logs, metrics, traces, and health checks with swappable defaults for production deployments.
Observability
Tako covers the three usual pillars — logs, metrics, traces — plus health checks, with sensible defaults that you can swap when the deployment demands something specific.
use tako::Method;
use tako::middleware::IntoMiddleware;
use tako::middleware::access_log::AccessLog;
use tako::middleware::healthcheck::Healthcheck;
use tako::middleware::request_id::RequestId;
use tako::middleware::traceparent::Traceparent;
use tako::plugins::metrics::PrometheusMetricsConfig;
use tako::responder::Responder;
use tako::router::Router;
async fn hello() -> impl Responder { "ok" }
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let listener = tokio::net::TcpListener::bind("127.0.0.1:8080").await?;
let mut router = Router::new();
// Request IDs: generate X-Request-ID for inbound, propagate for outbound.
let request_id = RequestId::new().into_middleware();
// Access log: one structured line per request via the `tracing` macros.
let access_log = AccessLog::new().into_middleware();
// W3C Trace Context: parse `traceparent` / `tracestate`, expose them as
// a TraceContext extension so handlers can propagate the span.
let traceparent = Traceparent::new().into_middleware();
// Health endpoints at /live, /ready, /__drain (and a SIGTERM-friendly handle).
let healthcheck = Healthcheck::new();
let _drain = healthcheck.handle();
let healthcheck_mw = healthcheck.into_middleware();
router.middleware(request_id);
router.middleware(access_log);
router.middleware(traceparent);
router.middleware(healthcheck_mw);
// Prometheus scrape endpoint at /metrics (set via PrometheusMetricsConfig).
let _registry = PrometheusMetricsConfig::default().install(&mut router);
router.route(Method::GET, "/", hello);
tako::serve(listener, router).await;
Ok(())
}The pieces:
- Logs —
AccessLogmiddleware emits one structured line per request. The default sink istracing::info!; supply a custom sink via.sink(|record| { ... })for JSON / OTLP / file rotation. - Metrics —
PrometheusMetricsConfig::install(&mut router)(featuremetrics-prometheus) wires a Prometheus scrape endpoint and a request-latency histogram withwith_buckets(..)overrides. The matched-route label is bounded so cardinality stays finite. For OpenTelemetry OTLP export, useOtelMetricsConfig::default().with_endpoint(..).install(&mut router)?from themetrics-opentelemetryfeature. See the metrics middleware reference for details. - Tracing —
Traceparentparses W3C Trace Context and stores aTraceContextextension; outbound spans propagate automatically through the v2 client. - Health —
Healthcheck::new()exposes/live,/ready,/__drainwith configurable paths via.live_path(..),.ready_path(..),.drain_path(..).HealthcheckHandle::drain()flips the gate so/readystarts returning503— a SIGTERM handler can call it before draining connections.
See:
examples/healthfor the readiness endpoint shape,examples/metrics-opentelemetryfor OTLP export.
HTTP/3 qlog and traceparent propagation through the v2 outbound
client are deferred follow-up items.