Technischer Leitfaden

Der komplette Leitfaden zur KI-Observability

Engineering-Leitfaden zu KI-Observability in der Produktion: Logging-Strategien, Metriken-Erfassung, Tracing, Prompt-Debugging und Kostentracking.

20. Januar 202618 Min. LesezeitOronts Engineering Team

Warum KI-Systeme andere Observability brauchen

Hier ist die Sache mit KI-Systemen: Traditionelles Monitoring reicht nicht aus. Wenn deine REST-API einen 500-Fehler zurückgibt, weißt du, dass etwas kaputt ist. Wenn deine KI selbstbewusst falsche Informationen zurückgibt, sieht technisch gesehen alles in Ordnung aus. Grüne Dashboards, gesunde Latenz, erfolgreiche HTTP-Antworten. Aber deine Nutzer bekommen Unsinn.

Wir haben das auf die harte Tour gelernt. Einer unserer Kunden hatte einen Kundensupport-Agenten, der anfing, Produkte von Wettbewerbern zu empfehlen. Keine Fehler in den Logs. Keine Latenz-Spikes. Er gab einfach drei Tage lang leise schreckliche Ratschläge, bevor es jemand bemerkte. Da wurde uns klar: KI zu beobachten bedeutet nicht zu prüfen, ob sie läuft. Es bedeutet zu prüfen, ob sie tatsächlich funktioniert.

Traditionelles Monitoring sagt dir, ob dein System lebt. KI-Observability sagt dir, ob dein System vernünftig ist.

Dieser Leitfaden deckt alles ab, was wir über die Beobachtung von KI-Systemen gelernt haben. Keine Theorie - echte Praktiken, die wir jeden Tag in der Produktion nutzen.

Die vier Säulen der KI-Observability

Lass uns aufschlüsseln, was du tatsächlich tracken musst:

SäuleWas sie abdecktWarum sie wichtig ist
LoggingJeder Prompt, jede Antwort, jeder ZwischenschrittDebugging, wenn Dinge schiefgehen
MetrikenLatenz, Token-Nutzung, Erfolgsraten, KostenKapazitätsplanung und Budgetierung
TracingVollständiger Request-Lifecycle über Services hinwegVerstehen komplexer KI-Workflows
QualitätAntwortgenauigkeit, Relevanz, SicherheitDegradation erkennen, bevor Nutzer es tun

Die meisten Teams beginnen mit Logging, merken dass sie Metriken für Kostenkontrolle brauchen, fügen Tracing hinzu wenn Debugging schmerzhaft wird, und implementieren schließlich Qualitätsmonitoring nach einem schlimmen Vorfall. Spar dir den Ärger und bau alle vier von Anfang an.

Logging: Deine erste Verteidigungslinie

Was du loggen solltest

Jede KI-Interaktion sollte erfassen:

const aiCallLog = {
  // Identität
  requestId: "uuid-v4",
  sessionId: "user-session-id",
  userId: "optionaler-nutzer-identifikator",

  // Input
  prompt: {
    system: "Du bist ein hilfreicher Assistent...",
    user: "Was ist die Rückgaberichtlinie?",
    context: ["abgerufenes_dok_1", "abgerufenes_dok_2"]
  },

  // Modell-Konfiguration
  model: "gpt-4-turbo",
  temperature: 0.7,
  maxTokens: 1000,

  // Output
  response: {
    content: "Unsere Rückgaberichtlinie erlaubt...",
    finishReason: "stop",
    toolCalls: []
  },

  // Performance
  latencyMs: 2340,
  inputTokens: 456,
  outputTokens: 234,
  totalTokens: 690,

  // Kosten
  estimatedCostUsd: 0.0138,

  // Metadaten
  timestamp: "2025-10-15T14:30:00Z",
  environment: "production",
  version: "1.2.3"
};

Strukturiertes Logging implementieren

Dump nicht einfach Strings nach stdout. Strukturiere deine Logs, damit du sie tatsächlich abfragen kannst:

