Ruby & Rails

Three questions your monitoring should answer

Is it broken, what is slow, and why did this one request fail? Most setups answer the first and leave you grepping for the third.

3 December 2025 2 min read Mohammad Aaquib Jawed

Observability tooling is usually adopted as a product decision rather than a question one. It helps to work backwards from what you actually need to know.

Is it broken right now?

This is metrics: request rate, error rate, latency percentiles, saturation of whatever is finite — connection pool, queue depth, memory.

They are cheap, aggregate, and suit alerting. They cannot tell you why, and they should not try.

Alert on symptoms users feel, not on causes. High CPU is not an incident; a rising error rate is. Alerting on causes produces pages for conditions nobody would have noticed.

What is slow, and where?

This is tracing. A trace follows one request across the work it triggers, with timing per span.

It answers the question metrics cannot: not "the endpoint is slow" but "the endpoint is slow because it makes forty database calls, and this is the one taking most of the time".

Sampling keeps the cost reasonable, and sampling errors and slow requests at a higher rate than successful fast ones gets you the interesting traces without the volume.

Why did this specific request fail?

This is logs, and it is where most setups are weakest — not because logs are missing but because they cannot be correlated.

A request id on every line, propagated across services and into background jobs, is the single highest-value change available. Without it, investigating one failure means grepping timestamps and hoping.

Structured logs — key-value rather than prose — make them queryable. "All errors for this user in the last hour" should be a query, not a text search.

A log line you cannot correlate to a request is a sentence with no context. It is not much better than nothing.

Tie it together with one identifier

The pattern that makes all three work: generate an id at the edge, attach it to every log line, every trace and every job the request enqueues, and return it in error responses.

Then a user reporting a problem can give you the id from the error page, and you can see exactly what happened — logs, trace, and the jobs it spawned — without guessing which of four thousand requests was theirs.

That single thread is worth more than any individual tool, and it costs one middleware and a logging configuration.

All writing Reply by email