logging-backend
Logging Backend - Wide Events
Implementa Wide Events (tambien conocidos como Canonical Log Lines): un evento estructurado por request que contiene TODO el contexto relevante en un solo registro.
Concepto Core
Un Wide Event es un unico log JSON que captura el ciclo completo de un request. En lugar de multiples logs dispersos ("user logged in", "fetched data", "returned response"), emitir UN evento al final con toda la informacion agregada.
Beneficios:
- Debuggear con UN query en vez de correlacionar multiples logs
- Analisis con SQL simple sobre campos estructurados
- Sin perdida de contexto entre logs
- Tail sampling efectivo (solo guardar eventos interesantes)
Comparacion: Log tradicional vs Wide Event:
// Log tradicional - multiples lineas dispersas
[10:30:00] INFO: User 789 logged in
[10:30:01] INFO: Fetching orders for user 789
[10:30:02] DEBUG: Query executed in 45ms
[10:30:02] INFO: Found 3 orders
[10:30:03] ERROR: Failed to send email notification
// Wide Event - todo en un solo registro
{
"timestamp": "2024-01-15T10:30:03.000Z",
"user": { "id": "789" },
"action": "fetch_orders",
"result": { "count": 3 },
"infra": { "db_time_ms": 45 },
"error": { "type": "email_failed", "message": "SMTP timeout" }
}
Estructura de un Wide Event
{
"timestamp": "2024-01-15T10:30:00.000Z",
"level": "info",
"service": "api-gateway",
"trace_id": "abc123",
"request": { "method": "POST", "path": "/api/orders", "duration_ms": 245 },
"user": { "id": "user_789", "plan": "premium" },
"business": { "order_id": "ord_456", "total": 150.00, "items_count": 3 },
"infra": { "db_queries": 4, "db_time_ms": 120, "cache_hits": 2 },
"error": null
}
Ver references/wide-event-schema.md para esquema completo con todos los campos recomendados.
Workflow de Implementacion
Fase 1: Middleware Base
- Crear middleware que inicializa el wide event al inicio del request
- Adjuntar el evento al contexto (req.wideEvent, AsyncLocalStorage, etc.)
- Emitir el log al finalizar el request
Ver references/implementation.md para codigo del middleware.
Fase 2: Enriquecimiento
- En cada handler/service, agregar campos al wide event
- Usar helpers tipados:
enrichUser(),enrichBusiness(),enrichError() - Acumular metricas: queries, cache hits, llamadas externas
Fase 3: Tail Sampling
- Implementar funcion de sampling que decide que loggear
- Siempre loggear: errores, latencia alta, usuarios especificos
- Samplear porcentaje de requests exitosos normales
Ver references/implementation.md para funcion de tail sampling.
Fase 4: Colorizacion (Desarrollo)
- Configurar colores por nivel (ERROR=rojo, WARN=amarillo)
- Configurar colores por contexto (Request=azul, User=verde)
- Formatear output legible en terminal
Ver references/colorization.md para configuracion de colores.
Checklist Rapido
- Middleware que crea wide event por request
- Contexto accesible en toda la cadena (AsyncLocalStorage / req)
- Campos request: method, path, status, duration_ms
- Campos user: id, plan, roles (si aplica)
- Campos business: entidades del dominio
- Campos infra: db_queries, cache_hits, external_calls
- Campos error: code, message, stack (si hay error)
- Tail sampling configurado
- Formato JSON en prod, coloreado en dev
Anti-patrones
Ver references/anti-patterns.md para errores comunes:
- Confundir structured logging con wide events
- Depender solo de OpenTelemetry
- Loggear multiples veces por request
- No incluir contexto de negocio
Referencias
references/wide-event-schema.md- Esquema JSON completo con todos los camposreferences/implementation.md- Codigo de middleware y helpersreferences/anti-patterns.md- Que NO hacerreferences/colorization.md- Configuracion de colores para dev
Troubleshooting
El wide event no captura datos del usuario
Sintoma: user: null en todos los logs
Causa comun: El middleware de auth corre despues del wide event middleware.
Solucion:
// Orden incorrecto
app.use(wideEventMiddleware('my-service'));
app.use(authMiddleware); // user no disponible cuando se crea el evento
// Orden correcto
app.use(authMiddleware);
app.use(wideEventMiddleware('my-service')); // user ya esta en req
Los logs salen vacios en infra.db
Sintoma: db: { queries_count: 0, total_time_ms: 0 }
Causa comun: No se estan usando los helpers de tracking.
Solucion: Wrappear las queries:
const query = async (sql: string) => {
const start = Date.now();
const result = await db.query(sql);
trackDbQuery(Date.now() - start);
return result;
};
Logs demasiado grandes en produccion
Sintoma: Costos altos de almacenamiento/ingesta
Solucion: Implementar tail sampling agresivo:
const shouldLog = (event: WideEvent): boolean => {
if (event.level === 'error') return true;
if (event.request.duration_ms > 1000) return true;
return Math.random() < 0.01; // Solo 1% del resto
};
No puedo correlacionar logs entre servicios
Sintoma: Cada servicio tiene su propio trace_id
Causa: No se esta propagando el header.
Solucion: Ver references/implementation.md seccion "Propagacion Cross-Service".
Lecturas Recomendadas
- Stripe Engineering - Canonical Log Lines - El articulo original que popularizo el patron
- Observability Wide Events 101 - Guia practica de implementacion
More from testacode/llm-toolkit
claude-md-writer
Escribe y mejora archivos CLAUDE.md siguiendo best practices de Anthropic. Este skill se activa cuando el usuario dice "crear CLAUDE.md", "mejorar CLAUDE.md", "actualizar CLAUDE.md", "revisar CLAUDE.md", "escribir instrucciones del proyecto", "create CLAUDE.md", "improve CLAUDE.md", "review CLAUDE.md", "write project instructions", "optimize docs for Claude", "auditar CLAUDE.md", "audit CLAUDE.md", "limpiar CLAUDE.md", "dead weight", o configura un nuevo repositorio.
53doc-writer
Este skill se usa para crear documentos tecnicos organizados en /docs (specs, planes de implementacion, ADRs, documentacion de referencia). Se activa cuando el usuario dice "crear documento", "escribir spec", "documentar esto", "creame una spec", "escribime documentacion", "hacer documentacion", "write a spec", "create documentation", "write an ADR", o quiere agregar documentacion tecnica al proyecto.
44llms-txt-generator
This skill generates llms.txt documentation optimized for AI/LLM consumption. It should be used when the user says "crear llms.txt", "generate llms.txt", "documentar para AI", "document for AI", "crear documentacion para LLMs", "generate docs for LLMs", "make repo readable for Claude", or wants to create structured machine-readable documentation following the llms.txt standard.
40doc-organizer
Este skill se usa cuando el usuario pide "organizar docs", "ordenar documentacion", "mover documentos a carpetas", "categorizar archivos md", "reorganizar documentacion", o cuando hay archivos .md sueltos en docs/ que necesitan ser movidos a subcarpetas tematicas. Organiza y categoriza documentos tecnicos en la estructura correcta del proyecto.
28feature-planner
Planifica features con entrevista estructurada y crea tareas. Este skill se activa cuando el usuario dice "quiero agregar", "planificar feature", "nueva funcionalidad", "implementar esto", "crear plan", "planificar antes de codear", "disenar feature", "como deberia implementar esto", "pensar la arquitectura", o quiere alinear antes de escribir codigo.
27nextjs-project-starter
Creates Next.js projects with a configurable stack (Mantine, Supabase, Zustand, Zod). This skill should be used when the user says "create a Next.js project", "new web project", "bootstrap fullstack app", "start new app", "crear proyecto Next.js", "nuevo proyecto web", "empezar app fullstack", or wants to scaffold a new personal project from scratch.
25