interface AILogEntry {
  level: 'debug' | 'info' | 'warn' | 'error';
  event: string;
  requestId: string;
  data: {
    model: string;
    promptHash: string;  // Zum Gruppieren ähnlicher Prompts
    inputTokens: number;
    outputTokens: number;
    latencyMs: number;
    success: boolean;
    errorType?: string;
  };
  context?: {
    userId?: string;
    feature?: string;
    experimentId?: string;
  };
}

function logAICall(entry: AILogEntry) {
  // An deine Logging-Infrastruktur senden
  // Wir nutzen eine Kombination aus strukturierten JSON-Logs + Time-Series-Metriken
  console.log(JSON.stringify({
    ...entry,
    timestamp: new Date().toISOString(),
    service: 'ai-gateway'
  }));
}

Sensible Daten loggen

Hier wird es knifflig. Du musst Prompts fürs Debugging loggen, aber Prompts enthalten oft Nutzerdaten. Unser Ansatz:

  1. Sensible Felder hashen - Speichere einen Hash von PII, nicht die tatsächlichen Werte
  2. Getrennte Speicherung - Vollständige Prompts gehen in einen eingeschränkten, verschlüsselten Speicher mit kurzer Aufbewahrung
  3. Sampling - Logge nur für einen Prozentsatz der Anfragen vollständige Prompts in Produktion
  4. Schwärzung - Nutze Regex-Muster, um gängige PII-Muster vor dem Loggen zu entfernen
const sensitivePatterns = [
  /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,  // Email
  /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g,  // Telefon
  /\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g,  // Kreditkarte
];

function redactPII(text: string): string {
  let redacted = text;
  sensitivePatterns.forEach(pattern => {
    redacted = redacted.replace(pattern, '[GESCHWÄRZT]');
  });
  return redacted;
}

Metriken: Zahlen, die wirklich zählen

Kernmetriken zum Tracken

MetrikTypWas sie dir sagt
ai.request.latencyHistogramWie lange Aufrufe dauern (p50, p95, p99)
ai.request.tokens.inputCounterInput-Token-Verbrauch
ai.request.tokens.outputCounterOutput-Token-Verbrauch
ai.request.costCounterDollar-Kosten pro Request
ai.request.success_rateGaugeProzentsatz erfolgreicher Completions
ai.request.error_rateGaugeFehler nach Fehlertyp
ai.model.rate_limit_hitsCounterWie oft du gedrosselt wirst
ai.cache.hit_rateGaugeSemantic-Cache-Effektivität

Metriken-Erfassung einrichten

So instrumentieren wir unser KI-Gateway:

import { Counter, Histogram, Gauge } from 'prom-client';

const aiLatency = new Histogram({
  name: 'ai_request_latency_ms',
  help: 'KI-Request-Latenz in Millisekunden',
  labelNames: ['model', 'feature', 'status'],
  buckets: [100, 250, 500, 1000, 2500, 5000, 10000]
});

const aiTokens = new Counter({
  name: 'ai_tokens_total',
  help: 'Gesamt verbrauchte Tokens',
  labelNames: ['model', 'type', 'feature']  // type: input/output
});

const aiCost = new Counter({
  name: 'ai_cost_usd',
  help: 'Geschätzte Kosten in USD',
  labelNames: ['model', 'feature']
});

async function instrumentedAICall(params: AICallParams) {
  const startTime = Date.now();

  try {
    const result = await makeAICall(params);

    const latency = Date.now() - startTime;
    aiLatency.observe({
      model: params.model,
      feature: params.feature,
      status: 'success'
    }, latency);

    aiTokens.inc({
      model: params.model,
      type: 'input',
      feature: params.feature
    }, result.usage.inputTokens);

    aiTokens.inc({
      model: params.model,
      type: 'output',
      feature: params.feature
    }, result.usage.outputTokens);

    const cost = calculateCost(params.model, result.usage);
    aiCost.inc({
      model: params.model,
      feature: params.feature
    }, cost);

    return result;
  } catch (error) {
    aiLatency.observe({
      model: params.model,
      feature: params.feature,
      status: 'error'
    }, Date.now() - startTime);

    throw error;
  }
}

