LLM Production Ops

Observability & Telemetrie

Ein Nutzer meldet eine falsche und langsame Antwort, doch im Dashboard steht nur eine globale Dauer. Ohne durchgängigen Trace, Laufzeit-Provenienz und ein begrenztes Telemetrieschema bleibt unklar, ob Retrieval, Queue, Modell oder eine neue Konfiguration verantwortlich war.

Lehrtext · 10 Abschnitte · zuletzt geprüft: 2026-09-04

Warum ein LLM-System ohne Telemetrie blind läuft

Ein LLM-Dienst in Produktion ist eine Blackbox mit probabilistischem Kern: keine Exceptions, keine Stacktraces, kein „geht/geht nicht“. Eine Antwort kann formal ein 200 OK sein und trotzdem inhaltlich falsch. Wenn du nicht pro Request festhältst, was hineinging, was herauskam und womit es bedient wurde, kannst du einen Incident weder erkennen noch reproduzieren.

Observability ist die Grundlage der ganzen Betriebsschleife: beobachten → erkennen → ändern → betreiben. Dieses Modul baut den ersten Schritt — die anderen drei bauen darauf auf. Alles Weitere im Track (Drift erkennen, sicher ausrollen, SLOs halten) setzt voraus, dass das System sichtbar ist.

MerksatzBei klassischen Diensten debuggst du den Fehler. Bei LLM-Diensten debuggst du die Antwort — und die ist ohne Telemetrie nach dem Request unwiederbringlich weg.

Was pro Request erfassen — Umfang gegen Volumen

Der brauchbare Minimalumfang je Request ist mehr als nur die Antwort. Ohne Input, Versionen und Retrieval-Kontext ist ein Fall nicht reproduzierbar; mit rohem Volltext von allem sprengst du bei hohem Traffic Speicher und Kosten.

Input & Output
Wortlaut oder gekürzt/referenziert — nötig, um den Fall nachzuspielen
Token-Zahlen
Prompt- und Completion-Tokens — Basis für Kosten und Latenz-Diagnose
Latenz
gesamt UND pro Pipeline-Stufe (siehe Tracing)
Kosten
pro Request abgeleitet, für Anomalie-Erkennung
Modell- & Prompt-Version
welcher Snapshot/welche Vorlage bediente den Request (siehe Provenienz)
Retrieval-Kontext
Referenzen (Doc-IDs, Scores) statt Volltext — spart Volumen, bleibt nachvollziehbar
PII gehört woanders hinInputs/Outputs enthalten oft personenbezogene Daten. Das Redaction- und Secrets-Handling ist ein eigenes Thema (llmops/security) — hier geht es nur um den Umfang-Trade-off: erfasse genug zum Reproduzieren, aber referenziere statt zu horten und plane Retention.

Verteiltes Tracing: eine Latenzzahl reicht nicht

Eine LLM-Antwort durchläuft meist mehrere Stufen. Eine einzige aggregierte Latenzzahl sagt dir, dass es langsam ist — aber nicht wo.

RetrievalRerankLLMPostprocess

Mit verteiltem Tracing wird jede Stufe zu einem Span unter einer gemeinsamen Trace-/Korrelations-ID. Der Trace zeigt die Zeit pro Stufe und ihre Verschachtelung (parent/child). So sieht man, dass die p95-Regression aus dem Retrieval kommt — und kann einen einzelnen langsamen Request durch alle Stufen verfolgen.

MerksatzAggregierte Zahlen verstecken wo und welcher Request. Ein Trace mit korrelierten Spans macht beides sichtbar — besonders bei Tail-Problemen, die nur eine Teilmenge der Requests treffen.

Betriebsprobe: TRACING-SPANS

Szenario

Eure LLM-Pipeline läuft in vier Stufen: Retrieval → Rerank → LLM → Postprocess. Ihr messt nur eine End-to-End-Latenz pro Request. Die p95 ist von 2 s auf 6 s gestiegen, die p50 blieb bei 1,8 s — also nur ein Teil der Requests ist langsam. Ihr müsst herausfinden, welche Stufe die Tail-Latenz verursacht.

