Observability Fundamentals
Observability is the ability to understand what a system is doing from its outputs. Learn the three pillars — metrics, logs and traces — plus white-box versus black-box monitoring and why observability is more than dashboards.
What is this?
Observability is the ability to reason about the internal state of a system purely from its external outputs. In software that is captured by three signals: metrics (numbers over time), logs (discrete events) and traces (the journey of a single request across services). Monitoring asks 'is something broken?'; observability asks 'why is it broken?' and lets you ask questions you never thought to ask in advance, because the raw data is there to interrogate.
Why do you need it?
- You cannot fix what you cannot see — most production incidents are prolonged by gaps in the telemetry, not by lack of effort.
- Monitoring tells you a service is down; observability tells you which dependency, which code path and which deploy caused it.
- The three pillars answer different questions: metrics tell you what is happening, logs tell you what happened, and traces tell you where it happened in the call graph.
- White-box versus black-box thinking changes what you collect: internal instrumentation versus synthetic checks from outside.
- Cardinality decisions made on day one are painful to reverse later, so understanding series growth is a core skill.
Mental model
Driving a car
Observability
The dashboard gauges are metrics — speed, fuel, temperature. The driver's memory of recent events is logs. A GPS route replay that reconstructs every turn and stop is a trace. You can drive with only a speedometer, but you cannot explain a near-miss or reroute efficiently without the full picture.
How it works
- Instrumentation inside the application emits telemetry as things happen: metrics are recorded on counters and gauges, logs are written per event, and spans are created per unit of work.
- Exporters or agents ship that telemetry to collectors and storage backends such as Prometheus, Elasticsearch or Jaeger.
- Consumers query the stored data: dashboards render it for humans, alert rules evaluate it automatically, and ad-hoc query languages let engineers explore.
- A trace ID and shared labels (service, environment, region) let a single user request be correlated across every service it touches.
- Engineers drill from a suspicious dashboard spike down into the relevant trace, then into the specific log lines, to root-cause in minutes instead of hours.
The observability data flow from a running service to humans and automation.
Key commands
curl -s http://localhost:9090/metrics | headDump a white-box /metrics endpoint to see what a service exposes.
curl -s http://localhost:3000/healthzCheck an application health endpoint for a fast liveness answer.
docker psSee which containers are running and emitting telemetry.
kubectl get podsList the pods in a cluster, each of which should expose metrics.
ps aux | grep nodeFind the process behind a port so you can trace it back to telemetry.
Examples
Inspect a white-box metrics endpoint
$ curl -s http://localhost:9090/metrics | head -n 8# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.# TYPE go_gc_duration_seconds summarygo_gc_duration_seconds{quantile="0"} 1.02e-05go_gc_duration_seconds{quantile="0.5"} 4.03e-05go_gc_duration_seconds{quantile="1"} 3.2e-03go_gc_duration_seconds_sum 17.9go_gc_duration_seconds_count 4721 $ curl -s http://localhost:3000/healthz{"status":"ok","version":"1.4.2","uptime_seconds":86412}The first curl reads the raw exposition text of a Prometheus-compatible endpoint: HELP and TYPE lines describe the metric, then samples carry label sets like quantile=0.5. The second curl hits an application health endpoint. Together they are white-box observability: data produced from inside the service rather than inferred from outside.
In production
- Every service exposes /healthz and /metrics from day one, so rollouts are gated on real signal instead of guesswork.
- On-call engineers start every incident on a golden-signals dashboard — latency, traffic, errors and saturation — before touching logs.
- Platform teams publish a 'measure everything by default' standard so new services emit telemetry without special effort.
- Black-box synthetic probes complement white-box metrics, catching outages that internal instrumentation never reports because the app is dead.
- Telemetry volume and cardinality are reviewed quarterly so cost and storage stay predictable as services grow.
Best practices
- Instrument from day one; retrofitting telemetry into a running service is slow and error-prone.
- Standardize naming and structure across services, e.g. http_requests_total{method,status,route} everywhere.
- Review cardinality in code review: a new label with unbounded values multiplies the series count.
- Tag every signal with stable identifiers: service name, version, environment and region.
- Default every service view to the golden signals so the most important questions are answered first.
Common mistakes
- Treating dashboards as observability — a dashboard is only as good as the data feeding it, and you can only monitor what you instrument.
- Confusing monitoring with observability: monitoring checks known conditions, observability lets you investigate unknowns.
- Adding high-cardinality labels such as request IDs or user IDs to metrics, exploding the number of stored series.
- Storing logs as free-form text, which makes queries and cross-service correlation guesswork.
- Collecting telemetry only in production, so staging bugs ship because they were never visible.
Common issues
There is a gap in my metric chartThe exporter stopped responding or the scrape timed out during that window.
Check scrape target health (up metric) and the exporter's own logs; confirm the target never changed labels mid-stream.
Dashboard is empty even though the app worksTelemetry is stored under different label names or values than the dashboard query uses.
Run the query in the backend's explorer, inspect real label names with a series lookup, then fix the dashboard selector.
Logs appear but metrics do notThe log shipper works while the metrics exporter was never wired into the scrape config.
curl the /metrics endpoint directly, then add the target to the scrape job and reload.
Debugging tips
- Drill top-down: golden-signals dashboard, then trace, then specific log lines — never start with raw log dumps.
- Reproduce an issue in staging with the same instrumentation enabled so you can compare signals.
- Take a slow response's trace ID and follow the call graph; the widest span gap points at the bottleneck.
- Compare telemetry before and after the last deploy to isolate a regression to a specific change.
- Verify end-to-end: if a metric is missing, check the exporter, the scrape network path and retention before suspecting the app.
Interview checkpoint
Hands-on lab
- Explain the three pillars by handling real telemetry data
- Scrape a white-box metrics endpoint with curl
- Correlate a structured log line with a specific request
- Clean up the sandbox after the experiment
Instrument a Service and Inspect Its Telemetry
20 min · beginner
Quick quiz
Which pillar records a discrete, timestamped event with context?
What makes a metric label high-cardinality?
White-box monitoring observes a system from the outside without any internal instrumentation.
Cheat sheet
GET /metricsPrometheus exposition format for metricsGET /healthzLiveness — is the process alive?GET /readyzReadiness — can the process serve traffic?GET /healthApplication-level status with version and uptimeGET /debug/pprofGo runtime profiling endpointscurl /metricsWhat is happening (metrics)journalctl -u myappWhat happened (logs)trace_id in log linesWhere in the call graph (traces)golden signals viewLatency, traffic, errors, saturation