Kostentracking: Die Metrik, die Executive-Aufmerksamkeit bekommt

Seien wir ehrlich - Kosten sind meist das, was Observability-Gespräche auf den Tisch bringt. So trackst du sie richtig:

const MODEL_PRICING = {
  'gpt-4-turbo': { input: 0.01, output: 0.03 },      // pro 1K Tokens
  'gpt-4o': { input: 0.005, output: 0.015 },
  'gpt-4o-mini': { input: 0.00015, output: 0.0006 },
  'claude-3-opus': { input: 0.015, output: 0.075 },
  'claude-3-sonnet': { input: 0.003, output: 0.015 },
  'claude-3-haiku': { input: 0.00025, output: 0.00125 }
};

function calculateCost(model: string, usage: TokenUsage): number {
  const pricing = MODEL_PRICING[model];
  if (!pricing) return 0;

  return (usage.inputTokens / 1000 * pricing.input) +
         (usage.outputTokens / 1000 * pricing.output);
}

// Kosten nach Feature, Team, Kunde aggregieren
interface CostAllocation {
  feature: string;
  team: string;
  customerId?: string;
  dailyCost: number;
  monthlyProjection: number;
}

Bau Dashboards, die zeigen:

  • Tägliche/wöchentliche/monatliche Ausgaben nach Modell
  • Kosten pro Feature oder Anwendungsfall
  • Kosten pro Kunde (für B2B)
  • Projizierte monatliche Ausgaben basierend auf aktueller Trajectory
  • Anomalie-Erkennung für plötzliche Kosten-Spikes

Tracing: Dem Faden folgen

KI-Workflows sind keine einzelnen Aufrufe mehr. Es sind Chains, Agenten und komplexe mehrstufige Prozesse. Tracing lässt dich einer Anfrage durch das gesamte System folgen.

Distributed Tracing implementieren

import { trace, SpanKind, SpanStatusCode } from '@opentelemetry/api';

const tracer = trace.getTracer('ai-service');

async function tracedAgentExecution(task: string, context: RequestContext) {
  return tracer.startActiveSpan('agent.execute', async (span) => {
    span.setAttributes({
      'ai.task': task,
      'ai.session_id': context.sessionId,
      'ai.user_id': context.userId
    });

    try {
      // Schritt 1: Planung
      const plan = await tracer.startActiveSpan('agent.plan', async (planSpan) => {
        const result = await planTask(task);
        planSpan.setAttributes({
          'ai.model': 'gpt-4-turbo',
          'ai.tokens.input': result.usage.input,
          'ai.tokens.output': result.usage.output,
          'ai.plan.steps': result.steps.length
        });
        return result;
      });

      // Schritt 2: Jeden Schritt ausführen
      for (const step of plan.steps) {
        await tracer.startActiveSpan(`agent.step.${step.type}`, async (stepSpan) => {
          stepSpan.setAttributes({
            'ai.step.type': step.type,
            'ai.step.tool': step.tool
          });

          if (step.type === 'llm_call') {
            await tracedLLMCall(step.params, stepSpan);
          } else if (step.type === 'tool_call') {
            await tracedToolCall(step.tool, step.params, stepSpan);
          }
        });
      }

      span.setStatus({ code: SpanStatusCode.OK });
    } catch (error) {
      span.setStatus({
        code: SpanStatusCode.ERROR,
        message: error.message
      });
      span.recordException(error);
      throw error;
    }
  });
}

Was gute Traces dir zeigen

Ein gut instrumentierter KI-Trace enthüllt:

[Agent-Ausführung] 4.2s
├── [Planung] 1.1s
│   └── [LLM-Aufruf: gpt-4] 1.0s - 234 Tokens rein, 156 Tokens raus
├── [Schritt 1: RAG-Retrieval] 0.3s
│   ├── [Embedding-Generierung] 0.1s
│   └── [Vektorsuche] 0.2s - 5 Dokumente abgerufen
├── [Schritt 2: LLM-Synthese] 2.1s
│   └── [LLM-Aufruf: gpt-4] 2.0s - 1.456 Tokens rein, 523 Tokens raus
└── [Schritt 3: Antwort-Formatierung] 0.7s
    └── [LLM-Aufruf: gpt-4o-mini] 0.6s - 678 Tokens rein, 234 Tokens raus

