Observability & DevOps

OpenTelemetry mit Claude Code:
Observability 2026

Traces, Metrics, Logs, Auto-Instrumentation — Claude Code instrumentiert Node.js, Python und Go vollständig mit dem OpenTelemetry SDK.

📅 6. Mai 2026 ⏱ 11 min Lesezeit ✍️ SpockyMagicAI Team

Inhalt dieses Artikels

  1. OpenTelemetry Konzepte: Traces, Metrics & Logs
  2. Node.js Setup mit dem OTel SDK
  3. Distributed Tracing: Spans, Context & Propagation
  4. Metrics: Counter, Gauge & Histogramme
  5. Logs Integration & OTel Log Bridge
  6. Backends & Dashboards: Jaeger, Grafana, Loki

Moderne Softwaresysteme — besonders verteilte Microservices und KI-Agenten-Architekturen — erzeugen ein schier unüberschaubares Rauschen aus Ereignissen, Zustandsänderungen und Fehlern. Ohne strukturierte Observability bleiben Latenzsausen, Memory Leaks und kaskadierte Ausfälle unsichtbar, bis sie sich als kritische Incidents materialisieren.

OpenTelemetry (OTel) hat sich 2026 als de-facto-Standard für herstellerneutrale Observability etabliert. Das CNCF-Projekt vereint Traces, Metrics und Logs unter einem einheitlichen SDK, einem standardisierten Protokoll (OTLP) und einem flexiblen Collector — ohne Vendor-Lock-in.

In diesem Artikel zeigen wir, wie Claude Code TypeScript/Node.js-Projekte vollständig mit OpenTelemetry instrumentiert: von der SDK-Initialisierung über Distributed Tracing und Custom Metrics bis zur Log-Integration und dem Aufbau von Backends mit Jaeger, Prometheus und Grafana.

