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ą:
- Pobierz ID korelacji z przebiegu testowego
- Zapytaj logi dla tego ID korelacji:
level=ERROR correlationId=abc-123-def service=inventory-service
message="Database connection timeout"
- 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ą:
- 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)
- 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ą:
- 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% ✅
- 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 APM → Traces → 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
- Pobierz ID korelacji z outputu testu:
test-1733012345-0.789 - Zapytaj Sentry dla tego ID korelacji
- 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
- 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:
- Zwiększ timeout dla testów stagingowych (pragmatyczna naprawa krótkoterminowa)
- 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.