Skip to content

[feature] Add info() and warn() methods to useLogger #68

@XStarlink

Description

@XStarlink

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

  1. 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)
  2. 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?

  3. 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

  1. Single wide event per request - No event pollution, keeps the "one event = one request" philosophy
  2. Request journey tracking - You can see what happened during the request
  3. Automatic level escalation - Final level reflects the worst thing that happened
  4. Better debugging - All context in one place when investigating issues
  5. 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

  1. Is this something you've considered? Maybe there's a reason for the current design I'm not seeing?
  2. Would this fit the evlog philosophy, or does it go against the "wide event = summary" concept?
  3. 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! 😊

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions