Comparing version 7.0.5 to 7.1.0
@@ -98,3 +98,14 @@ # API | ||
``` | ||
#### `depthLimit` (Number) | ||
Default: `5` | ||
Option to limit stringification at a specific nesting depth when logging circular object. | ||
#### `edgeLimit` (Number) | ||
Default: `100` | ||
Option to limit stringification of properties/elements when logging a specific object/array with circular references. | ||
#### `mixin` (Function): | ||
@@ -351,3 +362,4 @@ | ||
__DEPRECATED: use [`transport`](#transport) instead.__ | ||
__DEPRECATED: look at [pino-pretty documentation](https://github.com/pinojs/pino-pretty) | ||
for alternatives__. Using a [`transport`](#transport) is also an option.__ | ||
@@ -415,3 +427,4 @@ Enables pretty printing log logs. This is intended for non-production | ||
of `fs.createWriteStream`) but for peak log writing performance it is strongly | ||
recommended to use `pino.destination` to create the destination stream. | ||
recommended to use `pino.destination` to create the destination stream. | ||
Note that the `destination` parameter can be the result of `pino.transport()`. | ||
@@ -418,0 +431,0 @@ ```js |
@@ -121,3 +121,3 @@ # Help | ||
See [`pino.multistream`](/doc/api.md#pino-multistream). | ||
See [`pino.multistream`](/docs/api.md#pino-multistream). | ||
@@ -124,0 +124,0 @@ <a id="filter-logs"></a> |
@@ -26,13 +26,6 @@ # Transports | ||
```js | ||
import { Writable } from 'stream' | ||
import { createWriteStream } from 'fs' | ||
export default (options) => { | ||
const myTransportStream = new Writable({ | ||
autoDestroy: true, // Needed for Node v12+ | ||
write (chunk, enc, cb) { | ||
// apply a transform and send to stdout | ||
console.log(chunk.toString().toUpperCase()) | ||
cb() | ||
} | ||
}) | ||
return myTransportStream | ||
return createWriteStream(options.destination) | ||
} | ||
@@ -59,3 +52,4 @@ ``` | ||
The exported function can also be async. Imagine the following transport: | ||
The exported function can also be async. If we use an async function we can throw early | ||
if the transform could not be opened. As an example: | ||
@@ -112,2 +106,3 @@ ```js | ||
<a id="writing"></a> | ||
### Writing a Transport | ||
@@ -122,8 +117,24 @@ | ||
import build from 'pino-abstract-transport' | ||
import SonicBoom from 'sonic-boom' | ||
import { once } from 'events' | ||
export default async function (opts) { | ||
// SonicBoom is necessary to avoid loops with the main thread. | ||
// It is the same of pino.destination(). | ||
const destination = new SonicBoom({ dest: opts.destination || 1, sync: false }) | ||
await once(destination, 'ready') | ||
return build(async function (source) { | ||
for await (let obj of source) { | ||
console.log(obj) | ||
const toDrain = !destination.write(obj.message.toUpperCase() + '\n') | ||
// This block will handle backpressure | ||
if (toDrain) { | ||
await once(destination, 'drain') | ||
} | ||
} | ||
}, { | ||
async close (err) { | ||
destination.end() | ||
await once(destination, 'close') | ||
} | ||
}) | ||
@@ -139,8 +150,13 @@ } | ||
const build = require('pino-abstract-transport') | ||
const SonicBoom = require('sonic-boom') | ||
module.exports = function (opts) { | ||
const destination = new SonicBoom({ dest: opts.destination || 1, sync: false }) | ||
return build(function (source) { | ||
source.on('data', function (obj) { | ||
console.log(obj) | ||
}) | ||
source.pipe(destination) | ||
}, { | ||
close (err, cb) { | ||
destination.end() | ||
destination.on('close', cb.bind(null, err)) | ||
} | ||
}) | ||
@@ -154,2 +170,5 @@ } | ||
The `close()` function is needed to make sure that the stream is closed and flushed when its | ||
callback is called or the returned promise resolved. Otherwise log lines will be lost. | ||
### Creating a transport pipeline | ||
@@ -156,0 +175,0 @@ |
@@ -8,2 +8,4 @@ 'use strict' | ||
warning.create(warnName, 'PINODEP008', 'prettyPrint is deprecated, use the pino-pretty transport instead') | ||
warning.create(warnName, 'PINODEP008', 'prettyPrint is deprecated, look at https://github.com/pinojs/pino-pretty for alternatives.') | ||
warning.create(warnName, 'PINODEP009', 'The use of pino.final is discouraged in Node.js v14+ and not required. It will be removed in the next major version') |
@@ -22,2 +22,3 @@ 'use strict' | ||
const stringifySym = Symbol('pino.stringify') | ||
const stringifySafeSym = Symbol('pino.stringifySafe') | ||
const stringifiersSym = Symbol('pino.stringifiers') | ||
@@ -56,2 +57,3 @@ const endSym = Symbol('pino.end') | ||
stringifySym, | ||
stringifySafeSym, | ||
stringifiersSym, | ||
@@ -58,0 +60,0 @@ endSym, |
@@ -8,3 +8,2 @@ 'use strict' | ||
const SonicBoom = require('sonic-boom') | ||
const stringifySafe = require('json-stringify-safe') | ||
const warning = require('./deprecations') | ||
@@ -21,2 +20,3 @@ const { | ||
stringifySym, | ||
stringifySafeSym, | ||
wildcardFirstSym, | ||
@@ -99,2 +99,3 @@ needsMetadataGsym, | ||
const stringify = this[stringifySym] | ||
const stringifySafe = this[stringifySafeSym] | ||
const stringifiers = this[stringifiersSym] | ||
@@ -143,3 +144,3 @@ const end = this[endSym] | ||
default: | ||
value = (stringifier || stringify)(value) | ||
value = (stringifier || stringify)(value, stringifySafe) | ||
} | ||
@@ -174,3 +175,3 @@ if (value === undefined) continue | ||
default: | ||
value = (stringifier || stringify)(value) | ||
value = (stringifier || stringify)(value, stringifySafe) | ||
msgStr = ',"' + messageKey + '":' + value | ||
@@ -180,3 +181,3 @@ } | ||
if (this[nestedKeySym]) { | ||
if (this[nestedKeySym] && propStr) { | ||
// place all the obj properties under the specified key | ||
@@ -194,2 +195,3 @@ // the nested key is already formatted from the constructor | ||
const stringify = instance[stringifySym] | ||
const stringifySafe = instance[stringifySafeSym] | ||
const stringifiers = instance[stringifiersSym] | ||
@@ -211,3 +213,3 @@ const wildcardStringifier = stringifiers[wildcardFirstSym] | ||
value = serializers[key] ? serializers[key](value) : value | ||
value = (stringifiers[key] || wildcardStringifier || stringify)(value) | ||
value = (stringifiers[key] || wildcardStringifier || stringify)(value, stringifySafe) | ||
if (value === undefined) continue | ||
@@ -446,2 +448,5 @@ data += ',"' + key + '":' + value | ||
function final (logger, handler) { | ||
const major = Number(process.versions.node.split('.')[0]) | ||
if (major >= 14) warning.emit('PINODEP009') | ||
if (typeof logger === 'undefined' || typeof logger.child !== 'function') { | ||
@@ -496,3 +501,3 @@ throw Error('expected a pino logger instance') | ||
function stringify (obj) { | ||
function stringify (obj, stringifySafeFn) { | ||
try { | ||
@@ -502,3 +507,4 @@ return JSON.stringify(obj) | ||
try { | ||
return stringifySafe(obj) | ||
const stringify = stringifySafeFn || this[stringifySafeSym] | ||
return stringify(obj) | ||
} catch (_) { | ||
@@ -505,0 +511,0 @@ return '"[unable to serialize, circular reference is too complex to analyze]"' |
{ | ||
"name": "pino", | ||
"version": "7.0.5", | ||
"version": "7.1.0", | ||
"description": "super fast, all natural json logger", | ||
@@ -108,9 +108,9 @@ "main": "pino.js", | ||
"get-caller-file": "^2.0.5", | ||
"json-stringify-safe": "^5.0.1", | ||
"on-exit-leak-free": "^0.2.0", | ||
"pino-abstract-transport": "v0.4.0", | ||
"pino-abstract-transport": "v0.5.0", | ||
"pino-std-serializers": "^4.0.0", | ||
"quick-format-unescaped": "^4.0.3", | ||
"safe-stable-stringify": "^2.1.0", | ||
"sonic-boom": "^2.2.1", | ||
"thread-stream": "^0.11.1" | ||
"thread-stream": "^0.12.0" | ||
}, | ||
@@ -117,0 +117,0 @@ "tsd": { |
@@ -71,2 +71,3 @@ // Type definitions for pino 6.3 | ||
readonly stringifySym: unique symbol; | ||
readonly stringifySafeSym: unique symbol; | ||
readonly stringifiersSym: unique symbol; | ||
@@ -73,0 +74,0 @@ readonly endSym: unique symbol; |
26
pino.js
@@ -10,2 +10,3 @@ 'use strict' | ||
const symbols = require('./lib/symbols') | ||
const { configure } = require('safe-stable-stringify') | ||
const { assertDefaultLevelFound, mappings, genLsCache } = require('./lib/levels') | ||
@@ -16,6 +17,6 @@ const { | ||
final, | ||
stringify, | ||
buildSafeSonicBoom, | ||
buildFormatters, | ||
noop | ||
noop, | ||
stringify | ||
} = require('./lib/tools') | ||
@@ -31,2 +32,3 @@ const { version } = require('./lib/meta') | ||
stringifySym, | ||
stringifySafeSym, | ||
stringifiersSym, | ||
@@ -73,3 +75,5 @@ setLevelSym, | ||
customLevels: null, | ||
useOnlyCustomLevels: false | ||
useOnlyCustomLevels: false, | ||
depthLimit: 5, | ||
edgeLimit: 100 | ||
} | ||
@@ -98,5 +102,12 @@ | ||
formatters, | ||
hooks | ||
hooks, | ||
depthLimit, | ||
edgeLimit | ||
} = opts | ||
const stringifySafe = configure({ | ||
maximumDepth: depthLimit, | ||
maximumBreadth: edgeLimit | ||
}) | ||
const allFormatters = buildFormatters( | ||
@@ -116,5 +127,8 @@ formatters.level, | ||
const stringifiers = redact ? redaction(redact, stringify) : {} | ||
const stringifyFn = stringify.bind({ | ||
[stringifySafeSym]: stringifySafe | ||
}) | ||
const formatOpts = redact | ||
? { stringify: stringifiers[redactFmtSym] } | ||
: { stringify } | ||
: { stringify: stringifyFn } | ||
const end = '}' + (crlf ? '\r\n' : '\n') | ||
@@ -126,2 +140,3 @@ const coreChindings = asChindings.bind(null, { | ||
[stringifySym]: stringify, | ||
[stringifySafeSym]: stringifySafe, | ||
[formattersSym]: allFormatters | ||
@@ -157,2 +172,3 @@ }) | ||
[stringifySym]: stringify, | ||
[stringifySafeSym]: stringifySafe, | ||
[stringifiersSym]: stringifiers, | ||
@@ -159,0 +175,0 @@ [endSym]: end, |
@@ -596,3 +596,3 @@ 'use strict' | ||
test('use `json-stringify-safe` to avoid circular dependencies', async ({ same }) => { | ||
test('use `safe-stable-stringify` to avoid circular dependencies', async ({ same }) => { | ||
const stream = sink() | ||
@@ -605,7 +605,21 @@ const root = pino(stream) | ||
const { a } = await once(stream, 'data') | ||
same(a, { a: '[Circular ~]' }) | ||
same(a, { a: '[Circular]' }) | ||
}) | ||
test('json-stringify-safe must be used when interpolating', async (t) => { | ||
test('correctly log non circular objects', async ({ same }) => { | ||
const stream = sink() | ||
const root = pino(stream) | ||
const obj = {} | ||
let parent = obj | ||
for (let i = 0; i < 10; i++) { | ||
parent.node = {} | ||
parent = parent.node | ||
} | ||
root.info(obj) | ||
const { node } = await once(stream, 'data') | ||
same(node, { node: { node: { node: { node: { node: { node: { node: { node: { node: {} } } } } } } } } }) | ||
}) | ||
test('safe-stable-stringify must be used when interpolating', async (t) => { | ||
const stream = sink() | ||
const instance = pino(stream) | ||
@@ -618,3 +632,3 @@ | ||
const { msg } = await once(stream, 'data') | ||
t.equal(msg, 'test {"a":{"b":{"c":"[Circular ~.a.b]"}}}') | ||
t.equal(msg, 'test {"a":{"b":{"c":"[Circular]"}}}') | ||
}) | ||
@@ -704,1 +718,19 @@ | ||
}) | ||
test('nestedKey should not be used for non-objects', async ({ strictSame }) => { | ||
const stream = sink() | ||
const message = 'hello' | ||
const nestedKey = 'stuff' | ||
const instance = pino({ | ||
nestedKey | ||
}, stream) | ||
instance.info(message) | ||
const result = await once(stream, 'data') | ||
delete result.time | ||
strictSame(result, { | ||
pid, | ||
hostname, | ||
level: 30, | ||
msg: message | ||
}) | ||
}) |
@@ -11,2 +11,25 @@ 'use strict' | ||
test('should show warning for pino.final on node 14+', ({ equal, end, plan }) => { | ||
const major = Number(process.versions.node.split('.')[0]) | ||
if (major < 14) return end() | ||
plan(1) | ||
const dest = pino.destination({ dest: getPathToNull(), sync: false }) | ||
dest.flushSync = () => {} | ||
const instance = pino(dest) | ||
pino.final(instance, (_, finalLogger) => { | ||
finalLogger.info('hello') | ||
})() | ||
function onWarning (warning) { | ||
equal(warning.code, 'PINODEP009') | ||
end() | ||
} | ||
process.once('warning', onWarning) | ||
instance.info('hello') | ||
}) | ||
test('replaces onTerminated option', async ({ throws }) => { | ||
@@ -13,0 +36,0 @@ throws(() => { |
@@ -226,4 +226,7 @@ 'use strict' | ||
teardown(transport.end.bind(transport)) | ||
await once(transport, 'ready') | ||
const instance = pino(transport) | ||
instance.info('hello') | ||
await watchFileCreated(destination) | ||
@@ -230,0 +233,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
446831
10745
+ Addedsafe-stable-stringify@^2.1.0
+ Addedsafe-stable-stringify@2.5.0(transitive)
+ Addedthread-stream@0.12.1(transitive)
- Removedjson-stringify-safe@^5.0.1
- Removedjson-stringify-safe@5.0.1(transitive)
- Removedthread-stream@0.11.2(transitive)
Updatedthread-stream@^0.12.0