Core Concepts

Configuration

Complete reference for all evlog configuration options including global logger settings, middleware options, environment context, and framework-specific overrides.

evlog has two configuration surfaces: global options set once at startup, and middleware options set per-framework integration. This page documents both.

Global Options (initLogger)

These options apply to all frameworks. Call initLogger() once at application startup for standalone frameworks (Hono, Express, Fastify, Elysia, NestJS, SvelteKit, Cloudflare Workers). For Nuxt and Nitro, these are set via module config and passed through automatically.

import { initLogger } from 'evlog'

initLogger({
  enabled: true,
  env: { service: 'my-api', environment: 'production' },
  pretty: false,
  silent: false,
  stringify: true,
  sampling: { rates: { info: 10 }, keep: [{ status: 400 }] },
  drain: createAxiomDrain(),
})
OptionTypeDefaultDescription
enabledbooleantrueEnable/disable all logging globally. When false, all operations become no-ops
envPartial<EnvironmentContext>Auto-detectedEnvironment context overrides (see below)
prettybooleantrue in devPretty print with tree formatting. Auto-detected based on NODE_ENV
silentbooleanfalseSuppress console output. Events are still built, sampled, and passed to drains
stringifybooleantrueEmit JSON strings when pretty is disabled. Set to false for Cloudflare Workers
samplingSamplingConfigundefinedHead and tail sampling configuration. See Sampling
drain(ctx: DrainContext) => voidundefinedDrain callback for sending events to external services

Environment Context

The env option controls the fields included in every log event. Most values are auto-detected from environment variables and package.json.

FieldTypeDefaultAuto-detected from
servicestring'app'SERVICE_NAME, package.json name
environmentstring'development'NODE_ENV
versionstringundefinedAPP_VERSION, package.json version
commitHashstringundefinedCOMMIT_SHA, GIT_COMMIT, VERCEL_GIT_COMMIT_SHA
regionstringundefinedFLY_REGION, AWS_REGION, VERCEL_REGION

Silent Mode

Use silent when your deployment platform captures stdout as its primary log ingestion (GCP Cloud Run, AWS Lambda, Fly.io, Railway, etc.) and you want a drain adapter to control the output format.

initLogger({
  silent: process.env.NODE_ENV === 'production',
  drain: createCloudLoggingDrain(),
})
If silent is enabled without a drain, events are built and sampled but never output anywhere. evlog will warn you about this at startup.

Middleware Options

These options are passed to the framework middleware/plugin. They control per-request behavior: which routes to log, how to drain and enrich events, and custom tail sampling logic.

app.use(evlog({
  include: ['/api/**'],
  exclude: ['/api/health'],
  routes: { '/api/auth/**': { service: 'auth' } },
  drain: createAxiomDrain(),
  enrich: (ctx) => { ctx.event.region = process.env.FLY_REGION },
  keep: (ctx) => { if (ctx.duration > 2000) ctx.shouldKeep = true },
}))
OptionTypeDefaultDescription
includestring[]undefinedRoute glob patterns to log. If not set, all routes are logged
excludestring[]undefinedRoute patterns to exclude. Exclusions take precedence over inclusions
routesRecord<string, { service: string }>undefinedRoute-specific service name overrides
drain(ctx: DrainContext) => voidundefinedDrain callback called with every emitted event
enrich(ctx: EnrichContext) => voidundefinedEnrich callback called after emit, before drain
keep(ctx: TailSamplingContext) => voidundefinedCustom tail sampling callback
Nuxt and Nitro use module config and Nitro hooks (evlog:drain, evlog:enrich, evlog:emit:keep) instead of middleware options. See the Nuxt and Nitro pages.

Middleware drain vs global drain

When a middleware drain is set, it takes precedence over the global drain from initLogger(). If no middleware drain is set, the global drain is used as fallback, with the benefit of receiving the full enriched event with request context (method, path, headers).

import { initLogger } from 'evlog'
import { createAxiomDrain } from 'evlog/axiom'

initLogger({
  env: { service: 'my-api' },
  drain: createAxiomDrain(), // fallback: used by singleton log API AND middleware (if no middleware drain)
})

app.use(evlog({
  // no drain here - falls back to globalDrain from initLogger, with full request context
}))

Framework-Specific Options

Some frameworks have additional options beyond the shared config:

Nuxt

The Nuxt module accepts all global options and middleware options in nuxt.config.ts under the evlog key, plus:

OptionTypeDefaultDescription
consolebooleantrueEnable/disable browser console output (client-side only)
transport.enabledbooleanfalseSend client logs to the server via API endpoint
transport.endpointstring'/api/_evlog/ingest'Custom transport endpoint

See the full Nuxt configuration.

Nitro

The Nitro module accepts enabled, env, pretty, silent, sampling, include, exclude, and routes in nitro.config.ts. Drain and enrichment are done via Nitro hooks.

See Nitro drain & enrichers.