Gendi Notes

Observability Fundamentals

Monitoring tells you **that** something is wrong. Observability is whether you can work out **why** without shipping new code — and the difference is what you can ask, not how many dashboards you have.

Level 2 concept observabilitymetricslogstraces

What is it?#

Three kinds of telemetry, each answering a question the others cannot.

METRICS LOGS TRACES ─────── ──── ────── numbers over time discrete events one request's path "5% of requests fail" "user 8821: timeout "auth 3ms → db 1.9s connecting to db" → render 40ms" cheap, aggregated expensive, detailed sampled, structural ANSWERS ANSWERS ANSWERS is something wrong? what exactly happened? WHERE is the time going? is it worse than to this one request which service is at fault last week?
MetricsLogsTraces
ShapeNumber + labels, sampledTimestamped text/JSONA tree of timed spans
CostLow, boundedHigh, grows with trafficMedium, usually sampled
RetentionMonths to yearsDays to weeksDays
Good atTrends, alerting, SLOsDetail, forensicsLatency across services
Bad atExplaining a single requestAggregation, trendsBeing complete (sampling)

Monitoring versus observability#

The distinction is often marketing, but there is a real idea underneath:

MonitoringObservability
Watches known failure modesLets you investigate unknown ones
"Is CPU above 80%?""Why are Egyptian Android users on v2.3 slow?"
Dashboards you built in advanceQuestions you did not anticipate
Fails on novel problemsDesigned for novel problems

The tool landscape#

The common open-source stack#

YOUR APPLICATION │ │ instrumented with OpenTelemetry SDKs ↓ ┌─────────────────────────────────────────────┐ │ OpenTelemetry Collector │ receive → process → export └─────────────────────────────────────────────┘ │ │ │ ↓ ↓ ↓ ┌──────────┐ ┌──────────┐ ┌──────────┐ │Prometheus│ │ Loki │ │ Tempo │ │ metrics │ │ logs │ │ traces │ └──────────┘ └──────────┘ └──────────┘ │ │ │ └────────────────┼────────────────┘ ↓ ┌──────────┐ │ Grafana │ one UI over all three └──────────┘ │ ┌──────────────┐ │ Alertmanager │ routing, grouping, silencing └──────────────┘
LayerOptionsNotes
InstrumentationOpenTelemetry, vendor SDKsOTel is the standard; it ends vendor lock-in at the code level
MetricsPrometheus, Thanos/Mimir/Cortex, VictoriaMetricsPrometheus does not scale horizontally alone — the others add that
LogsLoki, Elasticsearch/OpenSearch, ClickHouseLoki indexes labels only, which is why it is cheap
TracesTempo, Jaeger, ZipkinTempo is object-storage backed, so retention is cheap
VisualisationGrafana, KibanaGrafana queries all of the above
AlertingAlertmanager, Grafana AlertingRouting and deduplication, not detection
CommercialDatadog, New Relic, Honeycomb, DynatraceOne integrated product; billed per host, per GB, or per event

Pull versus push#

PULL (Prometheus) PUSH (OTel, StatsD, Datadog agent) ───────────────── ───────────────────────────────── monitoring system scrapes app sends to a collector /metrics on a timer │ │ │ ├─ failing to scrape IS ├─ works behind NAT / firewalls │ the health signal (up) ├─ works for short-lived jobs ├─ no client config ├─ no service discovery needed └─ needs reachability └─ you must detect silence yourself

Neither is better in the abstract. Pull gives you a free liveness signal; push works where the monitoring system cannot reach in. Most real systems end up with both — Prometheus scraping long-lived services, and a Pushgateway or OTel collector for batch jobs and edge workloads.

Correlation is the actual goal#

Three signals in three tools is three investigations. The value appears when you can move between them:

alert fires on the error-rate metric │ click through (exemplar links a metric sample to a trace ID) ↓ trace shows the slow span is "checkout → payments" │ click through (trace ID is in the log labels) ↓ logs for that trace ID show the exact error and the failing dependency

