Skip to content
Logixlysia
Esc
↑↓navigate↵open⌘Jpreview
On this page

Configuration

Complete configuration reference for Logixlysia

Complete reference for all Logixlysia configuration options.

Configuration Object

All configuration options are passed through the config property:

logixlysia({
  preset: 'prod', // optional: 'dev' | 'prod' | 'json'
  config: {
    // ... configuration options (override preset)
  }
})

See Presets for defaults per environment.

Startup Options

showStartupMessage

Whether to display the startup message when the server starts.

  • Type: boolean
  • Default: true
showStartupMessage: true

startupMessageFormat

Format of the startup message.

  • Type: 'simple' | 'banner'
  • Default: 'banner'
startupMessageFormat: 'simple' // or 'banner'

Display Options

useColors

Enable colored output in console logs.

  • Type: boolean
  • Default: true
useColors: true

Colors require an interactive terminal: when stdout is not a TTY (Docker, CI, or output piped to a file), logs are printed uncolored even with useColors: true.

ip

Include client IP address in logs.

  • Type: boolean
  • Default: false
ip: true

How IP is resolved: The client IP is read from HTTP headers in this order:

  1. x-forwarded-for — uses the first (leftmost) IP in the comma-separated list (the original client when behind proxies)
  2. x-real-ip — fallback when x-forwarded-for is not present

Both headers are set by whoever sends the request unless a proxy in front of the app overwrites them, so treat the value as a hint for dashboards, not as an identity.

These headers are typically set by reverse proxies (nginx, Caddy, Cloudflare, etc.) and load balancers. When testing locally (localhost or LAN) without a proxy, these headers are usually absent, so the {ip} placeholder will be empty. To test IP logging locally, you can pass a header manually, e.g. curl -H 'x-real-ip: 1.2.3.4' http://localhost:3000/.

autoRedact

Automatically redacts sensitive data from log messages, context objects, errors, and request headers before they are outputted. Redaction runs in three ways:

  1. By key/header name — a built-in, case-insensitive denylist (authorization, cookie, x-api-key, password, secret, token, session, and more) wholly redacts the value of any matching object key or request header, regardless of what the value looks like. -, _, and camelCase variants (x-api-key, x_api_key, xApiKey) all match.
  2. By value pattern — emails, IP addresses, Luhn-valid payment card numbers, JWTs, the password part of a URL, and Bearer/Basic credentials are redacted wherever they appear in strings, even in fields not covered by the key denylist.
  3. Through toJSON — a value with a toJSON method (Bun’s CookieMap, your own classes) is redacted as what it serializes to. Errors keep their class.

Redaction also applies inside Headers, URL, URLSearchParams, Map, and Set values, not only plain objects and arrays.

The query of an absolute URL in a referer, location or content-location header is checked by key like a request URL. Values nested deeper than 64 levels are replaced by "[Depth]", and a value whose toJSON throws by "[Unserializable]".

Value-pattern redaction is best-effort — it only catches values matching those specific shapes. Always prefer key-based redaction (redactKeys) for known sensitive fields instead of relying on their value happening to match a pattern. For free-text PII that has no fixed shape — names, street addresses, phone numbers, national IDs — see neural PII redaction, which runs an on-device model over records on their way to a transport.

  • Type: boolean
  • Default: false
autoRedact: true

redactKeys

Additional key/header names to redact when autoRedact is enabled, extending the built-in denylist. Matching is case-insensitive and normalizes -, _, and camelCase variants. The same key-name matching also applies to query-string parameter names, since transports receive the full request URL.

Keys containing the whole word password, passwd, or secret, or ending in token, are always sensitive, whether written in camelCase, snake_case, or kebab-case. For example, newPassword and X-CSRF-Token match. tokenizer and maxTokens don’t.

  • Type: string[]
  • Default: undefined
autoRedact: true,
redactKeys: ['x-internal-token', 'customerSsn']

logErrorPayload

Log the offending payload (found/errors) from validation errors. Off by default — a failed schema validation embeds the entire request body (passwords, tokens, card fields) in the error message, so leaving this off keeps those values out of your logs and transports.

  • Type: boolean
  • Default: false
logErrorPayload: true

logQueryParams

Include query parameters in the logged URL path.

  • Type: boolean
  • Default: false
logQueryParams: true

Timestamp Options

timestamp

Timestamp configuration for the {now} console token.

  • Type: { translateTime?: string }
  • Default: undefined

translateTime accepts three forms:

  • A bare token pattern (yyyy, mm, dd, HH, MM, ss, SSS), rendered with local time:

    timestamp: {
      translateTime: 'yyyy-mm-dd HH:MM:ss'
    }
  • pino-pretty’s SYS: prefix, also local time — SYS:standard expands to yyyy-mm-dd HH:MM:ss.SSS, or supply your own pattern after the prefix:

    timestamp: {
      translateTime: 'SYS:standard'
    }
  • pino-pretty’s UTC: prefix, rendered with UTC getters instead of local time:

    timestamp: {
      translateTime: 'UTC:yyyy-mm-dd HH:MM:ss'
    }

Formatting Options

customLogFormat

