UNPKG

@loglayer/transport-log-file-rotation

Version:

Log file rotation transport for the LogLayer logging library.

420 lines (417 loc) 14.1 kB
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 };