Hinweis: Alle Codebeispiele nutzen OpenTelemetry SDK for Node.js v1.x / @opentelemetry/* v0.5x und TypeScript 5.4. Claude Code generiert den Boilerplate-Code in Sekunden — Ihr Job ist die fachliche Instrumentierungsstrategie.

1. OpenTelemetry Konzepte: Traces, Metrics & Logs

OpenTelemetry definiert drei primäre Observability Signals. Jedes Signal hat eine eigene Semantik, eigene Datenstrukturen und eigene Exportformate — wird aber über das gemeinsame OTLP-Protokoll transportiert und vom OTel Collector verarbeitet.

🔍

Traces & Spans

Verfolgen eine einzelne Anfrage durch alle beteiligten Services. Jeder Service erzeugt einen Span; alle Spans einer Anfrage bilden einen Trace Tree.

📊

Metrics

Numerische Messwerte über Zeit: Request-Rate, Latenz-Histogramme, Error-Rate, Business-Metriken. Hocheffizient aggregiert, ideal für Alerting.

📝

Logs

Strukturierte Ereignisnachrichten, die einem Span-Kontext zugeordnet werden. OTel verbindet Logs mit Trace-IDs für vollständige Korrelation.

⚙️

OTel Collector

Empfängt, verarbeitet, filtert und exportiert Telemetriedaten. Läuft als Sidecar oder Gateway — entkoppelt Applikation vom Backend.

OTLP — das universelle Protokoll

Das OpenTelemetry Protocol (OTLP) überträgt alle drei Signal-Typen über gRPC oder HTTP/JSON. OTLP ist Vendor-neutral: Jaeger, Zipkin, Grafana, Datadog, Honeycomb — alle unterstützen heute OTLP-Ingest.

Vendor-Neutralität: der entscheidende Vorteil

Wer heute in OpenTelemetry investiert, bindet sich an kein kommerzielles Observability-Tool. Die Instrumentierung bleibt konstant; nur der Exporter-Endpunkt ändert sich. Claude Code generiert genau diesen entkoppelten Code.

Architektur-Überblick

Schicht Komponente Aufgabe
SDK @opentelemetry/sdk-node Instrumentiert die Node.js-Applikation; erzeugt Spans, Metrics, Logs
Collector otelcol-contrib Empfängt OTLP, transformiert, exportiert zu Jaeger/Prometheus/Loki
Backend Jaeger Trace-Speicher und -Visualisierung; UI für Span-Analyse
Metrics Prometheus + Grafana Metriken scrapen, aggregieren, dashboarden und alerten
Logs Loki + Grafana Log-Aggregation mit Trace-ID-Korrelation

2. Node.js Setup mit dem OTel SDK

Claude Code beginnt ein Instrumentierungsprojekt stets mit der Dependency-Installation und einer sauberen tracing.ts-Datei, die vor dem eigentlichen Applikationsstart geladen wird.

Pakete installieren

Terminal bash
# Kern-SDK + Auto-Instrumentierungen npm install \ @opentelemetry/sdk-node \ @opentelemetry/api \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/sdk-metrics \ @opentelemetry/sdk-logs \ @opentelemetry/api-logs \ @opentelemetry/exporter-trace-otlp-http \ @opentelemetry/exporter-metrics-otlp-http \ @opentelemetry/exporter-logs-otlp-http \ @opentelemetry/resources \ @opentelemetry/semantic-conventions # Prometheus Exporter (Scraping-Endpunkt) npm install @opentelemetry/exporter-prometheus # TypeScript-Typen npm install -D @types/node typescript ts-node

SDK initialisieren — tracing.ts

Diese Datei wird via --require vor dem eigentlichen Einstiegspunkt geladen, damit alle Auto-Instrumentierungen greifen, bevor HTTP-Server, Datenbank-Clients oder Message-Broker initialisiert werden.

src/tracing.ts TypeScript
import { NodeSDK } from '@opentelemetry/sdk-node'; import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'; import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'; import { Resource } from '@opentelemetry/resources'; import { SemanticResourceAttributes as SRA } from '@opentelemetry/semantic-conventions'; const OTEL_ENDPOINT = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? 'http://localhost:4318'; // OTel Collector HTTP Port const resource = new Resource({ [SRA.SERVICE_NAME]: process.env.SERVICE_NAME ?? 'my-service', [SRA.SERVICE_VERSION]: process.env.SERVICE_VERSION ?? '1.0.0', [SRA.DEPLOYMENT_ENVIRONMENT]: process.env.NODE_ENV ?? 'development', }); const traceExporter = new OTLPTraceExporter({ url: `${OTEL_ENDPOINT}/v1/traces`, }); const metricExporter = new OTLPMetricExporter({ url: `${OTEL_ENDPOINT}/v1/metrics`, }); const metricReader = new PeriodicExportingMetricReader({ exporter: metricExporter, exportIntervalMillis: 15_000, // alle 15 Sekunden exportieren }); const sdk = new NodeSDK({ resource, traceExporter, metricReader, instrumentations: [ getNodeAutoInstrumentations({ // HTTP-Requests automatisch tracen '@opentelemetry/instrumentation-http': { ignoreIncomingRequestHook: (req) => req.url?.includes('/health') ?? false, }, // Express-Routes automatisch tracen '@opentelemetry/instrumentation-express': { enabled: true }, // Datenbankabfragen tracen '@opentelemetry/instrumentation-pg': { enabled: true }, '@opentelemetry/instrumentation-redis': { enabled: true }, '@opentelemetry/instrumentation-mongodb': { enabled: true }, }), ], }); sdk.start(); console.log('OpenTelemetry SDK gestartet', { endpoint: OTEL_ENDPOINT }); process.on('SIGTERM', () => { sdk.shutdown() .then(() => console.log('OTel SDK sauber beendet')) .catch((err) => console.error('OTel Shutdown-Fehler', err)) .finally(() => process.exit(0)); });

Package.json anpassen

package.json (Auszug) JSON
{ "scripts": { "start": "node --require ts-node/register --require ./src/tracing.ts ./src/index.ts", "dev": "NODE_ENV=development ts-node --require ./src/tracing.ts src/index.ts" } }

Claude Code Tipp: Prompt „Instrumentiere meine Express-App mit OpenTelemetry SDK, ignoriere /health und /metrics Endpunkte beim Tracing, exportiere via OTLP nach localhost:4318" — Claude Code generiert die komplette tracing.ts inkl. Resource-Konfiguration.

3. Distributed Tracing: Spans, Context & Propagation

Auto-Instrumentierung deckt HTTP, Datenbank und Queue-Calls automatisch ab. Für Business-Logik — Zahlungsverarbeitung, KI-Inference, komplexe Berechnungen — braucht es manuelle Spans.

Spans manuell erstellen

src/services/payment.service.ts TypeScript
import { trace, SpanStatusCode, SpanKind, context } from '@opentelemetry/api'; const tracer = trace.getTracer('payment-service', '1.0.0'); export async function processPayment( orderId: string, amount: number, currency: string, ): Promise<PaymentResult> { // Span starten — KIND.CLIENT für ausgehende Calls return tracer.startActiveSpan( 'payment.process', { kind: SpanKind.CLIENT, attributes: { 'payment.order_id': orderId, 'payment.amount': amount, 'payment.currency': currency, }, }, async (span) => { try { // Validierung als Child-Span const validated = await tracer.startActiveSpan( 'payment.validate', async (valSpan) => { const result = await validateCard(orderId); valSpan.setAttribute('validation.passed', result.ok); valSpan.end(); return result; } ); if (!validated.ok) { span.setStatus({ code: SpanStatusCode.ERROR, message: validated.reason }); span.setAttribute('payment.failure_reason', validated.reason); throw new Error(`Zahlung abgelehnt: ${validated.reason}`); } // Event für wichtige Meilensteine setzen span.addEvent('payment.gateway_called', { 'gateway.name': 'stripe', 'gateway.attempt': 1, }); const result = await callStripeAPI({ orderId, amount, currency }); // Erfolgsstatus und Ergebnis-Attribute span.setStatus({ code: SpanStatusCode.OK }); span.setAttributes({ 'payment.transaction_id': result.transactionId, 'payment.gateway_latency_ms': result.latencyMs, }); return result; } catch (err) { span.recordException(err as Error); span.setStatus({ code: SpanStatusCode.ERROR }); throw err; } finally { span.end(); // IMMER aufrufen — auch bei Fehler! } } ); }

Context Propagation zwischen Services

Für Trace-Kontext-Weitergabe über HTTP-Grenzen hinweg nutzt OpenTelemetry den W3C Trace Context Standard (traceparent/tracestate Header). Die Auto-Instrumentierung für http/fetch erledigt dies automatisch.

src/utils/fetch-with-context.ts TypeScript
import { context, propagation, trace } from '@opentelemetry/api'; /** * Manuelles Context-Inject für nicht-auto-instrumentierte Clients */ export async function fetchWithContext( url: string, options: RequestInit = {} ): Promise<Response> { const headers: Record<string, string> = { ...(options.headers as Record<string, string>), }; // W3C TraceContext-Header injizieren propagation.inject(context.active(), headers); return fetch(url, { ...options, headers }); } // Baggage — Key/Value-Daten die mit dem Kontext propagiert werden import { propagation, baggageEntryMetadataFromString } from '@opentelemetry/api'; export function withTenantBaggage<T>( tenantId: string, fn: () => T ): T { const baggage = propagation.createBaggage({ 'tenant.id': { value: tenantId, metadata: baggageEntryMetadataFromString('tenant'), }, }); const ctx = propagation.setBaggage(context.active(), baggage); return context.with(ctx, fn); }

Achtung: span.end() muss in jedem Pfad aufgerufen werden — auch bei Exceptions. Offene Spans blockieren den Flush-Buffer und verfälschen Latenz-Messungen. Nutze try/finally als Pattern.

4. Metrics: Counter, Gauge & Histogramme

Während Traces einzelne Request-Reisen aufzeichnen, aggregieren Metrics das Systemverhalten über Tausende von Requests. OpenTelemetry unterscheidet vier Instrument-Typen.

Die vier Metric-Instrument-Typen

Metrics-Provider und Instruments erstellen

src/metrics/app.metrics.ts TypeScript
import { metrics, ValueType } from '@opentelemetry/api'; const meter = metrics.getMeter('app-metrics', '1.0.0'); // --- COUNTER: HTTP-Requests --- export const httpRequestCounter = meter.createCounter( 'http.server.request.count', { description: 'Anzahl eingehender HTTP-Anfragen', unit: '{request}', valueType: ValueType.INT, } ); // --- HISTOGRAM: Anfrage-Latenz --- export const requestDuration = meter.createHistogram( 'http.server.request.duration', { description: 'HTTP-Anfrage-Dauer in Millisekunden', unit: 'ms', valueType: ValueType.DOUBLE, advice: { // Explizite Bucket-Grenzen für genauere Histogramme explicitBucketBoundaries: [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000], }, } ); // --- UP-DOWN COUNTER: Aktive Requests --- export const activeRequests = meter.createUpDownCounter( 'http.server.active_requests', { description: 'Anzahl aktuell laufender HTTP-Anfragen', valueType: ValueType.INT, } ); // --- OBSERVABLE GAUGE: Node.js Heap-Nutzung --- meter.createObservableGauge( 'nodejs.heap.used', { description: 'Genutzter V8 Heap in Bytes', unit: 'By', valueType: ValueType.INT, } ).addCallback((result) => { const mem = process.memoryUsage(); result.observe(mem.heapUsed, { 'process.type': 'main' }); }); meter.createObservableGauge( 'nodejs.event_loop.lag', { description: 'Event Loop Lag in Nanosekunden', unit: 'ns', valueType: ValueType.DOUBLE, } ).addCallback((result) => { const start = process.hrtime.bigint(); setImmediate(() => { const lag = Number(process.hrtime.bigint() - start); result.observe(lag); }); });

Metrics in Express-Middleware verwenden

src/middleware/metrics.middleware.ts TypeScript
import { Request, Response, NextFunction } from 'express'; import { httpRequestCounter, requestDuration, activeRequests } from '../metrics/app.metrics'; export function metricsMiddleware( req: Request, res: Response, next: NextFunction ): void { const start = Date.now(); const labels = { 'http.method': req.method, 'http.route': req.route?.path ?? req.path, }; activeRequests.add(1, labels); res.on('finish', () => { const duration = Date.now() - start; const fullLabels = { ...labels, 'http.status_code': String(res.statusCode), }; httpRequestCounter.add(1, fullLabels); requestDuration.record(duration, fullLabels); activeRequests.add(-1, labels); }); next(); }

5. Logs Integration & OTel Log Bridge

OpenTelemetry Logs sind in 2026 stabil. Die Log Bridge API verbindet bestehende Logging-Frameworks (Winston, Pino, Bunyan) mit dem OTel-Kontext, sodass jeder Log-Eintrag automatisch mit der aktuellen trace_id und span_id angereichert wird.

LoggerProvider initialisieren

src/logging/otel-logger.ts TypeScript
import { LoggerProvider, SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs'; import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; import { logs, SeverityNumber } from '@opentelemetry/api-logs'; import { trace, context } from '@opentelemetry/api'; import { Resource } from '@opentelemetry/resources'; const logExporter = new OTLPLogExporter({ url: `${process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? 'http://localhost:4318'}/v1/logs`, }); const loggerProvider = new LoggerProvider({ resource: new Resource({ 'service.name': process.env.SERVICE_NAME ?? 'my-service', }), }); loggerProvider.addLogRecordProcessor( new SimpleLogRecordProcessor(logExporter) ); logs.setGlobalLoggerProvider(loggerProvider); const otelLogger = logs.getLogger('app-logger'); /** * Strukturierter Logger der Logs automatisch mit * aktuellem Trace-Kontext verknüpft */ export function log( severity: 'debug' | 'info' | 'warn' | 'error', body: string, attributes: Record<string, unknown> = {} ): void { const severityMap: Record<string, SeverityNumber> = { debug: SeverityNumber.DEBUG, info: SeverityNumber.INFO, warn: SeverityNumber.WARN, error: SeverityNumber.ERROR, }; // Aktiven Span aus dem Kontext holen — für Trace-Korrelation const activeSpan = trace.getActiveSpan(); const spanContext = activeSpan?.spanContext(); otelLogger.emit({ severityNumber: severityMap[severity], severityText: severity.toUpperCase(), body, attributes: { ...attributes, // Trace-IDs automatisch mitführen ...(spanContext && { 'trace.id': spanContext.traceId, 'span.id': spanContext.spanId, }), 'timestamp': new Date().toISOString(), }, timestamp: Date.now(), }); // Parallel an lokale Konsole ausgeben (Entwicklung) if (process.env.NODE_ENV !== 'production') { console[severity](JSON.stringify({ body, ...attributes })); } }

Winston-Bridge — bestehende Logger integrieren

src/logging/winston-bridge.ts TypeScript
import winston from 'winston'; import { OpenTelemetryTransportV3 } from '@opentelemetry/winston-transport'; export const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.Console(), // OTel-Transport: leitet alle Winston-Logs an OTel Logger Provider weiter new OpenTelemetryTransportV3({ loggerName: 'winston-bridge', loggerVersion: '1.0.0', }), ], }); // Nutzung: Trace-ID wird automatisch von Winston-Bridge injiziert // logger.info('Zahlung verarbeitet', { orderId, amount, currency });

Korrelation in Grafana: Wenn Logs die trace_id enthalten und Loki mit Jaeger verknüpft ist, kann man direkt vom Log-Eintrag zum kompletten Trace-Tree springen — ein enormer Debugging-Zeitgewinn.

6. Backends & Dashboards: Jaeger, Grafana, Loki

Der OTel Collector ist das Herzstück der Infrastruktur: Er empfängt alle Telemetriedaten via OTLP, transformiert sie und leitet sie an die entsprechenden Backends weiter.

Docker Compose — kompletter Observability-Stack

docker-compose.observability.yml YAML
version: '3.9' services: # OTel Collector — Empfängt OTLP, leitet weiter otel-collector: image: otel/opentelemetry-collector-contrib:0.96.0 command: ["--config=/etc/otel-collector-config.yaml"] volumes: - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml ports: - "4317:4317" # OTLP gRPC - "4318:4318" # OTLP HTTP - "8889:8889" # Prometheus Scrape-Endpunkt depends_on: - jaeger - prometheus # Jaeger — Trace-Backend jaeger: image: jaegertracing/all-in-one:1.55 ports: - "16686:16686" # Jaeger UI - "4319:4317" # OTLP gRPC intern environment: COLLECTOR_OTLP_ENABLED: "true" # Prometheus — Metrics-Backend prometheus: image: prom/prometheus:v2.50.1 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - "9090:9090" # Grafana — Dashboards für alle Signale grafana: image: grafana/grafana:10.3.3 ports: - "3000:3000" environment: GF_SECURITY_ADMIN_PASSWORD: admin volumes: - ./grafana/datasources:/etc/grafana/provisioning/datasources - grafana-data:/var/lib/grafana depends_on: - prometheus - loki # Loki — Log-Aggregation loki: image: grafana/loki:2.9.4 ports: - "3100:3100" command: -config.file=/etc/loki/local-config.yaml # Promtail — sendet Logs an Loki promtail: image: grafana/promtail:2.9.4 volumes: - /var/log:/var/log:ro - ./promtail-config.yaml:/etc/promtail/config.yaml command: -config.file=/etc/promtail/config.yaml depends_on: - loki volumes: grafana-data:

OTel Collector Konfiguration

otel-collector-config.yaml YAML
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: timeout: 5s send_batch_size: 1024 memory_limiter: limit_mib: 512 check_interval: 5s resource: attributes: - key: environment value: production action: upsert exporters: # Traces → Jaeger otlp/jaeger: endpoint: jaeger:4317 tls: insecure: true # Metrics → Prometheus prometheus: endpoint: 0.0.0.0:8889 namespace: myapp # Logs → Loki loki: endpoint: http://loki:3100/loki/api/v1/push labels: resource: service.name: service_name deployment.environment: environment # Debug-Output (Entwicklung) debug: verbosity: normal service: pipelines: traces: receivers: [otlp] processors: [memory_limiter, batch, resource] exporters: [otlp/jaeger, debug] metrics: receivers: [otlp] processors: [memory_limiter, batch] exporters: [prometheus] logs: receivers: [otlp] processors: [memory_limiter, batch, resource] exporters: [loki, debug]

Prometheus Scrape-Konfiguration

prometheus.yml YAML
global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'otel-collector' static_configs: - targets: ['otel-collector:8889'] metrics_path: /metrics # Direktes Prometheus-Scraping der App (Fallback) - job_name: 'my-service' static_configs: - targets: ['my-service:9464'] alerting: alertmanagers: - static_configs: - targets: ['alertmanager:9093'] rule_files: - 'alerts/*.yml'

Grafana Datasources provisioning

grafana/datasources/datasources.yaml YAML
apiVersion: 1 datasources: - name: Prometheus type: prometheus url: http://prometheus:9090 isDefault: true jsonData: timeInterval: 15s - name: Jaeger type: jaeger url: http://jaeger:16686 jsonData: tracesToLogs: datasourceUid: loki filterByTraceID: true - name: Loki type: loki url: http://loki:3100 jsonData: derivedFields: - name: TraceID matcherRegex: "trace.id=(\\w+)" url: '${__value.raw}' datasourceUid: jaeger

Empfohlene Grafana-Dashboards

PromQL — wichtige Alert-Queries

alerts/service-alerts.yml (Auszug) YAML
groups: - name: service_alerts rules: # Error-Rate über 5% in den letzten 5 Minuten - alert: HighErrorRate expr: | rate(myapp_http_server_request_count_total{http_status_code=~"5.."}[5m]) / rate(myapp_http_server_request_count_total[5m]) > 0.05 for: 2m labels: severity: critical annotations: summary: "Hohe Error-Rate: {{ $value | humanizePercentage }}" # p99-Latenz über 2 Sekunden - alert: HighP99Latency expr: | histogram_quantile(0.99, rate(myapp_http_server_request_duration_bucket[5m]) ) > 2000 for: 3m labels: severity: warning annotations: summary: "P99-Latenz kritisch: {{ $value }}ms"

Claude Code Workflow: Prompt „Erstelle Grafana-Dashboard JSON für die RED-Methode mit meinen OTel-Metrics http.server.request.count und http.server.request.duration, Zeitbereich 1h, Refresh 30s" — Claude Code liefert das komplette Dashboard-JSON in unter einer Minute.

Zusammenfassung: Was Claude Code automatisiert

Aufgabe Manuell Mit Claude Code
SDK-Setup + tracing.ts 45–90 Min Recherche + Implementierung 2–5 Min (Prompt → Code)
Custom Spans für Business-Logik Pro Service 30–60 Min 5–10 Min pro Service
Metrics-Instruments definieren Semantik-Recherche + Implementierung Automatisch mit Semantic Conventions
Collector-Konfiguration YAML-Doku, Trial & Error Prompt → fertige Config
Grafana-Dashboards UI-Klickarbeit, Stunden JSON generieren, importieren
Alert-Regeln (PromQL) PromQL-Expertise nötig Natürlichsprachige Beschreibung → PromQL

Observability sofort starten — kostenlos testen

Instrumentiere deine Node.js, Python oder Go-Applikation mit OpenTelemetry — Claude Code generiert den kompletten Setup in Minuten.

Kostenlos testen — kein Kreditkarte nötig

14 Tage Trial · Kein Setup-Aufwand · DSGVO-konform

Fazit: Observability als Engineering-Grundlage

OpenTelemetry hat 2026 den Status eines de-facto-Standards erreicht. Wer heute in OTel-Instrumentierung investiert, schafft eine herstellerneutrale Grundlage, die mit jeder Backend-Entscheidung kompatibel bleibt — ob Jaeger on-premise, Honeycomb Cloud oder Grafana Cloud.

Die größte Hürde war bislang der Boilerplate: SDK-Konfiguration, Collector-YAML, Prometheus-Scrape-Configs, Grafana-Provisioning. Claude Code eliminiert diesen Aufwand. Was Entwickler brauchen, ist die Instrumentierungsstrategie: Welche Spans sind business-kritisch? Welche Metrics triggern Alerts? Welche Log-Felder braucht das Team zum Debuggen?

Der technische Boilerplate folgt in Minuten. Die fachliche Beurteilung bleibt beim Team — unterstützt durch einen KI-Coding-Assistenten, der den OpenTelemetry-Standard vollständig versteht.