Obserwowalność dla testerów — logi, ślady, awarie

Dowiedz się, jak używać logów, rozproszonych śladów i narzędzi APM do szybszego debugowania awarii podobnych do produkcyjnych, zrozumienia zachowania systemu pod obciążeniem i poprawy jakości sygnału.

To jest część 3 serii Architektura testów. Jeśli przegapiłeś Część 2 — Środowiska testowe bez wspólnego chaosu, zacznij tam.


Wprowadzenie — poza „Test przeszedł” i „Test nie przeszedł”

Test zawodzi. Asercja mówi: Oczekiwano 200, otrzymano 500.

To wszystko, co wiesz. Uruchamiasz test ponownie. Przechodzi. Wzruszasz ramionami i idziesz dalej.

To jest niewystarczający sygnał. Błąd 500 ma przyczynę. Coś przekroczyło limit czasu. Połączenie z bazą danych zawiodło. Serwis downstream zwrócił błąd. Brakowało klucza API. Ale wynik testu nie mówi Ci, które.

Tradycyjna automatyzacja testów daje Ci binarny sygnał: przeszedł lub nie przeszedł. W środowiskach podobnych do produkcyjnych z prawdziwymi integracjami ten sygnał nie wystarcza. Potrzebujesz obserwowalności — zdolności do sprawdzenia, co faktycznie wydarzyło się wewnątrz systemu podczas przebiegu testowego.

Obserwowalność nie jest tylko dla produkcji. Jest dla testowania. Logi, ślady i metryki zamieniają nieprzejrzyste awarie testów w debugowalne incydenty. Redukują czas od „test zawiódł” do „zidentyfikowano główną przyczynę” z godzin do minut.

Ten post pokaże Ci, jak używać narzędzi obserwowalności jako tester, aby debugować szybciej, rozumieć zachowanie systemu i poprawiać jakość sygnału testowego.


Trzy filary obserwowalności

1. Logi — dyskretne wiadomości o zdarzeniach

Czym są: Wiadomości ze znacznikiem czasowym, ustrukturyzowane, emitowane przez aplikację podczas wykonywania.

Przykład (strukturalny log w JSON):

{
  "timestamp": "2026-05-31T14:23:17Z",
  "level": "ERROR",
  "service": "checkout-api",
  "correlationId": "abc-123-def",
  "message": "Payment gateway timeout",
  "details": {
    "gatewayUrl": "https://payments.example.com/charge",
    "timeoutMs": 5000,
    "orderId": "order-789"
  }
}

Do czego są dobre:

  • Znajdowanie błędów, ostrzeżeń i wyjątków
  • Śledzenie sekwencji operacji w żądaniu
  • Debugowanie konkretnych awarii po ich wystąpieniu

Do czego nie są dobre:

  • Rozumienia wąskich gardeł wydajności (użyj śladów)
  • Śledzenia zagregowanych metryk w czasie (użyj metryk)

:::info[Logi strukturalne > Logi niestrukturalne] Logi strukturalne (JSON, pary klucz-wartość) są queryowalne. Możesz filtrować według correlationId, service, level lub dowolnego pola. Logi niestrukturalne (zwykły tekst) wymagają parsowania regex i są znacznie trudniejsze do pracy na dużą skalę. :::

2. Ślady — przepływ żądania przez serwisy

Czym są: Zapisy podróży pojedynczego żądania przez system rozproszony, pokazujące, które serwisy zostały wywołane, w jakiej kolejności i jak długo trwała każda operacja.

Przykład (wizualizacja rozproszonego śladu):

Request: POST /checkout
├─ checkout-api (120ms)
│  ├─ validate-cart (15ms)
│  ├─ inventory-service (80ms) ⚠️ WOLNE
│  │  └─ database query (75ms) ⚠️ WOLNE
│  └─ payment-service (20ms)
│     └─ payment-gateway (18ms)
└─ Total: 120ms

Do czego są dobre:

  • Identyfikowania, który serwis lub operacja spowodowała spowolnienie
  • Debugowania awarii timeout (który krok przekroczył limit czasu?)
  • Rozumienia zależności systemu (które serwisy wywołują które?)