Anforderungen

  • Wie instrumentiert ihr, um die Ursache zu finden?
  • Bewerte Ursache, wirksame Grenze und den Preis der tragfähigen Maßnahme getrennt.

Schritte

  1. Tragfähiger Ansatz: Jede Stufe als eigener Span unter einer gemeinsamen Trace-/Korrelations-ID, sodass ihr die Zeit pro Stufe seht und einen einzelnen langsamen Request durch alle vier Stufen verfolgen könnt.. Richtig. Nur korrelierte Spans attribuieren die Zeit auf eine Stufe und lassen sich pro Request verfolgen — so seht ihr, dass die langsamen Requests z. B. großes Retrieval haben, das dann auch das LLM bremst. Genau das braucht ein Tail-Problem.
  2. Plausibler Fehlweg: Feinere End-to-End-Perzentile ergänzen (p50/p90/p95/p99), um das Tail-Verhalten genauer zu sehen — als zentrale Collector-Regel für alle Pfade versioniert und mit festem Aufbewahrungsziel ausgerollt. Feinere Aggregate der Gesamtzeit bestätigen nur, dass ein Tail existiert — sie attribuieren keine Sekunde auf eine Stufe. Du weißt danach präziser, dass es langsam ist, aber weiterhin nicht wo.
  3. Plausibler Fehlweg: Pro Stufe eine eigene Latenz-Metrik (Histogramm je Stufe) erfassen, ohne Trace-Korrelation.. Stufen-Aggregate zeigen die Durchschnittslast je Stufe, aber du kannst einen einzelnen langsamen Request nicht durch die Stufen verfolgen und nicht sehen, dass Retrieval- und LLM-Langsamkeit im selben Request zusammenfallen. Ein p95-Tail aus einer Request-Teilmenge verschwindet im Stufen-Durchschnitt.
  4. Plausibler Fehlweg: Einen Zeitstempel bei Request-Start und -Ende loggen und die Differenz bilden.. Das ist dieselbe eine Zahl in Log-Form — keine Aufschlüsselung nach Stufe. Und unkorrelierte Logs der vier Stufen lassen sich ohne gemeinsame ID nicht zu einem Request zusammenfügen.

Merksatz: Eine aggregierte Latenz verdichtet mehrere Stufen und viele Requests zu einer Zahl — sie verliert Ort und Request-Bezug. Ursachensuche über eine mehrstufige Pipeline braucht per-Request-Korrelation, kein feineres Aggregat. + Ort und einzelner Request werden sichtbar, auch bei intermittierenden Tail-Problemen. Instrumentierung jeder Stufe plus Context-Propagation der Trace-ID ist Aufwand, und volle Traces kosten Volumen — weshalb du gleich Sampling brauchst.

Sampling: welche Traces vollständig behalten

100 % aller Traces mit vollem Payload zu speichern ist bei hohem Traffic zu teuer und PII-lastig. Sampling entscheidet, welche Traces bleiben — und wann die Entscheidung fällt:

Head-based
Entscheidung am Trace-Start, meist zufällig (z. B. 5 %). Billig, aber outcome-blind — der Ausgang ist noch unbekannt, also fallen die meisten Fehler weg.
Tail-based
Entscheidung nachdem alle Spans da sind. Erlaubt outcome-basierte Regeln, braucht aber einen Puffer für alle laufenden Traces.
Error-/latency-biased
eine Tail-Regel: behalte alle Fehler und langsamen Traces, plus eine kleine Zufallsbasis normaler Traces.
Merksatz„Alle Fehler behalten“ ist mit Head-Sampling unmöglich — beim Trace-Start weißt du noch nicht, ob er fehlschlägt. Fehler-Erhalt braucht Tail-based.

Betriebsprobe: RUNTIME-PROVENANCE

Szenario

