Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: keep parent formatters bindings function option #1950

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,12 +378,31 @@ const hooks = {
<a id=opt-formatters></a>
#### `formatters` (Object)

An object containing functions for formatting the shape of the log lines.
An object containing an `options` object and functions for formatting
the shape of the log lines.
These functions should return a JSONifiable object and
should never throw. These functions allow for full customization of
the resulting log lines. For example, they can be used to change
the level key name or to enrich the default metadata.

##### `options`

The formatters `options` object is passed to the child loggers, except if a new formatters `options` object is passed to the `child()` method.

###### `keepParentBindings`

If `true`, child loggers will keep their parent `bindings` formatters function.

If `false` or `undefined`, child loggers will have their `bindings` formatters function reset to a "no-op" formatter function.

```js
const formatters = {
options: {
keepParentBindings: true
}
}
```

##### `level`

Changes the shape of the log level. The default shape is `{ level: number }`.
Expand Down
11 changes: 7 additions & 4 deletions lib/proto.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ module.exports = function () {
return Object.create(prototype)
}

const resetChildingsFormatter = bindings => bindings
const noOpFormatter = bindings => bindings
function child (bindings, options) {
if (!bindings) {
throw Error('missing bindings for child Pino')
Expand Down Expand Up @@ -110,17 +110,20 @@ function child (bindings, options) {
instance[serializersSym][bks] = options.serializers[bks]
}
} else instance[serializersSym] = serializers
const keepParentBindings = typeof formatters.options === 'object' && formatters.options.keepParentBindings
if (options.hasOwnProperty('formatters')) {
const { level, bindings: chindings, log } = options.formatters
const { options: formattersOptions, level, bindings: chindings, log } = options.formatters
instance[formattersSym] = buildFormatters(
formattersOptions || formatters.options,
level || formatters.level,
chindings || resetChildingsFormatter,
chindings || (keepParentBindings ? formatters.bindings || noOpFormatter : noOpFormatter),
log || formatters.log
)
} else {
instance[formattersSym] = buildFormatters(
formatters.options,
formatters.level,
resetChildingsFormatter,
keepParentBindings ? formatters.bindings || noOpFormatter : noOpFormatter,
formatters.log
)
}
Expand Down
3 changes: 2 additions & 1 deletion lib/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,9 @@ function stringify (obj, stringifySafeFn) {
}
}

function buildFormatters (level, bindings, log) {
function buildFormatters (options, level, bindings, log) {
return {
options,
level,
bindings,
log
Expand Down
1 change: 1 addition & 0 deletions pino.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ function pino (...args) {
})

const allFormatters = buildFormatters(
formatters.options,
formatters.level,
formatters.bindings,
formatters.log
Expand Down
39 changes: 39 additions & 0 deletions test/formatters.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,45 @@ test('Formatters in child logger', async ({ match }) => {
})
})

test('Formatters with keepParentBindings option', async ({ match }) => {
const stream = sink()

const logger = pino({
formatters: {
options: {
keepParentBindings: true
},
bindings (bindings) {
if (bindings.foobar) bindings.foobar = bindings.foobar.toUpperCase()
if (bindings.faz) bindings.faz = bindings.faz.toUpperCase()
if (bindings.foobat) bindings.foobat = bindings.foobat.toUpperCase()
if (bindings.foobaz) bindings.foobaz = bindings.foobaz.toUpperCase()
return bindings
}
}
}, stream)
logger.setBindings({ foobar: 'foobar' })

const child = logger.child({
faz: 'baz',
nested: { object: true }
})
child.setBindings({ foobat: 'foobat' })

const childChild = child.child({ foobaz: 'foobaz' })

const o = once(stream, 'data')
childChild.info({ foo: 'bar', nested: { object: true } }, 'hello world')
match(await o, {
foobar: 'FOOBAR',
faz: 'BAZ',
foobat: 'FOOBAT',
foobaz: 'FOOBAZ',
foo: 'bar',
nested: { object: true }
})
})

test('Formatters without bindings in child logger', async ({ match }) => {
const stream = sink()
const logger = pino({
Expand Down