Jetzt, wenn jemand eine langsame Antwort meldet, kannst du genau sehen, wohin die Zeit ging.

Prompt-Debugging: Der schwierige Teil

Hier unterscheidet sich KI-Observability am meisten vom traditionellen Monitoring. Wie debuggst du etwas, das jedes Mal anders funktioniert?

Prompt-Versionierung

Behandle Prompts wie Code. Versioniere sie:

interface PromptVersion {
  id: string;
  name: string;
  version: string;
  template: string;
  variables: string[];
  model: string;
  temperature: number;
  createdAt: Date;
  createdBy: string;
  parentVersion?: string;
}

const promptRegistry = {
  'customer-support-v2.3': {
    id: 'cs-001',
    name: 'Kundensupport Agent',
    version: '2.3',
    template: `Du bist ein hilfreicher Kundensupport-Agent für {{company_name}}.

Deine Rolle ist es, Kunden bei ihren Anfragen zu {{product_area}} zu helfen.

Richtlinien:
- Verifiziere immer die Identität des Kunden bevor du Kontodetails besprichst
- Versprich niemals Rückerstattungen ohne Richtlinienprüfung
- Eskaliere an menschlichen Agenten wenn der Kunde Frustration zeigt

Kundenanfrage: {{query}}
Kontext: {{context}}`,
    variables: ['company_name', 'product_area', 'query', 'context'],
    model: 'gpt-4-turbo',
    temperature: 0.3
  }
};

A/B-Testing von Prompts

Du kannst nicht verbessern, was du nicht misst. Führe Experimente mit Prompt-Variationen durch:

interface PromptExperiment {
  id: string;
  name: string;
  variants: {
    id: string;
    promptVersion: string;
    trafficPercentage: number;
  }[];
  metrics: string[];  // Was gemessen wird
  startDate: Date;
  endDate?: Date;
}

function selectPromptVariant(experimentId: string, userId: string): string {
  const experiment = getExperiment(experimentId);

  // Deterministische Zuweisung basierend auf User-ID
  const hash = hashString(userId + experimentId);
  const bucket = hash % 100;

  let cumulative = 0;
  for (const variant of experiment.variants) {
    cumulative += variant.trafficPercentage;
    if (bucket < cumulative) {
      return variant.promptVersion;
    }
  }

  return experiment.variants[0].promptVersion;
}

Fehlgeschlagene Antworten debuggen

Wenn eine KI-Antwort schiefgeht, musst du beantworten:

  1. Was war der Input? - Vollständiger Prompt inkl. System-Message, Kontext und User-Input
  2. Welcher Kontext wurde abgerufen? - Für RAG-Systeme: welche Dokumente beeinflussten die Antwort
  3. Was war das Reasoning des Modells? - Bei Chain-of-Thought: welche Schritte wurden gemacht
  4. Wie beeinflussten Parameter den Output? - Temperature, top_p, frequency penalty
  5. War es ein Einzelfall oder Muster? - Nach ähnlichen Inputs suchen, die ähnliche Fehler produzierten

Bau eine Debugging-Oberfläche, die dir erlaubt:

-- Ähnliche Fehler finden
SELECT
  request_id,
  prompt_hash,
  response_content,
  error_type,
  timestamp
FROM ai_logs
WHERE
  feature = 'customer-support'
  AND (
    response_content LIKE '%wettbewerber%'  -- Wettbewerber erwähnt
    OR quality_score < 0.5                   -- Niedriger Qualitätsscore
    OR user_feedback = 'negative'            -- Nutzer hat geflaggt
  )
  AND timestamp > NOW() - INTERVAL '7 days'
ORDER BY timestamp DESC
LIMIT 100;

Qualitätsmonitoring: Ist die KI wirklich gut?

Das ist der schwierigste Teil der KI-Observability. Technische Metriken können grün sein, während die KI Müll produziert.

Automatisierte Qualitätsprüfungen

