pino-pretty
Advanced tools
Comparing version 1.0.1 to 2.0.0-rc.1
11
bin.js
@@ -14,3 +14,2 @@ #!/usr/bin/env node | ||
.option(['f', 'crlf'], 'Append CRLF instead of LF to formatted lines') | ||
.option(['d', 'dateFormat'], 'A format string to govern display of dates. When not set to the default value, `--translateTime` is implied', CONSTANTS.DATE_FORMAT) | ||
.option(['e', 'errorProps'], 'Comma separated list of properties on error objects to show (`*` for all properties)', '') | ||
@@ -20,4 +19,4 @@ .option(['l', 'levelFirst'], 'Display the log level as the first output field') | ||
.option(['m', 'messageKey'], 'Highlight the message under the specified key', CONSTANTS.MESSAGE_KEY) | ||
.option(['n', 'localTime'], 'Display timestamps according to system timezone') | ||
.option(['t', 'translateTime'], 'Convert Epoch timestamps to ISO format') | ||
.option(['t', 'translateTime'], 'Display epoch timestamps as UTC ISO format or according to an optional format string (default ISO 8601)') | ||
.option(['s', 'search'], 'specifiy a search pattern according to jmespath') | ||
@@ -28,3 +27,5 @@ args | ||
.example('cat log | pino-pretty -t', 'To convert Epoch timestamps to ISO timestamps use the -t option') | ||
.example('cat log | pino-pretty -t "SYS:yyyy-mm-dd HH:MM:ss"', 'To convert Epoch timestamps to local timezone format use the -t option with "SYS:" prefixed format string') | ||
.example('cat log | pino-pretty -l', 'To flip level and time/date in standard output use the -l option') | ||
.example('cat log | pino-pretty -s "msg == \'hello world\'"', 'Only prints messages with msg equals to \'hello world\'') | ||
@@ -34,3 +35,5 @@ const opts = args.parse(process.argv) | ||
const prettyTransport = through.obj(function (chunk, enc, cb) { | ||
process.stdout.write(pretty(chunk.toString())) | ||
const line = pretty(chunk.toString()) | ||
if (line === undefined) return cb() | ||
process.stdout.write(line) | ||
cb() | ||
@@ -37,0 +40,0 @@ }) |
67
index.js
@@ -5,3 +5,5 @@ 'use strict' | ||
const dateformat = require('dateformat') | ||
// remove jsonParser once Node 6 is not supported anymore | ||
const jsonParser = require('fast-json-parse') | ||
const jmespath = require('jmespath') | ||
@@ -23,7 +25,5 @@ const CONSTANTS = require('./lib/constants') | ||
crlf: false, | ||
dateFormat: CONSTANTS.DATE_FORMAT, | ||
errorLikeObjectKeys: ['err', 'error'], | ||
errorProps: '', | ||
levelFirst: false, | ||
localTime: false, | ||
messageKey: CONSTANTS.MESSAGE_KEY, | ||
@@ -43,6 +43,14 @@ translateTime: false, | ||
function formatTime (epoch, formatString, localTime) { | ||
function formatTime (epoch, translateTime) { | ||
const instant = new Date(epoch) | ||
if (localTime) return dateformat(instant, formatString) | ||
return dateformat(instant, 'UTC:' + formatString) | ||
if (translateTime === true) { | ||
return dateformat(instant, 'UTC:' + CONSTANTS.DATE_FORMAT) | ||
} else { | ||
const upperFormat = translateTime.toUpperCase() | ||
return (!upperFormat.startsWith('SYS:')) | ||
? dateformat(instant, 'UTC:' + translateTime) | ||
: (upperFormat === 'SYS:STANDARD') | ||
? dateformat(instant, CONSTANTS.DATE_FORMAT) | ||
: dateformat(instant, translateTime.slice(4)) | ||
} | ||
} | ||
@@ -62,6 +70,2 @@ | ||
if (opts.dateFormat.length > 0 && opts.dateFormat !== CONSTANTS.DATE_FORMAT) { | ||
opts.translateTime = true | ||
} | ||
const color = { | ||
@@ -89,3 +93,3 @@ default: nocolor, | ||
pretty.asMetaWrapper = asMetaWrapper | ||
const search = opts.search | ||
@@ -107,2 +111,6 @@ return pretty | ||
if (search && !jmespath.search(log, search)) { | ||
return | ||
} | ||
const standardKeys = [ | ||
@@ -118,3 +126,3 @@ 'pid', | ||
if (opts.translateTime) { | ||
log.time = formatTime(log.time, opts.dateFormat, opts.localTime) | ||
log.time = formatTime(log.time, opts.translateTime) | ||
} | ||
@@ -254,38 +262,1 @@ | ||
} | ||
function asMetaWrapper (dest) { | ||
const parsed = Symbol('parsedChindings') | ||
if (!dest) { | ||
dest = process.stdout | ||
} else if (!dest.write) { | ||
throw new Error('the destination must be writable') | ||
} | ||
const pretty = this | ||
return { | ||
[Symbol.for('needsMetadata')]: true, | ||
lastLevel: 0, | ||
lastMsg: null, | ||
lastObj: null, | ||
lastLogger: null, | ||
write (chunk) { | ||
var chindings = this.lastLogger[parsed] | ||
if (!chindings) { | ||
chindings = JSON.parse('{"v":1' + this.lastLogger.chindings + '}') | ||
this.lastLogger[parsed] = chindings | ||
} | ||
const obj = Object.assign({ | ||
level: this.lastLevel, | ||
msg: this.lastMsg, | ||
time: this.lastTime | ||
}, chindings, this.lastObj) | ||
const formatted = pretty(obj) | ||
dest.write(formatted) | ||
} | ||
} | ||
} |
{ | ||
"name": "pino-pretty", | ||
"version": "1.0.1", | ||
"version": "2.0.0-rc.1", | ||
"description": "Prettifier for Pino log lines", | ||
@@ -33,6 +33,7 @@ "main": "index.js", | ||
"dependencies": { | ||
"args": "^3.0.8", | ||
"args": "^4.0.0", | ||
"chalk": "^2.3.2", | ||
"dateformat": "^3.0.3", | ||
"fast-json-parse": "^1.0.3", | ||
"jmespath": "^0.15.0", | ||
"pump": "^3.0.0", | ||
@@ -43,3 +44,3 @@ "split2": "^2.2.0", | ||
"devDependencies": { | ||
"pino": "^4.16.0", | ||
"pino": "^5.0.0-rc.2", | ||
"pre-commit": "^1.2.2", | ||
@@ -46,0 +47,0 @@ "snazzy": "^7.1.1", |
@@ -43,8 +43,2 @@ <a id="intro"></a> | ||
feed, to the formatted log line. | ||
+ `--dateFormat` (`-d`): Sets the format string to apply when translating the date | ||
to human readable format (see: `--translateTime`). The default format string | ||
is `'yyyy-mm-dd HH:MM:ss.l o'`. For a list of available patter letters | ||
see the [`dateformat` documentation](https://www.npmjs.com/package/dateformat). | ||
When the value is anything other than the default value, `--translateTime` is | ||
implied. | ||
+ `--errorProps` (`-e`): When formatting an error object, display this list | ||
@@ -57,6 +51,9 @@ of properties. The list should be a comma separated list of properties Default: `''`. | ||
Default: `msg`. | ||
+ `--localTime` (`-n`): When translating the time to a human readable format, | ||
use the system timezone for displaying the time. | ||
+ `--translateTime` (`-t`): Translate the epoch time value into a human readable | ||
date and time string. See `--dateFormat` for information on the output format. | ||
date and time string in `UTC`. The default pattern is `'yyyy-mm-dd HH:MM:ss.l o'`. | ||
If you want to translate to the local system's timezone, then you must prefix the format | ||
string with `SYS:`, e.g. `'SYS:yyyy-mm-dd HH:MM:ss'`. See [`dateformat` documentation](https://www.npmjs.com/package/dateformat#mask-options) | ||
for more available pattern letters. | ||
+ `--search` (`-s`): Specifiy a search pattern according to | ||
[jmespath](http://jmespath.org/). | ||
@@ -74,39 +71,16 @@ <a id="api"></a> | ||
crlf: false, // --crlf | ||
dateFormat: 'yyyy-mm-dd HH:MM:ss.l o', // --dateFormat | ||
errorLikeObjectKeys: ['err', 'error'], // --errorLikeObjectKeys | ||
errorProps: '', // --errorProps | ||
levelFirst: false, // --levelFirst | ||
localTime: false, // --localTime | ||
messageKey: 'msg', // --messageKey | ||
translateTime: false // --translateTime | ||
translateTime: false, // --translateTime | ||
search: 'foo == `bar`' // --search | ||
} | ||
``` | ||
See the [next subsection](#usemetadata) for information on how to use this | ||
directly with `pino`. | ||
See the [Pino's prettifier documentation](#usemetadata) for information on how | ||
to use this directly with `pino`. | ||
<a id="usemetadata"></a> | ||
### pretty.asMetaWrapper(writable) | ||
[#usemetadata]: https://getpino.io/#/docs/pretty | ||
```js | ||
const factory = require('pino-pretty') | ||
const pino = require('pino') | ||
// writable is any Writable stream | ||
const writable = process.stdout | ||
const dest = factory({ colorize: true }).asMetaWrapper(writable) | ||
const logger = pino({}, dest) | ||
``` | ||
The function returned by the factory has a `.asMetaWrapper(dest)` function attached | ||
which will return an object that can be supplied directly to Pino as a stream | ||
that is compatible with Pino's [metadata stream API][mdstream]. | ||
This allows `pino-pretty` to skip the expensive task of parsing JSON log lines | ||
and instead work directly with Pino's log object. | ||
The default stream is `process.stdout`. | ||
[mdstream]: https://github.com/pinojs/pino/blob/fc4c83b/docs/API.md#metadata | ||
<a id="license"><a> | ||
@@ -113,0 +87,0 @@ ## License |
@@ -100,3 +100,3 @@ 'use strict' | ||
t.test('will format date to UTC', (t) => { | ||
t.test('will format time to UTC', (t) => { | ||
t.plan(1) | ||
@@ -117,11 +117,26 @@ const pretty = prettyFactory({translateTime: true}) | ||
t.test('will format date to local time', (t) => { | ||
t.test('will format time to UTC in custom format', (t) => { | ||
t.plan(1) | ||
const pretty = prettyFactory({ | ||
translateTime: true, | ||
localTime: true | ||
}) | ||
const pretty = prettyFactory({ translateTime: 'HH:MM:ss o' }) | ||
const log = pino({}, new Writable({ | ||
write (chunk, enc, cb) { | ||
const formatted = pretty(chunk.toString()) | ||
const utcHour = dateformat(epoch, 'UTC:' + 'HH') | ||
const offset = dateformat(epoch, 'UTC:' + 'o') | ||
t.is( | ||
formatted, | ||
`[${utcHour}:35:28 ${offset}] INFO (${pid} on ${hostname}): foo\n` | ||
) | ||
cb() | ||
} | ||
})) | ||
log.info('foo') | ||
}) | ||
t.test('will format time to local systemzone in ISO 8601 format', (t) => { | ||
t.plan(1) | ||
const pretty = prettyFactory({ translateTime: 'sys:standard' }) | ||
const log = pino({}, new Writable({ | ||
write (chunk, enc, cb) { | ||
const formatted = pretty(chunk.toString()) | ||
const localHour = dateformat(epoch, 'HH') | ||
@@ -140,11 +155,16 @@ const localDate = dateformat(epoch, 'yyyy-mm-dd') | ||
t.test('will format date with a custom format string', (t) => { | ||
t.test('will format time to local systemzone in custom format', (t) => { | ||
t.plan(1) | ||
const pretty = prettyFactory({dateFormat: 'yyyy-mm-dd HH:MM'}) | ||
const pretty = prettyFactory({ | ||
translateTime: 'SYS:yyyy/mm/dd HH:MM:ss o' | ||
}) | ||
const log = pino({}, new Writable({ | ||
write (chunk, enc, cb) { | ||
const formatted = pretty(chunk.toString()) | ||
const localHour = dateformat(epoch, 'HH') | ||
const localDate = dateformat(epoch, 'yyyy/mm/dd') | ||
const offset = dateformat(epoch, 'o') | ||
t.is( | ||
formatted, | ||
`[2018-03-30 17:35] INFO (${pid} on ${hostname}): foo\n` | ||
`[${localDate} ${localHour}:35:28 ${offset}] INFO (${pid} on ${hostname}): foo\n` | ||
) | ||
@@ -357,4 +377,6 @@ cb() | ||
}) | ||
const prettyStream = prettyFactory().asMetaWrapper(dest) | ||
const log = pino({}, prettyStream) | ||
const log = pino({ | ||
prettifier: prettyFactory, | ||
prettyPrint: true | ||
}, dest) | ||
log.info('foo') | ||
@@ -376,9 +398,45 @@ }) | ||
}) | ||
const log = pino({ | ||
prettifier: prettyFactory, | ||
prettyPrint: { | ||
levelFirst: true | ||
} | ||
}, dest) | ||
log.info('foo') | ||
}) | ||
const prettyStream = prettyFactory({ levelFirst: true }).asMetaWrapper(dest) | ||
const log = pino({}, prettyStream) | ||
t.test('filter some lines based on jmespath', (t) => { | ||
t.plan(3) | ||
const pretty = prettyFactory({ search: 'foo.bar' }) | ||
const expected = [ | ||
undefined, | ||
undefined, | ||
`[${epoch}] INFO (${pid} on ${hostname}): foo\n foo: {\n "bar": true\n }\n` | ||
] | ||
const log = pino({}, new Writable({ | ||
write (chunk, enc, cb) { | ||
const formatted = pretty(chunk.toString()) | ||
t.is( | ||
formatted, | ||
expected.shift() | ||
) | ||
cb() | ||
} | ||
})) | ||
log.info('foo') | ||
log.info({ something: 'else' }, 'foo') | ||
// only this line will be formatted | ||
log.info({ foo: { bar: true } }, 'foo') | ||
}) | ||
t.test('handles `undefined` return values', (t) => { | ||
t.plan(2) | ||
const pretty = prettyFactory({search: 'msg == \'hello world\''}) | ||
let formatted = pretty(`{"msg":"nope", "time":${epoch}, "level":30, "v":1}`) | ||
t.is(formatted, undefined) | ||
formatted = pretty(`{"msg":"hello world", "time":${epoch}, "level":30, "v":1}`) | ||
t.is(formatted, `[${epoch}] INFO: hello world\n`) | ||
}) | ||
t.end() | ||
}) |
@@ -45,3 +45,14 @@ 'use strict' | ||
t.test('does search', (t) => { | ||
t.plan(1) | ||
const child = spawn(process.argv0, [bin, '-s', 'msg == `hello world`']) | ||
child.on('error', t.threw) | ||
child.stdout.on('data', (data) => { | ||
t.is(data.toString(), `[${epoch}] INFO (42 on foo): hello world\n`) | ||
}) | ||
child.stdin.write(logLine) | ||
t.tearDown(() => child.kill()) | ||
}) | ||
t.end() | ||
}) |
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
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
214635
905
8
1
87
+ Addedjmespath@^0.15.0
+ Addedargs@4.0.0(transitive)
+ Addedcamelcase@5.0.0(transitive)
+ Addedchalk@2.3.2(transitive)
+ Addedjmespath@0.15.0(transitive)
+ Addedleven@2.1.0(transitive)
- Removedargs@3.0.8(transitive)
- Removedcamelcase@4.1.0(transitive)
- Removedchalk@2.1.0(transitive)
- Removedhas-flag@2.0.0(transitive)
- Removedlodash@4.17.21(transitive)
- Removedpkginfo@0.4.1(transitive)
- Removedstring-similarity@1.2.0(transitive)
- Removedsupports-color@4.5.0(transitive)
Updatedargs@^4.0.0