Custom log message format using placeholders.

  • Type: string
  • Default: undefined
customLogFormat: '{now} {level} {duration} {method} {pathname} {status}'

When customLogFormat is omitted, Logixlysia uses a built-in default that includes {now}, {service}, {icon}, {method}, {pathname}, {status}, {duration}, {message}, and {speed}.

Available placeholders:

  • {now} - Current timestamp
  • {level} - Log level
  • {duration} - Request duration (formatted, e.g. 12ms, 1.5s)
  • {method} - HTTP method
  • {pathname} - Request path
  • {path} - Alias of {pathname}
  • {query} - Raw query string (e.g. ?id=123)
  • {status} - Response status code
  • {statusText} - HTTP status text from Node’s http.STATUS_CODES (e.g. Not Found for 404)
  • {message} - Custom message
  • {icon} - Logixlysia fox (🦊); with colors enabled, a level-colored background chip around the emoji
  • {speed} - When duration is at or above verySlowThreshold, appends ⚡ slow (yellow when colors are on)
  • {service} - Service label from the service config option, shown as [name] (dim when colors are on); empty if unset
  • {context} - Request context as JSON when showContextTree is off; empty while the context tree shows it
  • {ip} - Client IP (from x-forwarded-for or x-real-ip; see ip option)
  • {epoch} - Unix time in milliseconds
  • {requestId} - Request ID when requestId is on; empty otherwise

service

Service name used by the {service} placeholder (evlog-style [my-app] prefix).

  • Type: string
  • Default: undefined (no prefix)
service: 'my-api'

slowThreshold

Duration threshold (ms) for green duration text when colors are enabled. Between this value and verySlowThreshold, duration is yellow.

  • Type: number
  • Default: 500
slowThreshold: 500

verySlowThreshold

Duration threshold (ms) at or above which duration is red (bold when colors are on) and the {speed} token adds ⚡ slow.

  • Type: number
  • Default: 1000
verySlowThreshold: 1000

showContextTree

When true, structured context passed to logger helpers is printed as tree lines under the main log line instead of being crammed into {message} on the same line.

  • Type: boolean
  • Default: true
showContextTree: true

contextDepth

How many levels of nested objects to expand in the context tree.

  • Type: number
  • Default: 1
contextDepth: 2

Output Options

transports

Array of custom transport implementations.

  • Type: Transport[]
  • Default: []
transports: [
  {
    log: async (level, message, meta) => {
      // Custom transport logic
    }
  }
]

useTransportsOnly

Use only transports, disable console and file logging.

  • Type: boolean
  • Default: false
useTransportsOnly: true

disableInternalLogger

Disable console logging.

  • Type: boolean
  • Default: false
disableInternalLogger: true

disableFileLogging

Disable file logging.

  • Type: boolean
  • Default: false
disableFileLogging: true

onError

Called when a sink (transport, file, or rotation) or an enricher fails, and when a shutdown flush runs out of time (sink: 'shutdown'). sink: 'format' means building or printing a log record failed. The request itself is unaffected. Errors thrown by the hook itself are swallowed. When absent, failures go to stderr (rate-limited for transports, file writes, rotation, enrichers, and formatting).

  • Type: (context: { sink: 'transport' | 'file' | 'rotation' | 'shutdown' | 'enricher' | 'format'; error: unknown }) => void
  • Default: undefined
onError: ({ sink, error }) => {
  metrics.increment(`logixlysia.sink_error.${sink}`)
}

flushTimeoutMs

How long the plugin waits for transports and the file sink to flush when the app stops. 0 starts the flush but does not wait. A flush that exceeds the budget is reported through onError with sink: 'shutdown'.

  • Type: number
  • Default: 5000
flushTimeoutMs: 2000

enrichers

Context contributors run on every request. Whatever they return is merged into the request context, so the fields reach the console tree, file logs, and every transport at once. See Enrichers.

  • Type: EnricherLike[]
  • Default: undefined
import { geoEnricher, traceparentEnricher } from 'logixlysia/enrichers'

enrichers: [
  traceparentEnricher(),
  geoEnricher(),
  request => ({ tenant: request.headers.get('x-tenant') })
]

requestId

Reads the request id from the configured header or generates one, and echoes it on the response; see request IDs.

  • Type: boolean | RequestIdConfig
  • Default: undefined
requestId: true

useAsyncLocalStorage

Makes useLogger() return the current request’s logger from anywhere in the call stack; without it useLogger() is a no-op. See request context.

  • Type: boolean
  • Default: false
useAsyncLocalStorage: true

disableWebSocketLogging

Turns off the open, message and close lines that wrapWs writes; see WebSocket logging.

  • Type: boolean
  • Default: false
disableWebSocketLogging: true

Filtering Options

logFilter

Restricts which log levels get processed. See Filtering.

  • Type: { level?: LogLevel[] }
  • Default: all levels
logFilter: {
  level: ['ERROR', 'WARNING']
}

Sampling Options

sampling

Head + tail sampling. Head sampling keeps a percentage of records per level; tail sampling replays what head dropped once the finished request matches a rule. See Sampling for the full guide.

  • Type: { head?: Partial<Record<LogLevel, number>>; tail?: { status?: number; durationMs?: number; paths?: string[] }; maxBufferedPerRequest?: number }
  • Default: undefined (no sampling)