interface QualityCheck {
  name: string;
  check: (response: AIResponse, context: RequestContext) => QualityResult;
}

const qualityChecks: QualityCheck[] = [
  {
    name: 'response_length',
    check: (response) => ({
      pass: response.content.length > 50 && response.content.length < 5000,
      score: normalizeLength(response.content.length),
      reason: 'Antwortlänge im akzeptablen Bereich'
    })
  },
  {
    name: 'no_hallucinated_urls',
    check: (response) => {
      const urls = extractUrls(response.content);
      const validUrls = urls.filter(url => isKnownValidUrl(url));
      return {
        pass: urls.length === validUrls.length,
        score: urls.length === 0 ? 1 : validUrls.length / urls.length,
        reason: `${urls.length - validUrls.length} potenziell halluzinierte URLs`
      };
    }
  },
  {
    name: 'factual_grounding',
    check: (response, context) => {
      // Prüfen ob Kernaussagen durch abgerufenen Kontext gestützt werden
      const claims = extractClaims(response.content);
      const groundedClaims = claims.filter(claim =>
        isClaimSupportedByContext(claim, context.retrievedDocuments)
      );
      return {
        pass: groundedClaims.length / claims.length > 0.8,
        score: groundedClaims.length / claims.length,
        reason: `${groundedClaims.length}/${claims.length} Aussagen im Kontext verankert`
      };
    }
  },
  {
    name: 'safety_check',
    check: (response) => {
      const safetyResult = runSafetyClassifier(response.content);
      return {
        pass: safetyResult.safe,
        score: safetyResult.confidence,
        reason: safetyResult.category || 'Antwort hat Sicherheitsprüfung bestanden'
      };
    }
  }
];

async function evaluateResponse(
  response: AIResponse,
  context: RequestContext
): Promise<QualityReport> {
  const results = await Promise.all(
    qualityChecks.map(check => ({
      check: check.name,
      ...check.check(response, context)
    }))
  );

  return {
    overallScore: average(results.map(r => r.score)),
    allPassed: results.every(r => r.pass),
    details: results
  };
}

Human-in-the-Loop Evaluierung

Automatisierte Prüfungen fangen offensichtliche Probleme. Für subtile Qualitätsprobleme brauchst du menschliche Überprüfung:

interface HumanEvaluationQueue {
  // Prozentsatz der Antworten für menschliche Überprüfung samplen
  sampleRate: number;

  // Bestimmte Typen immer überprüfen
  alwaysReviewWhen: {
    lowConfidence: boolean;           // Modell-Unsicherheit
    userFeedbackNegative: boolean;
    automatedChecksFailed: boolean;
    highValueCustomer: boolean;
  };

  // Evaluierungskriterien für Reviewer
  criteria: {
    accuracy: 'Enthielt die Antwort korrekte Informationen?';
    relevance: 'Adressierte die Antwort die Nutzeranfrage?';
    completeness: 'War die Antwort gründlich genug?';
    tone: 'War der Ton dem Kontext angemessen?';
    safety: 'Gab es besorgniserregende Elemente?';
  };
}

Alerting: Wissen, wenn Dinge schiefgehen

Alert-Schwellenwerte für KI-Systeme

AlertSchwellenwertSchweregradAktion
Latency p95 > 10s5 Min. anhaltendWarnungModell-Provider untersuchen
Fehlerrate > 5%2 Min. anhaltendKritischAPI-Status prüfen, Failover
Kosten-Spike > 3x Baseline1 StundeWarnungTraffic prüfen, auf Loops checken
Qualitätsscore-Drop > 20%1 StundeKritischFeature pausieren, untersuchen
Rate-Limit-Hits > 10/Min5 Min.WarnungZurückskalieren, auf Missbrauch prüfen
Prompt-Injection erkanntJederKritischRequest blockieren, reviewen

Smarte Alerts implementieren

interface AIAlert {
  name: string;
  condition: (metrics: AIMetrics) => boolean;
  severity: 'info' | 'warning' | 'critical';
  cooldown: number;  // Minuten vor erneutem Alert
  notification: {
    slack?: string;
    pagerduty?: string;
    email?: string[];
  };
}

