Observability Middleware (RED metrics) (Rust)
Topics: middleware, atomics, RED metrics, Service/Layer
Problem
Build a middleware that records the RED signals for every request — Rate, Errors,
Duration — plus a live in-flight gauge. The middleware wraps a Service (the same hand-written
synchronous shape as the other HTTP challenges).
pub struct Metrics { /* … */ }
impl Metrics {
pub fn new() -> Self;
pub fn middleware<S: Service>(&self, next: S) -> MetricsService<S>;
pub fn snapshot(&self) -> Snapshot;
}
pub struct Stat { pub count: i64, pub avg: Duration }
pub struct Snapshot { pub in_flight: i64, pub stats: HashMap<String, Stat> }
For each request the wrapped service must:
- increment an in-flight gauge on entry, decrement on exit (even on an early return/panic);
- time the inner
call;
- record count + total duration keyed by
"{method} {path} {status}" (e.g. "GET /users 200").
snapshot() returns a consistent copy: per-key count and average latency, plus the current
in-flight count.
Key concepts
- Atomic gauge: the in-flight count is incremented/decremented concurrently — an
AtomicI64
avoids a lock on the hot path. A Drop guard makes the decrement panic-safe.
- Mutex map: the per-key
(count, total_ns) map needs a Mutex; snapshot derives each
average as total_ns / count.
- Status from the response: unlike Go's
ResponseWriter wrapping, the Response already
carries its status, so the key is built directly from it.
- RED method: Rate (count), Errors (count of 5xx keys), Duration (avg/percentiles) — the
standard request-level signals for a service.
Grading
Your solution.rs is compiled together with a trusted tests.rs (which include!s it) using
rustc --test. Only solution.rs is yours to edit.
Sign in to submit your solution.