First of all: Thank you! 🙏
I just want to start by saying evlog is amazing! The wide event concept is exactly what I was looking for - structured logging without the complexity of traditional logging libraries. The Nuxt/Nitro integration is seamless, and the pretty console output in dev is chef's kiss. It's helped me clean up my entire backend logging strategy. Seriously, great work!
Context: Understanding the current design
I've been using evlog for a few days now and I think I understand the architecture, but I wanted to confirm a few things:
Questions about current behavior
-
Request logger vs standalone log: Am I correct that useLogger(event) and log.info() serve different purposes?
useLogger() → builds ONE wide event per request (accumulates context with set())
log.info/warn() → standalone logs (console in dev, separate wide events in prod)
-
Dev vs Prod behavior: In dev mode (globalPretty = true), standalone log.info() only prints to console and doesn't go through the drain, correct? Only the request logger's wide event goes through the drain?
-
Request logger levels: The request logger only has two final levels - info (success) or error (if log.error() was called). There's no way to have a warn level wide event from the request logger, right?
Feature proposal: Aggregate logs within request logger
The problem
Sometimes during a request, I want to log intermediate information that should be part of the wide event, not separate events. For example:
const log = useLogger(event)
// These feel like they should be part of the request context
log.info('Cache miss, fetching from database')
log.warn('Using deprecated parameter "old_field", please use "new_field"')
log.set({ user_id: '123' })
// But currently I have to use standalone log, which creates separate events in prod
// or use log.set({ debug_info: 'Cache miss...' }) which feels hacky
Proposed solution
What if the request logger had info() and warn() methods that aggregate messages into the wide event?
const log = useLogger(event)
log.info('User authenticated successfully')
log.info('Cache miss, fetching from DB')
log.warn('Deprecated param "v1_format" used')
log.set({ user_id: '123', action: 'checkout' })
// Final wide event:
{
level: 'warn', // Highest severity encountered (error > warn > info)
user_id: '123',
action: 'checkout',
logs: [
{ level: 'info', message: 'User authenticated successfully', timestamp: '...' },
{ level: 'info', message: 'Cache miss, fetching from DB', timestamp: '...' },
{ level: 'warn', message: 'Deprecated param "v1_format" used', timestamp: '...' }
]
}
Benefits
- Single wide event per request - No event pollution, keeps the "one event = one request" philosophy
- Request journey tracking - You can see what happened during the request
- Automatic level escalation - Final level reflects the worst thing that happened
- Better debugging - All context in one place when investigating issues
- Unified API - Everything on the same logger object (
log.info(), log.warn(), log.set(), log.error()). Currently, having to switch between useLogger() and the standalone log export can be a bit confusing at first - this would make the mental model simpler: "one request = one logger = one wide event"
Configuration idea
Some users might not want to store all these intermediate logs (to reduce payload size or for privacy reasons). It could be useful to have options to:
- Enable/disable the logs array in wide events entirely
- Filter by level (e.g., only store
warn+ logs, ignore info)
This could be configured globally (in nuxt.config or initLogger()) and/or overridable per-request in useLogger(). Just an idea - you know the API best!
Alternative formats
If the nested object with timestamps feels too heavy, simpler formats could work:
Option A: Simple array with level prefix
logs: [
'[info] User authenticated successfully',
'[warn] Deprecated param used'
]
Option B: Separate keys per level
{
infos: ['User authenticated successfully', 'Cache miss'],
warns: ['Deprecated param used']
}
Personally I think a single logs array (original proposal) is cleaner since it preserves chronological order, but these are just ideas!
Questions for you
- Is this something you've considered? Maybe there's a reason for the current design I'm not seeing?
- Would this fit the evlog philosophy, or does it go against the "wide event = summary" concept?
- If you're open to it, I'd be happy to contribute a PR!
Thanks again for this awesome library. Looking forward to hearing your thoughts! 😊
First of all: Thank you! 🙏
I just want to start by saying evlog is amazing! The wide event concept is exactly what I was looking for - structured logging without the complexity of traditional logging libraries. The Nuxt/Nitro integration is seamless, and the pretty console output in dev is chef's kiss. It's helped me clean up my entire backend logging strategy. Seriously, great work!
Context: Understanding the current design
I've been using evlog for a few days now and I think I understand the architecture, but I wanted to confirm a few things:
Questions about current behavior
Request logger vs standalone log: Am I correct that
useLogger(event)andlog.info()serve different purposes?useLogger()→ builds ONE wide event per request (accumulates context withset())log.info/warn()→ standalone logs (console in dev, separate wide events in prod)Dev vs Prod behavior: In dev mode (
globalPretty = true), standalonelog.info()only prints to console and doesn't go through the drain, correct? Only the request logger's wide event goes through the drain?Request logger levels: The request logger only has two final levels -
info(success) orerror(iflog.error()was called). There's no way to have awarnlevel wide event from the request logger, right?Feature proposal: Aggregate logs within request logger
The problem
Sometimes during a request, I want to log intermediate information that should be part of the wide event, not separate events. For example:
Proposed solution
What if the request logger had
info()andwarn()methods that aggregate messages into the wide event?Benefits
log.info(),log.warn(),log.set(),log.error()). Currently, having to switch betweenuseLogger()and the standalonelogexport can be a bit confusing at first - this would make the mental model simpler: "one request = one logger = one wide event"Configuration idea
Some users might not want to store all these intermediate logs (to reduce payload size or for privacy reasons). It could be useful to have options to:
warn+ logs, ignoreinfo)This could be configured globally (in
nuxt.configorinitLogger()) and/or overridable per-request inuseLogger(). Just an idea - you know the API best!Alternative formats
If the nested object with timestamps feels too heavy, simpler formats could work:
Option A: Simple array with level prefix
Option B: Separate keys per level
Personally I think a single
logsarray (original proposal) is cleaner since it preserves chronological order, but these are just ideas!Questions for you
Thanks again for this awesome library. Looking forward to hearing your thoughts! 😊