···99Features:
10101111* Fully typed for Typescript projects
1212-* One-line, turn-key logging to console and rotating file
1313-* Child (nested) loggers with hierarchical label prefixes for log messages
1212+* One-line, [turn-key logging](#quick-start) to console and rotating file
1313+* [Child (nested) loggers](#child-loggers) with hierarchical label prefixes for log messages
1414* Per-destination level filtering configurable via ENV or arguments
1515* Clean, opinionated log output format powered by [pino-pretty](https://github.com/pinojs/pino-pretty):
1616- * Standard timestamp (iso8601)
1716 * Colorized output when stream is TTY and supports it
1818- * Automatically serialize passed objects and Errors, including [Error Cause](https://github.com/tc39/proposal-error-cause)
1919-* Bring-Your-Own settings
2020- * Add or use your own streams for destinations
1717+ * Automatically [serialize passed objects and Errors](#serializing-objects-and-errors), including [Error Cause](https://github.com/tc39/proposal-error-cause)
1818+* [Bring-Your-Own settings](#additional-app-logger-configuration)
1919+ * Add or use your own streams/[transports](https://getpino.io/#/docs/transports?id=known-transports) for destinations
2120 * All pino-pretty configs are exposed and extensible
2121+* [Build-Your-Own Logger](#building-a-logger)
2222+ * Don't want to use any of the pre-built transports? Leverage the convenience of @foxxmd/logging wrappers and default settings but build your logger from scratch
22232324<img src="/assets/example.png" alt="example log output">
2525+2626+**Documentation best viewed on [https://foxxmd.github.io/logging](https://foxxmd.github.io/logging)**
24272528# Install
2629···145148 * For rolling log files
146149 *
147150 * When
148148- * * value passed to rolling destination is a string (`filePath` from LogOptions is a string)
151151+ * * value passed to rolling destination is a string (`path` option) and
149152 * * `frequency` is defined
150153 *
151154 * This determines the format of the datetime inserted into the log file name:
152155 *
153156 * * `unix` - unix epoch timestamp in milliseconds
154154- * * `iso` - Full [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) datetime IE '2024-03-07T20:11:34Z'
157157+ * * `iso` - Full ISO8601 datetime IE '2024-03-07T20:11:34Z'
155158 * * `auto`
156159 * * When frequency is `daily` only inserts date IE YYYY-MM-DD
157160 * * Otherwise inserts full ISO8601 datetime
···181184```
182185183186</details>
187187+188188+### Additional App Logger Configuration
189189+190190+`loggerApp` and `loggerAppRolling` accept an optional second parameter, [`LoggerAppExtras`](https://foxxmd.github.io/logging/types/index.LoggerAppExtras.html) that allows adding additional log destinations or pino-pretty customization:
191191+192192+```ts
193193+export interface LoggerAppExtras {
194194+ /**
195195+ * Additional pino-pretty options that are applied to the built-in console/log streams
196196+ * */
197197+ pretty?: PrettyOptions
198198+ /**
199199+ * Additional logging destinations to use alongside the built-in console/log stream. These can be any created by buildDestination* functions or other Pino Transports
200200+ * */
201201+ destinations?: LogLevelStreamEntry[]
202202+}
203203+```
204204+205205+Some defaults and convenience variables for pino-pretty options are available in `@foxxmd/logging/factory` prefixed with `PRETTY_`. See [factory variables docs](https://foxxmd.github.io/logging/modules/factory.html) for all options.
206206+207207+An example using the extras parameter:
208208+209209+```ts
210210+import { loggerApp } from '@foxxmd/logging';
211211+import {
212212+ PRETTY_ISO8601, // replaces standard timestamp with ISO8601 format
213213+ buildDestinationFile
214214+} from "@foxxmd/logging/factory";
215215+216216+const warnFileDestination = buildDestinationFile('warn', {path: './myLogs/warn.log'});
217217+218218+const logger = loggerApp({}, {
219219+ destinations: [warnFileDestination],
220220+ pretty: {
221221+ translateTime: PRETTY_ISO8601
222222+ }
223223+});
224224+logger.debug('Test');
225225+// [2024-03-07T11:27:41-05:00] DEBUG: Test
226226+```
227227+228228+See [Building A Logger](#building-a-logger) for more information.
184229185230## Usage
186231
···11import {PrettyOptions} from "pino-pretty";
22import {CWD} from "./util.js";
3344+/**
55+ * Additional levels included in @foxxmd/logging as an object
66+ *
77+ * These are always applied when using prettyOptsFactory() but can be overridden
88+ * */
99+export const PRETTY_LEVELS: Extract<PrettyOptions['customLevels'], object> = {
1010+ verbose: 25,
1111+ log: 21,
1212+};
1313+/**
1414+ * Additional levels included in @foxxmd/logging as a string
1515+ *
1616+ * These are always applied when using prettyOptsFactory() but can be overridden
1717+ * */
1818+export const PRETTY_LEVELS_STR: Extract<PrettyOptions['customLevels'], string> = 'verbose:25,log:21';
1919+2020+/**
2121+ * Additional level colors included in @foxxmd/logging as an object
2222+ *
2323+ * These are always applied when using prettyOptsFactory() but can be overridden
2424+ * */
2525+export const PRETTY_COLORS_STR: Extract<PrettyOptions['customColors'], string> = 'verbose:magenta,log:greenBright';
2626+/**
2727+ * Additional level colors included in @foxxmd/logging as a string
2828+ *
2929+ * These are always applied when using prettyOptsFactory() but can be overridden
3030+ * */
3131+export const PRETTY_COLORS: Extract<PrettyOptions['customColors'], object> = {
3232+ 'verbose': 'magenta',
3333+ 'log': 'greenBright'
3434+}
3535+3636+/**
3737+ * Use on `translateTime` pino-pretty option to print timestamps in ISO8601 format
3838+ * */
3939+export const PRETTY_ISO8601 = 'SYS:yyyy-mm-dd"T"HH:MM:ssp';
4040+441export const prettyOptsFactory = (opts: PrettyOptions = {}): PrettyOptions => {
4242+ const {customLevels = {}, customColors = {}, ...rest} = opts;
4343+544 return {
645 messageFormat: (log, messageKey, levelLabel, {colors}) => {
746 const labels: string[] = log.labels as string[] ?? [];
···1857 hideObject: false,
1958 ignore: 'pid,hostname,labels,err',
2059 translateTime: 'SYS:standard',
2121- customLevels: {
2222- verbose: 25,
2323- log: 21,
2424- },
2525- customColors: 'verbose:magenta,log:greenBright',
6060+ customLevels: buildLevels(customLevels),
6161+ customColors: buildColors(customColors),
2662 colorizeObjects: true,
2763 // @ts-ignore
2864 useOnlyCustomProps: false,
2929- ...opts
6565+ ...rest
3066 }
3167}
6868+6969+const buildLevels = (userLevels: PrettyOptions['customLevels'] = {}): PrettyOptions['customLevels'] => {
7070+ let levels: PrettyOptions['customLevels'];
7171+ if (typeof userLevels === 'string') {
7272+ levels = `${PRETTY_LEVELS_STR},${userLevels}`;
7373+ } else {
7474+ levels = {
7575+ ...PRETTY_LEVELS,
7676+ ...userLevels
7777+ }
7878+ }
7979+ return levels;
8080+}
8181+8282+const buildColors = (userColors: PrettyOptions['customColors'] = {}): PrettyOptions['customColors'] => {
8383+ // pino-pretty has a bug that assumes customColors is always a string
8484+ // so we need to rebuild as string even if an object is given
8585+8686+ let colors: PrettyOptions['customColors'];
8787+ if (typeof userColors === 'string') {
8888+ colors = `${PRETTY_COLORS_STR},${userColors}`;
8989+ } else {
9090+ colors = {
9191+ ...PRETTY_COLORS,
9292+ ...userColors
9393+ }
9494+ colors = Object.entries(colors).reduce((acc, [k, v]) => {
9595+ return acc.concat(`${k}:${v}`)
9696+ }, []).join(',');
9797+ }
9898+ return colors;
9999+}
100100+32101/**
33102 * Pre-defined pretty options for use with console/stream output
34103 *
+12-1
src/types.ts
···8888 * For rolling log files
8989 *
9090 * When
9191- * * value passed to rolling destination is a string (`filePath` from LogOptions is a string)
9191+ * * value passed to rolling destination is a string (`path` from LogOptions is a string) and
9292 * * `frequency` is defined
9393 *
9494 * This determines the format of the datetime inserted into the log file name:
···152152export type StreamDestination = Omit<PrettyOptions, 'destination'> & {destination: number | DestinationStream | NodeJS.WritableStream};
153153154154export type LogOptionsParsed = Omit<Required<LogOptions>, 'file'> & { file: FileLogOptionsParsed }
155155+156156+export interface LoggerAppExtras {
157157+ /**
158158+ * Additional pino-pretty options that are applied to the built-in console/log streams
159159+ * */
160160+ pretty?: PrettyOptions
161161+ /**
162162+ * 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)
163163+ * */
164164+ destinations?: LogLevelStreamEntry[]
165165+}