sampling: {
  head: { DEBUG: 1, INFO: 10 }, // levels left out keep 100%
  tail: {
    status: 400, // rescue any response at or above 400
    durationMs: 1000, // rescue anything that took a second or longer
    paths: ['/checkout/**'] // rescue these routes whatever happened
  },
  maxBufferedPerRequest: 100
}

Sampling is off unless at least one head rate is below 100 — tail alone rescues nothing, because only head-dropped records are buffered. Invalid values throw at plugin construction.

File Logging Options

logFilePath

Path to the log file.

  • Type: string
  • Default: undefined
logFilePath: './logs/app.log'

logDirMode

Mode for the directories the file sink creates.

  • Type: number
  • Default: 0o700
logDirMode: 0o750

logFileMode

Mode for the log files the sink creates. Compressed rotation archives use it too.

  • Type: number
  • Default: 0o600
logFileMode: 0o640

logRotation

Log rotation configuration.

  • Type: LogRotationConfig
  • Default: undefined
logRotation: {
  maxSize: '10m',
  maxFiles: '7d',
  compress: true
}

logRotation.maxSize

Maximum file size before rotation.

  • Type: string | number
  • Format: '1k', '1m', '1g' or bytes
logRotation: {
  maxSize: '10m'
}

logRotation.interval

Rotate when the live log file’s age reaches the given interval. Evaluated on write — an idle process does not rotate until it logs again. See Log Rotation for details.

  • Type: string
  • Format: '1h', '1d', '1w'

logRotation.maxFiles

Maximum number of files or retention period.

  • Type: number | string
  • Format: Number or '7d', '30d'
logRotation: {
  maxFiles: '7d' // or 10
}

logRotation.compress

Enable compression for rotated logs.

  • Type: boolean
  • Default: false
logRotation: {
  compress: true
}

logRotation.compression

Compression algorithm.

  • Type: 'gzip'
  • Default: 'gzip'
logRotation: {
  compression: 'gzip'
}

Pino Options

pino

Pino logger configuration. Accepts all Pino options.

  • Type: PinoLoggerOptions & { prettyPrint?: boolean | object }
  • Default: undefined
pino: {
  level: 'info',
  prettyPrint: true,
  redact: ['password', 'token'],
  base: {
    service: 'my-api',
    version: '1.0.0'
  }
}

Common Pino Options

Every pino.* option configures the pino instance exposed as store.pino; none of them changes what the plugin logs for a request.

pino.level

Minimum level for store.pino only. The plugin’s own lines are filtered by logFilter.

  • Type: 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace'
  • Default: 'info'
pino: {
  level: 'debug'
}

pino.prettyPrint

Enable pretty printing for development.

  • Type: boolean | object
  • Default: false
pino: {
  prettyPrint: true
}

Or with options:

pino: {
  prettyPrint: {
    colorize: true,
    translateTime: 'HH:MM:ss Z',
    ignore: 'pid,hostname'
  }
}

Common prettyPrint Options

Option Type Description
colorize boolean Enable colors in output
translateTime string | boolean Format timestamps
ignore string Comma-separated keys to exclude
singleLine boolean Print each log on one line
messageFormat string Custom message format
levelFirst boolean Show level before timestamp
messageKey string Key containing log message
errorKey string Key containing error info

See pino-pretty documentation for complete reference.

pino.redact

Redact paths for store.pino only. The plugin’s own console, file and transport output is masked by autoRedact and redactKeys; setting pino.redact also replaces the automatic paths autoRedact would give store.pino.

  • Type: string[] | object
  • Default: undefined
pino: {
  redact: ['password', 'token', 'apiKey']
}

Or with paths:

pino: {
  redact: {
    paths: ['user.password', 'req.headers.authorization'],
    remove: true
  }
}

pino.base

Base fields added to every store.pino record. They do not appear on the plugin’s own lines.

  • Type: object
  • Default: undefined
pino: {
  base: {
    service: 'my-api',
    version: '1.0.0',
    environment: process.env.NODE_ENV
  }
}

Complete Example

logixlysia({
  config: {
    // Startup
    showStartupMessage: true,
    startupMessageFormat: 'banner',

    // Display
    useColors: true,
    ip: true,
    autoRedact: false,
    logQueryParams: false,

    // Formatting
    timestamp: {
      translateTime: 'yyyy-mm-dd HH:MM:ss'
    },
    customLogFormat: '{now} {level} {duration} {method} {pathname} {status}',

    // File Logging
    logFilePath: './logs/app.log',
    logRotation: {
      maxSize: '100m',
      maxFiles: '30d',
      compress: true
    },

    // Output Control
    disableInternalLogger: false,
    disableFileLogging: false,
    useTransportsOnly: false,
    transports: [],

    // Pino
    pino: {
      level: 'info',
      prettyPrint: false,
      redact: ['password', 'token'],
      base: {
        service: 'my-api',
        version: '1.0.0'
      }
    }
  }
})

Was this page helpful?