Monitoring & Observability

Metrics, logs, and traces, so you hear about a failure before your users do.

What I do

Metrics on what you already run

I put metrics on the hosts, the app, and the cloud services you already run.

Which call ate the time

I trace the slow request so you can see which call ate the time.

An alarm that reaches a person

An alarm should reach the person who can fix it, and it should not fire all day.

What you get

The whole path

Host, app, and the dependency in between. A green dashboard that hides the failure is useless.

A dashboard you will open

I put the few graphs you'd check during an incident on one screen.

Page before the users do

The alarm fires on the thing that breaks the app, not on every CPU twitch.

After the graphs exist

Once the graphs exist, the slow path and the wasted capacity are easier to see.

How the work goes

What fails silently

I look at what you can already see, and what fails silently.

Which alarm pages a person

You get the metrics, the logs, and which alarm pages a person.

A dashboard and a test page

I install it, build the dashboard, and send a test page.

Quiet the noisy alarms

I tune the noisy alarms before I add more graphs.

Tools I use

These show up when they fit the job.

Prometheus logoPrometheus
Grafana logoGrafana
ELK Stack logoELK Stack
Datadog logoDatadog
New Relic logoNew Relic
Splunk logoSplunk
Nagios logoNagios
Zabbix logoZabbix
Jaeger logoJaeger
Zipkin logoZipkin
AWS CloudWatch logoAWS CloudWatch
Prometheus logoPrometheus
Grafana logoGrafana
ELK Stack logoELK Stack
Datadog logoDatadog
New Relic logoNew Relic
Splunk logoSplunk
Nagios logoNagios
Zabbix logoZabbix
Jaeger logoJaeger
Zipkin logoZipkin
AWS CloudWatch logoAWS CloudWatch

Situations I get called in for

Users report the outage before the alarm does

The dashboards were green while checkout failed. The alarms watched CPU and disk, and nothing watched the requests that broke.

On-call gets paged all night for nothing

Most pages clear on their own before anyone opens a laptop. After a few weeks people stop reading them, and the real one gets missed.

The monitoring bill grew faster than the app

Debug logs ship at full volume, and custom metrics multiply with every new label. The CloudWatch or Datadog invoice becomes its own line item.

A slow request with no clue where the time went

The request passes through several services and a queue. Each log says it was fine. Without a trace, nobody can say which hop was slow.

What I check first

Alarms on what users feel

On an ALB I start with HTTPCode_Target_5XX_Count and TargetResponseTime. Errors and latency come before CPU, because users feel those first.

Percentiles, not averages

An average latency can look fine while one request in a hundred takes ten seconds. I alarm on p99, or at least p95.

What happens when the data stops

A CloudWatch alarm treats missing data as missing by default. A service that dies and stops sending metrics can sit in INSUFFICIENT_DATA instead of ALARM. For heartbeat metrics I set missing data to breaching.

Label cardinality and log retention

A Prometheus label holding a user ID or a raw URL creates a new series for every value. In CloudWatch, each dimension combination is a separate custom metric. Log groups also never expire unless someone sets retention.

Trace context across every hop

OpenTelemetry passes the W3C traceparent header over HTTP. A queue drops it unless the producer writes it into the message attributes and the consumer reads it back.

If users hear about a failure before you do, start there.

Questions people ask