Ein Nutzer meldet eine schlechte Antwort von vor drei Tagen. Seither habt ihr zweimal einen neuen Prompt deployt, und euer Provider hat sein Modell hinter derselben API still aktualisiert. Zusätzlich läuft gerade ein A/B-Test, der pro Request eine von zwei Prompt-Varianten zuweist. Ihr wollt Requests künftig so festhalten, dass ein solcher Fall reproduzierbar ist.

Anforderungen

  • Was stempelt ihr pro Request fest, damit Incidents reproduzierbar sind?
  • Bewerte Ursache, wirksame Grenze und den Preis der tragfähigen Maßnahme getrennt.

Schritte

  1. Tragfähiger Ansatz: Die exakte Prompt-Version (Hash/Tag), die Modell-Identität inklusive Snapshot/Version und die aufgelöste Config (Temperatur, Retrieval-Parameter, zugewiesene A/B-Variante).. Richtig. Genau dieses Tripel — Prompt-Version, Modell-Snapshot, aufgelöste Config inkl. Experiment-Zuweisung — identifiziert eindeutig, was den Request bedient hat, unabhängig von späteren Deploys und stillen Provider-Wechseln.
  2. Plausibler Fehlweg: Den Git-Commit-SHA der App zum Request-Zeitpunkt — damit ist der Stand ja eindeutig festgehalten.. Der Commit pinnt euren Code, nicht das provider-seitige Modell (das sich unabhängig ändert) und nicht die per-Request aufgelöste A/B-Variante. Notwendig, aber nicht hinreichend — die reproduktionsrelevanten Teile fehlen.
  3. Plausibler Fehlweg: Nur den Zeitstempel — welcher Prompt und welches Modell live waren, rekonstruiert ihr im Incident aus dem Deploy-Log.. Rekonstruktion aus dem Zeitstempel bricht genau hier: Der stille Modell-Wechsel steht in keinem eurer Deploy-Logs, und die per-Request zugewiesene A/B-Variante lässt sich aus der Uhrzeit nicht ableiten. Aufzeichnen schlägt Rekonstruieren.
  4. Plausibler Fehlweg: Die Sampling-Parameter (Temperatur, top_p) pro Request — die bestimmen ja das Ergebnis.. Config allein ohne Prompt- und Modell-Identität sagt nicht, was die Antwort erzeugt hat. Selbst bei identischen Parametern liefert ein anderer Modell-Snapshot andere Ausgaben — die Identität fehlt.

Merksatz: Reproduzierbarkeit verlangt, die vollständige Bedien-Identität eines Requests aufzuzeichnen statt später zu rekonstruieren — denn Teile davon (Provider-Modell, Experiment-Zuweisung) liegen außerhalb deiner Deploy-Historie und ändern sich still. + Jeder Incident wird deterministisch nachstellbar, auch über stille Wechsel hinweg. Jeder Request trägt mehr Felder, und stromaufwärts braucht es Versionierungs-Disziplin: eine Prompt-Registry und gepinnte, benannte Modell-IDs statt „latest“.

Laufzeit-Provenienz: womit wurde dieser Request bedient?

Ein Nutzer meldet eine schlechte Antwort von vor drei Tagen. Seitdem wurde ein neuer Prompt deployt und der Provider hat sein Modell still aktualisiert. Ohne festgehaltene Provenienz ist der Fall nicht reproduzierbar.

Stemple jeden Request mit der exakten Prompt-Version (Hash/Tag), der Modell-Identität inkl. Snapshot/Version und der aufgelösten Config (Temperatur, Retrieval-Parameter, aktive Feature-Flags/Experiment-Zuweisung). Diese Provenienz reist mit dem Trace.

MerksatzEin App-Commit pinnt deinen Code — nicht das provider-seitige Modell noch die per-Request aufgelöste Config. Provenienz aufzeichnen ist robust; sie später aus dem Deploy-Log rekonstruieren bricht beim ersten stillen Wechsel.

