Spanlens – Open-Source-Observability-Plattform, um LLM-Aufrufe und Agent-Trace an einem Ort zu sehen
(spanlens.io)Hallo. Ich entwickle Spanlens, eine Open-Source-Observability-Plattform, mit der man LLM-Call-Logging, Kosten-Tracking und Agent-Trace an einem Ort sehen kann.
Warum ich es gebaut habe
Während ich LLMs in persönlichen Side Projects genutzt habe, haben mich immer wieder zwei Dinge gestört.
Das eine war Kosten-Tracking.
Es fing damit an, dass ich beim Bauen einer GPT-basierten Browser-Erweiterung zum ersten Mal überrascht war, als am Monatsende die OpenAI-Rechnung kam. Als Student war der Betrag nicht riesig, aber man sah nur die Gesamtsumme – nicht, welche Funktion wie viel verursacht hatte oder welches Modell im Durchschnitt wie viele Tokens verbrauchte. Also habe ich immer wieder console.log in den Code gesetzt, CSVs exportiert, die Werte in Excel summiert und Schätzungen berechnet, indem ich die Preise pro Modell multipliziert habe.
Das andere war Agent-Debugging.
Das habe ich direkt erlebt, als ich Spanlens mit LangGraph integriert habe: Wenn ein einzelner Trace mit mehreren gemischten LLM-Aufrufen 30 Sekunden dauerte, musste ich per Hand durch ausgebreitete Logs gehen, um Dinge wie diese nachzuverfolgen:
- In welchem Node ging Zeit verloren?
- Warum wurde dasselbe Tool zweimal aufgerufen?
- An welchem Punkt hat sich der LangGraph-State geändert?
Ich wollte diese beiden Probleme verringern, deshalb habe ich Spanlens gebaut.
Hauptfunktionen
- Ein-Zeilen-Integration per baseURL
Wenn man die baseURL der OpenAI-/Anthropic-/Gemini-SDKs auf https://api.spanlens.io/proxy/openai/v1 ändert, werden Requests, Responses, Tokens und Kosten automatisch protokolliert. Die Responses werden unverändert durchgereicht, daher funktionieren Streaming, Tool Calling und JSON Mode genauso wie im Original.
Für Fälle wie Agenten, in denen ein Wrap-Ansatz nötig ist, habe ich es so umgesetzt, dass man per SDK trace_id und span_id injizieren kann, damit auch Parent-Child-Beziehungen mitprotokolliert werden.
- Agent-Trace + LangGraph-Topology-Ansicht
Traces werden nicht nur als Timeline in zeitlicher Reihenfolge angezeigt, sondern direkt über die tatsächlichen Graph-Nodes gelegt. Bei einem mit LangGraph gebauten Agenten sieht man auf einem Bildschirm, in welchem Node Zeit verloren ging und welche Edge am häufigsten durchlaufen wird.
- Automatische Critical-Path-Analyse
Innerhalb eines Trace wird die Call-Chain, die am meisten Latenz verursacht hat, automatisch hervorgehoben. Ich wollte die Anzahl der Klicks reduzieren, bis man die Antwort auf „Warum war dieser Trace langsam?“ findet.
- Statistischer Vergleich von Prompts per A/B-Test
Zwei Versionen desselben Prompts werden anhand von Latenz, Kosten und Token-Verbrauch verglichen. Statt nur Mittelwertsunterschiede zu zeigen, wird ein Welch-t-Test angewendet, damit auch Unterschiede unter Berücksichtigung der Stichprobenvarianz sichtbar werden. Ich habe das eingebaut, damit man nicht nur sagen kann: „Der Durchschnitt ist etwas niedriger“, sondern: „Der Unterschied ist signifikant.“
- Self-Hosting
Es kann per Docker-Image auf einem eigenen Server betrieben werden. Derselbe Code wie in der SaaS-Version liegt unverändert im öffentlichen Repository. Der gesamte Code steht unter der MIT-Lizenz.
Wie es umgesetzt ist
Die aktuelle Pipeline sieht grob so aus.
- Proxy-Requests werden mit Hono entgegengenommen, wobei der
Authorization-Header undX-Spanlens-*-Metadaten getrennt werden; der Provider-Key wird mit AES-256-GCM entschlüsselt und nur unmittelbar vor dem Aufruf im Speicher verwendet. - Bei Streaming-Responses wird per
body.tee()der Original-Stream sofort an den Client zurückgegeben, während ein Duplikat im Hintergrund vom Parser für Token- und Kostenberechnung verarbeitet wird. - Logs werden asynchron in ClickHouse geschrieben. Wenn
INSERTfehlschlägt, werden sie in einer Supabase-Fallback-Queue gespeichert und später per Cron erneut versucht. Es ist also ein Fire-and-forget-Ansatz, aber ich wollte Datenverlust trotzdem vermeiden. - Modellpreise liegen in einer DB-Tabelle und werden mit 5-Minuten-TTL per stale-while-revalidate gecacht. Fallback-Preise dienen als Sicherheitsnetz bei Cold Starts.
Am Anfang war es nur ein einfacher Proxy, aber in der praktischen Nutzung wurde klar, dass nicht rohe Logs, sondern normalisierte Traces wichtiger sind. Um die Antwort auf „Warum war dieser Trace langsam?“ zu finden, braucht man nicht nur die Reihenfolge der Aufrufe, sondern auch Parent-Child-Beziehungen, parallele Aufrufe und den Critical Path. Daraus sind Funktionen wie die LangGraph-Topology-Ansicht und der automatische Critical Path entstanden.
Der Stack besteht aus Next.js 14, Hono, Supabase Postgres, ClickHouse – alles in einem TypeScript-pnpm-Monorepo.
Punkte, über die ich noch nachdenke
-
Ich würde Self-Hosting gern als Ein-Zeilen-
docker runanbieten, aber dafür müsste auch Supabase Postgres mit ausgeliefert werden. Aktuell gehtdocker-composeunter der Annahme von managed Supabase von drei Containern aus:web,server, ClickHouse. Ich überlege noch, ob eine Self-Hosting-Option für Supabase sinnvoller wäre oder ob die managed-Annahme beibehalten werden sollte. -
Beim Prompts-A/B-Vergleich ist die Berechnung des Welch-t-Tests schon drin, aber ich bin noch unschlüssig, ob es hilfreicher ist, den p-Wert direkt zu zeigen, oder nur ein Ergebnis-Badge (signifikant/nicht signifikant). Gleichzeitig denke ich darüber nach, wie bei kleinen Stichproben (
n<30) gewarnt werden sollte. -
In der LangGraph-Topology-Ansicht visualisiere ich Nodes, Edges und den Critical Path, aber Änderungen im State-Channel habe ich bewusst weggelassen, weil das zu viel Rauschen erzeugt. Ich würde gern wissen, ob State-Tracking im echten Debugging wichtiger ist oder ob das aktuelle Niveau passend ist.
Das Projekt ist aus selbst erlebten Unannehmlichkeiten entstanden und wird seitdem kontinuierlich weiter verfeinert.
[ Spanlens ]
Web: https://www.spanlens.io
GitHub: https://github.com/spanlens/Spanlens
Self-Hosting-Guide: https://www.spanlens.io/docs/self-host
Ich wäre wirklich dankbar für Feedback – egal ob zur Dashboard-UX, zur Trace-Visualisierung, zur Proxy-Integration, zur Self-Hosting-Erfahrung oder aus irgendeiner anderen Perspektive. Wenn es neben OpenAI/Anthropic/Gemini noch andere Provider gibt, die ihr gern unterstützt sehen würdet, schreibt es bitte in die Kommentare.
Auf der Website gibt es eine Demo-Version, ich freue mich über viel Interesse.
Die aktuelle UI ist auf Englisch, Unterstützung für Deutsch ist derzeit nicht angekündigt; Unterstützung für Koreanisch soll bald hinzugefügt werden.
Noch keine Kommentare.