traza-log
v0.2.1
Published
Drop-in tracer y logger para Node, browser y edge runtimes. Envía eventos y spans a tu dashboard de Traza sin bloquear el flujo principal.
Maintainers
Readme
traza-log
SDK ligero de tracing y logging para Node, navegador y edge runtimes. Envía eventos y spans al dashboard de Traza sin bloquear el flujo principal de tu aplicación.
traza.log / info / warn / error / debug— drop-in replacement deconsole.traza.startSpan,traza.time,traza.instrument— mide latencia de queries, peticiones HTTP, o cualquier bloque async.traza.middleware()— instrumenta cada request HTTP automáticamente.instrumentBrowser()(entrytraza-log/browser) — errores no manejados, Web Vitals, fetch fallidos/lentos y page views en el frontend, sin dependencias.- Cola en memoria + batching HTTP + reintentos con backoff: nunca bloquea, descarta antes que retrasar.
- Compatible con Node 18+, Bun, Deno, Cloudflare Workers, Vercel Edge, navegadores modernos, React Native / Capacitor / Ionic.
Instalación
pnpm add traza-log # o npm i traza-log / yarn add traza-log / bun add traza-logConfiguración
Solo necesitas el token. El endpoint por defecto es https://traza.gd.pe — pásalo explícitamente solo si self-hosteas.
import { traza } from 'traza-log'
traza.configure({
token: process.env.TRAZA_TOKEN!, // generado en el dashboard
service: 'api', // opcional
environment: process.env.NODE_ENV, // opcional
release: process.env.GIT_SHA, // opcional
defaultAttributes: { region: 'lima' }, // se adjunta a todo evento
// endpoint: 'https://tu-traza.miempresa.com', // solo si self-hosteas
flushIntervalMs: 3000, // default
maxBatchSize: 100, // default
maxQueueSize: 10000, // default
sampleRate: 1, // 0..1
forwardToConsole: true, // imprime también en consola local
})Logs
traza.log('Hola mundo')
traza.info('usuario autenticado', { userId: 42 })
traza.warn('consulta lenta', { ms: 1200 })
traza.error('fallo en checkout', { err })
traza.debug('cache miss', { key: 'user:42' })Medir rendimiento
Tres formas, elige la que te quede más natural:
1. Span manual
const span = traza.startSpan('db.query', { attributes: { table: 'users' } })
try {
const rows = await db.select().from(users)
span.setAttribute('rowCount', rows.length)
span.end({ status: 'ok' })
} catch (err) {
span.end({ status: 'error', error: err })
}2. time() — wrap automático
const users = await traza.time('db.users', () => db.select().from(usersTable))3. instrument() — para funciones reutilizables
const getUser = traza.instrument(
'db.getUser',
async (id: string) => db.query.users.findFirst({ where: eq(users.id, id) }),
(id) => ({ userId: id }),
)Middleware HTTP
Express / Connect / Polka
import express from 'express'
import { traza } from 'traza-log'
const app = express()
app.use(traza.middleware())Nuxt 3 / Nitro / H3
// server/middleware/traza.ts
import { traza } from 'traza-log'
export default defineEventHandler((event) => {
return traza.h3((e) => e)(event)
})Cada request HTTP genera una span con http.method, http.url, http.status_code y propaga el traceId a todos los logs y spans hijos.
Observabilidad en el navegador
La entry traza-log/browser instrumenta automáticamente el frontend:
import { traza } from 'traza-log'
import { instrumentBrowser } from 'traza-log/browser'
traza.configure({ token: TRAZA_TOKEN, service: 'web' })
const teardown = instrumentBrowser(traza, {
errors: true, // window.onerror + unhandledrejection
webVitals: true, // LCP, CLS, INP, TTFB → eventos web_vital.*
network: { // fetch fallidos (>= 400 / error de red) o lentos → spans
slowMs: 3000,
ignoreUrls: [/analytics/],
},
pageViews: true, // carga inicial + navegación SPA → eventos page_view
})- Fuera del navegador es un no-op seguro (puedes llamarlo en código universal).
- Los requests al propio endpoint de ingest de Traza se ignoran siempre.
teardown()restaurafetch,historyy los listeners (útil en HMR o tests).- Usa un token de tipo browser (se crea en el dashboard con un allowlist de orígenes): la ingesta rechaza requests de orígenes no listados, así que el token puede viajar en el bundle del cliente. Nunca uses el token de tu backend en el navegador.
Contexto
traza.runWithContext({ attributes: { requestId } }, async () => {
traza.info('start') // incluye requestId
await traza.time('work', work)
})Comportamiento no bloqueante
- Los eventos se acumulan en una cola en memoria (max 10 000 por defecto).
- Se envían al dashboard cada
flushIntervalMso cuando la cola alcanzamaxBatchSize. - Si la red falla: reintentos con backoff exponencial (200 ms → 5 s, 3 intentos).
- Si la cola se llena: se descartan los eventos más antiguos, el código de aplicación nunca espera.
- Hooks de shutdown (
beforeExiten Node,pagehideen navegador) hacen flush final.
Apagar limpiamente
process.on('SIGTERM', async () => {
await traza.shutdown()
process.exit(0)
})Licencia
MIT.
