Tracing für KI-Anwendungen
Ein ManagedTracing ist ein OTLP-Endpunkt für die Aufrufe, die deine App an ein LLM macht: Richte den OpenTelemetry-Exporter deines Modell-Clients darauf, und jeder Prompt, jede Antwort, jede Token-Zahl und jede Latenz landet an einer Stelle, an der du sie siehst — OpenLIT (Apache-2.0) über ClickHouse, direkt gerendert, ohne eigenen Operator zu installieren.
Einschalten
Abschnitt betitelt „Einschalten“Tracing ist eine Capability, standardmäßig aus, pro Shoot in der Konfiguration der paasbox-paas-Extension eingeschaltet — derselbe Block, den paasbox garden shoot create in dein Shoot-Manifest schreibt:
apiVersion: core.gardener.cloud/v1beta1kind: Shootspec: extensions: - type: paasbox-paas providerConfig: apiVersion: paas.paasbox.com/v1alpha1 kind: PaasConfig capabilities: [apps, postgres, valkey, tracing]Füge tracing der Liste hinzu und wende den Shoot erneut an. Das Einschalten selbst kostet nichts — kein Operator wird installiert, nur das Objekt und ein Reconciler, der ohnehin schon läuft. Die Kosten fangen erst mit deinem ersten ManagedTracing an.
Eines anlegen
Abschnitt betitelt „Eines anlegen“apiVersion: paas.paasbox.com/v1alpha1kind: ManagedTracingmetadata: { name: traces, namespace: shop }spec: plan: s store: { mode: managed }status: conditions: [Reconciled, Ready, Degraded, StoreHealthy, SpansDropping] phase: Ready endpoint: otlp: http://traces.shop.svc:4318 ui: http://traces.shop.svc:3000 secretName: traces-otlpkubectl apply -f traces.yaml gibt dir eine Ready-Instanz in etwa einer Minute — gemessen 52 Sekunden auf einem bezahlten Hetzner-Shoot bei Plan s (2026-09-16). plan bemisst den OpenLIT-Pod; store.mode: managed rendert eine einzelne ClickHouse-Instanz daneben, im selben Namespace, die sonst niemand liest. retention (Standard 30d) ist die einzige Schranke dafür, wie viel ein ManagedTracing behält: ClickHouse hat kein Kontingent für gespeicherte Bytes pro Instanz.
Deine App darauf zeigen lassen
Abschnitt betitelt „Deine App darauf zeigen lassen“# auf der Appuses: [{ name: traces, kind: ManagedTracing }]injiziert fünf Umgebungsvariablen: OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_PROTOCOL (http/protobuf) und OTEL_EXPORTER_OTLP_HEADERS (ein x-api-key) als Referenzen auf traces-otlp, dazu zwei feste Werte: OTEL_BSP_MAX_EXPORT_BATCH_SIZE=512 und, die entscheidende, OTEL_BSP_MAX_QUEUE_SIZE=32768. Jedes OpenTelemetry-SDK, das die Standard-Variablen OTEL_EXPORTER_OTLP_TRACES_* liest — dazu gehören OpenLITs eigenes und die meisten LLM-Tracing-Bibliotheken —, braucht sonst nichts. Ein prefix auf dieser Abhängigkeit wird akzeptiert, tut aber nichts: Die Namen sind fest.
Warum die Queue-Größe nicht optional ist
Abschnitt betitelt „Warum die Queue-Größe nicht optional ist“Ein OTel-SDK sammelt Spans im Speicher, bevor es sie verschickt, in einer Queue fester Größe; ist sie voll, verwirft das SDK neue Spans selbst, bevor sie je das Netzwerk erreichen. Die meisten SDKs setzen diese Queue standardmäßig auf 2048. Gemessen auf einem bezahlten Shoot (2026-09-16): Ein Burst von 10.002 Spans gegen ein ManagedTracing mit der Standard-Queue des SDKs schickte nur 2.688 an den Store — 7.314 Spans, 73 %, wurden im eigenen Prozess der App verworfen, während der eigene Ablehnungszähler des Stores die ganze Zeit bei null stand. Auf der Empfangsseite sah nichts nach einem Problem aus; die Spans waren verschwunden, bevor sie den Pod verließen.
Deshalb setzt uses OTEL_BSP_MAX_QUEUE_SIZE=32768 automatisch für dich. Unter sauberer Last ohne Bursts verlor derselbe Aufbau nichts (1.002 geschickt, 1.002 gespeichert). Die Falle betrifft gezielt einen Burst gegen die SDK-Vorgabe — und sie ist still, weil status.drops.storeRefused die ganze Zeit über unauffällig bleibt.
Auf Verluste achten
Abschnitt betitelt „Auf Verluste achten“status.drops trägt beide Zähler, denn nur einer davon ist echter Gegendruck:
storeRefused— Spans, die ClickHouse tatsächlich abgelehnt hat. Ein Wert über null hier heißt: der Store ist überlastet.clientDropped— Spans, die das eigene SDK deiner App verworfen hat, bevor sie verschickt wurden, über denselben OTLP-Endpunkt zurückgelesen. Das ist die Zahl, in der sich die Queue-Größen-Falle zeigt.
Die Condition SpansDropping wird True, sobald einer der beiden Zähler steigt — du musst also nicht beide Zahlen von Hand abfragen, um es zu bemerken.
Was es kostet
Abschnitt betitelt „Was es kostet“plan bemisst OpenLIT; ClickHouse (Modus managed) wird nicht nach Plan bemessen — es fordert immer 600Mi mit einem Limit von 2Gi an, weil dieser Spielraum für Abfragen gedacht ist, nicht für eine größere Instanz:
| Plan | OpenLIT-CPU | OpenLIT-Speicher | ClickHouse-Speicherboden |
|---|---|---|---|
xs | 100m | 256Mi | 5Gi |
s | 250m | 512Mi | 10Gi |
m | 500m | 1Gi | 20Gi |
l | 1 | 2Gi | 50Gi |
Addiere ClickHouses feste 600Mi-Anforderung zum eigenen Speicher des Plans, um zu sehen, was eine Instanz reserviert: 1.112Mi bei Plan s, 856Mi bei xs — beide zweimal unabhängig gemessen, auf einem bezahlten Shoot (2026-09-16). Das ist mehr, als die elf eigenen Operatoren der Plattform zusammen reservieren. Das Portal soll diese Zahl vor dem Schalter zeigen; bis es das tut, ist diese Seite diese Zahl.
Beim Speicher gibt es dieselbe Art Überraschung. OpenLITs eigenes Datenvolume ist eine feste 2Gi-Anforderung, unabhängig vom Plan. Hetzners Blockspeicher stellt nie weniger als 10Gi bereit, also wird aus dieser 2Gi-Anforderung ein 10Gi-Volume — und bei Plan s, wo ClickHouses eigene 10Gi-Anforderung schon genau auf diesem Boden liegt, kostet eine ManagedTracing-Instanz 20Gi Blockspeicher, nicht die 12Gi, auf die ihre beiden Anforderungen zusammen kämen. Derselbe 10Gi-Boden pro Volume gilt bei jedem Plan; nur m und l verlangen von ClickHouse mehr als diesen Boden selbst.
Nie skalieren
Abschnitt betitelt „Nie skalieren“ManagedTracing hat absichtlich kein replicas-Feld. OpenLITs eigener Identitätszustand — Organisationen, Projekte, API-Keys, die Konfiguration, die Mandanten auseinanderhält — liegt in einer einzigen SQLite-Datei auf einem Read-Write-Once-Volume. Ein zweiter Pod scheitert entweder beim Scheduling oder beschädigt diese Datei. Eine Instanz ist dafür gedacht, ein ganzes Team über ihre eigenen Dashboards zu bedienen, nicht dafür, wie eine zustandslose App skaliert zu werden.
Ansehen
Abschnitt betitelt „Ansehen“Es gibt noch keine öffentliche Route zur OpenLIT-Oberfläche — status.endpoint.ui ist absichtlich eine clusterinterne Adresse. Erreiche sie von deinem Rechner aus mit:
kubectl -n shop port-forward svc/traces 3000:3000Wie es weitergeht
Abschnitt betitelt „Wie es weitergeht“- Eine App deployen:
uses, und alles andere, was eineAppannimmt. - Beispiel: eine Django-SaaS: dieselbe App mit eingebundenem Tracing.
- Das pb-CLI:
pb statuslistetManagedTracingnebenApp,ManagedPostgresundManagedValkey.