Skip to content

Commit

Permalink
Add support for minimumLevel (#233)
Browse files Browse the repository at this point in the history
* Add support for minimumLevel

* Update Readme.md

Co-authored-by: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
bitjson and mcollina committed Sep 21, 2021
1 parent 7e802b4 commit a1526b0
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
1 change: 1 addition & 0 deletions Readme.md
Expand Up @@ -69,6 +69,7 @@ node app.js | pino-pretty
Default: `level`.
- `--levelLabel` (`-b`): Output the log level using the specified label.
Default: `levelLabel`.
- `--minimumLevel` (`-L`): Hide messages below the specified log level. Accepts a number, `trace`, `debug`, `info`, `warn`, `error`, or `fatal`. If any more filtering is required, consider using [`jq`](https://stedolan.github.io/jq/).
- `--messageFormat` (`-o`): Format output of message, e.g. `{levelLabel} - {pid} - url:{request.url}` will output message: `INFO - 1123 - url:localhost:3000/test`
Default: `false`
- `--timestampKey` (`-a`): Define the key that contains the log timestamp.
Expand Down
6 changes: 4 additions & 2 deletions bin.js
Expand Up @@ -35,14 +35,14 @@ args
.option(['f', 'crlf'], 'Append CRLF instead of LF to formatted lines')
.option(['e', 'errorProps'], 'Comma separated list of properties on error objects to show (`*` for all properties) (defaults to ``)')
.option(['l', 'levelFirst'], 'Display the log level as the first output field')
.option(['L', 'minimumLevel'], 'Hide messages below the specified log level')
.option(['k', 'errorLikeObjectKeys'], 'Define which keys contain error objects (`-k err,error`) (defaults to `err,error`)')
.option(['m', 'messageKey'], 'Highlight the message under the specified key', CONSTANTS.MESSAGE_KEY)
.option('levelKey', 'Detect the log level under the specified key', CONSTANTS.LEVEL_KEY)
.option(['b', 'levelLabel'], 'Output the log level using the specified label', CONSTANTS.LEVEL_LABEL)
.option(['o', 'messageFormat'], 'Format output of message')
.option(['a', 'timestampKey'], 'Display the timestamp from the specified key', CONSTANTS.TIMESTAMP_KEY)
.option(['t', 'translateTime'], 'Display epoch timestamps as UTC ISO format or according to an optional format string (default ISO 8601)')
.option(['s', 'search'], 'Specify a search pattern according to jmespath')
.option(['i', 'ignore'], 'Ignore one or several keys: (`-i time,hostname`)')
.option(['H', 'hideObject'], 'Hide objects from output (but not error object)')
.option(['S', 'singleLine'], 'Print all non-error objects on a single line')
Expand All @@ -57,7 +57,7 @@ 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\'')
.example('cat log | pino-pretty -L info', 'Only prints messages with a minimum log level of info')
.example('cat log | pino-pretty -i pid,hostname', 'Prettify logs but don\'t print pid and hostname')
.example('cat log | pino-pretty --config=/path/to/config.json', 'Loads options from a config file')

Expand All @@ -67,13 +67,15 @@ let opts = args.parse(process.argv, {
mri: {
default: {
messageKey: DEFAULT_VALUE,
minimumLevel: DEFAULT_VALUE,
levelKey: DEFAULT_VALUE,
timestampKey: DEFAULT_VALUE
},
// NOTE: The following key-value pairs values should be in sync with the
// short version values defined in each `args.option([value, key], ...)`
alias: {
messageKey: 'm',
minimumLevel: 'L',
timestampKey: 'a'
}
}
Expand Down
9 changes: 8 additions & 1 deletion index.js
Expand Up @@ -8,7 +8,7 @@ const sonic = require('sonic-boom')
const sjs = require('secure-json-parse')

const colors = require('./lib/colors')
const { ERROR_LIKE_KEYS, MESSAGE_KEY, TIMESTAMP_KEY } = require('./lib/constants')
const { ERROR_LIKE_KEYS, MESSAGE_KEY, TIMESTAMP_KEY, LEVEL_KEY, LEVEL_NAMES } = require('./lib/constants')
const {
isObject,
prettifyErrorLog,
Expand Down Expand Up @@ -52,6 +52,7 @@ function prettyFactory (options) {
const messageKey = opts.messageKey
const levelKey = opts.levelKey
const levelLabel = opts.levelLabel
const minimumLevel = opts.minimumLevel
const messageFormat = opts.messageFormat
const timestampKey = opts.timestampKey
const errorLikeObjectKeys = opts.errorLikeObjectKeys
Expand All @@ -77,6 +78,12 @@ function prettyFactory (options) {
log = inputData
}

if (minimumLevel) {
const minimum = LEVEL_NAMES[minimumLevel] || Number(minimumLevel)
const level = log[levelKey === undefined ? LEVEL_KEY : levelKey]
if (level < minimum) return
}

const prettifiedMessage = prettifyMessage({ log, messageKey, colorizer, messageFormat, levelLabel })

if (ignoreKeys) {
Expand Down
47 changes: 47 additions & 0 deletions test/basic.test.js
Expand Up @@ -443,6 +443,53 @@ test('basic prettifier tests', (t) => {
log.info('foo')
})

t.test('filter some lines based on minimumLevel', (t) => {
t.plan(3)
const pretty = prettyFactory({ minimumLevel: 'info' })
const expected = [
undefined,
undefined,
`[${epoch}] INFO (${pid} on ${hostname}): baz\n`
]
const log = pino({}, new Writable({
write (chunk, enc, cb) {
const formatted = pretty(chunk.toString())
t.equal(
formatted,
expected.shift()
)
cb()
}
}))
log.info({ msg: 'foo', level: 10 })
log.info({ msg: 'bar', level: 20 })
// only this line will be formatted
log.info({ msg: 'baz', level: 30 })
})

t.test('filter lines based on minimumLevel using custom levels and level key', (t) => {
t.plan(3)
const pretty = prettyFactory({ minimumLevel: 20, levelKey: 'bar' })
const expected = [
undefined,
`[${epoch}] DEBUG (${pid} on ${hostname}): bar\n`,
`[${epoch}] INFO (${pid} on ${hostname}): baz\n`
]
const log = pino({}, new Writable({
write (chunk, enc, cb) {
const formatted = pretty(chunk.toString())
t.equal(
formatted,
expected.shift()
)
cb()
}
}))
log.info({ msg: 'foo', bar: 10 })
log.info({ msg: 'bar', bar: 20 })
log.info({ msg: 'baz', bar: 30 })
})

t.test('formats a line with an undefined field', (t) => {
t.plan(1)
const pretty = prettyFactory()
Expand Down

0 comments on commit a1526b0

Please sign in to comment.