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ď 100 requestů od nejrychlejšího k nejpomalejšímu; p99 je ten 99. v řadě, tedy „skoro nejhorší" zkušenost. p99 = 1 ze 100 uživatelů to má takhle špatné — a často jsou to ti největší zákazníci. Průměr ti tyhle pomalé případy schová mezi rychlými.


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áš 100 dob odezvy: 99× 50 ms a 1× 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ě toho „1 ze 100").
  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 = (99×50 + 2000) / 100 = 69,5 ms (vypadá skvěle), ale p99 = 2000 ms (99. hodnota v seřazené řadě), což je přesně ten „1 ze 100", co to má hrozně pomalé. Pozor: průměr ten jeden pomalý případ 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í.