const alerts: AIAlert[] = [
  {
    name: 'high_latency',
    condition: (m) => m.latencyP95 > 10000,
    severity: 'warning',
    cooldown: 30,
    notification: { slack: '#ai-alerts' }
  },
  {
    name: 'quality_degradation',
    condition: (m) => m.qualityScore < 0.7 && m.previousQualityScore > 0.85,
    severity: 'critical',
    cooldown: 60,
    notification: {
      slack: '#ai-alerts',
      pagerduty: 'ai-oncall'
    }
  },
  {
    name: 'cost_anomaly',
    condition: (m) => m.hourlyCost > m.expectedHourlyCost * 3,
    severity: 'warning',
    cooldown: 60,
    notification: {
      slack: '#ai-alerts',
      email: ['ai-team@company.com']
    }
  }
];

Deinen Observability-Stack aufbauen

Empfohlene Architektur

┌─────────────────────────────────────────────────────────────────┐
│                        KI-Anwendung                              │
├─────────────────────────────────────────────────────────────────┤
│                     Instrumentierungs-Layer                      │
│  (OpenTelemetry SDK, Custom Metrics, Strukturiertes Logging)    │
└─────────────────────────────┬───────────────────────────────────┘
                              │
        ┌─────────────────────┼─────────────────────┐
        │                     │                     │
        ▼                     ▼                     ▼
