Konfiguracja obserwowalności z Claude Code
Konfiguracja obserwowalności z Claude Code polega na tym, że agent dodaje do istniejącej usługi tracing OpenTelemetry, logi strukturalne skorelowane ze śladami, reguły alertów Prometheus i dashboardy Grafana, a hooki, reguła deny, subagent weryfikujący i serwer MCP Grafany sprawdzają każdy wygenerowany plik. Nikt nie czyta YAML-a linijka po linijce; dowodem są testy promtool i zapytania na żywo.
Jest druga w nocy i odzywa się pager: „wysoki odsetek błędów na API”. Dashboard pokazuje skok odpowiedzi 5xx, ale bez trace ID, bez korelacji z logami i bez śladu, które wywołanie zewnętrzne pada. Przez 40 minut grepujesz niestrukturalne logi, żeby znaleźć timeout u dostawcy płatności, którego naprawa zajmuje dwie minuty. Ta strona jest dla developera, który odpowiada za taką usługę, i dla tech leada, który zatwierdza jej alerty.
Ta strona opisuje warstwę Claude Code wokół samej pracy: tryb planowania, CLAUDE.md, hooki, reguły uprawnień, subagentów i uruchomienie headless (bez interakcji). Sam stos (kolektor, Loki, Tempo, nazwy metryk i kontrole w CI) opisuje niezależnie od narzędzia strona monitoring i obserwowalność z agentami AI. Obserwowanie samego Claude Code, czyli jego sesji, kosztów i wywołań narzędzi, opisuje strona obserwowalność agentów.
Co zyskujesz, konfigurując obserwowalność z Claude Code
Dział zatytułowany „Co zyskujesz, konfigurując obserwowalność z Claude Code”- Prompt dla trybu planowania, który inwentaryzuje usługę, zanim powstanie jakakolwiek instrumentacja.
- Blok w
CLAUDE.md, który utrwala konwencje obserwowalności dla każdej kolejnej sesji. - Hook
PostToolUse, który po każdej edycji uruchamiapromtooliamtool, oraz regułę deny, która trzyma testy alertów poza zasięgiem agenta. - Gotowe prompty: OpenTelemetry ze skorelowanymi logami, alerty burn-rate z testami jednostkowymi i sprawdzenie dashboardu przez serwer MCP Grafany.
- Subagenta weryfikującego i uruchomienie headless, które wytwarzają dowody dołączane do pull requesta.
W jakiej kolejności Claude Code powinien budować obserwowalność?
Dział zatytułowany „W jakiej kolejności Claude Code powinien budować obserwowalność?”Każda warstwa jest tak dobra jak ta pod nią. Alert na metrykę, której usługa nigdy nie emituje, milczy zawsze, i nic nie zgłasza, że milczy. Buduj w tej kolejności i nie pozwól Claude przeskakiwać etapów.
| Krok | Co robi Claude Code | Mechanizm Claude Code | Co to udowadnia bez czytania |
|---|---|---|---|
| 1. Mapa | Inwentaryzuje punkty wejścia, klienty, kolejki i logowanie | Tryb planowania (tylko odczyt) | Tabela inwentaryzacji, którą zatwierdzasz |
| 2. Instrumentacja | Dodaje SDK OpenTelemetry i logger strukturalny | Konwencje w CLAUDE.md | Trace ID jednego żądania w kolektorze i w linii logu |
| 3. Alerty | Pisze reguły i testy promtool | Hook PostToolUse, reguła deny na testy | Zielone promtool test rules z przypadkami „musi odpalić” i „musi milczeć” |
| 4. Dashboard | Pisze JSON dashboardu | Serwer MCP Grafany, tylko odczyt | Tabela, w której każdy panel zwraca serie |
| 5. Dowody | Ponownie uruchamia wszystkie kontrole i raportuje | Subagent weryfikujący, claude -p | Raport JSON dołączony do pull requesta |
Zmapuj usługę, zanim Claude napisze jakąkolwiek instrumentację
Dział zatytułowany „Zmapuj usługę, zanim Claude napisze jakąkolwiek instrumentację”Zacznij w trybie planowania: Claude czyta kod i proponuje plan, niczego nie edytując. Oceniasz inwentaryzację, czyli 20 linijek zamiast diffu na 600.
# Terminal, w katalogu głównym repozytoriumclaude --permission-mode planNajważniejszy jest wiersz 6. Automatyczna instrumentacja obejmuje standardowe serwery HTTP i sterowniki baz danych, a pomija konsumentów kolejek i ręcznie pisane klienty. W tej luce ślady później urywają się na granicy usług.
Utrwal konwencje obserwowalności w CLAUDE.md
Dział zatytułowany „Utrwal konwencje obserwowalności w CLAUDE.md”Każda kolejna sesja, także ta, która za pół roku poprawi alert, powinna trzymać się tych samych zasad. Zapisz je w projektowym CLAUDE.md, a nie w każdym prompcie.
## Observability conventions
- Tracing: OpenTelemetry via src/instrumentation.ts, loaded with node --require before the app. Build resources with resourceFromAttributes(); the Resource class is gone in resources 2.x.- Logging: pino only. JSON in production. Every entry carries trace_id and span_id from the active span. Redact password, token, secret, authorization, cookie and card fields.- Metric names: read them from the running Prometheus before writing any query (curl -s localhost:9090/api/v1/label/__name__/values). Never write a metric name from memory.- Alerts live in observability/alerts.yml. observability/alerts_test.yml is the oracle: never edit it. If a test fails, fix the rule or explain why the test is wrong.- Every alert has severity, summary and runbook_url labels or annotations.- Dashboards live in observability/dashboards/*.json and use a $service template variable.Dodaj tracing i skorelowane logi
Dział zatytułowany „Dodaj tracing i skorelowane logi”Po zatwierdzeniu planu przełącz się na zwykły tryb i uruchom prompt startowy. Przypina on aktualne API OpenTelemetry, bo modele uczone na starszych tutorialach sięgają po usuniętą klasę Resource. Wersje pakietów aktualne na 2026-09-26 (odczytane przez npm view): @opentelemetry/sdk-node 0.222.0, @opentelemetry/auto-instrumentations-node 0.80.0, @opentelemetry/resources 2.11.0 i pino 10.3.1.
Krok 6 sprawdź sam na prawdziwym kolektorze, zamiast ufać transkryptowi. Jednorazowy kolektor z eksporterem debug wypisuje każdy odebrany span:
# otel-debug.yaml: lokalny kolektor, który tylko wypisuje to, co odebrałreceivers: otlp: protocols: grpc: { endpoint: 0.0.0.0:4317 } http: { endpoint: 0.0.0.0:4318 }exporters: debug: { verbosity: detailed }service: pipelines: traces: { receivers: [otlp], exporters: [debug] }# Terminal 1: uruchom kolektordocker run --rm -p 4317:4317 -p 4318:4318 \ -v "$PWD/otel-debug.yaml:/etc/otelcol-contrib/config.yaml" otel/opentelemetry-collector-contrib
# Terminal 2: wyślij żądanie, potem wyszukaj w wyjściu kolektora trace ID wypisane przez Claudecurl -s localhost:3000/healthInstrumentacja jest udowodniona, gdy ten sam trace ID pojawia się w wyjściu kolektora i w jednej linii logu JSON. Jeśli pojawia się tylko w jednym miejscu, korelacja nie działa i żaden późniejszy krok tego nie naprawi.
Niech każda edycja alertu sama się sprawdza dzięki hookowi
Dział zatytułowany „Niech każda edycja alertu sama się sprawdza dzięki hookowi”Reguły alertów to małe programy, a promtool test rules to narzędzie, które je testuje. Specyfika Claude Code polega na tym, że kontrola dzieje się automatycznie: hook PostToolUse uruchamia walidator po każdej edycji w observability/, a kod wyjścia 2 zwraca błąd prosto do Claude, który poprawia go w następnym kroku. Mechanikę opisuje strona automatyzacja z hookami.
#!/usr/bin/env bash# .claude/hooks/check-observability.sh (PostToolUse, matcher "Edit|Write")set -uo pipefailfile=$(jq -r '.tool_input.file_path // empty')dir=$CLAUDE_PROJECT_DIR/observability
case "$file" in "$dir"/alerts*.yml) if ! out=$(cd "$dir" && promtool check rules alerts.yml 2>&1 && promtool test rules alerts_test.yml 2>&1); then echo "Alert rules fail their checks. Fix alerts.yml, not the test file:" >&2 tail -n 30 <<<"$out" >&2 exit 2 fi ;; "$dir"/alertmanager.yml) if ! out=$(amtool check-config "$file" 2>&1); then echo "Alertmanager config is invalid:" >&2; tail -n 20 <<<"$out" >&2; exit 2 fi ;; "$dir"/dashboards/*.json) jq empty "$file" 2>/dev/null || { echo "Dashboard JSON does not parse: $file" >&2; exit 2; } ;;esacexit 0Zarejestruj hook i regułę deny w .claude/settings.json. Reguła deny powstrzymuje agenta, któremu kazano „sprawić, by testy przechodziły”, przed osłabieniem asercji zamiast poprawienia reguły; uzasadnienie znajdziesz na stronie ochrona wyroczni testowej.
{ "permissions": { "deny": ["Edit(./observability/alerts_test.yml)"] }, "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/check-observability.sh", "args": [], "timeout": 60 }] } ] }}alerts_test.yml pisze człowiek albo Claude szkicuje go w osobnej sesji, zanim zacznie obowiązywać reguła deny, a tech lead go przegląda. Plik jest krótki: kilka syntetycznych serii i momenty, w których alert musi i nie może odpalić. To w nim zapisana jest intencja, więc to jedyny plik, który warto przeczytać.
Spodziewaj się tu jednej pułapki z nazwami. W wersji 0.222.0 pakietu @opentelemetry/instrumentation-http (sprawdzone 2026-09-26) instrumentacja HTTP dla Node emituje wyłącznie stabilny histogram http.server.request.duration, w sekundach. Większość danych treningowych używa starszego http.server.duration albo http_requests_total. Właśnie dlatego istnieje krok 1 promptu; szczegóły opisuje strona monitoring i obserwowalność z agentami AI.
Sprawdź każdy panel dashboardu przez serwer MCP Grafany
Dział zatytułowany „Sprawdź każdy panel dashboardu przez serwer MCP Grafany”Dashboard z błędną nazwą metryki wyświetla „No data”, co wygląda jak spokojny system. Daj Claude dostęp do Grafany tylko do odczytu i każ mu uruchomić zapytanie każdego panelu, zamiast klikać po nich samodzielnie. Dodaj serwer w zakresie projektu, żeby ładował się tylko w tym repozytorium. mcp-grafana 1.6.0 z PyPI to oficjalny serwer Grafana Labs (sprawdzone 2026-09-26); szerszy katalog jest na stronie serwery MCP do obserwowalności.
# Terminal: token konta serwisowego z rolą Viewer, zapisy wyłączoneclaude mcp add grafana --scope project \ -e GRAFANA_URL=https://grafana.example.com \ -e 'GRAFANA_SERVICE_ACCOUNT_TOKEN=${GRAFANA_SERVICE_ACCOUNT_TOKEN}' \ -- uvx mcp-grafana --disable-write--scope project zapisuje .mcp.json, który trafia do repozytorium. Pojedyncze cudzysłowy są tu istotne: zapisują dosłowne ${GRAFANA_SERVICE_ACCOUNT_TOKEN}, które Claude Code przy starcie rozwija ze środowiska każdego developera. Przy podwójnych cudzysłowach powłoka najpierw podstawi token i trafi on jawnym tekstem do commitowanego pliku.
Zbierz dowody z pomocą subagenta weryfikującego
Dział zatytułowany „Zbierz dowody z pomocą subagenta weryfikującego”Sesja, która napisała konfiguracje, słabo nadaje się do ich oceny. Własny subagent bez narzędzi edycji uruchamia wszystkie kontrole od nowa, w czystym kontekście, i raportuje wynik. Zapisz go jako .claude/agents/observability-verifier.md:
---name: observability-verifierdescription: Verifies observability changes. Use before opening a pull request that touches observability/, src/instrumentation.ts or src/logger.ts.tools: Read, Grep, Glob, Bash---
You verify, you never edit. Run and report, each with its exit code:1. promtool check rules and promtool test rules in observability/.2. amtool check-config observability/alertmanager.yml.3. jq empty on every observability/dashboards/*.json.4. A grep for console.log/warn/error under src/ (expect zero outside tests).5. A grep for logger calls that pass req, req.body, req.headers or a whole user object.6. git diff --exit-code origin/HEAD -- observability/alerts_test.yml (expect no diff).Finish with a PASS or FAIL line per check and nothing else.Ten sam raport uzyskasz bez sesji interaktywnej: uruchom go w trybie headless i dołącz JSON do pull requesta. dontAsk odrzuca wszystko, czego nie dopuszczają twoje reguły uprawnień, więc przebieg nie zboczy w stronę edycji.
# Terminal, w katalogu głównym repozytorium (nie w jobie CI z sekretami produkcyjnymi)claude -p "Use the observability-verifier subagent on this branch, wait for it to finish, and print its report." \ --permission-mode dontAsk \ --allowedTools "Bash(promtool *)" "Bash(amtool *)" "Bash(jq *)" "Bash(grep *)" "Bash(git diff *)" \ --output-format json > observability-evidence.jsonKontrole deterministyczne (promtool, amtool) powinny też działać w CI jako wymagane kroki; strona międzynarzędziowa ma gotowy job CI dla testów alertów. Subagent dokłada oceny, których linter nie zrobi, na przykład wywołanie loggera, przez które wycieka treść żądania.
Kto zatwierdza obserwowalność zbudowaną przez Claude Code?
Dział zatytułowany „Kto zatwierdza obserwowalność zbudowaną przez Claude Code?”Właściciel usługi zatwierdza na podstawie dowodów; tech lead odpowiada za progi i routing. Żaden z nich nie czyta wygenerowanych konfiguracji od deski do deski. Pull request zawiera:
- Zatwierdzoną inwentaryzację z trybu planowania, łącznie z wierszem ścieżek, które pomija automatyczna instrumentacja.
- Jeden trace ID widoczny w wyjściu kolektora i w linii logu JSON.
- Raport
observability-evidence.jsonz każdą kontrolą na PASS. - Tabelę paneli z promptu dashboardu, bez pustych paneli.
- Diff, który nie dotyka
alerts_test.yml, albo osobny, przejrzany commit, który go zmienia.
Tech lead czyta alerts_test.yml, cel SLO i trasy Alertmanagera, bo to one kodują intencję: co uznajemy za awarię i kogo budzimy.
Jak monitorować sam Claude Code?
Dział zatytułowany „Jak monitorować sam Claude Code?”Claude Code eksportuje własne metryki i zdarzenia OpenTelemetry. W wersji 2.1.283 nazwy metryk obejmują claude_code.session.count, claude_code.token.usage, claude_code.cost.usage, claude_code.lines_of_code.count, claude_code.commit.count, claude_code.pull_request.count i claude_code.code_edit_tool.decision. Żeby sprawdzić, czy eksport działa na twojej maszynie, najpierw wypisz metryki w terminalu:
# Terminal: punkt danych session.count powinien pojawić się po około 10 sekundachexport CLAUDE_CODE_ENABLE_TELEMETRY=1export OTEL_METRICS_EXPORTER=consoleexport OTEL_METRIC_EXPORT_INTERVAL=10000claudeNastępnie zmień OTEL_METRICS_EXPORTER na otlp i ustaw OTEL_EXPORTER_OTLP_PROTOCOL oraz OTEL_EXPORTER_OTLP_ENDPOINT tak, by wskazywały twój kolektor. Zmienna nazywa się CLAUDE_CODE_ENABLE_TELEMETRY; CLAUDE_CODE_TELEMETRY nie jest odczytywana (sprawdzone na 2.1.283). Wdrożenie dla całego zespołu przez ustawienia zarządzane, łączenie sesji z pull requestami i dashboard kosztu na zmianę opisuje strona obserwowalność agentów. Kontrolę wydatków opisuje kontrola kosztów.
Co się psuje, gdy Claude Code buduje obserwowalność?
Dział zatytułowany „Co się psuje, gdy Claude Code buduje obserwowalność?”Zapytania i alerty używają nazw metryk, które nie istnieją. Panele pokazują „No data”, a promtool przechodzi, bo serie testowe używają tych samych zmyślonych nazw. Naprawa: wklej do sesji wynik curl -s localhost:9090/api/v1/label/__name__/values | jq -r '.data[]' | grep '^http_server' i poproś Claude o przepisanie każdego zapytania i serii testowej w observability/ na te nazwy, z listą wszystkich zmian.
Hook nigdy się nie uruchamia. Claude edytuje alerts.yml i nic się nie dzieje. Otwórz /hooks w sesji, żeby zobaczyć, które hooki się załadowały i z którego pliku ustawień. Typowe przyczyny to skrypt bez bitu wykonywalności, brak promtool w PATH albo exit 1 tam, gdzie powinno być exit 2: tylko kod 2 zwraca wynik do Claude.
Claude obchodzi chroniony plik testów. Gdy edycja jest zablokowana, może skopiować testy do nowego pliku albo poluzować regułę tak, że stare testy przechodzą trywialnie. Naprawa: zapytaj „List every file you created or changed under observability/ and explain each change to alerts.yml in terms of which test it fixed.” Odrzuć każdą zmianę progów, której tech lead nie zatwierdził. Reguła deny obejmuje tylko narzędzia edycji plików: polecenie Bash, takie jak sed -i albo cp, nadal może nadpisać alerts_test.yml, dlatego kontrola 6 subagenta weryfikującego porównuje ten plik z gałęzią bazową.
Po migracji logowania rośnie wolumen albo koszt logów. Linie JSON są dłuższe, a health check logujący przy każdej próbie mnoży ich liczbę. Poproś: „Drop logging for GET /health and GET /ready, sample other 2xx request logs at 10%, and keep every warn and error. Show the change in log lines per minute on a local load run of 60 seconds.”
W logach pojawiają się dane osobowe. Logger zapisuje całe obiekty żądań w miejscach wskazanych przez inwentaryzację. Naprawa: uruchom kontrolę 5 subagenta weryfikującego, a potem poproś Claude o zastąpienie każdego wskazanego wywołania jawną listą pól i o rozszerzenie ścieżek redakcji. Logi już wysłane traktuj jako incydent w procesie ochrony danych, a nie jako poprawkę w kodzie.
Ślady urywają się na kolejce albo własnym kliencie. Automatyczna instrumentacja nie objęła wiersza 6 inwentaryzacji. Poproś: „For each consumer and client in row 6, show where the traceparent is injected on send and extracted on receive, add what is missing, and prove it with one trace that spans producer and consumer in the collector output.”