Do czego nie są dobre:

  • Debugowania błędów logiki w pojedynczej funkcji (użyj logów)
  • Zagregowanych statystyk (użyj metryk)

:::tip[ID korelacji łączą logi i ślady] ID korelacji (zwany też trace ID lub request ID) to unikalny identyfikator przekazywany przez każdy komunikat logu i span śladu dla pojedynczego żądania. To pozwala filtrować wszystkie logi i ślady dla konkretnego przebiegu testowego. Zawsze dodawaj ID korelacji w konfiguracji testów. :::

3. Metryki — zagregowane statystyki w czasie

Czym są: Numeryczne pomiary zachowania systemu zagregowane w oknach czasowych (np. żądania na sekundę, wskaźnik błędów, latencja P95).

Przykład (dashboard metryk):

checkout-api.requests_per_second: 120
checkout-api.error_rate: 0.02 (2%)
checkout-api.latency_p95: 450ms
inventory-service.latency_p95: 2100ms ⚠️ WYSOKIE

Do czego są dobre:

  • Monitorowania ogólnego stanu systemu
  • Wykrywania trendów degradacji wydajności
  • Wyzwalania alertów, gdy progi są przekroczone

Do czego nie są dobre:

  • Debugowania pojedynczych awarii testów (użyj logów i śladów)

Jak testerzy używają narzędzi obserwowalności

Przypadek użycia 1: Debugowanie niestabilnego testu

Scenariusz: Test API, który tworzy zamówienie, zawodzi sporadycznie z błędem 500.

Bez obserwowalności:

  • Uruchom test ponownie 10 razy
  • Spróbuj reprodukować lokalnie (często niemożliwe, bo lokalne nie pasuje do stagingu)
  • Zgaduj przyczynę („prawdopodobnie race condition?”)

Z obserwowalnością:

  1. Pobierz ID korelacji z przebiegu testowego
  2. Zapytaj logi dla tego ID korelacji:
level=ERROR correlationId=abc-123-def service=inventory-service
message="Database connection timeout"
  1. Zidentyfikowano główną przyczynę: Pula połączeń bazodanowych serwisu inventory jest wyczerpana pod równoczesnym obciążeniem. Test nie jest niestabilny — infrastruktura jest niedoprowizjonowana.

Rozwiązanie: Zwiększ rozmiar puli połączeń lub zmniejsz współbieżność testów.

:::warning[Niestabilne testy często sygnalizują prawdziwe problemy] Test, który zawodzi sporadycznie na stagingu, często wskazuje na rzeczywiste ryzyko produkcyjne: niewystarczające pule połączeń, race conditions, błędne konfiguracje timeout. Nie ignoruj niestabilnych testów — użyj obserwowalności, aby znaleźć główną przyczynę. :::

Przypadek użycia 2: Rozumienie awarii timeout

Scenariusz: Test UI przekracza limit czasu, czekając na załadowanie strony.

Bez obserwowalności:

  • Zwiększ timeout i miej nadzieję, że przejdzie
  • Obwiniaj „wolne CI”

Z obserwowalnością:

  1. Sprawdź ślad dla żądania załadowania strony:
Request: GET /dashboard
├─ web-server (5200ms) ⚠️ TIMEOUT
│  ├─ auth-check (50ms)
│  └─ fetch-user-data (5100ms) ⚠️ TIMEOUT
│     └─ database query (5050ms) ⚠️ WOLNE ZAPYTANIE
└─ Total: 5200ms (timeout at 5000ms)
  1. Zidentyfikowano główną przyczynę: Zapytanie bazodanowe dla danych użytkownika zajęło 5 sekund. Domyślny timeout to 5 sekund. Test zawiódł, ponieważ zapytanie jest nieefektywne, nie dlatego, że CI jest wolne.

Rozwiązanie: Zoptymalizuj zapytanie bazodanowe (dodaj indeks, zmniejsz zbiór danych lub zdenormalizuj).

Przypadek użycia 3: Weryfikowanie zachowania systemu pod obciążeniem