The mechanism that makes this work is a shared trace ID propagated through every service and attached to logs, plus exemplars linking metric samples to traces. That is a large part of why OpenTelemetry exists: one context propagation standard across all three pillars.

What goes wrong#

SymptomCauseFix
Prometheus OOMsCardinality — unbounded label valuesDrop the label with metric_relabel_configs
Log bill triples in a monthDebug logging left on; no samplingSample, and set per-service quotas
Dashboards everywhere, nobody looksBuilt per-tool, not per-questionFew dashboards, tied to SLOs
Alerts ignoredToo many, or none actionableAlert on symptoms with a runbook; delete the rest
Traces show nothing usefulSampling dropped the slow requestsTail-based sampling keeps errors and slow traces
Cannot correlateNo shared trace_id, unstructured logsOpenTelemetry context propagation
Metrics disagree with realityScrape interval hides short spikesdescribe / kernel counters are authoritative

Interview corner · الأسئلة اللي بتتسأل#

What are the three pillars, and when does each one fail you?

Metrics, logs and traces — and the useful half of the answer is the failure modes, because that is what shows you have used them.

PillarAnswersFails when
MetricsIs something wrong? Is it worse than before?You need one specific request — and high cardinality kills the system
LogsWhat exactly happened, in detailVolume and cost; aggregation is slow; useless if unstructured
TracesWhere is the latency, across servicesSampling — the interesting request may not have been kept

The order you actually use them: a metric alert says that something is wrong, a trace says where, and logs say what. Skipping to logs first is the common time-waster, because you are searching text for a problem you have not localised.

A service is slow. Walk me through using telemetry to find out why.

Go top-down, and say what each step eliminates:

① METRICS is it actually slow, and for whom? │ p99 by endpoint, by version, by region. │ → narrow: one endpoint? one deploy? one AZ? ↓ ② COMPARE what changed? overlay a deploy marker │ → "it started at 14:02, which is when v2.3 rolled out" ↓ ③ TRACES where does the time go inside a slow request? │ find a p99 exemplar, read the span breakdown │ → "1.9s of 2.0s is in the payments call" ↓ ④ LOGS what is that service actually saying? │ filter by trace_id, not by free text ↓ ⑤ CONFIRM fix, and watch the same p99 metric recover

What each step rules out: metrics eliminate "it is not actually slow" and narrow the blast radius; the change correlation eliminates most causes outright; traces eliminate "which service"; logs give the specific error.

Self-host Prometheus/Grafana/Loki, or buy Datadog?

It is a cost and focus question, not a technical one — say that first.

Self-hostedCommercial
Licence costNonePer host / per GB / per event
Real costEngineer time + storage + being on call for itThe bill
ScalingPrometheus does not scale horizontally alone — you add Thanos or MimirTheir problem
Data controlYours; required in some regulated environmentsLeaves your network
Time to valueWeeksDays

A defensible default: below roughly 20–30 engineers, buy. The salary cost of operating a reliable observability stack exceeds most licences, and observability is infrastructure that produces no product.

Reasons to self-host anyway: regulatory or data-residency constraints; a log volume where per-GB pricing is genuinely prohibitive; or you already have a platform team running it well.

And the hedge: instrument with OpenTelemetry regardless. It decouples your code from the backend, so the decision becomes a collector configuration change rather than touching every service — which turns a one-way door into a reversible one.

Key takeaways#

  • **Metrics say that, traces say where, logs say what.** Use them in that order.
  • Cardinality is the hard limit on metrics; sampling is the hard limit on traces. Tail-based sampling fixes the second.
  • Structured logs with a trace_id are what make correlation possible — retrofitting is expensive.
  • OpenTelemetry decouples instrumentation from backend, which keeps the build-versus-buy decision reversible.
  • Alert on symptoms with an action. Alert fatigue destroys the value of everything else.
  • Buy below ~20–30 engineers. Self-hosting is engineer-time, not free.
  • Sampled metrics can miss short spikes — the kernel's account is authoritative.

Last updated 2026-09-13