Reference

Configuration

Configure evlog once in evlog.config.ts. Every option, and how framework options override it.

evlog reads its options from evlog.config.ts at the root of your app. The same file drives your server and the CLI.

The config file

evlog.config.ts
import { defineEvlog } from 'evlog'
import { createAxiomDrain } from 'evlog/axiom'

export default defineEvlog({
  service: 'my-api',
  sampling: { rates: { info: 10 }, keep: [{ status: 400 }] },
  drain: createAxiomDrain(),
})

npx evlog init writes this file for you.

evlog looks for evlog.config.ts, .mts, .js or .mjs, starting in your app and walking up to the workspace root. The nearest file wins, so one file at the root of a monorepo covers every app that has none of its own.

Load it

Nuxt, Nitro and TanStack Start load the file for you. Other frameworks import it:

src/index.ts
import { initLogger, toLoggerConfig, toMiddlewareOptions } from 'evlog'
import { evlog } from 'evlog/hono'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))
app.use(evlog(toMiddlewareOptions(config)))

toLoggerConfig passes the logger options, and toMiddlewareOptions passes the request options. Each framework page shows the exact lines.

Precedence

The file applies first, and options you pass to the framework override it.

On Nuxt and Nitro, the override merges with the file key by key. The file's drain, enrich and keep are never overridden: they run alongside the evlog:* hooks, so an event reaches both. On other frameworks, a field you pass next to the file, as in evlog({ ...toMiddlewareOptions(config), exclude: ['/health'] }), replaces that field; it is not merged.

Options

OptionTypeDefaultDescription
servicestringSERVICE_NAME or 'app'Service name on every event
environmentstringNODE_ENV or 'development'Environment name
enabledbooleantruefalse turns every call into a no-op
prettybooleantrue in devTree output instead of JSON
silentbooleanfalseNo console output; events still reach the drain
stringifybooleantruePrint JSON strings when pretty is off
minLevelLogLevel'debug'Lowest level for the log API. Request events use sampling
samplingSamplingConfig–Head rates and tail keep rules. See Sampling
redactboolean | RedactConfigtrue in productionSee Redaction
drain(ctx) => void–Where events go. See Adapters
pluginsEvlogPlugin[]–See Plugins
include / excludestring[]–Route globs to log or skip
routesRecord<string, { service }>–Service name per route
enrich(ctx) => void–Add fields before the drain
keep(ctx) => void–Custom tail sampling
dev'evlog' | 'nitro' | 'both' | object'evlog'Dev terminal output. See Structured errors
extendsEvlogConfig–Build on a shared preset. See Share settings
map, logs––CLI only. See evlog config

Nuxt also takes console and transport in nuxt.config.ts. See Nuxt.

Inline config for scripts

For a small standalone script, passing options straight to initLogger in the file that starts the logger is fine:

scripts/sync.ts
import { initLogger } from 'evlog'

initLogger({ env: { service: 'sync-job' } })