Middleware toolkit
The framework integration helpers (defineFrameworkIntegration, evlog() middlewares) cover the typical "HTTP request goes in → wide event comes out" case. When that abstraction doesn't fit — a queue worker, a cron job, a durable workflow with no request object — drop down to the toolkit primitives.
What is this and when do I want it?
You're here when:
- The unit of work is not a request (a job, a saga step, a CLI invocation)
- You need to control logger lifetime explicitly (
createRequestLogger/emit/_forceKeep) - You're wiring evlog into framework internals from scratch
For 95% of HTTP framework integrations, defineFrameworkIntegration is the right tool. Use this page only when that doesn't fit.
Minimal example — a queue worker
import { createRequestLogger } from 'evlog/toolkit'
async function processJob(job: Job) {
const logger = createRequestLogger({
method: 'JOB',
path: `/jobs/${job.type}`,
requestId: job.id,
})
try {
logger.set({ jobId: job.id, queue: job.queue })
await doWork(job)
logger.set({ status: 'success' })
} catch (err) {
logger.error(err as Error)
logger.set({ status: 'failed' })
throw err
} finally {
// Emit a single wide event for the job
logger.emit({ _forceKeep: true })
}
}
The _forceKeep flag bypasses sampling — for jobs you typically want every execution recorded.
Full API reference
The canonical home for the toolkit lives at Toolkit reference. Key exports:
| Export | What |
|---|---|
createRequestLogger(opts) | Create a request-scoped logger outside the framework integration path |
getGlobalPluginRunner() | Access the global plugin runner (register plugins, run lifecycle hooks) |
defineFrameworkIntegration() | High-level helper — see Custom framework |
attachForkToLogger() | Wire log.fork() to a request-scoped logger |
Common pitfalls
- Don't forget to
emit()— without it, the logger accumulates context but no wide event ever leaves - Use
_forceKeep: truefor short-running batch jobs unless your sampling rules already keep them - Wrap in
try/finally— emit even on error so failed jobs produce events
Going further
Most readers should start with the Frameworks overview and stay on the high-level integration path. Drop here only when that path doesn't accommodate your runtime shape.
Custom framework
Build evlog support for an HTTP framework that doesn't ship a built-in integration — Medusa, AdonisJS, h3 directly, custom dispatchers, queue workers.
Overview
Send your logs to external services with evlog adapters. Built-in support for popular observability platforms and custom destinations.