---
title: Configuration
description: Complete configuration reference for Logixlysia
---

Complete reference for all Logixlysia configuration options.

## Configuration Object

All configuration options are passed through the `config` property:

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

See [Presets](/docs/features/presets) for defaults per environment.

## Startup Options

### `showStartupMessage`

Whether to display the startup message when the server starts.

- **Type:** `boolean`
- **Default:** `true`

```ts
showStartupMessage: true
```

### `startupMessageFormat`

Format of the startup message.

- **Type:** `'simple' | 'banner'`
- **Default:** `'banner'`

```ts
startupMessageFormat: 'simple' // or 'banner'
```

## Display Options

### `useColors`

Enable colored output in console logs.

- **Type:** `boolean`
- **Default:** `true`

```ts
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`

```ts
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

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 two 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, and JWTs are redacted wherever they appear in strings, even in fields not covered by the key denylist.

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.

- **Type:** `boolean`
- **Default:** `false`

```ts
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.

- **Type:** `string[]`
- **Default:** `undefined`

```ts
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`

```ts
logErrorPayload: true
```

### `logQueryParams`

Include query parameters in the logged URL path.

- **Type:** `boolean`
- **Default:** `false`

```ts
logQueryParams: true
```

## Timestamp Options

### `timestamp`

Timestamp configuration.

- **Type:** `{ translateTime?: string }`
- **Default:** `undefined`

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

## Formatting Options

### `customLogFormat`

Custom log message format using placeholders.

- **Type:** `string`
- **Default:** `undefined`

```ts
customLogFormat: '{now} {level} {duration}ms {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
- `{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
- `{ip}` - Client IP (from `x-forwarded-for` or `x-real-ip`; see `ip` option)
- `{epoch}` - Unix timestamp

### `service`

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

- **Type:** `string`
- **Default:** `undefined` (no prefix)

```ts
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`

```ts
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`

```ts
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`

```ts
showContextTree: true
```

### `contextDepth`

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

- **Type:** `number`
- **Default:** `1`

```ts
contextDepth: 2
```

## Output Options

### `transports`

Array of custom transport implementations.

- **Type:** `Transport[]`
- **Default:** `[]`

```ts
transports: [
  {
    log: async (level, message, meta) => {
      // Custom transport logic
    }
  }
]
```

### `useTransportsOnly`

Use only transports, disable console and file logging.

- **Type:** `boolean`
- **Default:** `false`

```ts
useTransportsOnly: true
```

### `disableInternalLogger`

Disable console logging.

- **Type:** `boolean`
- **Default:** `false`

```ts
disableInternalLogger: true
```

### `disableFileLogging`

Disable file logging.

- **Type:** `boolean`
- **Default:** `false`

```ts
disableFileLogging: true
```

### `onError`

Called when a sink (transport, file, or rotation) or an [enricher](/docs/features/enrichers) fails. Errors thrown by the hook itself are swallowed. When absent, failures go to stderr (rate-limited for transports and enrichers).

- **Type:** `(context: { sink: 'transport' | 'file' | 'rotation' | 'enricher'; error: unknown }) => void`
- **Default:** `undefined`

```ts
onError: ({ sink, error }) => {
  metrics.increment(`logixlysia.sink_error.${sink}`)
}
```

### `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](/docs/features/enrichers).

- **Type:** `EnricherLike[]`
- **Default:** `undefined`

```ts
import { geoEnricher, traceparentEnricher } from 'logixlysia/enrichers'

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

## 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](/docs/features/sampling) for the full guide.

- **Type:** `{ head?: Partial<Record<LogLevel, number>>; tail?: { status?: number; durationMs?: number; paths?: string[] }; maxBufferedPerRequest?: number }`
- **Default:** `undefined` (no sampling)

```ts
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`

```ts
logFilePath: './logs/app.log'
```

### `logRotation`

Log rotation configuration.

- **Type:** `LogRotationConfig`
- **Default:** `undefined`

```ts
logRotation: {
  maxSize: '10m',
  maxFiles: '7d',
  compress: true
}
```

#### `logRotation.maxSize`

Maximum file size before rotation.

- **Type:** `string | number`
- **Format:** `'1k'`, `'1m'`, `'1g'` or bytes

```ts
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](/docs/features/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'`

```ts
maxFiles: '7d' // or 10
```

#### `logRotation.compress`

Enable compression for rotated logs.

- **Type:** `boolean`
- **Default:** `false`

```ts
compress: true
```

#### `logRotation.compression`

Compression algorithm.

- **Type:** `'gzip'`
- **Default:** `'gzip'`

```ts
compression: 'gzip'
```

## Pino Options

### `pino`

Pino logger configuration. Accepts all [Pino options](https://github.com/pinojs/pino/blob/master/docs/api.md#options).

- **Type:** `PinoLoggerOptions & { prettyPrint?: boolean | object }`
- **Default:** `undefined`

```ts
pino: {
  level: 'info',
  prettyPrint: true,
  redact: ['password', 'token'],
  base: {
    service: 'my-api',
    version: '1.0.0'
  }
}
```

### Common Pino Options

#### `pino.level`

Minimum log level.

- **Type:** `'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace'`
- **Default:** `'info'`

```ts
pino: {
  level: 'debug'
}
```

#### `pino.prettyPrint`

Enable pretty printing for development.

- **Type:** `boolean | object`
- **Default:** `false`

```ts
pino: {
  prettyPrint: true
}
```

Or with options:

```ts
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](https://github.com/pinojs/pino-pretty#options) for complete reference.

#### `pino.redact`

Redact sensitive fields from logs.

- **Type:** `string[] | object`
- **Default:** `undefined`

```ts
pino: {
  redact: ['password', 'token', 'apiKey']
}
```

Or with paths:

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

#### `pino.base`

Base fields added to all logs.

- **Type:** `object`
- **Default:** `undefined`

```ts
pino: {
  base: {
    service: 'my-api',
    version: '1.0.0',
    environment: process.env.NODE_ENV
  }
}
```

## Complete Example

```ts
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}ms {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'
      }
    }
  }
})
```