Scenariusz: Testujesz nową warstwę cachingową. Chcesz potwierdzić, że cache hits rosną, a zapytania bazodanowe maleją.

Bez obserwowalności:

  • Uruchom test, sprawdź, czy przechodzi
  • Miej nadzieję, że cache działa

Z obserwowalnością:

  1. Sprawdź metryki przed i po włączeniu cache:
Przed cache:
  database.queries_per_second: 45
  api.latency_p95: 850ms

Po cache:
  database.queries_per_second: 8 ⬇️ 82% redukcja
  api.latency_p95: 120ms ⬇️ 86% poprawa
  cache.hit_rate: 92% ✅
  1. Potwierdzenie: Cache działa zgodnie z oczekiwaniami. Obciążenie bazy danych jest znacznie zmniejszone, a latencja poprawiona.

Konfigurowanie obserwowalności dla testów

Krok 1: Emituj logi strukturalne

Upewnij się, że Twoja aplikacja emituje logi strukturalne z:

  • Znacznikiem czasowym
  • Poziomem logu (INFO, WARN, ERROR)
  • Nazwą serwisu
  • ID korelacji
  • Danymi kontekstowymi (ID użytkownika, ID zamówienia, nazwa operacji)

Przykład (Node.js z Winston):

import winston from 'winston';

const logger = winston.createLogger({
  format: winston.format.json(),
  defaultMeta: { service: 'checkout-api' },
  transports: [new winston.transports.Console()]
});

logger.info('Utworzono zamówienie', {
  correlationId: req.headers['x-correlation-id'],
  orderId: order.id,
  userId: user.id
});

Krok 2: Zaimplementuj rozproszone śledzenie

Użyj narzędzia APM (Application Performance Monitoring) do zbierania śladów:

  • Sentry — Doskonałe do śledzenia błędów i monitorowania wydajności
  • Datadog APM — Kompleksowa platforma obserwowalności
  • Application Insights (Azure) — Natywna integracja z serwisami Azure
  • OpenTelemetry — Vendor-neutral standard dla śladów i metryk

Przykład (śledzenie Sentry):

import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: 1.0 // 100% próbkowania na stagingu
});

app.use((req, res, next) => {
  const transaction = Sentry.startTransaction({
    op: 'http.server',
    name: `${req.method} ${req.path}`
  });
  
  res.on('finish', () => transaction.finish());
  next();
});

Krok 3: Dołącz ID korelacji do przebiegów testowych

Generuj unikalny ID korelacji dla każdego przebiegu testowego i przekazuj go do każdego żądania API.

Przykład (Playwright):

test('stwórz zamówienie', async ({ request }) => {
  const correlationId = `test-${Date.now()}-${Math.random()}`;
  
  const response = await request.post('/api/orders', {
    headers: { 'X-Correlation-ID': correlationId },
    data: { productId: 123, quantity: 2 }
  });
  
  console.log(`Correlation ID: ${correlationId}`);
  expect(response.status()).toBe(201);
});

Gdy test zawodzi, możesz przeszukać logi i ślady dla tego ID korelacji, aby zobaczyć dokładnie, co się wydarzyło.

Krok 4: Zapytaj logi i ślady po awariach

Gdy test zawodzi, natychmiast zapytaj swoją platformę obserwowalności:

Sentry:

  • Przejdź do Issues → filtruj według ID korelacji
  • Zobacz pełny ślad i powiązane logi

Datadog:

  • Przejdź do APMTraces → filtruj według correlationId
  • Zobacz wykres płomieniowy i logi

Application Insights:

  • Przejdź do Transaction search → filtruj według customDimensions.correlationId

Przykład z rzeczywistości: Debugowanie timeout płatności

Awaria

Test dla przepływu checkout zawodzi z:

Error: Timeout waiting for element 'text=Zamówienie potwierdzone'

Śledztwo

  1. Pobierz ID korelacji z outputu testu: test-1733012345-0.789
  2. Zapytaj Sentry dla tego ID korelacji
  3. Znajdź ślad:
POST /api/checkout (8500ms) ⚠️ TIMEOUT
├─ validate-cart (10ms)
├─ charge-payment (8400ms) ⚠️ TIMEOUT
│  └─ payment-gateway-api (8350ms) ⚠️ TIMEOUT
│     └─ HTTP timeout after 8000ms
└─ Total: 8500ms
  1. Znajdź wpis w logu:
{
  "level": "ERROR",
  "service": "payment-service",
  "correlationId": "test-1733012345-0.789",
  "message": "Payment gateway timeout",
  "details": {
    "gatewayUrl": "https://payments-staging.example.com/charge",
    "timeoutMs": 8000,
    "httpStatusCode": null
  }
}

Główna przyczyna

Bramka płatności na stagingu jest wolna (8+ sekund). Timeout testu to 5 sekund. Test zawodzi nie dlatego, że aplikacja jest zepsuta, ale dlatego, że infrastruktura stagingu jest niedoprowizjonowana.

Naprawa

Dwie opcje:

  1. Zwiększ timeout dla testów stagingowych (pragmatyczna naprawa krótkoterminowa)
  2. Doprowizjonuj szybszą infrastrukturę dla bramki płatności (naprawa długoterminowa)

Bez obserwowalności zajęłoby to godziny zgadywania. Z obserwowalnością zajęło 2 minuty.


Antywzorce obserwowalności dla testerów

Antywzorzec 1: Ignorowanie logów, bo „Test przeszedł”

To, że test przeszedł, nie oznacza, że system zachowywał się optymalnie. Sprawdź logi pod kątem ostrzeżeń, wolnych zapytań i ponownych prób, nawet gdy testy przechodzą. Te sygnalizują przyszłe problemy z niezawodnością.

Antywzorzec 2: Nieuważanie ID korelacji

Jeśli Twoje testy nie emitują ID korelacji, nie możesz niezawodnie filtrować logów i śladów do konkretnego przebiegu testowego. Zawsze dołączaj unikalny ID do każdego testu.

Antywzorzec 3: Nadmierne poleganie na obserwowalności do naprawy złych testów

Obserwowalność pomaga debugować awarie, ale nie usprawiedliwia źle zaprojektowanych testów. Jeśli Twój test jest niestabilny, bo nie czeka prawidłowo, napraw test — nie patrz tylko na logi i wzruszaj ramionami.


Podsumowanie

Obserwowalność przekształca testowanie z binarnego sygnału przeszedł/nie przeszedł w bogaty, debugowalny proces śledczy.

Narzędzia:

  • Logi — znajdź błędy i wyjątki
  • Ślady — zrozum przepływ żądań i wąskie gardła wydajności
  • Metryki — monitoruj stan systemu w czasie

Praktyki:

  • Emituj logi strukturalne z ID korelacji
  • Używaj rozproszonego śledzenia do wizualizacji przepływu żądań
  • Dołączaj ID korelacji do każdego przebiegu testowego
  • Zapytaj logi i ślady natychmiast po awariach

Gdy przyjmujesz obserwowalność jako tester, spędzasz mniej czasu na zgadywaniu, a więcej na naprawie prawdziwych problemów. Awarie testów stają się okazjami do nauki o zachowaniu systemu, nie frustrującymi zagadkami.

:::tip[Obserwowalność opłaca się w produkcji] Te same narzędzia obserwowalności, których używasz do testowania, są jeszcze bardziej wartościowe w produkcji. Jeśli instrumentujesz swoją aplikację pod kątem testowalności, instrumentujesz ją również pod kątem niezawodności produkcyjnej. :::

Zadanie na ten tydzień: Wybierz jeden niestabilny test. Dodaj ID korelacji do testu. Uruchom go 10 razy i zbierz ID korelacji. Zapytaj swoje logi/ślady dla tych ID i zidentyfikuj główną przyczynę. Podziel się swoimi odkryciami z zespołem.


Dalej w serii: Część 4 — Projektowanie pod kątem testowalności, gdzie zbadamy, jak współpracować z deweloperami, aby budować aplikacje łatwe do testowania, z szwami, test ID, feature flags i hakami API.