Betriebsprobe: TRACE-CONTEXT

Szenario

Ein Chat-Request erscheint im Backend als drei voneinander unabhängige Traces. Latenz und Fehler lassen sich deshalb nicht bis zum Modellanbieter zurückverfolgen.

Anforderungen

  • Welches Ereignis bricht die Kausalitätskette?
  • Bewerte Ursache, wirksame Grenze und den Preis der tragfähigen Maßnahme getrennt.

Schritte

  1. Tragfähiger Ansatz: Den aktiven W3C-Trace-Kontext in erlaubte Message-Metadaten injizieren und beim Konsumenten extrahieren. Producer und Consumer bleiben dadurch kausal verbunden. Für Messaging braucht es eine bewusste Kontextübertragung, nicht nur lokale Spans.
  2. Plausibler Fehlweg: Im Worker denselben festen Trace-Identifier für alle Queue-Nachrichten dieses Tages verwenden — als zentrale Collector-Regel für alle Pfade versioniert und mit festem Aufbewahrungsziel ausgerollt. Ein geteilter Tageswert vermischt unabhängige Requests. Trace-IDs müssen eine konkrete verteilte Operation korrelieren.
  3. Plausibler Fehlweg: Nur die Provider-Dauer als Histogramm exportieren und die drei Traces unverändert lassen. Das Histogramm zeigt eine Verteilung, stellt aber die verlorene Kausalität eines einzelnen Requests nicht wieder her.

Merksatz: Verteiltes Tracing benötigt Kontextpropagation an jeder Prozess- und Transportgrenze; lokale Span-Erzeugung allein ergibt noch keinen zusammenhängenden Trace. + Queue-Wartezeit und Inferenz werden einem Request zurechenbar. Message-Metadaten und Instrumentierung werden Teil des zu pflegenden Telemetrievertrags.

Feedback-Signale als Telemetrie

Ohne Labels ist Nutzer-Feedback ein wertvolles Qualitätssignal. Explizit ist 👍/👎 — aber freiwilliges Feedback ist spärlich und verzerrt (meist nur sehr verärgerte oder begeisterte Nutzer, oft unter wenigen Prozent Klickrate).

Implizite Signale aus dem Nutzerverhalten ergänzen das Bild und decken die Mehrheit ab:

  • Regenerate / „nochmal“ — die Antwort taugte nicht
  • Copy-to-Clipboard — die Antwort war brauchbar (mit Vorsicht: kann auch Eskalation sein)
  • Folgefrage als Umformulierung — das Ziel wurde verfehlt
  • schneller Abbruch der Sitzung — kein Erfolg
MerksatzJedes Signal — explizit wie implizit — muss an die Trace-/Request-ID geknüpft werden. Ein loser 👎-Zähler sagt, dass etwas schlecht ist; erst die Verknüpfung sagt, welche Prompt-/Modell-Version es war.

Metrik vs. Trace vs. Log — und die Kardinalitäts-Falle

Nicht jedes Signal gehört in denselben Store. Die richtige Wahl hängt an der Kardinalität — der Anzahl unterschiedlicher Werte:

Metrik
aggregierbar, günstig, niedrige Kardinalität (Labels wie Modell, Endpoint, Status). Für Dashboards & Alerts.
Trace
ein Request über alle Stufen, mit hoher Detailtiefe. Für Ursachensuche eines konkreten Requests.
Log
diskrete Ereignisse mit Kontext. Für nachträgliche Detail-Recherche.

In Zeitreihen-Backends erzeugt jede eindeutige Kombination aus Metrik-Name und Label-Werten eine eigene Zeitreihe. Hochkardinale Labels wie user_id oder prompt_id (tausende Werte) multiplizieren sich mit den übrigen Labels und sprengen Speicher und Ingestion — die „Cardinality Bomb“. Solche per-Request-Details gehören in Traces/Logs, nicht in Metrik-Labels.

