@loglayer/transport-log-file-rotation
Version:
Log file rotation transport for the LogLayer logging library.
420 lines (417 loc) • 14.1 kB
TypeScript
import { LoggerlessTransportConfig, LoggerlessTransport, LogLayerTransportParams } from '@loglayer/transport';
interface LogFileRotationCallbacks {
/**
* Called when a log file is rotated
* @param oldFile - The path to the old log file
* @param newFile - The path to the new log file
*/
onRotate?: (oldFile: string, newFile: string) => void;
/**
* Called when a new log file is created
* @param newFile - The path to the new log file
*/
onNew?: (newFile: string) => void;
/**
* Called when a log file is opened
*/
onOpen?: () => void;
/**
* Called when a log file is closed
*/
onClose?: () => void;
/**
* Called when an error occurs
* @param error - The error that occurred
*/
onError?: (error: Error) => void;
/**
* Called when the stream is finished
*/
onFinish?: () => void;
/**
* Called when a log file is removed due to retention policy
* @param info - Information about the removed log file
*/
onLogRemoved?: (info: {
date: number;
name: string;
hash: string;
}) => void;
}
interface LogFileRotationFieldNames {
/**
* Field name for the log level
* @default "level"
*/
level?: string;
/**
* Field name for the log message
* @default "message"
*/
message?: string;
/**
* Field name for the timestamp
* @default "timestamp"
*/
timestamp?: string;
}
interface LogFileRotationLevelMap {
/**
* Mapping for the 'fatal' log level
* @example 60 or "FATAL"
*/
fatal?: string | number;
/**
* Mapping for the 'error' log level
* @example 50 or "ERROR"
*/
error?: string | number;
/**
* Mapping for the 'warn' log level
* @example 40 or "WARN"
*/
warn?: string | number;
/**
* Mapping for the 'info' log level
* @example 30 or "INFO"
*/
info?: string | number;
/**
* Mapping for the 'debug' log level
* @example 20 or "DEBUG"
*/
debug?: string | number;
/**
* Mapping for the 'trace' log level
* @example 10 or "TRACE"
*/
trace?: string | number;
}
interface LogFileRotationBatchConfig {
/**
* Maximum number of log entries to queue before writing.
* Default: 1000
*/
size?: number;
/**
* Maximum time in milliseconds to wait before writing queued logs.
* Default: 5000 (5 seconds)
*/
timeout?: number;
}
interface LogFileRotationTransportConfig extends LoggerlessTransportConfig {
/**
* The filename pattern to use for the log files.
* Supports date format using numerical values.
* Example: "./logs/application-%DATE%.log"
*/
filename: string;
/**
* Static data to be included in every log entry.
* Can be either:
* - A function that returns an object containing static data
* - A direct object containing static data
*
* The data will be merged with the log entry before any other data.
* If using a function, it will be called for each log entry.
* @example
* ```typescript
* // Using a function
* staticData: () => ({
* hostname: hostname(),
* pid: process.pid
* })
*
* // Using an object
* staticData: {
* hostname: hostname(),
* pid: process.pid
* }
* ```
*/
staticData?: (() => Record<string, any>) | Record<string, any>;
/**
* The frequency of rotation. Can be:
* - 'daily' for daily rotation
* - 'date' for rotation on date format change
* - '[1-30]m' for rotation every X minutes
* - '[1-12]h' for rotation every X hours
*/
frequency?: string;
/**
* The date format to use in the filename.
* Uses single characters for each date component:
* - 'Y' for full year
* - 'M' for month
* - 'D' for day
* - 'H' for hour
* - 'm' for minutes
* - 's' for seconds
*
* Common patterns:
* - For daily rotation: use "YMD" (creates files like app-20240117.log)
* - For hourly/minute rotation: use "YMDHm" (creates files like app-202401171430.log)
*
* @default "YMD"
*/
dateFormat?: string;
/**
* The size at which to rotate.
* Examples: "10M", "100K", "100B"
* If frequency is specified, this will be ignored.
*/
size?: string;
/**
* Maximum number of logs to keep.
* Can be a number of files or days (e.g., "10d" for 10 days)
*/
maxLogs?: string | number;
/**
* Location to store the log audit file.
* If not set, it will be stored in the root of the application.
*/
auditFile?: string;
/**
* File extension to be appended to the filename.
* Useful when using size restrictions as the rotation adds a count at the end.
*/
extension?: string;
/**
* Create a tailable symlink to the current active log file.
* Default: false
*/
createSymlink?: boolean;
/**
* Name to use when creating the symbolic link.
* Default: 'current.log'
*/
symlinkName?: string;
/**
* Use UTC time for date in filename.
* Default: false
*/
utc?: boolean;
/**
* Use specified hashing algorithm for audit.
* Default: 'md5'
* Use 'sha256' for FIPS compliance.
*/
auditHashType?: "md5" | "sha256";
/**
* File mode to be used when creating log files.
* Default: 0o640 (user read/write, group read, others none)
*/
fileMode?: number;
/**
* Options passed to the file stream.
* See: https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_options
*/
fileOptions?: {
flags?: string;
encoding?: string;
mode?: number;
};
/**
* Event callbacks for various file stream events
*/
callbacks?: LogFileRotationCallbacks;
/**
* Custom field names for the log entry JSON
* Default: { level: "level", message: "message", data: "data", timestamp: "timestamp" }
*/
fieldNames?: LogFileRotationFieldNames;
/**
* Delimiter between log entries.
* Default: "\n"
*/
delimiter?: string;
/**
* Custom function to generate timestamps for log entries.
* Can return either a string (e.g., ISO string) or a number (e.g., Unix timestamp)
* If not provided, defaults to new Date().toISOString()
*/
timestampFn?: () => string | number;
/**
* Custom mapping for log levels.
* Each log level can be mapped to either a string or number.
* Example: { error: 50, warn: 40, info: 30, debug: 20, trace: 10, fatal: 60 }
* Example: { error: "ERROR", warn: "WARN", info: "INFO", debug: "DEBUG", trace: "TRACE", fatal: "FATAL" }
*/
levelMap?: LogFileRotationLevelMap;
/**
* Whether to compress rotated log files using gzip.
* When enabled, rotated files will be compressed with .gz extension.
* Default: false
*/
compressOnRotate?: boolean;
/**
* Whether to enable verbose mode in the underlying file-stream-rotator.
* When enabled, the rotator will log detailed information about its operations.
* Default: false
*/
verbose?: boolean;
/**
* Batch processing configuration.
* If defined, batch processing will be enabled.
* When batching is enabled, logs are queued in memory and written to disk in batches.
* Queued logs are automatically flushed in the following situations:
* - When the batch size is reached
* - When the batch timeout is reached
* - When the transport is disposed
* - When the process exits (including SIGINT and SIGTERM signals)
*/
batch?: LogFileRotationBatchConfig;
}
/**
* A transport that writes logs to rotating files with support for time-based and size-based rotation.
* Features include:
* - Automatic log file rotation based on time (hourly, daily) or size
* - Support for date patterns in filenames using numerical values (YYYY, MM, DD, etc.)
* - Size-based rotation with support for KB, MB, and GB units
* - Compression of rotated log files using gzip
* - Maximum file count or age-based retention
* - Automatic cleanup of old log files
* - Batch processing of logs for improved performance
* - Safe handling of process termination signals
*
* Each instance must have a unique filename to prevent race conditions.
* If you need multiple loggers to write to the same file, share the same transport instance between them.
*/
declare class LogFileRotationTransport extends LoggerlessTransport implements Disposable {
/** Registry of active filenames to prevent multiple transports writing to the same file */
private static activeFilenames;
/** The current write stream for the log file */
private stream;
/** Custom field names for log entries */
private fieldNames;
/** Delimiter between log entries */
private delimiter;
/** Function to generate timestamps for log entries */
private timestampFn;
/** Custom mapping for log levels */
private levelMap;
/** Whether to compress rotated files */
private compressOnRotate;
/** Whether a file is currently being compressed */
private isCompressing;
/** The base filename pattern for log files */
private filename;
/** Static data to be included in every log entry */
private staticData?;
/** Whether batch processing is enabled */
private batchEnabled;
/** Maximum number of log entries to queue before writing */
private batchSize;
/** Maximum time in milliseconds to wait before writing queued logs */
private batchTimeout;
/** Queue of log entries waiting to be written */
private batchQueue;
/** Timer for batch flush timeout */
private batchTimer;
/** Whether the transport is being disposed */
private isDisposing;
/** Event callbacks for various file stream events */
private callbacks?;
/** Frequency of rotation (daily, hourly, etc.) */
private frequency?;
/** Whether to enable verbose mode */
private verbose?;
/** Date format for filename patterns */
private dateFormat?;
/** Size threshold for rotation */
private size?;
/** Maximum number of log files to keep */
private maxLogs?;
/** Path to the audit file */
private auditFile?;
/** File extension for log files */
private extension?;
/** Whether to create a symlink to current log */
private createSymlink?;
/** Name of the symlink file */
private symlinkName?;
/** Whether to use UTC time in filenames */
private utc?;
/** Hash algorithm for audit file */
private auditHashType?;
/** Options for file streams */
private fileOptions?;
/** File mode to be used when creating log files */
private fileMode?;
/**
* Generates the options for FileStreamRotator consistently across the transport
* @returns FileStreamRotatorOptions object
* @private
*/
private getRotatorOptions;
/**
* Creates a new LogFileRotationTransport instance.
* @param params - Configuration options for the transport
* @throws {Error} If the filename is already in use by another transport instance
*/
constructor(params: LogFileRotationTransportConfig);
/**
* Initializes the write stream and sets up event listeners.
* This is called either immediately if batching is disabled,
* or lazily when the first batch needs to be written if batching is enabled.
* @param options - Options for the file stream rotator
* @private
*/
private initStream;
/**
* Generates a unique path for a compressed log file.
* If a file with .gz extension already exists, appends timestamp and counter.
* @param filePath - The original log file path
* @returns The unique path for the compressed file
* @private
*/
private getUniqueCompressedFilePath;
/**
* Compresses a log file using gzip.
* @param filePath - Path to the file to compress
* @returns Path to the compressed file
* @private
*/
private compressFile;
/**
* Flushes queued log entries to disk asynchronously.
* This is used for normal batch processing operations.
* @private
*/
private flush;
/**
* Synchronously flush logs to disk.
* This is used during process termination (SIGINT/SIGTERM) to ensure logs are written
* before the process exits. This method uses synchronous file I/O to guarantee that
* logs are written even during abrupt process termination.
* @private
*/
private flushSync;
/**
* Schedules a batch flush operation.
* This creates a timer that will flush the batch after the configured timeout.
* The timer is unref'd to prevent keeping the process alive.
* @private
*/
private scheduleBatchFlush;
/**
* Processes and writes a log entry.
* If batching is enabled, the entry is queued and written based on batch settings.
* If batching is disabled, the entry is written immediately.
* @param params - The log entry parameters
* @returns The original messages array
*/
shipToLogger({ logLevel, messages, data, hasData }: LogLayerTransportParams): any[];
/**
* Disposes of the transport, cleaning up resources and flushing any remaining logs.
* This method:
* 1. Prevents new batch flushes from being scheduled
* 2. Cancels any pending batch flush
* 3. Flushes any remaining logs
* 4. Waits for any in-progress compression to complete
* 5. Closes the write stream
* 6. Removes the filename from the registry
*/
[Symbol.dispose](): void;
}
export { type LogFileRotationBatchConfig, type LogFileRotationCallbacks, type LogFileRotationFieldNames, type LogFileRotationLevelMap, LogFileRotationTransport, type LogFileRotationTransportConfig };