Getting Started

Quick Start

Get up and running with evlog in minutes.

This guide covers the core APIs you'll use most often with evlog.

useLogger (Nuxt/Nitro)

In API routes, use useLogger(event) to get a request-scoped logger:

// server/api/checkout.post.ts
export default defineEventHandler(async (event) => {
  const log = useLogger(event)

  log.set({ user: { id: 1, plan: 'pro' } })
  log.set({ cart: { items: 3, total: 9999 } })

  // Auto-emits on request end
  return { success: true }
})
The logger automatically emits when the request ends. No manual emit() call needed.

createError (Structured Errors)

Use createError() to throw errors with actionable context:

// server/api/checkout.post.ts
import { createError } from 'evlog'

throw createError({
  message: 'Payment failed',
  status: 402,
  why: 'Card declined by issuer',
  fix: 'Try a different payment method',
  link: 'https://docs.example.com/payments/declined',
})

Error Fields

FieldRequiredDescription
messageYesWhat happened (user-facing)
statusNoHTTP status code (default: 500)
whyNoTechnical reason (for debugging)
fixNoActionable solution
linkNoDocumentation URL for more info
causeNoOriginal error (if wrapping)

Frontend Integration

Use parseError() to extract all error fields on the client:

composables/useCheckout.ts
import { parseError } from 'evlog'

export async function checkout(cart: Cart) {
  try {
    await $fetch('/api/checkout', { method: 'POST', body: cart })
  } catch (err) {
    const error = parseError(err)

    // Direct access to all fields
    toast.add({
      title: error.message,
      description: error.why,
      color: 'error',
      actions: error.link
        ? [{ label: 'Learn more', onClick: () => window.open(error.link) }]
        : undefined,
    })

    if (error.fix) {
      console.info(`Fix: ${error.fix}`)
    }
  }
}

log (Simple Logging)

For quick one-off logs anywhere in your code:

// server/utils/auth.ts
import { log } from 'evlog'

log.info('auth', 'User logged in')
log.error({ action: 'payment', error: 'card_declined' })
log.warn('cache', 'Cache miss')
Prefer wide events (useLogger) over simple logs when possible. Use log for truly one-off events that don't belong to a request.

Wide Event Fields

Every wide event should include context from different layers:

// server/api/checkout.post.ts
const log = useLogger(event)

// Request context (often auto-populated)
log.set({ method: 'POST', path: '/api/checkout' })

// User context
log.set({ userId: 1, subscription: 'pro' })

// Business context
log.set({ cart: { items: 3, total: 9999 }, coupon: 'SAVE10' })

// Outcome
log.set({ status: 200, duration: 234 })

Next Steps