Logging

Client Logging

Capture browser events with structured logging. Same API as the server, with automatic console styling, user identity context, and optional server transport.

Server logs tell you what happened on the backend. Client logs complete the picture: user interactions, page views, frontend errors, and performance signals that never reach the server unless you capture them.

Quick Start

evlog provides a client-side logging API that works in any browser environment:

import { initLog, log } from 'evlog/client'

export default defineNuxtPlugin(() => {
  initLog({ service: 'web' })

  log.info({ action: 'app_init', path: window.location.pathname })
})

The log object works anywhere in your client code: components, composables, event handlers.

Two Call Signatures

The log API accepts two forms depending on the context.

Object Form (structured context)

Pass an object to capture structured data, just like server-side log.set():

pages/products.vue
log.info({ action: 'page_view', path: '/products', referrer: document.referrer })
Browser console
[web] info  { action: 'page_view', path: '/products', referrer: 'https://google.com' }

Tag + Message Form (quick logs)

Pass a tag and a message for quick, readable logs:

composables/useAuth.ts
log.info('auth', 'User logged in')
Browser console
[auth] User logged in

Available Levels

Both forms support four levels: log.info(), log.warn(), log.error(), and log.debug().

Identity Context

Track which user generated a log with setIdentity():

composables/useAuth.ts
import { setIdentity, clearIdentity, log } from 'evlog/client'

// After login
setIdentity({ userId: 'usr_123', plan: 'pro' })

log.info({ action: 'dashboard_view' })
// → { userId: 'usr_123', plan: 'pro', action: 'dashboard_view', ... }

// After logout
clearIdentity()

Identity fields are automatically merged into every log event until cleared. This lets you correlate browser events to specific users in your observability tools.

Configuration

initLog() accepts the following options:

OptionDefaultDescription
enabledtrueEnable or disable all client logging
consoletrueOutput logs to the browser console
prettytrueUse colored, formatted console output
service'client'Service name included in every log event
transport-Send logs to a server endpoint (see below)
app/plugins/logger.client.ts
initLog({
  service: 'web',
  transport: {
    enabled: true,
    endpoint: '/api/_evlog/ingest', // default endpoint
  },
})
enabled, console, and pretty all default to true. You only need to set them if you want to change the defaults.

Sending Logs to the Server

By default, client logs only appear in the browser console. To persist them, you have two options:

Built-in Transport

The simplest approach is to enable the built-in transport in initLog(). Each log is sent individually via fetch with keepalive: true. Good for low-volume apps.

import { initLog } from 'evlog/client'

export default defineNuxtPlugin(() => {
  initLog({
    service: 'web',
    transport: {
      enabled: true,
      endpoint: '/api/_evlog/ingest',
    },
  })
})
In Nuxt with the evlog module, the server ingest endpoint is auto-registered. For other frameworks, you need to create the endpoint yourself. See the Browser Drain docs for Express and Hono examples.

Browser Drain Pipeline

For higher volume or when you need batching, retries, and page-exit flushing, use the browser drain. This works with any frontend and has no framework dependency.

import { initLogger, log } from 'evlog'
import { createBrowserLogDrain } from 'evlog/browser'

export default defineNuxtPlugin(() => {
  const drain = createBrowserLogDrain({
    drain: { endpoint: '/api/_evlog/ingest' },
    pipeline: {
      batch: { size: 25, intervalMs: 2000 },
      retry: { maxAttempts: 2 },
    },
  })

  initLogger({ drain })
  log.info({ action: 'app_init' })
})

The browser drain automatically:

  • Batches events by size and time interval
  • Retries failed sends with exponential backoff
  • Flushes buffered events via sendBeacon when the page becomes hidden (tab switch, navigation, close)
See the Browser Drain adapter docs for full configuration reference, authentication, and server endpoint examples.

Next Steps