Observability

Logy, metriky, traces, p99, SLO/error budget.

Až ti jednou v noci spadne produkce, observability (pozorovatelnost) rozhodne, jestli problém najdeš za 5 minut, nebo za 5 hodin. Je to schopnost zvenčí pochopit, co se uvnitř systému děje — z toho, co o sobě systém „vypráví". Bez ní lítáš naslepo: víš, že něco nefunguje, ale netušíš proč. Mysli na to jako na palubní desku a diagnostiku auta — bez nich poznáš leda to, že nejedeš.


Pár pojmů na úvod

  • Monitoring = sleduješ předem dané ukazatele („kolik je volné paměti").
  • Observability = umíš se doptat i na věci, které tě předem nenapadly („proč byl zrovna tenhle request pomalý"). Monitoring je podmnožina.
  • Log = textový zápis jedné události („v 12:03 selhalo přihlášení uživatele 42").
  • Metrika = číslo měřené v čase (počet requestů za sekundu, využití paměti).
  • Trace = záznam cesty jednoho requestu, jak prošel přes jednotlivé služby.
  • Incident = situace, kdy je něco rozbité a řeší se to (často pod tlakem).

Tři pilíře observability

Stojí na třech druzích dat, každý odpovídá na jinou otázku:

PilířNa co odpovídáPodoba
LogyCo přesně se stalo v tomhle requestu?Jednotlivé záznamy událostí
MetrikyJak se systém chová celkově a v čase?Čísla měřená průběžně
TracesKudy request prošel a kde se zdržel?Cesta napříč službami

K dobrému debugu obvykle potřebuješ všechny tři.


Logy

  • Strukturované logování (ve formátu JSON, ne jen text) umožní v lozích strojově hledat a filtrovat — má pole jako čas, úroveň, jméno služby, ID requestu, ID uživatele, zpráva.
  • Úrovně: ERROR (něco se rozbilo), WARN (podezřelé), INFO (důležitá událost), DEBUG (detaily, v produkci obvykle vypnuté).
  • Correlation ID (ID requestu) v každém logu = lepidlo, kterým spojíš všechny logy jednoho requestu napříč službami. Bez něj je debug peklo.
  • Nikdy neloguj hesla, tokeny, čísla karet ani osobní údaje (bezpečnost a GDPR).
  • Logy se sbírají na jedno místo (centralizují), protože „prohledávat ručně 20 serverů" nejde.

Metriky

Čísla měřená průběžně, levná na uložení, ideální pro grafy a alerty. Užitečná zkratka pro služby je RED: Rate (kolik requestů za sekundu), Errors (kolik z nich chybuje), Duration (jak dlouho trvají).

⚠️ Sleduj percentily, ne průměr! Průměrná doba odezvy lže. Co je percentil: seřaď requesty od nejrychlejšího k nejpomalejšímu; p99 je hodnota, pod kterou padá 99 % z nich — tedy „skoro nejhorší" zkušenost: jen 1 ze 100 requestů je ještě pomalejší (a často ho mají ti největší zákazníci). Průměr ti tyhle pomalé případy schová mezi rychlými.

Pozor: percentily se nedají průměrovat ani sčítat napříč servery/okny (p99 ze dvou serverů není průměr jejich p99) — proto se posílají histogramy a percentil se dopočítá až z těch sečtených.


Traces (sledování cesty requestu)

Když jeden požadavek uživatele projde přes víc služeb, trace ho sleduje celou cestou a ukáže, kde se zdržel. Skládá se ze spanů — každý span je jeden úsek (volání služby, dotaz do databáze). Výsledek vypadá jako „vodopád", ze kterého hned vidíš viníka:

Aby trace fungovala, musí se trace ID protáhnout všemi službami — předává se v hlavičkách (standard W3C traceparent). Standard pro sbírání těchhle dat se jmenuje OpenTelemetry.

⚠️ Trace se nejčastěji „utne" na asynchronní hranici. Když request hodí úlohu do fronty a worker ji zpracuje o vteřiny později, musíš traceparent vložit do hlavičky zprávy a worker s ním pokračovat — jinak trace skončí u fronty a ztratíš souvislost přesně tam, kde to nejvíc bolí. (U fan-outu na víc zpráv se používají span links.)


SLI / SLO / SLA — jazyk spolehlivosti

Tyhle tři zkratky popisují, „jak moc má služba fungovat":

  • SLI (Indicator) = co konkrétně měříš (např. % requestů rychlejších než 200 ms).
  • SLO (Objective) = tvůj cíl pro tu metriku (např. 99,9 % requestů úspěšných za měsíc). Interní závazek.
  • SLA (Agreement) = smluvní slib zákazníkovi, často s pokutou. Bývá volnější než SLO.

A z toho plyne error budget (rozpočet na chyby): SLO 99,9 % znamená, že smíš být 0,1 % času mimo — to je asi 43 minut za měsíc. Dokud rozpočet máš, můžeš pouštět rizikovější novinky (jedeš rychle). Když ho vyčerpáš, přestaneš s novinkami a stabilizuješ. Spor „rychlost vs stabilita" se tím mění z dohadování na číslo, na kterém se tým shodne.


Alerting — ať tě budí jen důležité věci

  • Upozorňuj (alertuj) na dopady na uživatele (roste chybovost, p99 latence, fronta neklesá), ne na každý vnitřní výkyv.
  • Alert fatigue (únava z alertů) = když je planých alertů moc, lidi je začnou ignorovat — a tím přehlédnou i ten skutečný. Méně, ale smysluplných.
  • Dobrý alert je akční (vím z něj, co mám dělat) a má runbook (návod, jak na to reagovat).

Sampling, cardinality a co po incidentu

  • Sampling (vzorkování). Ukládat trace každého requestu by bylo strašně moc dat (a drahé). Proto se ukládá jen vzorek (třeba 1 % běžných) — plus obvykle všechny chybové a pomalé. Pozor: „ulož všechny chybové" jde jen u tail samplingu (rozhoduješ se až po dokončení trace, když znáš výsledek) — naivní head sampling (rozhodnu na začátku requestu) to neumí, protože na startu ještě nevíš, že request skončí chybou. Tail sampling je přesnější, ale dražší (musí celý trace nejdřív podržet v paměti).
  • Cardinality (kardinalita) — past u metrik. Kardinalita je rozpočet: je to součin počtu hodnot všech štítků (endpoint × status × region × pod ti vyrobí kombinatorický výbuch i bez ID). Štítek s hodně unikátními hodnotami (user_id) ten rozpočet rozstřelí na miliony časových řad a metrický systém zabije. Pravidlo: štítky jen pro věci s málo hodnotami. A most z agregované metriky ke konkrétnímu pomalému requestu jsou exemplars (metrika u sebe nese ukázkové trace ID).
  • Runbook. Návod „když naskočí tenhle alert, udělej krok 1, 2, 3". Ve 3 ráno nechceš vymýšlet — chceš číst.
  • Postmortem (rozbor po incidentu). Po větším výpadku se sepíše: co se stalo, proč, jak se to opravilo a co uděláme, aby se to neopakovalo. Klíčové je dělat ho bez hledání viníka (blameless) — cílem je opravit systém a proces, ne potrestat člověka. Jinak lidi přestanou chyby přiznávat.

Health checks — kontroly „zdraví" služby

  • Liveness = „žiju?" Když selže, orchestrátor službu restartuje (nejspíš se zasekla).
  • Readiness = „můžu už přijímat provoz?" Když selže (služba se ještě rozjíždí, databáze není dostupná), load balancer na ni přestane posílat requesty, ale nerestartuje ji. Živá ≠ připravená.

Failure modes — jak observability selže

  • Chybí correlation ID → nespojíš logy jednoho requestu, debug je peklo.
  • Jen průměry → pomalé p99 případy zůstanou skryté („u nás je to rychlé" — a přitom ne).
  • Alert fatigue → ignorovaný skutečný incident.
  • Logování citlivých dat → únik osobních údajů a problém s GDPR.

🛠️ Cvičení

  1. Tři pilíře na incidentu. Pro „uživatelé hlásí pomalé načítání" napiš, co bys hledal v metrikách, v traces a v lozích — a v jakém pořadí.
  2. Průměr lže. Máš 1000 dob odezvy: 990× 50 ms a 10× 2000 ms. Spočítej průměr a p99 a vysvětli, proč tě průměr uklidní neprávem (a proč p99 zachytí přesně ty „nejhorší 1 %").
  3. Navrhni RED metriky. Pro jeden endpoint urči Rate, Errors a Duration a řekni, na co bys nastavil alert (a na co ne).
  4. Error budget. Při SLO 99,9 % za měsíc — kolik minut smíš být mimo? Co uděláš, když ti rozpočet dojde už v půlce měsíce?
  5. Correlation ID. Request projde 4 službami. Popiš, jak skrz ně protáhneš jedno ID, abys spojil všechny logy téhož requestu.
Náčrt řešení — rozbal, až si cvičení zkusíš sám
  1. Tři pilíře na incidentu — pořadí: nejdřív metriky (RED — vyletěla error rate nebo p99 latence? odkdy?), pak traces (na waterfallu konkrétního pomalého requestu uvidíš, který span se zdržel — třeba databáze), nakonec logy daného requestu (proč se zdržel — spojíš je přes correlation ID). Pozor: jdeš od celkového obrazu (metriky) k jednomu requestu (trace) k detailu (log), ne naopak — od logů naslepo bys hledal věčně.
  2. Průměr lže — průměr = (990×50 + 10×2000) / 1000 = 69,5 ms (vypadá skvěle), ale p99 = 2000 ms (těch 10 nejpomalejších = nejhorší 1 %), což je přesně to, co ten „1 ze 100" reálně cítí. Pozor: průměr ten pomalý ocásek rozpustí mezi rychlými, takže tě uklidní neprávem — a bývají to ti nejaktivnější zákazníci, proto sleduj percentily.
  3. Navrhni RED metriky — pro endpoint urči Rate (requestů/s), Errors (kolik z nich chybuje, např. % 5xx) a Duration (p99 latence); alertuj na dopady na uživatele (skok chybovosti, p99 přes práh), ne na běžné kolísání Rate. Pozor: alert musí být akční a mít runbook — planý alert na každý výkyv vede k alert fatigue a přehlédneš ten skutečný.
  4. Error budget — SLO 99,9 % za měsíc znamená rozpočet 0,1 % času mimo, tj. asi 43 minut; když ti dojde v půlce měsíce, zmrazíš rizikové novinky a soustředíš se na stabilizaci. Pozor: error budget mění věčný spor „rychlost vs stabilita" na jedno číslo — dokud rozpočet máš, můžeš jet rychle, když ho vyčerpáš, brzdíš.
  5. Correlation ID — na vstupu requestu vygeneruj (nebo převezmi) jedno ID, vlož ho do každého logu a předávej dál v hlavičkách mezi službami (standard W3C traceparent), aby všechny čtyři služby logovaly pod stejným ID. Pozor: trace se nejčastěji utne na asynchronní hranici — když request hodí úlohu do fronty, musíš ID vložit do hlavičky zprávy, jinak souvislost ztratíš přesně tam, kde to nejvíc bolí.

🧠 Otázky & odpovědi

Jaký je rozdíl mezi logy, metrikami a traces?

Logy odpovídají na „co přesně se stalo v tomhle requestu" (jednotlivé události). Metriky odpovídají na „jak se systém chová celkově a v čase" (čísla, levná na grafy a alerty). Traces odpovídají na „kudy request prošel a kde se zdržel" (cesta napříč službami). Každý pilíř řeší jinou otázku — k debugu obvykle potřebuješ všechny tři.

Proč sledovat p99 místo průměru doby odezvy?

Průměr rozpustí pár velmi pomalých requestů mezi spoustou rychlých, takže vypadá vše v pořádku. Ale p99 (skoro nejhorší případ) ukáže, že 1 ze 100 uživatelů to má hrozně pomalé — a to bývají ti nejaktivnější zákazníci. Percentily odhalí reálné nejhorší případy, které průměr schová.

Co je error budget a jak řeší spor rychlost vs stabilita?

SLO 99,9 % znamená, že smíš být 0,1 % času mimo (~43 min/měsíc) — to je tvůj error budget. Dokud ho máš, můžeš pouštět rizikovější novinky (jedeš rychle). Když ho vyčerpáš, zmrazíš novinky a stabilizuješ. Věčný spor „rychlost vs spolehlivost" se tím promění v jedno číslo, na kterém se tým shodne.

Jaký je rozdíl mezi liveness a readiness?

Liveness = „žiju?" — když selže, orchestrátor službu restartuje (nejspíš se zasekla). Readiness = „můžu přijímat provoz?" — když selže (služba se rozjíždí, databáze je nedostupná), load balancer na ni přestane posílat requesty, ale nerestartuje ji. Živá ≠ připravená; míchání obojího vede buď ke zbytečným restartům, nebo k posílání requestů na nepřipravenou instanci.

Co je alert fatigue a jak se mu vyhnout?

Když je alertů moc (hlavně planých), tým je začne ignorovat — a tím přehlédne i ten skutečný incident. Vyhneš se mu tím, že upozorňuješ na dopady na uživatele (roste chybovost, p99, fronta neklesá), ne na každý vnitřní výkyv, a každý alert je akční a má runbook. Méně, ale smysluplných.

Proč nedávat user_id jako štítek (label) k metrice?

Protože vyrobíš obrovskou kardinalitu — každá unikátní hodnota štítku je samostatná časová řada, a ID uživatele jich má miliony. Metrický systém to zabije (drahé, pomalé, spadne). Štítky dávej jen pro věci s málo hodnotami (status, region, jméno endpointu). Na hledání konkrétního uživatele jsou logy a traces, ne metriky.

Co je blameless postmortem a proč na tom bez hledání viníka záleží?

Postmortem je rozbor po incidentu: co se stalo, proč, jak se to opravilo a co změnit, aby se to neopakovalo. Blameless (bez hledání viníka) znamená, že cílem je opravit systém a proces, ne potrestat člověka. Důvod je praktický: když lidé vědí, že je za chybu nikdo nepopraží, ochotně ji přiznají a popíšou, jak vznikla — a tým se z toho poučí. Hledání viníka vede k zatajování.