Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/FoxxMD/logging. A typed, opinionated, batteries-included, Pino-based logging solution for backend T foxxmd.github.io/logging
child-logger logging logging-library nodejs pinojs typescript-library
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335import {DestinationStream, Logger as PinoLogger, LoggerOptions, StreamEntry, Level} from 'pino';import {PrettyOptions} from "pino-pretty";import {MarkRequired} from "ts-essentials";
/** * Names of log levels that can be invoked on the logger * * From lowest to highest: * * * `trace` * * `debug` * * `verbose` * * `log` * * `info` * * `warn` * * `error` * * `fatal` * * `silent` (will never output anything) * * When used in `LogOptions` specifies the **minimum** level the output should log at. * */export type LogLevel = typeof LOG_LEVEL_NAMES[number];
/** * Pino default levels * * @see pino/lib/constants.js * */const PINO_DEFAULT_LEVELS = { trace: 10, debug: 20, info: 30, warn: 40, error: 50, fatal: 60}
const PINO_DEFAULT_LEVEL_NAMES = Object.keys(PINO_DEFAULT_LEVELS) as (Level)[];
/** * Additional levels included in @foxxmd/logging as an object * * These are always applied when using `prettyOptsFactory` but can be overridden * */export const CUSTOM_LEVELS: LoggerOptions<"verbose" | "log">['customLevels'] = { verbose: 25, log: 21}
const CUSTOM_LEVEL_NAMES = Object.keys(CUSTOM_LEVELS);
export const LOG_LEVEL_NAMES= ['silent', 'fatal', 'error', 'warn', 'info', 'log', 'verbose', 'debug', 'trace'] as const;
export type ChildLabel = (string | CallableFunction);
export type FilterLabelsFunc = (labels: ChildLabel[]) => boolean;
export interface ChildLoggerOptions { labelEnable?: (labels: ChildLabel[]) => boolean, labelEnableLevel?: LogLevel, labelDisable?: (labels: ChildLabel[]) => boolean, labelDisableLevel?: LogLevel [key: string]: any}
/** * Configure log levels and file options for an AppLogger. * * ```ts * const infoLogger = loggerApp({ * level: 'info' // console and file will log any levels `info` and above * }); * * const logger = loggerApp({ * console: 'debug', // console will log `debug` and higher * file: 'warn' // file will log `warn` and higher * }); * * const fileLogger = loggerRollingApp({ * console: 'debug', // console will log `debug` and higher * file: { * level: 'warn', // file will log `warn` and higher * path: '/my/cool/path/output.log', // optionally, output to log file at this path * frequency: 'hourly', // optionally, rotate hourly * } * }); * ``` * */export interface LogOptions { /** * Specify the minimum log level for all log outputs without their own level specified. * * Defaults to env `LOG_LEVEL` or `info` if not specified. * * @default 'info' * */ level?: LogLevel /** * Specify the minimum log level to output to rotating files or file output options. If `false` no log files will be created. * */ file?: LogLevel | false | FileLogOptions /** * Specify the minimum log level streamed to the console (or docker container) * */ console?: LogLevel}
export type Logger = PinoLogger<LogLevel> & { labels: any[] addLabel: (value: any) => void}
/** * An object with a `write` function that can be used by pino as a [Transport](https://getpino.io/#/docs/transports) * * All `buildDestination*` functions return this type as well as any [Pino Transport](https://getpino.io/#/docs/transports?id=known-transports) * */export type LogLevelStreamEntry = StreamEntry<LogLevel>
/** * The structure of a Log object when returned by a stream `data` event * */export type LogData = Record<string, any> & { level: number time: number pid: number hostname: string labels: any[] msg: string | Error}
export type LogDataPretty = LogData & { line: string}
export interface PinoRollOptions { /** * The maximum size of a given rolling log file. * * Can be combined with frequency. Use k, m and g to express values in KB, MB or GB. * * Numerical values will be considered as MB. * * @default '10MB' * */ size?: number | string /** * The amount of time a given rolling log file is used. Can be combined with size. * * Use `daily` or `hourly` to rotate file every day (or every hour). Existing file within the current day (or hour) will be re-used. * * Numerical values will be considered as a number of milliseconds. Using a numerical value will always create a new file upon startup. * * @default 'daily' * */ frequency?: 'daily' | 'hourly' | number}
export interface RollOptions { /** * For rolling log files * * When * * value passed to rolling destination is a string (`path` from LogOptions is a string) and * * `frequency` is defined * * This determines the format of the datetime inserted into the log file name: * * * `unix` - unix epoch timestamp in milliseconds * * `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z' * * `auto` * * When frequency is `daily` only inserts date IE YYYY-MM-DD * * Otherwise inserts full ISO8601 datetime * * @default 'auto' * */ timestamp?: 'unix' | 'iso' | 'auto'}
/** * Specify and override default log file options * * ```ts * const fileLogger = loggerRollingApp({ * file: { * level: 'warn', // file will log `warn` and higher * path: '/my/cool/path/output.log', // output to log file at this path * frequency: 'daily', // rotate hourly * size: '20MB', // rotate if file size grows larger than 20MB * timestamp: 'unix' // use unix epoch timestamp instead of iso8601 in rolling file * } * }); * ``` * */export interface FileOptions extends PinoRollOptions, RollOptions { /** * The path and filename to use for log files. * * If using rolling files the filename will be appended with `.N` (a number) BEFORE the extension based on rolling status. * * May also be specified using env LOG_PATH or a function that returns a string. * * If path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD * * @default './logs/app.log' * @see LoggerAppExtras * */ path?: string | (() => string)}
export type FileOptionsParsed = MarkRequired<FileOptions, 'path'>;
export interface FileLogOptions extends FileOptions { /** * Specify the minimum log level to output to rotating files. If `false` no log files will be created. * */ level?: LogLevel | false}
export interface FileLogOptionsStrong extends FileLogOptions { level: LogLevel path: string | (() => string)}
export type FileLogOptionsParsed = (Omit<FileLogOptions, 'file'> & {level: false}) | FileLogOptionsStrong
export type FileDestination = Omit<PrettyOptionsExtra, 'destination' | 'sync'> & FileOptionsParsed;export type StreamDestination = Omit<PrettyOptionsExtra, 'destination'> & {destination: number | DestinationStream | NodeJS.WritableStream};export type JsonPrettyDestination = StreamDestination & { /** * Specify if the stream should output log as object or stringified JSON * */ object?: boolean};
export type LogOptionsParsed = Omit<Required<LogOptions>, 'file'> & { file: FileLogOptionsParsed }
export interface FileLogPathOptions { /** * The base path to use when parsing file logging options. * * @see FileOptions * * @default 'CWD' * */ logBaseDir?: string /** * The default path to use when parsing file logging options. * * If this path is relative it is joined with `logBaseDir` * * @see FileOptions * * @default './logs/app.log' * */ logDefaultPath?: string}
/** * Additional settings and Pino Transports to apply to the returned Logger. * */export interface LoggerAppExtras extends FileLogPathOptions { /** * Additional pino-pretty options that are applied to the built-in console/log streams * */ pretty?: PrettyOptionsExtra /** * Additional logging destinations to use alongside the built-in console/log stream. These can be any created by `buildDestination*` functions or other [Pino Transports](https://getpino.io/#/docs/transports?id=known-transports) * */ destinations?: LogLevelStreamEntry[] /** * Additional [Pino Log options](https://getpino.io/#/docs/api?id=options) that are passed to `pino()` on logger creation * */ pino?: PinoLoggerOptions}
/** * Additional [Pino Log options](https://getpino.io/#/docs/api?id=options) that are passed to `pino()` on logger creation * */export type PinoLoggerOptions = Omit<LoggerOptions, 'level' | 'mixin' | 'mixinMergeStrategy' | 'customLevels' | 'useOnlyCustomLevels' | 'transport'>
/** * pino-pretty options and additional options specific to how @foxxmd/logging uses pino-pretty * */export interface PrettyOptionsExtra extends Omit<PrettyOptions, 'customLevels'> { /** * Control whether the current working directory should be replaced with 'CWD' in log output * * Useful for eliminating noisy parent paths that aren't relevant during debugging -- or to protect user privacy. * * **NOTE:** Only applies to log message and errors. If you need to redact arbitrary properties you should use pino's [`redact`](https://getpino.io/#/docs/api?id=redact-array-object) or pino-pretty's [`customPrettifiers`](https://github.com/pinojs/pino-pretty?tab=readme-ov-file#options) * * @default true * */ redactCwd?: boolean /** * Pads levels in log string so all are the same length * * @default true * */ padLevels?: boolean}
/** * Additional levels included in @foxxmd/logging as an object * * These are always applied when using `prettyOptsFactory` but can be overridden * */export const PRETTY_LEVELS: Extract<PrettyOptions['customLevels'], object> = CUSTOM_LEVELS;/** * Additional levels included in @foxxmd/logging as a string * * These are always applied when using `prettyOptsFactory` but can be overridden * */export const PRETTY_LEVELS_STR: Extract<PrettyOptions['customLevels'], string> = 'verbose:25,log:21';/** * Additional level colors included in @foxxmd/logging as an object * * These are always applied when using `prettyOptsFactory` but can be overridden * */export const PRETTY_COLORS_STR: Extract<PrettyOptions['customColors'], string> = 'verbose:magenta,log:greenBright';/** * Additional level colors included in @foxxmd/logging as a string * * These are always applied when using `prettyOptsFactory` but can be overridden * */export const PRETTY_COLORS: Extract<PrettyOptions['customColors'], object> = { 'verbose': 'magenta', 'log': 'greenBright'}/** * Use on `translateTime` pino-pretty option to print timestamps in ISO8601 format * */export const PRETTY_ISO8601 = 'SYS:yyyy-mm-dd"T"HH:MM:ssp';