MerksatzSignal zum Store passend wählen: niedrige Kardinalität → Metrik (aggregieren & alarmieren), hohe Kardinalität → Trace/Log (auf Abruf durchsuchen). Hardware löst unbeschränkte Kardinalität nicht — sie wächst multiplikativ.

Zusammenfassung — gleich entscheidest du

Du kennst jetzt die Achsen, ein LLM-System sichtbar zu machen: Telemetrie-Umfang, Tracing & Spans, Trace-Sampling, Laufzeit-Provenienz, Feedback-Signale und die Metrik-vs-Trace-vs-Log-Entscheidung mit ihrer Kardinalitäts-Falle.

Gleich im CheckIn den nächsten sechs Entscheidungen wählst du für konkrete Ops-Szenarien selbst — und siehst pro Option, warum sie trägt oder aus welchem benannten Grund sie kippt.

Praxisachse: FEEDBACK-SIGNAL

Betriebsprobe: FEEDBACK-SIGNAL

Szenario

Euer Chat-Assistent hat keine Qualitäts-Labels. Ihr habt 👍/👎-Buttons eingebaut, aber weniger als 2 % der Nutzer klicken je darauf — und wer klickt, ist meist besonders verärgert oder begeistert. Product will trotzdem verlässlich wissen, ob die Antworten taugen.

Anforderungen

  • Wie gewinnt ihr ein brauchbares Qualitätssignal aus dem Betrieb?
  • Bewerte Ursache, wirksame Grenze und den Preis der tragfähigen Maßnahme getrennt.

Schritte

  1. Tragfähiger Ansatz: Zusätzlich implizite Signale erfassen (Regenerate, Copy, umformulierte Folgefrage, schneller Abbruch) und jedes Signal — explizit wie implizit — an die Trace-/Request-ID der auslösenden Antwort knüpfen.. Richtig. Implizite Signale decken die schweigende Mehrheit ab, und die Verknüpfung an den Trace macht sie pro Prompt-/Modell-Version auswertbar. So wird aus spärlichem Feedback ein belastbares, attribuierbares Signal.
  2. Plausibler Fehlweg: Beim expliziten 👍/👎 bleiben und die Klickrate durch UI-Nudges hochtreiben.. Freiwilliges Feedback ist strukturell spärlich und verzerrt (nur die Ränder klicken). Selbst verdoppelte 2 % repräsentieren nicht den Median — und das Mehrheitsverhalten, das die impliziten Signale zeigen, bleibt ungenutzt.
  3. Plausibler Fehlweg: Feedback als eigenständige Metrik führen: ein täglicher Zähler der 👎, ohne Bezug zum einzelnen Request.. Ein aggregierter 👎-Zähler zeigt, dass etwas schlecht ist, aber nicht welche Prompt-Version, welches Modell oder welcher Request-Typ. Ohne Trace-Verknüpfung kannst du nicht triagieren oder attribuieren.
  4. Plausibler Fehlweg: Nutzer-Feedback durch einen automatischen LLM-Judge ersetzen, der jede Antwort bewertet.. Ein Judge misst modell-geurteilte Qualität, nicht die tatsächliche Nutzer-Zufriedenheit — und der Bau von Eval-Judges ist ein anderes Thema (llmops/evaluation). Hier geht es darum, echte Nutzer-Signale als Telemetrie an Traces zu binden.

Merksatz: Explizites Feedback unterliegt Selektionsverzerrung und ist dünn; implizites Verhalten ist dicht und repräsentativer. Erst die Verknüpfung eines Signals an seinen Ursprungs-Trace macht es attribuierbar — ein loses Aggregat kann man nicht triagieren. + Dichtes, pro Version attribuierbares Qualitätssignal ohne Labels. Implizite Signale sind verrauschte Proxys (ein Copy kann Erfolg oder resignierte Eskalation heißen) und müssen vorsichtig interpretiert werden; Verhaltens-Tracking wirft zudem Datenschutzfragen auf.

Praxisachse: TELEMETRY-SCOPE

