Spanlens - plataforma de observabilidad open source para ver llamadas de LLM y trazas de agentes en un solo lugar
(spanlens.io)Hola. Estoy creando Spanlens, una plataforma de observabilidad open source para ver en un solo lugar el logging de llamadas de LLM, el seguimiento de costos y las trazas de agentes.
Por qué lo hice
Mientras usaba LLM en proyectos personales, hubo dos cosas que me siguieron molestando.
Una era el seguimiento de costos.
Todo empezó cuando estaba creando una extensión de navegador basada en GPT y me sorprendió por primera vez al recibir la factura de OpenAI a fin de mes. Como soy estudiante universitario, no era una cantidad enorme, pero aunque podía ver el total, no podía ver por separado cuánto salía de cada función ni cuánto usaba en promedio de tokens cada modelo. Así que terminaba repitiendo el proceso de meter console.log en el código, exportar a CSV, sumar todo en Excel y estimar los costos multiplicando por la tarifa de cada modelo.
La otra era la depuración de agentes.
Fue algo que viví directamente al integrar LangGraph en Spanlens: cuando una sola traza mezclando múltiples llamadas a LLM tardaba 30 segundos, tenía que abrir los logs y seguir todo manualmente para ver
- en qué nodo se había ido el tiempo
- por qué se llamó dos veces a la misma herramienta
- en qué momento había cambiado el estado de LangGraph
Quise reducir esos dos problemas, y por eso creé Spanlens.
Funciones principales
- Integración de una sola línea con
baseURL
Si cambias el baseURL de los SDK de OpenAI/Anthropic/Gemini a algo como https://api.spanlens.io/proxy/openai/v1, las solicitudes, respuestas, tokens y costos se registran automáticamente. Las respuestas hacen passthrough tal cual, así que streaming, tool calling y JSON mode funcionan exactamente igual que en el original.
Para casos como agentes, donde se necesita un enfoque de wrap, hice que el SDK pueda inyectar trace_id y span_id para registrar también la relación padre-hijo.
- Trazas de agentes + vista de topología de LangGraph
Las trazas se pueden ver no solo como una línea de tiempo cronológica, sino también superpuestas sobre los nodos reales del grafo. Si el agente está hecho con LangGraph, puedes ver en una sola pantalla en qué nodo se fue el tiempo y qué arista se recorre con más frecuencia.
- Análisis automático de Critical Path
Dentro de una traza se marca automáticamente la cadena de llamadas que más latencia consumió. Quise reducir la cantidad de clics necesarios para responder la pregunta: “¿por qué esta traza fue lenta?”.
- Comparación estadística A/B de prompts
Compara dos versiones del mismo prompt según latencia, costo y uso de tokens. No muestra solo una diferencia de promedios: aplica Welch t-test para mostrar diferencias considerando también la varianza de la muestra. Lo incluí para poder decir no solo “el promedio parece un poco menor”, sino “hay una diferencia significativa”.
- Self-hosting
Se puede desplegar en tu propio servidor con una imagen de Docker. El mismo código de la versión SaaS está público tal cual en el repositorio. Todo el código está bajo licencia MIT.
Cómo está implementado
Actualmente el pipeline es más o menos así.
- Las solicitudes del proxy se reciben con Hono, se separan el header
Authorizationy los metadatosX-Spanlens-*, y la provider key se descifra con AES-256-GCM para usarse solo en memoria justo antes de la llamada. - En respuestas en streaming, con
body.tee()se devuelve de inmediato el stream original al cliente, y la copia se procesa en segundo plano para calcular tokens y costos. - Los logs se cargan de forma asíncrona en ClickHouse. Si falla un
INSERT, se guardan en una cola de respaldo en Supabase y un cron reintenta después; es una estructura fire-and-forget, pero intenté evitar la pérdida de datos. - Los precios de modelos se guardan en una tabla de la base de datos y se cachean con un TTL de 5 minutos usando stale-while-revalidate. El precio de fallback sirve como red de seguridad para cold start.
Al principio era solo un proxy simple, pero al usarlo en la práctica me di cuenta de que lo importante no eran los logs raw, sino las trazas normalizadas. Para responder “¿por qué esta traza fue lenta?” no basta con el orden de llamadas: también hacen falta relaciones padre-hijo, llamadas paralelas y el Critical Path, y de ahí salieron funciones como la vista de topología de LangGraph y el Critical Path automático.
El stack es Next.js 14, Hono, Supabase Postgres, ClickHouse, todo en un monorepo de TypeScript con pnpm.
Puntos que todavía estoy evaluando
-
Quiero que el self-hosting se pueda hacer con una sola línea de
docker run, pero para eso también tendría que bajar Supabase Postgres. Ahora mismo, asumiendo Supabase administrado,docker-composeusa 3 contenedores: web, server y ClickHouse. Estoy pensando si conviene crear también una opción de self-hosting para Supabase o mantener la premisa de usar la versión administrada. -
En la comparación A/B de prompts ya está incluido el cálculo de Welch t-test, pero todavía no decido si conviene mostrar el p-value tal cual o solo una insignia de conclusión (significativo / no significativo). También estoy pensando cómo mostrar advertencias cuando la muestra es pequeña (
n<30). -
En la vista de topología de LangGraph se visualizan nodos, aristas y Critical Path, pero dejé fuera a propósito los cambios del state channel porque generan demasiado ruido. Me gustaría saber si en la depuración real hace más falta seguir los cambios de estado o si el nivel actual es suficiente.
Es un proyecto que comenzó a partir de molestias que viví personalmente y que he ido puliendo de forma constante.
[ Spanlens ]
Web: https://www.spanlens.io
GitHub: https://github.com/spanlens/Spanlens
Guía de self-hosting: https://www.spanlens.io/docs/self-host
Agradecería muchísimo cualquier feedback, ya sea sobre la UX del dashboard, la visualización de trazas, el enfoque de integración del proxy, la experiencia de self-hosting o cualquier otra perspectiva. En especial, si hay algún provider que les gustaría que se soporte además de OpenAI/Anthropic/Gemini, por favor díganmelo en los comentarios.
Hay una versión demo en el sitio web, así que agradeceré mucho su interés.
Actualmente la UI está en inglés y planeo añadir soporte en coreano pronto.
Aún no hay comentarios.