┌───────────────┐   ┌─────────────────┐   ┌───────────────┐
│    Traces     │   │     Metriken    │   │     Logs      │
│   (Jaeger/    │   │  (Prometheus/   │   │ (Elasticsearch│
│    Tempo)     │   │   Datadog)      │   │   /Loki)      │
└───────┬───────┘   └────────┬────────┘   └───────┬───────┘
        │                    │                    │
        └────────────────────┼────────────────────┘
                             │
                             ▼
                    ┌─────────────────┐
                    │   Dashboards    │
                    │    (Grafana)    │
                    └────────┬────────┘
                             │
                             ▼
                    ┌─────────────────┐
                    │    Alerting     │
                    │  (PagerDuty/    │
                    │   Slack/OpsGenie│
                    └─────────────────┘

Tools, die wir empfehlen

KategorieOpen SourceKommerziell
TracingJaeger, ZipkinDatadog, New Relic
MetrikenPrometheus + GrafanaDatadog, Dynatrace
LoggingELK Stack, LokiSplunk, Datadog
KI-spezifischLangSmith, PhoenixWeights & Biases, Helicone
AlertingAlertmanagerPagerDuty, OpsGenie

Praxisbeispiel: Vollständiges Observability-Setup

So instrumentieren wir ein KI-Feature in Produktion End-to-End:

import { trace, metrics, context } from '@opentelemetry/api';
import { logger } from './logging';
import { qualityChecker } from './quality';
import { costTracker } from './costs';

class ObservableAIService {
  private tracer = trace.getTracer('ai-service');
  private meter = metrics.getMeter('ai-service');

  private latencyHistogram = this.meter.createHistogram('ai.latency');
  private tokenCounter = this.meter.createCounter('ai.tokens');
  private costCounter = this.meter.createCounter('ai.cost');
  private qualityGauge = this.meter.createObservableGauge('ai.quality');

  async complete(request: AIRequest): Promise<AIResponse> {
    const span = this.tracer.startSpan('ai.complete');
    const startTime = Date.now();

    const requestId = generateRequestId();
    span.setAttribute('request_id', requestId);
    span.setAttribute('model', request.model);
    span.setAttribute('feature', request.feature);

    try {
      // Request loggen
      logger.info('ai.request.start', {
        requestId,
        model: request.model,
        feature: request.feature,
        promptHash: hashPrompt(request.prompt),
        inputTokenEstimate: estimateTokens(request.prompt)
      });

      // KI-Aufruf machen
      const response = await this.makeAICall(request);

      const latency = Date.now() - startTime;
      const cost = costTracker.calculate(request.model, response.usage);

      // Metriken aufzeichnen
      this.latencyHistogram.record(latency, {
        model: request.model,
        feature: request.feature,
        status: 'success'
      });

      this.tokenCounter.add(response.usage.inputTokens, {
        model: request.model,
        type: 'input'
      });

      this.tokenCounter.add(response.usage.outputTokens, {
        model: request.model,
        type: 'output'
      });

      this.costCounter.add(cost, {
        model: request.model,
        feature: request.feature
      });

      // Qualitätsprüfungen durchführen
      const quality = await qualityChecker.evaluate(response, request);

      // Antwort loggen
      logger.info('ai.request.complete', {
        requestId,
        latencyMs: latency,
        inputTokens: response.usage.inputTokens,
        outputTokens: response.usage.outputTokens,
        costUsd: cost,
        qualityScore: quality.overallScore,
        qualityPassed: quality.allPassed
      });

      // Für Debugging speichern (mit passender Aufbewahrung)
      await this.storeForDebugging(requestId, request, response, quality);

      span.setStatus({ code: SpanStatusCode.OK });
      return response;

    } catch (error) {
      const latency = Date.now() - startTime;

      this.latencyHistogram.record(latency, {
        model: request.model,
        feature: request.feature,
        status: 'error'
      });

      logger.error('ai.request.error', {
        requestId,
        error: error.message,
        errorType: error.constructor.name,
        latencyMs: latency
      });

      span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
      span.recordException(error);

      throw error;
    } finally {
      span.end();
    }
  }
}

Loslegen: Deine erste Woche

Tag 1-2: Basis-Logging

  • Strukturiertes Logging zu allen KI-Aufrufen hinzufügen
  • Enthalten: Modell, Latenz, Token-Counts, Feature-Name
  • Logs irgendwo querybar speichern

Tag 3-4: Kernmetriken

  • Token- und Kosten-Counter einrichten
  • Latenz-Histogramme nach Modell und Feature erstellen
  • Dein erstes Dashboard bauen

Tag 5: Alerting

  • Bei Fehlerraten-Spikes alerten
  • Bei Kosten-Anomalien alerten
  • Bei Latenz-Degradation alerten

Woche 2: Qualität und Tracing

  • Basis-Qualitätsprüfungen implementieren
  • Distributed Tracing für mehrstufige KI-Workflows hinzufügen
  • Nutzer-Feedback sammeln

Fazit

KI-Observability ist keine Option mehr. Da KI-Systeme kritischere Workflows übernehmen, musst du nicht nur wissen, ob sie laufen, sondern ob sie tatsächlich korrekt funktionieren.

Die gute Nachricht: Das meiste, was du brauchst, kann auf bestehender Observability-Infrastruktur aufgebaut werden. OpenTelemetry, Prometheus, strukturiertes Logging - diese Tools funktionieren auch für KI. Der Unterschied liegt darin zu wissen, was zu messen ist und wie man es interpretiert.

Fang einfach an. Logge alles. Tracke Kosten. Füge Qualitätsprüfungen hinzu. Bau von dort aus weiter.

Die beste Zeit, Observability hinzuzufügen, war vor dem Launch. Die zweitbeste Zeit ist jetzt.

Wir haben Teams geholfen, von "wir haben keine Ahnung, was unsere KI macht" zu "wir haben das Problem in 3 Minuten gefunden" in wenigen Wochen zu kommen. Die Investition zahlt sich beim ersten Mal aus, wenn du ein Produktionsproblem in Minuten statt Stunden debuggst.

Wenn du KI-Systeme baust und über Observability-Strategien sprechen möchtest, melde dich. Wir haben viele Fehlermodi gesehen und teilen gerne, was wir gelernt haben.

Behandelte Themen

KI-ObservabilityLLM-MonitoringPrompt-DebuggingKI-MetrikenModell-PerformanceKostentrackingKI-TracingProduktions-KIKI-Logging

Bereit, produktionsreife KI-Systeme zu bauen?

Unser Team ist spezialisiert auf produktionsreife KI-Systeme. Lass uns besprechen, wie wir deinem Unternehmen helfen können.

Gespräch starten