Skip to content

Commit

Permalink
Fix 'ignore' for keys containing key delimiter (#209)
Browse files Browse the repository at this point in the history
* Fix 'ignore' for keys containing key delimiter

* Split ignore keys in a loop for better performance

* Remove commented out code
  • Loading branch information
TzeWey committed Jul 19, 2021
1 parent b32ffb5 commit 289de2b
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 3 deletions.
4 changes: 3 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ node app.js | pino-pretty
system time zone.
- `--search` (`-s`): Specify a search pattern according to
[jmespath](http://jmespath.org/).
- `--ignore` (`-i`): Ignore one or several keys, nested keys are supported: (`-i time,hostname,req.headers`)
- `--ignore` (`-i`): Ignore one or several keys, nested keys are supported with each property delimited by a dot character (`.`),
keys may be escaped to target property names that contains the delimiter itself:
(`-i time,hostname,req.headers,log\\.domain\\.corp/foo`)
- `--hideObject` (`-H`): Hide objects from output (but not error object)
- `--singleLine` (`-S`): Print each log message on a single line (errors will still be multi-line)
- `--config`: Specify a path to a config file containing the pino-pretty options. pino-pretty will attempt to read from a `.pino-prettyrc` in your current directory (`process.cwd`) if not specified
Expand Down
52 changes: 50 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module.exports.internals = {
joinLinesWithIndentation,
prettifyError,
deleteLogProperty,
splitIgnoreKey,
createDate,
isValidDate
}
Expand Down Expand Up @@ -479,17 +480,64 @@ function prettifyError ({ keyName, lines, eol, ident }) {
return result
}

/**
* Splits the input key delimited by a dot character but not when it is preceded
* by a backslash.
*
* @param {string} key A string identifying the property.
*
* @returns {string[]} Returns a list of string containing each delimited property.
* e.g. `'prop2\.domain\.corp.prop2'` should return [ 'prop2.domain.com', 'prop2' ]
*/
function splitIgnoreKey (key) {
const result = []
let backslash = false
let segment = ''

for (let i = 0; i < key.length; i++) {
const c = key.charAt(i)

if (c === '\\') {
backslash = true
continue
}

if (backslash) {
backslash = false
segment += c
continue
}

/* Non-escaped dot, push to result */
if (c === '.') {
result.push(segment)
segment = ''
continue
}

segment += c
}

/* Push last entry to result */
if (segment.length) {
result.push(segment)
}

return result
}

/**
* Deletes a specified property from a log object if it exists.
* This function mutates the passed in `log` object.
*
* @param {object} log The log object to be modified.
* @param {string} property A string identifying the property to be deleted from
* the log object. Accepts nested properties delimited by a `.`
* e.g. `'prop1.prop2'`.
* Delimiter can be escaped to preserve property names that contain the delimiter.
* e.g. `'prop1.prop2'` or `'prop2\.domain\.corp.prop2'`
*/
function deleteLogProperty (log, property) {
const props = property.split('.')
const props = splitIgnoreKey(property)
const propToDelete = props.pop()

props.forEach((prop) => {
Expand Down
13 changes: 13 additions & 0 deletions test/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ test('cli', (t) => {
t.teardown(() => child.kill())
})

t.test('does ignore escaped keys', (t) => {
t.plan(1)
const env = { TERM: 'dumb' }
const child = spawn(process.argv[0], [bin, '-i', 'log\\.domain\\.corp/foo'], { env })
child.on('error', t.threw)
child.stdout.on('data', (data) => {
t.equal(data.toString(), '[1522431328992] INFO: hello world\n')
})
const logLine = '{"level":30,"time":1522431328992,"msg":"hello world","log.domain.corp/foo":"bar"}\n'
child.stdin.write(logLine)
t.teardown(() => child.kill())
})

t.test('passes through stringified date as string', (t) => {
t.plan(1)
const env = { TERM: 'dumb' }
Expand Down
29 changes: 29 additions & 0 deletions test/lib/utils.internals.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,32 @@ tap.test('#deleteLogProperty', t => {

t.end()
})

tap.test('#splitIgnoreKey', t => {
t.test('splitIgnoreKey does not change key', async t => {
const result = internals.splitIgnoreKey('data1')
t.same(result, ['data1'])
})

t.test('splitIgnoreKey splits nested key', async t => {
const result = internals.splitIgnoreKey('data1.data2.data-3')
t.same(result, ['data1', 'data2', 'data-3'])
})

t.test('splitIgnoreKey splits nested keys ending with a dot', async t => {
const result = internals.splitIgnoreKey('data1.data2.data-3.')
t.same(result, ['data1', 'data2', 'data-3'])
})

t.test('splitIgnoreKey splits nested escaped key', async t => {
const result = internals.splitIgnoreKey('logging\\.domain\\.corp/operation.foo.bar-2')
t.same(result, ['logging.domain.corp/operation', 'foo', 'bar-2'])
})

t.test('splitIgnoreKey splits nested escaped key with special characters', async t => {
const result = internals.splitIgnoreKey('logging\\.domain\\.corp/operation.!\t@#$%^&*()_+=-<>.bar\\.2')
t.same(result, ['logging.domain.corp/operation', '!\t@#$%^&*()_+=-<>', 'bar.2'])
})

t.end()
})
17 changes: 17 additions & 0 deletions test/lib/utils.public.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,23 @@ tap.test('#filterLog', t => {
t.same(result, { level: 30 })
})

const logData2 = Object.assign({
'logging.domain.corp/operation': {
id: 'foo',
producer: 'bar'
}
}, logData)

t.test('filterLog removes entry with escape sequence', async t => {
const result = filterLog(logData2, ['data1', 'logging\\.domain\\.corp/operation'])
t.same(result, { level: 30, time: 1522431328992 })
})

t.test('filterLog removes entry with escape sequence nested', async t => {
const result = filterLog(logData2, ['data1', 'logging\\.domain\\.corp/operation.producer'])
t.same(result, { level: 30, time: 1522431328992, 'logging.domain.corp/operation': { id: 'foo' } })
})

t.end()
})

Expand Down

0 comments on commit 289de2b

Please sign in to comment.