axum-prometheus

A Tower middleware that instruments Axum applications with Prometheus-ready HTTP request metrics out of the box.

Library
Cargo
v0.10.1
91stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
54/100Fair
Development Activity52
Maintenance48
Community40
Maturity56
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture80
Code Quality78
Innovation62
Learning Curve85

axum-prometheus is a small, focused Tower middleware for the Axum web framework that collects HTTP request metrics and exposes them through the metrics.rs ecosystem. Dropped onto a Router as a layer, it automatically tracks request totals, request duration histograms, and in-flight request counts, labeled by endpoint, method, and status, with no manual instrumentation of individual handlers required.

The crate builds on metrics.rs rather than binding directly to Prometheus, so while the default prometheus feature wires up metrics-exporter-prometheus as the backend, the same middleware can be repointed at StatsD or any other recorder by implementing a small MakeDefaultHandle trait. A dedicated PrometheusMetricLayerBuilder adds route-grouping patterns, ignore/allow lists, custom metric prefixes, and optional response body size tracking for teams that need more control than the one-line default setup.

What You Get

  • A ready-to-use PrometheusMetricLayer that tracks axum_http_requests_total, axum_http_requests_duration_seconds, and axum_http_requests_pending automatically
  • A MetricLayerBuilder for customizing endpoint labeling strategy, ignoring or grouping route patterns, and renaming metrics via a prefix
  • Optional response body size tracking as a histogram via enable_response_body_size
  • A GenericMetricLayer and MakeDefaultHandle trait so the same middleware can target StatsD or other metrics.rs backends instead of Prometheus
  • Optional push-gateway and http-listener feature flags that forward configuration straight to metrics-exporter-prometheus
  • Runnable examples covering a minimal setup, the builder API, endpoint-type customization, StatsD export, and raw BaseMetricLayer usage with a manual recorder

Common Use Cases

  • Exposing a /metrics Prometheus scrape endpoint for an Axum API without writing per-route timing code
  • Grouping dynamic path segments (like /users/:id) into a single labeled metric to keep cardinality under control
  • Excluding health-check or metrics endpoints themselves from being counted in request metrics
  • Renaming metrics with an application-specific prefix so multiple services can share one Prometheus instance without collisions
  • Swapping the default Prometheus exporter for StatsD or another metrics.rs recorder while keeping the same instrumentation code

Under The Hood

Architecture axum-prometheus is structured as a Tower Layer/Service pair: src/lifecycle/layer.rs and service.rs implement the middleware’s entry point, wrapping each inner Axum service call, while src/lifecycle/future.rs and body.rs track request duration and response body size across the async request lifecycle by wrapping the response future and body stream respectively. src/builder.rs implements a type-state builder (MetricLayerBuilder<T, M, S> with LayerOnly/Paired marker states via a sealed trait) that assembles a Traffic configuration — ignore/allow patterns, path-grouping rules, and an EndpointLabel strategy (exact URI, Axum’s MatchedPath, or a user fallback function) — before producing the layer. src/lib.rs ties this together behind PrometheusMetricLayer/PrometheusMetricLayerBuilder type aliases and a generic GenericMetricLayer for non-Prometheus backends, so swapping exporters changes only which concrete recorder is wired in, not the instrumentation path itself.

Tech Stack The crate targets Axum 0.8 and builds on tower 0.5 and tower-http 0.7 for its middleware plumbing, http/http-body 1.x for request/response types, and pin-project-lite for the projected async state in its future and body wrappers. Metrics collection goes through metrics 0.24, with metrics-exporter-prometheus 0.18 pulled in as an optional default-feature backend; matchit powers route-pattern matching for grouping and ignore rules. It’s a Tokio-based async crate (tokio with the multi-thread runtime and macros features) with no database, ORM, or CLI surface — it’s purely an in-process middleware library, distributed via crates.io with docs.rs API documentation.

Code Quality The crate has a real integration test suite in tests/ (base.rs, prefix.rs, plus shared helpers in common.rs) built around insta snapshot testing and http-body-util, exercising the middleware end-to-end against a fake Axum service rather than only unit-testing internals. CI (.github/workflows/base.yml) runs cargo clippy --all --all-targets --all-features and cargo fmt --all -- --check across both the crate root and the examples workspace on every push and PR, plus a separate cargo doc job with -D rustdoc::broken-intra-doc-links to keep the public API docs honest — a deliberately strict bar for a project of this size. Public types lean on Rust’s type system for correctness (the sealed type-state builder prevents building an invalid layer at compile time) and the crate carries an extensive CHANGELOG documenting behavior changes across releases.

What Makes It Unique Rather than hard-coding a Prometheus dependency, the crate separates “collect Axum HTTP metrics” from “export them somewhere,” using the MakeDefaultHandle trait and GenericMetricLayer so the identical instrumentation layer can target Prometheus, StatsD, or a hand-rolled recorder by swapping a single generic parameter — most comparable Axum metrics middlewares are Prometheus-only. Its EndpointLabel handling is also more careful than typical request-metrics middleware: it defaults to Axum’s MatchedPath extractor for low-cardinality route labels, only falling back to the raw request URI when no matched pattern is available, with an escape hatch for teams to supply their own fallback normalization function.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search