Installation
evlog supports multiple environments: Nuxt, Nitro, and standalone TypeScript.
Nuxt
Install evlog via your preferred package manager:
pnpm add evlog
npm install evlog
yarn add evlog
bun add evlog
Then add it to your Nuxt config using the evlog/nuxt module:
export default defineNuxtConfig({
modules: ['evlog/nuxt'],
evlog: {
env: {
service: 'my-app',
},
// Optional: only log specific routes (supports glob patterns)
include: ['/api/**'],
},
})
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
env.service | string | 'app' | Service name shown in logs |
env.environment | string | Auto-detected | Environment name |
include | string[] | undefined | Route patterns to log. Supports glob (/api/**). If not set, all routes are logged |
pretty | boolean | true in dev | Pretty print with tree formatting |
sampling.rates | object | undefined | Head sampling rates per log level (0-100%). See Sampling |
sampling.keep | array | undefined | Tail sampling conditions to force-keep logs. See Sampling |
Sampling
At scale, logging everything can become expensive. evlog supports two sampling strategies:
Head Sampling (rates)
Random sampling based on log level, decided before the request completes:
export default defineNuxtConfig({
modules: ['evlog/nuxt'],
evlog: {
sampling: {
rates: {
info: 10, // Keep 10% of info logs
warn: 50, // Keep 50% of warning logs
debug: 5, // Keep 5% of debug logs
error: 100, // Always keep errors (default)
},
},
},
})
error: 100, error logs are never sampled out unless you explicitly set error: 0.Tail Sampling (keep)
Force-keep logs based on request outcome, evaluated after the request completes. Useful to always capture slow requests or critical paths even when head sampling would drop them:
export default defineNuxtConfig({
modules: ['evlog/nuxt'],
evlog: {
sampling: {
rates: { info: 10 }, // Only 10% of info logs
keep: [
{ duration: 1000 }, // Always keep if duration >= 1000ms
{ status: 400 }, // Always keep if status >= 400
{ path: '/api/critical/**' }, // Always keep critical paths
],
},
},
})
Conditions use >= comparison and follow OR logic (any match = keep).
Custom Tail Sampling Hook
For business-specific conditions (premium users, feature flags, etc.), use the evlog:emit:keep Nitro hook:
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('evlog:emit:keep', (ctx) => {
// Always keep logs for premium users
const user = ctx.context.user as { premium?: boolean } | undefined
if (user?.premium) {
ctx.shouldKeep = true
}
})
})
The hook receives a TailSamplingContext with status, duration, path, method, and the full accumulated context.
Log Draining
Send logs to external services like Axiom, Loki, or custom endpoints using the evlog:drain hook. The hook is called in fire-and-forget mode, meaning it never blocks the HTTP response.
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('evlog:drain', async (ctx) => {
await fetch('https://api.axiom.co/v1/datasets/logs/ingest', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.AXIOM_TOKEN}` },
body: JSON.stringify([ctx.event])
})
})
})
The hook receives a DrainContext with:
event: The completeWideEvent(timestamp, level, service, and all accumulated context)request: Optional request metadata (method,path,requestId)
$production override to sample only in production while keeping full visibility in development:export default defineNuxtConfig({
modules: ['evlog/nuxt'],
evlog: {
env: { service: 'my-app' },
},
$production: {
evlog: {
sampling: {
rates: { info: 10, warn: 50, debug: 0 },
keep: [{ duration: 1000 }, { status: 400 }],
},
},
},
})
That's it! You can now use useLogger(event) in any API route.
Nitro
Install evlog via your preferred package manager:
pnpm add evlog
npm install evlog
yarn add evlog
bun add evlog
Then, add evlog as a Nitro plugin (without Nuxt) using the evlog/nitro plugin:
export default defineNitroConfig({
plugins: ['evlog/nitro'],
})
evlog/nitro/v3 instead of evlog/nitro. When using Nitro v3, import createError from evlog/nitro/v3 instead of evlog.Standalone TypeScript
Install evlog via your preferred package manager:
pnpm add evlog
npm install evlog
yarn add evlog
bun add evlog
Then, use it as any other TypeScript library within your scripts, CLI tools, workers, or apps:
import { initLogger, createRequestLogger } from 'evlog'
// Initialize once at startup
initLogger({
env: {
service: 'my-worker',
environment: 'production',
},
// Optional: sample logs
sampling: {
rates: { info: 10, debug: 5 },
},
})
// Create a logger for each operation
const log = createRequestLogger({ jobId: job.id })
log.set({ source: job.source, target: job.target })
log.set({ recordsSynced: 150 })
log.emit() // Manual emit required in standalone mode
log.emit() manually. In Nuxt/Nitro, this happens automatically at request end.TypeScript Configuration
evlog is written in TypeScript and ships with full type definitions. No additional configuration is required.
Next Steps
- Quick Start - Learn the core concepts and start using evlog