Introduction
evlog is a structured logging library for TypeScript. It gives you simple one-liner logs, wide events that accumulate context over any operation, and structured errors that explain why something failed and how to fix it.
Inspired by Logging Sucks by Boris Tane.
Philosophy
Traditional logging is broken. Your logs are scattered across dozens of files. Each request generates 10+ log lines. When something goes wrong, you're left grep-ing through noise hoping to find signal.
evlog takes a different approach:
Structured Logging
console.log with typed, structured events that flow through a drain pipeline.Wide Events
Structured Errors
Pretty for Dev
Three Ways to Log
evlog provides three APIs for different contexts. You can use all three in the same project.
Simple Logging
Fire-and-forget structured logs. Replace console.log, consola, or pino:
import { log } from 'evlog'
log.info('auth', 'User logged in')
log.error({ action: 'payment', error: 'card_declined', userId: 42 })
Wide Events
Accumulate context progressively over any operation, then emit a single comprehensive event:
import { createLogger } from 'evlog'
const log = createLogger({ jobId: 'sync-001', queue: 'emails' })
log.set({ batch: { size: 50, processed: 50 } })
log.emit()
import { createRequestLogger } from 'evlog'
const log = createRequestLogger({ method: 'POST', path: '/api/checkout' })
log.set({ user: { id: 1, plan: 'pro' } })
log.emit()
import { useLogger } from 'evlog'
export default defineEventHandler(async (event) => {
const log = useLogger(event)
log.set({ user: { id: 1, plan: 'pro' } })
return { success: true }
// auto-emitted on response end
})
One log, all context. Everything you need to understand what happened.
Structured Errors
Errors with actionable context: why it happened, how to fix it, and a link to docs:
import { createError } from 'evlog'
throw createError({
message: 'Payment failed',
status: 402,
why: 'Card declined by issuer (insufficient funds)',
fix: 'Try a different payment method or contact your bank',
link: 'https://docs.example.com/payments/declined',
})
{
"statusCode": 402,
"message": "Payment failed",
"data": {
"why": "Card declined by issuer (insufficient funds)",
"fix": "Try a different payment method or contact your bank",
"link": "https://docs.example.com/payments/declined"
}
}
Why Context Matters
We're entering an era where AI agents build, debug, and maintain applications. These agents need structured context to work effectively:
why: The root cause, so the agent understands what went wrongfix: An actionable solution the agent can suggest or applylink: Documentation for complex issues
Traditional console.log and generic throw new Error() provide no actionable context. evlog's structured output is designed for both humans and AI to parse and act on.
Next Steps
- Installation - Install evlog in your project
- Quick Start - Get up and running in minutes
- Logging Overview - Understand the three logging modes in depth