diff --git a/docs/api.md b/docs/api.md index 7c2a78405..8e0004c39 100644 --- a/docs/api.md +++ b/docs/api.md @@ -507,6 +507,19 @@ when using the `transport` option. In this case an `Error` will be thrown. * See [pino.transport()](#pino-transport) +#### `onChild` (Function) + +The `onChild` function is a synchronous callback that will be called on each creation of a new child, passing the child instance as its first argument. +Any error thrown inside the callback will be uncaught and should be handled inside the callback. +```js +const parent = require('pino')({ onChild: (instance) => { + // Exceute call back code for each newly created child. +}}) +// `onChild` will now be executed with the new child. +parent.child(bindings) +``` + + ### `destination` (SonicBoom | WritableStream | String | Object) diff --git a/lib/proto.js b/lib/proto.js index 25c0c5b99..400945282 100644 --- a/lib/proto.js +++ b/lib/proto.js @@ -141,7 +141,7 @@ function child (bindings, options) { instance[chindingsSym] = asChindings(instance, bindings) const childLevel = options.level || this.level instance[setLevelSym](childLevel) - + this.onChild(instance) return instance } diff --git a/lib/tools.js b/lib/tools.js index 3ac99c739..674198b43 100644 --- a/lib/tools.js +++ b/lib/tools.js @@ -298,8 +298,9 @@ function createArgsNormalizer (defaultOptions) { throw new Error('prettyPrint option is no longer supported, see the pino-pretty package (https://github.com/pinojs/pino-pretty)') } - const { enabled } = opts + const { enabled, onChild } = opts if (enabled === false) opts.level = 'silent' + if (!onChild) opts.onChild = noop if (!stream) { if (!hasBeenTampered(process.stdout)) { // If process.stdout.fd is undefined, it means that we are running diff --git a/pino.d.ts b/pino.d.ts index 6ad74ba38..8e7fe6ea9 100644 --- a/pino.d.ts +++ b/pino.d.ts @@ -36,6 +36,12 @@ type MixinMergeStrategyFn = (mergeObject: object, mixinObject: object) => object type CustomLevelLogger = Options extends { customLevels: Record } ? Record : Record +/** +* A synchronous callback that will run on each creation of a new child. +* @param child: The newly created child logger instance. +*/ +type OnChildCallback = (child: pino.Logger) => void + interface redactOptions { paths: string[]; censor?: string | ((value: any, path: string[]) => any); @@ -79,6 +85,11 @@ interface LoggerExtras extends EventEmitter { */ child(bindings: pino.Bindings, options?: ChildOptions): pino.Logger; + /** + * This can be used to modify the callback function on creation of a new child. + */ + onChild: OnChildCallback; + /** * Registers a listener function that is triggered when the level is changed. * Note: When browserified, this functionality will only be available if the `events` module has been required elsewhere @@ -601,6 +612,11 @@ declare namespace pino { * Stringification limit of properties/elements when logging a specific object/array with circular references. Default: `100`. */ edgeLimit?: number + + /** + * Optional child creation callback. + */ + onChild?: OnChildCallback; } interface ChildLoggerOptions { diff --git a/pino.js b/pino.js index 9ace3a71d..934eb7476 100644 --- a/pino.js +++ b/pino.js @@ -102,7 +102,8 @@ function pino (...args) { formatters, hooks, depthLimit, - edgeLimit + edgeLimit, + onChild } = opts const stringifySafe = configure({ @@ -175,7 +176,8 @@ function pino (...args) { [chindingsSym]: chindings, [formattersSym]: allFormatters, [hooksSym]: hooks, - silent: noop + silent: noop, + onChild }) Object.setPrototypeOf(instance, proto()) diff --git a/test/basic.test.js b/test/basic.test.js index 2f9700f0d..ca4ca1e97 100644 --- a/test/basic.test.js +++ b/test/basic.test.js @@ -725,3 +725,13 @@ test('throws if prettyPrint is passed in as an option', async (t) => { }) }, new Error('prettyPrint option is no longer supported, see the pino-pretty package (https://github.com/pinojs/pino-pretty)')) }) + +test('Should invoke `onChild` with the newly created child', async ({ equal }) => { + let innerChild + const child = pino({ + onChild: (instance) => { + innerChild = instance + } + }).child({ foo: 'bar' }) + equal(child, innerChild) +}) diff --git a/test/types/pino.test-d.ts b/test/types/pino.test-d.ts index b2a6515ba..57b8ca43c 100644 --- a/test/types/pino.test-d.ts +++ b/test/types/pino.test-d.ts @@ -340,3 +340,8 @@ cclog3.myLevel('') cclog3.childLevel('') // child itself cclog3.childLevel2('') + +const withChildCallback = pino({ + onChild: (child: Logger) => {} +}) +withChildCallback.onChild = (child: Logger) => {} \ No newline at end of file