TL;DR: Obserwowalność to zdolność zadawania systemowi produkcyjnemu pytań, których nie przewidziano przy pisaniu kodu. Zacznij od sygnałów wpływu na użytkownika, nie od dashboardów; najpierw instrumentuj granice; pilnuj kardynalności etykiet, zanim ona przypilnuje Twojej faktury; a każdy alert trzymaj do jednego standardu: budzi człowieka tylko wtedy, gdy potrzebna jest ludzka decyzja.
System powinien się tłumaczyć
Kiedy produkcja zawodzi, najgorszą odpowiedzią jest cisza. Drugą najgorszą — ściana zielonych dashboardów, podczas gdy użytkownicy wyraźnie cierpią. Debugowałem oba przypadki i mają wspólną przyczynę: telemetrię dodaną, żeby odhaczyć checklistę, a nie po to, żeby odpowiadać na pytania.
Rozróżnienie między monitoringiem a obserwowalnością jest u mnie praktyczne, nie akademickie. Monitoring odpowiada na pytania przewidziane: czy CPU jest wysokie, czy dysk pełny, czy endpoint żyje. Obserwowalność pozwala pytać o rzeczy nieprzewidziane: dlaczego checkout jest wolny dokładnie dla jednego tenanta, tylko przy retry, tylko od wtorkowego deployu. Incydenty produkcyjne żyją niemal w całości w tej drugiej kategorii.
Szczery system to taki, który potrafi zeznawać o własnym zachowaniu — również tym, którego się po nim nie spodziewano.
Metryki, logi, trace'y — do czego służy każdy
Trzy typy sygnałów to uzupełnienia, nie konkurenci — a większość budżetów na telemetrię przepala się, używając jednego tam, gdzie należał się inny:
- Metryki są tanie, zagregowane i szybkie w odpytywaniu. Mówią, że coś jest nie tak i jak bardzo. To właściwy kręgosłup alertowania, bo są stabilne i niedrogie w skali.
- Trace'y prowadzą pojedyncze żądanie przez usługi. Mówią, gdzie poszedł czas albo błąd. Jeden dobry trace często zastępuje godzinę grzebania w logach pięciu usług.
- Logi niosą dowolny szczegół. Mówią, dlaczego — kształt payloadu, wybraną gałąź, kontekst wyjątku. Ustrukturyzowane, skorelowane logi to złoto; nieustrukturyzowane to archiwum tylko do zapisu.
Spoiwem jest korelacja: identyfikator trace'u odbity na każdej linii loga i exemplary łączące metryki z trace'ami. Bez korelacji masz trzy osobne archiwa; z nią — jedną powierzchnię śledczą, w której każdy sygnał przekazuje pałeczkę następnemu.
Sygnały przed dashboardami
Typowy tryb porażki to obserwowalność „od dashboardu": zbuduj tablicę w Grafanie, zapełnij ją wszystkim, co eksportuje runtime, uznaj temat za zamknięty. Takie tablice robią wrażenie i nie odpowiadają na nic — bo nikt nie zdecydował, na jakie pytanie istnieje każdy panel.
Zaczynam od drugiego końca — od sygnałów wpływu na użytkownika, z których każdy ma pytanie i właściciela:
| Sygnał | Pytanie, na które odpowiada | Właściciel |
|---|---|---|
| Opóźnienie żądań (p50/p95/p99) | Czy użytkownicy czekają? | Zespół API |
| Wskaźnik błędów per endpoint | Czy użytkownikom się nie udaje? | Zespół API |
| Wiek kolejki (nie tylko głębokość) | Czy praca asynchroniczna utknęła? | Zespół workerów |
| Tempo spalania error budgetu | Czy wydajemy niezawodność za szybko? | Właściciel usługi |
| Nasycenie najrzadszego zasobu | Jak blisko jest sufit? | Platforma |
Wiek kolejki zasługuje na to wyróżnienie. Głębokość kolejki wygląda uspokajająco, podczas gdy zatruta wiadomość blokuje jej czoło; wiek obnaża problem natychmiast. Mierz, jak długo czeka najstarszy element, a nie ile elementów czeka.
Dashboardy stają się wtedy widokiem na te sygnały — jedna usługa, jeden ekran, wpływ na górze, przyczyny niżej. Dashboard wymagający przewijania podczas incydentu to dashboard porzucany podczas incydentu.
Trace'uj granice
Nie zinstrumentujesz wszystkiego i nie powinno się próbować. Tracing zarabia na swój koszt na granicach: wywołania API, handlery wiadomości, zapytania do bazy, joby w tle, integracje z zewnętrznymi systemami. Tam chowa się opóźnienie, tam mnożą się retry i tam zmienia się odpowiedzialność — czyli dokładnie tam, gdzie podczas incydentu wybuchają spory.
Dopinaj atrybuty, po których naprawdę będziesz filtrować. W systemach multi-tenant identyfikator tenanta jest niepodważalny; rozbicie opóźnień per tenant zlokalizowało mi więcej produkcyjnych zagadek niż jakiekolwiek inne pojedyncze zapytanie.
activity?.SetTag("tenant.id", tenantId);
activity?.SetTag("operation.name", "invoice.calculate");
activity?.SetTag("queue.age_ms", queueAge.TotalMilliseconds);
activity?.SetTag("retry.attempt", attempt);
activity?.SetTag("peer.service", "payments-gateway");
Używaj OpenTelemetry i jego konwencji semantycznych zamiast wymyślać własne nazwy atrybutów. Zysk nie jest ideologiczny — chodzi o to, że każdy backend, szablon dashboardu i przyszły członek zespołu rozumie http.response.status_code, a nikt nie rozumie mojStatusKod2.
Kardynalność to prawdziwy rachunek
Cennik telemetrii ma prostą fizykę: metryki kosztują za unikalną kombinację etykiet, logi i trace'y — za bajt. Błąd produkujący szokujące faktury to wkładanie wartości nieograniczonych — ID użytkowników, URL-i z parametrami, tokenów sesji — do etykiet metryk. Jedna nieuważna etykieta na ruchliwym liczniku potrafi wybić miliony szeregów czasowych.
Zasada kciuka: etykiety metryk muszą pochodzić z małego, zamkniętego zbioru, który dałoby się wypisać w code review. Wszystko nieograniczone należy do atrybutów trace'ów albo pól logów, gdzie kardynalność jest tania.
Trace'y przy dużym wolumenie próbkuj — ale z intencją. Head sampling na poziomie kilku procent trzyma koszty płasko i wystarcza do analizy opóźnień; tail sampling zachowujący każdy błąd i każde wolne żądanie przechowuje dokładnie te trace'y, których będziesz chcieć o trzeciej w nocy. Większość zespołów, z którymi pracuję, ląduje na hybrydzie: niski bazowy head sampling plus reguły tail dla błędów i odchyleń.
Alerty, którym ludzie ufają
Zmęczenie alertami to nie problem narzędzi, tylko dług projektowy, który procentuje. Każdy alert odpalony bez potrzeby działania uczy dyżurnego ignorować alerty — i ta lekcja przenosi się na ten jeden alert, który miał znaczenie.
Standard, do którego trzymam alerty: page oznacza, że teraz potrzebna jest ludzka decyzja. Wszystko inne to ticket albo adnotacja na dashboardzie. W praktyce:
- Alertuj na symptomy (opóźnienie widziane przez użytkownika, wskaźnik błędów, spalanie budżetu), nie na przyczyny (CPU, pamięć, restarty podów). Przyczyny należą do dashboardu otwieranego po symptomie.
- Każdy alert linkuje do runbooka — choćby trzy linie: co to znaczy, co sprawdzić najpierw, do kogo eskalować.
- Każdy odpalony alert przeglądany co tydzień: czy wymagał działania? Jeśli nie — strojenie albo kasacja. Bez wyjątków, inaczej zbiór tylko rośnie.
- Dla SLO — alertowanie po burn rate zamiast sztywnych progów: szybkie spalanie budzi natychmiast, powolny dryf spokojnie czeka na ticket.
Uwagi z produkcji
- Instrumentuj, zanim będzie potrzebne. Trace'u, którego zabrakło podczas incydentu, nie da się dodać wstecz. Instrumentacja granic wchodzi razem z funkcją, jako element definicji ukończenia.
- Testuj telemetrię. Zła metryka jest gorsza niż brak metryki — daje fałszywą pewność. W testach integracyjnych asertuj, że kluczowe zdarzenia i liczniki naprawdę emitują z oczekiwanymi atrybutami.
- Pilnuj kolektora jak usługi. Pipeline obserwowalności też zawodzi: gubione spany, opóźnione eksportery, pełne bufory. Monitoruj jego przepustowość — inaczej pierwszym znakiem kłopotów będzie podejrzanie cichy dashboard.
- Retencja to decyzja, nie domyślna wartość. Trzydzieści dni trace'ów, dziewięćdziesiąt metryk i warstwa archiwalna dla logów compliance pokrywa większość produktów. Decyduj świadomie — domyślne ustawienia vendora optymalizują vendora.
Podsumowanie
- Obserwowalność odpowiada na pytania nieprzewidziane; monitoring tylko na przewidziane. Incydenty żyją w pierwszej kategorii.
- Metryki mówią „że", trace'y „gdzie", logi „dlaczego" — korelacja czyni z nich jedną powierzchnię.
- Zdefiniuj sygnały wpływu na użytkownika z właścicielami, zanim powstanie jakikolwiek dashboard.
- Najpierw instrumentuj granice; odbijaj atrybuty tenanta i operacji, po których będziesz filtrować.
- Etykiety metryk trzymaj ograniczone; dane nieograniczone kieruj do trace'ów i logów; próbkuj z regułami tail dla błędów.
- Page znaczy: teraz potrzebna ludzka decyzja — przeglądaj odpalone alerty co tydzień i kasuj szum.