evlog vs Consola: reporters and request context
A Nuxt application can need both readable terminal messages and request events that reach a logging backend. Consola and evlog address those needs with different APIs. Start with where the output goes and who maintains the delivery code.
At a glance
| Consola | evlog | |
|---|---|---|
| Primary job | Readable console output for Node.js, browsers and CLIs, and the logger behind Nuxt Kit's useLogger | Structured logs and request events delivered to a logging backend |
| Output | Fancy reporter by default, basic reporter in CI and tests, browser reporter; consola/basic and consola/browser builds are smaller | Pretty output in development, JSON events in production |
| Extension point | Reporters implementing log(logObject) | Plugins, enrichers and drain adapters |
| Context | withTag() and withDefaults() scope records | set() accumulates fields on an operation logger until emit() |
| CLI helpers | prompt() (powered by clack), wrapConsole() / wrapStd(), pause/resume, throttling of repeated logs | None. Keep Consola for terminal interaction |
| Levels | Numeric levels (default 3), configurable with the level option or CONSOLA_LEVEL | Fixed severities, with sampling for wide events |
Sources: the Consola README and the Nuxt Kit logging docs.
Keep the reporter behavior you rely on
Consola reporters receive log objects and control rendering or delivery. A custom reporter can serialize JSON and forward records, so structured output is possible even though a JSON reporter is not included by default. Consola also provides tags, console wrapping, and prompt helpers. Paused logs are queued, and repeated messages can be throttled. See the Consola documentation.
Those behaviors can suit a CLI or a production application. Replacing them requires more than changing an import.
Compare the application work
| Need | evlog approach | Migration question |
|---|---|---|
| Context across a request | set() accumulates fields on an operation logger | Which layers add fields, and who finishes the event? |
| Output to a backend | Drain adapters and pipeline configuration | Does an adapter preserve the protocol your reporter currently implements? |
| Individual messages | Global structured logging API | Which call signatures and fields need changing? |
| Terminal interaction | Logging output | Should prompts and other CLI interaction remain with Consola? |
Consola tags scope records. An evlog operation logger accumulates context until emission. These are different contracts, so map tags to an application field only if that preserves how you query or display them.
Adopt request events where they help
In an application, keep terminal interaction separate from request instrumentation. Choose the evlog framework integration for handlers and use useLogger() in the layers that contribute fields. Avoid also capturing those emitted records through a custom reporter that forwards to the same destination, unless duplicate ingestion is intentional.
For a CLI, the Standalone TypeScript guide covers explicit initialization and pending delivery. For handlers, Wide Events explains when to accumulate and emit. Check a drain adapter before replacing a custom delivery reporter.
FAQ
Nuxt already uses Consola. Do I need evlog in a Nuxt app?
Nuxt Kit's useLogger is a Consola instance meant for module and build output. Add the evlog Nuxt module when you want one structured event per server request delivered to a backend. The two can coexist.
Can Consola emit JSON? Yes, through a custom reporter. Consola doesn't ship a JSON reporter (its custom reporters section shows how to write one), so delivery, batching and retries stay in your code.
Keep Consola when its reporters and terminal workflow meet your needs. Add or adopt evlog when its request context, structured errors, and drain pipeline remove code you would otherwise maintain. Consult the logger overview for other configuration models.