Skip to content

Commit

Permalink
Merge pull request #759 from northscaler/object-key
Browse files Browse the repository at this point in the history
Support new nestedKey config to avoid property name collisions with pino standard properties when logging objects
  • Loading branch information
davidmarkclements committed Jan 11, 2020
2 parents 542e165 + 6d80dbf commit 6fae12a
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 1 deletion.
26 changes: 26 additions & 0 deletions docs/api.md
Expand Up @@ -201,6 +201,32 @@ Default: `'msg'`

The string key for the 'message' in the JSON object.

<a id=opt-nestedkey></a>
#### `nestedKey` (String)

Default: `null`

If there's a chance that objects being logged have properties that conflict with those from pino itself (`level`, `timestamp`, `v`, `pid`, etc)
and duplicate keys in your log records are undesirable, pino can be configured with a `nestedKey` option that causes any `object`s that are logged
to be placed under a key whose name is the value of `nestedKey`.

This way, when searching something like Kibana for values, one can consistently search under the configured `nestedKey` value instead of the root log record keys.

For example,
```js
const logger = require('pino')({
nestedKey: 'payload'
})

const thing = { level: 'hi', time: 'never', foo: 'bar'} // has pino-conflicting properties!
logger.info(thing)

// logs the following:
// {"level":30,"time":1578357790020,"pid":91736,"hostname":"x","payload":{"level":"hi","time":"never","foo":"bar"},"v":1}
```
In this way, logged objects' properties don't conflict with pino's standard logging properties,
and searching for logged objects can start from a consistent path.

<a id=prettyPrint></a>
#### `prettyPrint` (Boolean | Object)

Expand Down
2 changes: 2 additions & 0 deletions lib/symbols.js
Expand Up @@ -24,6 +24,7 @@ const stringifiersSym = Symbol('pino.stringifiers')
const endSym = Symbol('pino.end')
const formatOptsSym = Symbol('pino.formatOpts')
const messageKeySym = Symbol('pino.messageKey')
const nestedKeySym = Symbol('pino.nestedKey')

const wildcardFirstSym = Symbol('pino.wildcardFirst')

Expand Down Expand Up @@ -54,6 +55,7 @@ module.exports = {
endSym,
formatOptsSym,
messageKeySym,
nestedKeySym,
wildcardFirstSym,
changeLevelNameSym,
wildcardGsym,
Expand Down
4 changes: 3 additions & 1 deletion lib/tools.js
Expand Up @@ -20,7 +20,8 @@ const {
needsMetadataGsym,
wildcardGsym,
redactFmtSym,
streamSym
streamSym,
nestedKeySym
} = require('./symbols')

function noop () {}
Expand All @@ -33,6 +34,7 @@ function genLog (z) {
} else if (typeof o.setHeader === 'function') {
o = mapHttpResponse(o)
}
if (this[nestedKeySym]) o = { [this[nestedKeySym]]: o }
this[writeSym](o, format(null, n, this[formatOptsSym]), z)
} else this[writeSym](null, format(o, n, this[formatOptsSym]), z)
}
Expand Down
4 changes: 4 additions & 0 deletions pino.js
Expand Up @@ -27,6 +27,7 @@ const {
endSym,
formatOptsSym,
messageKeySym,
nestedKeySym,
useLevelLabelsSym,
changeLevelNameSym,
mixinSym,
Expand All @@ -40,6 +41,7 @@ const defaultOptions = {
level: 'info',
useLevelLabels: false,
messageKey: 'msg',
nestedKey: null,
enabled: true,
prettyPrint: false,
base: { pid, hostname },
Expand All @@ -66,6 +68,7 @@ function pino (...args) {
serializers,
timestamp,
messageKey,
nestedKey,
base,
name,
level,
Expand Down Expand Up @@ -112,6 +115,7 @@ function pino (...args) {
[endSym]: end,
[formatOptsSym]: formatOpts,
[messageKeySym]: messageKey,
[nestedKeySym]: nestedKey,
[serializersSym]: serializers,
[mixinSym]: mixin,
[chindingsSym]: chindings
Expand Down
20 changes: 20 additions & 0 deletions test/basic.test.js
Expand Up @@ -286,6 +286,26 @@ test('set the messageKey', async ({ is, same }) => {
})
})

test('set the nestedKey', async ({ is, same }) => {
const stream = sink()
const object = { hello: 'world' }
const nestedKey = 'stuff'
const instance = pino({
nestedKey
}, stream)
instance.info(object)
const result = await once(stream, 'data')
is(new Date(result.time) <= new Date(), true, 'time is greater than Date.now()')
delete result.time
same(result, {
pid: pid,
hostname: hostname,
level: 30,
stuff: object,
v: 1
})
})

test('set undefined properties', async ({ is, same }) => {
const stream = sink()
const instance = pino(stream)
Expand Down

0 comments on commit 6fae12a

Please sign in to comment.