Expand description
Request ids, access logs and Prometheus metrics
use ullun::observability::{AccessLog, Metrics, RequestIdLayer};
use ullun::prelude::*;
let metrics = Metrics::new();
App::new()
.middleware(RequestIdLayer::new()) // first: the others read the id
.middleware(AccessLog::new()) // one line per request
.middleware(metrics.clone()) // counters and latency histograms
.get("/metrics", metrics.handler()) // Prometheus text format
.get("/users/{id}", |req: Request| async move {
// requests of this route are logged and counted as `/users/{id}`,
// not once per id
Ok(Response::text(req.request_id().unwrap_or("-").to_string()))
})
.run("127.0.0.1:3000")
.await
.unwrap();Metric labels use Request::matched_path, the route pattern, so the
number of series is bounded by your routes, not by the ids or by whatever
paths scanners probe (all unmatched requests share route="unmatched").
Do not expose /metrics publicly without authentication or a network
boundary.
Structsยง
- Access
Log - One log line per request, written when the response is ready
- LogEntry
- One finished request, as handed to the log sink
- Metrics
- Request counters, latency histograms and an in-flight gauge, rendered in the Prometheus text format. Clone it: all clones share the numbers.
- Request
Id - The id of the current request, stored in
Request::extensions - Request
IdLayer - Assigns every request an id (or keeps a sane one sent by the caller),
exposes it as
Request::request_idand echoes it in a response header