Monitorowanie i obserwowalność
Twój serwis checkout rzuca sporadycznymi błędami 504. Ślady urywają się na spanie bramki, dashboardy pokazują „wszystko na zielono”, a Twój PM chce ETA. Podejrzewasz dostawcę płatności, ale nie potrafisz tego udowodnić, bo połowa serwisów nie jest zinstrumentowana, a te które są, eksportują do instancji Jaeger, na którą nikt nie patrzy. To właśnie tę lukę asystenci AI do kodowania domykają najszybciej: zamieniają na wpół podłączony stos obserwowalności w ślady, metryki, dashboardy i alerty, które naprawdę odpowiadają na pytanie „co i dlaczego się zepsuło”.
Co z tego wyniesiesz
Dział zatytułowany „Co z tego wyniesiesz”- Działającą konfigurację OpenTelemetry dla Node.js z aktualnym API
@opentelemetry/resources2.x (bez przestarzałej klasyResource). - Trzy przepływy pracy specyficzne dla narzędzi (Cursor, Claude Code, Codex) do instrumentacji serwisu i postawienia stosu Grafany.
- Gotowe do wklejenia prompty na dashboardy z metrykami RED, korelację sygnałów i polowanie na wąskie gardła, które działają przy minimalnej edycji.
- Poprawne, zweryfikowane konfiguracje MCP dla Sentry i Grafany — te dwie, które naprawdę istnieją i są wydawane przez producentów.
- Podręcznik trybów awarii dla trzech problemów z obserwowalnością, które marnują najwięcej czasu: wysokiej kardynalności, brakujących śladów i burz alertów.
Przepływ pracy
Dział zatytułowany „Przepływ pracy”Krok 1: Zinstrumentuj serwis za pomocą OpenTelemetry
Dział zatytułowany „Krok 1: Zinstrumentuj serwis za pomocą OpenTelemetry”Zacznij od poproszenia agenta o podłączenie OTel. Przepływ instrumentacji jest w dużej mierze identyczny we wszystkich trzech narzędziach — różnica polega na tym, jak je wywołujesz i jak każde radzi sobie z edycją wielu plików. Wskaż agentowi jawnie aktualne API 2.x; pozostawiony sam sobie sięgnie po usuniętą klasę Resource i przestarzałe SemanticResourceAttributes.
Otwórz tryb Agent (Cmd/Ctrl+I) i odwołaj się do bazy kodu, aby podchwycił Twój istniejący punkt wejścia i zależności:
@codebase Set up OpenTelemetry for our Node.js Express service.
Requirements:- Use @opentelemetry/sdk-node with getNodeAutoInstrumentations- Build the Resource with resourceFromAttributes() from @opentelemetry/resources (the Resource class is removed in resources 2.x) and ATTR_SERVICE_NAME / ATTR_SERVICE_VERSION from @opentelemetry/semantic-conventions- OTLP/gRPC exporters for traces and metrics- Disable the fs instrumentation (too noisy)- Load it via node --require before app code, not inlinePrzejrzyj diff w edytorze wieloplikowym, zanim go zaakceptujesz — Cursor zwykle dotknie package.json, nowego instrumentation.ts oraz Twojego skryptu startowego.
Uruchom go z katalogu głównego repozytorium, aby Claude mógł zainstalować pakiety i utworzyć plik bootstrap w jednym przebiegu:
claude "Set up OpenTelemetry for this Express service. Use @opentelemetry/sdk-node,resourceFromAttributes() from @opentelemetry/resources (the Resource class is gone in 2.x),ATTR_SERVICE_NAME from @opentelemetry/semantic-conventions, and OTLP/gRPC exporters.Disable fs instrumentation. Wire it via --require in the start script."Claude instaluje pakiety, pisze instrumentation.ts i łata skrypt startowy w package.json. Użyj claude --output-format json, jeśli chcesz przechwycić listę plików do kontroli w CI.
Użyj Codex CLI (działającego na GPT-5.5) z poziomu repozytorium. Sandbox i zatwierdzenia sprawiają, że instalacje pakietów pozostają możliwe do przejrzenia:
codex --ask-for-approval on-request \ "Set up OpenTelemetry for this Express service: @opentelemetry/sdk-node with getNodeAutoInstrumentations, resourceFromAttributes() from @opentelemetry/resources (Resource class removed in 2.x), ATTR_SERVICE_NAME from @opentelemetry/semantic-conventions, OTLP/gRPC exporters, fs instrumentation disabled, loaded via --require."Dla przebiegu bez nadzoru w czystym checkoucie codex --full-auto pozwala mu instalować i edytować bez pytania. W rozszerzeniu IDE Codeksa lub w Codex Cloud wklej tę samą instrukcję jako zadanie — Cloud przydaje się, gdy chcesz, by zmiana wylądowała jako PR, który przejrzysz później.
Agent powinien wyprodukować coś zbliżonego do tego. Zwróć uwagę na API 2.x — resourceFromAttributes zamiast new Resource(...) oraz stałe z prefiksem ATTR_ zamiast SemanticResourceAttributes:
// instrumentation.ts — loaded via: node --require ./instrumentation.ts app.jsimport { NodeSDK } from '@opentelemetry/sdk-node';import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';import { resourceFromAttributes } from '@opentelemetry/resources';import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, ATTR_DEPLOYMENT_ENVIRONMENT_NAME,} from '@opentelemetry/semantic-conventions';import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
const sdk = new NodeSDK({ resource: resourceFromAttributes({ [ATTR_SERVICE_NAME]: process.env.SERVICE_NAME ?? 'checkout', [ATTR_SERVICE_VERSION]: process.env.SERVICE_VERSION ?? '0.0.0', [ATTR_DEPLOYMENT_ENVIRONMENT_NAME]: process.env.NODE_ENV ?? 'development', }), traceExporter: new OTLPTraceExporter({ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT }), metricReader: new PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter({ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT }), exportIntervalMillis: 30_000, }), instrumentations: [ getNodeAutoInstrumentations({ '@opentelemetry/instrumentation-fs': { enabled: false }, }), ],});
sdk.start();Dla spanów na poziomie biznesowym importuj API jawnie — trace i metrics pochodzą z @opentelemetry/api, którego automatyczna instrumentacja nie importuje za Ciebie:
import { trace } from '@opentelemetry/api';
export function startBusinessSpan(operation: string, attrs: Record<string, string>) { const tracer = trace.getTracer('business-operations'); return tracer.startSpan(operation, { attributes: { 'business.operation': operation, ...attrs } });}Krok 2: Postaw stos i dashboardy
Dział zatytułowany „Krok 2: Postaw stos i dashboardy”Gdy spany i metryki już płyną, postaw warstwę składowania i wizualizacji. Typowy stos to OTel Collector do rozdzielania ruchu, Prometheus na metryki, Loki na logi, Tempo na ślady i Grafana na wierzchu. Poproś agenta o plik Compose, a następnie o dashboard.
Konfiguracja Loki to miejsce, gdzie agenci najczęściej emitują martwą składnię. Nalegaj na aktualny schemat TSDB — boltdb-shipper, schema: v11 oraz klucz shared_store są przestarzałe i nie wystartują na Loki 3.x:
# Loki 3.x — TSDB schema (v13). shared_store is removed; do not add it.schema_config: configs: - from: 2024-04-01 store: tsdb object_store: s3 schema: v13 index: prefix: index_ period: 24h
storage_config: tsdb_shipper: active_index_directory: /loki/tsdb-index cache_location: /loki/tsdb-cache aws: s3: s3://endpoint/bucket s3forcepathstyle: true
compactor: working_directory: /loki/compactor compaction_interval: 10m # storage backend comes from storage_config; no shared_store hereKrok 3: Wygeneruj reguły alertów, które reagują na właściwy sygnał
Dział zatytułowany „Krok 3: Wygeneruj reguły alertów, które reagują na właściwy sygnał”Reguły alertów łatwo skonfigurować w subtelnie błędny sposób — nazwa metryki dryfuje, próg jest arbitralny albo reguła odwołuje się do metryki, której Twój eksporter już nie emituje. Poproś o reguły świadome SLO i przypnij metryki do tego, co kube-state-metrics faktycznie produkuje dzisiaj.
# Prometheus alert rules. Memory headroom uses kube_pod_container_resource_limits,# not the removed cAdvisor container_spec_memory_limit_bytes metric.groups: - name: service_health interval: 30s rules: - alert: HighErrorRate expr: | sum(rate(http_requests_total{status=~"5.."}[5m])) by (service) / sum(rate(http_requests_total[5m])) by (service) > 0.05 for: 5m labels: { severity: critical, team: platform } annotations: summary: "High error rate on {{ $labels.service }}" runbook_url: "https://wiki.example.com/runbooks/high-error-rate"
- alert: PodMemoryUsageHigh expr: | sum(container_memory_working_set_bytes{pod!=""}) by (pod, container) / sum(kube_pod_container_resource_limits{resource="memory"}) by (pod, container) > 0.9 for: 5m labels: { severity: warning } annotations: summary: "Pod {{ $labels.pod }} memory usage > 90%"Serwery MCP do monitorowania
Dział zatytułowany „Serwery MCP do monitorowania”Dwa serwery MCP zamieniają Twojego agenta w asystenta dyżurnego, który potrafi odczytywać dane na żywo o błędach i z dashboardów. Oba są oficjalne od producentów — zachowaj ostrożność, bo rejestr npm ma dla obu zarówno zaślepki, jak i podróbki firm trzecich.
Kanoniczna instalacja to zdalny serwer przez HTTP z OAuth — żadnego tokenu do zarządzania, działa identycznie w Cursorze, Claude Code i Codeksie:
claude mcp add --transport http sentry https://mcp.sentry.dev/mcpJeśli potrzebujesz lokalnego serwera stdio (środowisko odcięte od sieci albo self-hosted Sentry), użyj oficjalnego pakietu @sentry/mcp-server — a nie sentry-mcp, który jest niepowiązaną zaślepką 0.0.1. Zmienna środowiskowa to SENTRY_ACCESS_TOKEN, a instancje self-hosted przekazują --host z samą nazwą hosta:
{ "mcpServers": { "sentry": { "command": "npx", "args": [ "-y", "@sentry/mcp-server", "--access-token=${SENTRY_ACCESS_TOKEN}", "--host=your-org.sentry.io" ] } }}Grafana
Dział zatytułowany „Grafana”Oficjalny serwer to grafana/mcp-grafana, binarka Go dystrybuowana przez uvx (lub Docker/Helm) — a nie wrapper npm firmy trzeciej @leval/mcp-grafana. Uwierzytelniaj się tokenem konta serwisowego (GRAFANA_SERVICE_ACCOUNT_TOKEN); klucze API Grafany są przestarzałe:
{ "mcpServers": { "grafana": { "command": "uvx", "args": ["mcp-grafana"], "env": { "GRAFANA_URL": "https://grafana.example.com", "GRAFANA_SERVICE_ACCOUNT_TOKEN": "${GRAFANA_SERVICE_ACCOUNT_TOKEN}" } } }}Kiedy to się psuje
Dział zatytułowany „Kiedy to się psuje”Trzy tryby awarii odpowiadają za większość zmarnowanych godzin. Przekaż agentowi objaw wraz z konkretnym zapytaniem, które powinien uruchomić.
Prometheus zwalnia do pełzania, a pamięć puchnie — zwykle przez etykietę taką jak user_id lub surowy URL wysadzający liczbę szeregów czasowych.
Analyze our Prometheus instance for high-cardinality metrics:- Run topk(10, count by (__name__)({__name__=~".+"})) to find the worst metrics- Identify which labels are unbounded (user IDs, request IDs, raw paths)- Propose recording rules to pre-aggregate, and relabel_config to drop the offending labelsSpany pojawiają się dla niektórych serwisów, ale znikają na granicy — niemal zawsze to zepsuta propagacja kontekstu albo zbyt agresywny sampler.
Debug why traces stop at our API gateway:- Confirm W3C traceparent headers are forwarded on outbound calls- Check the sampler config (is it tail-based dropping the children?)- Verify the OTLP exporter endpoint and TLS for the downstream service- Show me how to force-sample one request end-to-end to prove the pathJeden incydent wyzwala pięćdziesiąt alertów i PagerDuty się topi. Lekarstwem jest grupowanie i inhibicja, a nie kolejne progi.
Our AlertManager floods during incidents. Rewrite the routing config to:- Group by alertname, cluster, and service with sane group_wait/group_interval- Add an inhibit_rule so a critical alert silences related warnings- Route critical to PagerDuty and warnings to Slack only during business hoursCo dalej
Dział zatytułowany „Co dalej”- Pipeline’y CI/CD — wepnij walidację dashboardów i reguł alertów do swojego pipeline’u wdrożeniowego.
- Reagowanie na incydenty — wykorzystaj sygnały, które właśnie zinstrumentowałeś, do szybszego postmortemu.
- Wzorce debugowania — przepływ trace-to-logs, gdy alert w końcu zareaguje.