Betriebsprobe: TELEMETRY-SCOPE

Szenario

Euer LLM-Support-Assistent macht ~50.000 Requests/Tag. Heute wird pro Request nur der finale Antworttext geloggt. Gestern kam ein Beschwerdefall — die Antwort war fachlich falsch — und ihr konntet ihn nicht nachstellen: Ihr wisst nicht, was der Nutzer fragte, welcher Prompt aktiv war und welche Dokumente das Retrieval lieferte. Ihr definiert jetzt den Telemetrie-Umfang neu.

Anforderungen

  • Was erfasst ihr pro Request?
  • Bewerte Ursache, wirksame Grenze und den Preis der tragfähigen Maßnahme getrennt.

Schritte

  1. Tragfähiger Ansatz: Ein strukturierter Datensatz je Request: Input, Output, Token-Zahlen, Latenz, Kosten, Modell- und Prompt-Version sowie Retrieval-Kontext als Referenzen (Doc-IDs + Scores). PII-Redaction läuft in der dafür zuständigen Schicht, Retention ist definiert.. Richtig. Das ist der reproduzierbare Minimalumfang: Input + Versionen + Retrieval-Kontext erlauben, den Fall nachzuspielen; Referenzen statt Volltext und eine Retention halten das Volumen im Griff; PII wird gesondert behandelt statt hier ignoriert.
  2. Plausibler Fehlweg: Input und Output vollständig im Klartext, unbegrenzt aufbewahrt — lieber zu viel als zu wenig, damit nie wieder etwas fehlt — als zentrale Collector-Regel für alle Pfade versioniert und mit festem Aufbewahrungsziel ausgerollt sowie ohne Unterscheidung nach Diagnosewert oder Datenklasse dauerhaft beibehalten. Vollständigkeit ohne Grenzen ist der andere Fehler: bei 50.000 Requests/Tag explodieren Speicher und Kosten, und unbegrenzt gehortete Klartext-Inputs sind eine PII- und Compliance-Haftung. Umfang braucht Retention und Referenzierung, nicht Horten.
  3. Plausibler Fehlweg: Nur aggregierte Metriken — Token-Zahlen, Latenz und Kosten pro Zeitfenster. Das genügt für Dashboards und ist am günstigsten.. Damit baust du Kosten- und Latenz-Dashboards, aber kein einzelner Beschwerdefall wird reproduzierbar: Aggregate zeigen nie, was das Modell sah oder sagte. Genau diese Lücke hat euch gestern blockiert.
  4. Plausibler Fehlweg: Output plus eine Request-ID — Input, Versionen und Retrieval-Kontext lasst ihr weg, um Volumen zu sparen.. Eine Request-ID korreliert nur, sie rekonstruiert nichts. Ohne Input, Prompt-/Modell-Version und Retrieval-Kontext bleibt der Fall unreproduzierbar — das ist fast der Status quo, der gerade versagt hat.

Merksatz: Telemetrie-Umfang ist ein Trade-off zwischen Reproduzierbarkeit und Volumen/PII — die richtige Grenze ist „genug, um den Request nachzuspielen“, per Referenzen und Retention gebändigt, nicht das eine oder andere Extrem. + Jeder Incident wird nachstellbar, Volumen und PII bleiben beherrschbar. Mehr Felder pro Request und eine Referenz-/Retention-Mechanik, die es zu bauen und zu pflegen gilt; die PII-Redaction muss in ihrer eigenen Schicht wirklich greifen.

Jetzt anwenden

Diesen Stoff gibt es als Modul mit bewerteten Entscheidungs-Checks — dieselbe Einführung, danach die Übungen.

Zum Modul →
Quellen & Aktualität5 Primärquellen · zuletzt geprüft:
  1. 01OpenTelemetry Generative AI Semantic Conventions
  2. 02OpenTelemetry Sampling
  3. 03W3C Trace Context
  4. 04Prometheus Metric and Label Naming
  5. 05Google SRE Book, Monitoring Distributed Systems