# OmniRoute Logging Mechanisms: Pino-Based Structured Logging with Automatic Rotation

> Explore OmniRoute's Pino-based structured logging. Discover worker-thread transports, automatic credential redaction, and configurable file rotation for robust application insights.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: internals
- Published: 2026-09-12

---

**OmniRoute provides enterprise-grade logging mechanisms built on Pino, featuring worker-thread transports, automatic credential redaction via pre-serialization hooks, and configurable file rotation with retention policies.**

OmniRoute implements a high-performance logging architecture designed for proxy workloads requiring both observability and security. The system leverages Pino as its underlying JSON logger to minimize overhead while providing human-readable output during development. This implementation is centralized in [`src/shared/utils/logger.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/utils/logger.ts) and supported by dedicated rotation and redaction modules in `src/lib/` and `src/shared/utils/`.

## Core Logger Architecture

The logging subsystem revolves around a singleton `logger` instance exported from [`src/shared/utils/logger.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/utils/logger.ts). This module configures base Pino options—including log level, timestamp formatting, and service tagging—and installs a critical **log-method hook** that executes `redactLogArgs` to strip credential-like values before they reach the transport layer (lines 10-43).

### Transport Layer and Worker Threads

Transport creation is handled by `buildTransportStream` (lines 54-78), which evaluates the `APP_LOG_TO_FILE` environment flag to determine the output strategy:

- **Worker-thread transport**: Preferred for production to prevent I/O blocking on the main thread
- **Synchronous fallback**: Used when worker threads are unavailable or during specific debugging scenarios

The transport attaches an `error` listener that writes warnings to `stderr` without crashing the process, ensuring resilience during disk-pressure events.

### Environment Profiles

The `buildLoggerResource` function (lines 36-91) assembles transports based on the runtime environment:

- **Development** (`isDev: true`): Combines `pino-pretty` for console output with a JSON file stream via `pino/file`
- **Production**: Dual `pino/file` streams writing raw JSON to both stdout and a persistent log file for ingestion by external log aggregators

The function returns a `SharedLoggerResource` object that exposes a `close` method for graceful shutdown during HMR reloads or process termination.

### Singleton Resource Management

The [`src/shared/utils/loggerResource.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/utils/loggerResource.ts) module ensures only one Pino transport stream is created per process. It manages the `SharedLoggerResource` lifecycle, preventing transport leaks during development hot-reloading and providing centralized cleanup capabilities.

## Security and Credential Redaction

OmniRoute prevents accidental secret leakage through [`src/shared/utils/logRedaction.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/utils/logRedaction.ts). This module implements the `redactLogArgs` function used by the logger's pre-serialization hook. Before Pino formats any log entry, this utility scans arguments for credential-like patterns—such as API keys, tokens, or passwords—and replaces them with redaction markers, ensuring sensitive data never persists to disk or external log streams.

## Log Rotation and Retention Policies

File-based logging incorporates automatic rotation and cleanup via [`src/lib/logRotation.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/logRotation.ts). The `initLogRotation()` function establishes background maintenance that respects three environment variables:

- `APP_LOG_MAX_FILE_SIZE`: Byte threshold triggering rotation (default implementation checks file size)
- `APP_LOG_RETENTION_DAYS`: Duration to preserve archived logs before deletion
- `APP_LOG_MAX_FILES`: Maximum number of rotated files to maintain in the log directory

### Rotation Strategy

When enabled, the system monitors the active log file through `rotateIfNeeded` (lines 78-88). Upon exceeding the configured size limit, the current file is atomically renamed to `app.YYYY-MM-DD_HHmmss.log`. A recurring timer—initialized by `initLogRotation` (lines 84-101) and defaulting to 60-second intervals—continuously evaluates rotation conditions and purges expired archives based on retention policies.

## Practical Usage and Child Loggers

Developers interact with the system through the `createLogger` factory function, which produces child loggers scoped to specific modules. This pattern is demonstrated in [`src/lib/usage/resilienceExplain.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/usage/resilienceExplain.ts), where a module-level logger prefixes all entries with a custom name (`resilience-explain`) for traceability.

```ts
// Import the shared logger and create a child scoped to your module
import { logger, createLogger } from "@/shared/utils/logger";

const log = createLogger("proxy");      // → { module: "proxy" } attached to every entry
log.info({ model: "gpt-4o" }, "Incoming request");

// Logging an error – the hook redacts any secret fields before Pino formats
try {
  await upstreamCall();
} catch (err) {
  log.error({ err }, "Upstream failure");
}

// The logger automatically writes to both stdout and a rotating file
// (file path and rotation behaviour are driven by env vars)
process.env.APP_LOG_TO_FILE = "true";          // enable file logging
process.env.APP_LOG_MAX_FILE_SIZE = "52428800"; // 50 MiB rotation threshold

```

## Summary

- **Pino Foundation**: OmniRoute uses Pino for high-throughput JSON logging with configurable pretty-printing in development
- **Worker-Thread Transports**: Asynchronous logging via `buildTransportStream` prevents I/O blocking, with graceful error handling that avoids process crashes
- **Automatic Redaction**: The `redactLogArgs` hook in [`logRedaction.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/logRedaction.ts) sanitizes credentials before serialization
- **Configurable Rotation**: `initLogRotation` manages file size limits, datetime-stamped archives, and retention policies via environment variables
- **Singleton Pattern**: [`loggerResource.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/loggerResource.ts) ensures a single transport instance per process with proper cleanup support

## Frequently Asked Questions

### What underlying logging library does OmniRoute use?

OmniRoute uses **Pino**, a fast JSON logger for Node.js. The implementation in [`src/shared/utils/logger.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/utils/logger.ts) configures Pino with custom transport streams, pre-serialization hooks for security, and environment-specific formatting options for both human-readable development output and machine-parseable production logs.

### How does OmniRoute prevent sensitive data from appearing in log files?

The system implements a **redaction hook** via [`src/shared/utils/logRedaction.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/utils/logRedaction.ts). Before any log entry is serialized, the `redactLogArgs` function scans the arguments for credential-like values and removes them. This ensures that API keys, passwords, or tokens accidentally passed to log methods never reach the transport layer or persistent storage.

### Does OmniRoute support automatic log file rotation?

Yes. When `APP_LOG_TO_FILE` is enabled, the `initLogRotation` function in [`src/lib/logRotation.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/logRotation.ts) actively monitors log files. It rotates files when they exceed `APP_LOG_MAX_FILE_SIZE` by renaming them with timestamps (`app.YYYY-MM-DD_HHmmss.log`) and periodically cleans up expired files based on `APP_LOG_RETENTION_DAYS` and `APP_LOG_MAX_FILES` settings.

### How do I create a module-specific logger in OmniRoute?

Import `createLogger` from `@/shared/utils/logger` and invoke it with your module name to create a child logger. This automatically attaches the module name to every log entry's metadata, as shown in [`src/lib/usage/resilienceExplain.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/usage/resilienceExplain.ts). Child loggers inherit the parent's transport configuration and redaction hooks while allowing scoped log contexts.