Repository: pinojs/pino-pretty (javascript)

Issue:
add jq-like functionality to only print some of the rows on a criteria



Discussion:
Why not just provide an example for using `jq`?
That is also possible.

We can easily add something like https://github.com/trentm/node-bunyan/blob/master/bin/bunyan#L230-L238.
https://www.npmjs.com/package/jmespath may be helpful in this endeavor.
I think we should use this, it seems very nice and it’s already implemented.
Looks like a good basis for a general search function .. do we maybe want
to put that into a seperate module that's pino specific

Then other prettifiers could use and have
the same interface (and also anything else
that involves querying logs)

On Sat, 7 Apr 2018 at 22:56, Matteo Collina <notifications@github.com>
wrote:

> I think we should use this, it seems very nice and it’s already
> implemented.
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/pinojs/pino-pretty/issues/6#issuecomment-379498666>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/ABIrPMHaTpU3wshY5LXoSyRNtbdNH3VZks5tmSgEgaJpZM4TI1NQ>
> .
>

It's up to you guys. I have no interest in implementing this feature. The utilities on my systems are enough for me. 

Patch:
diff --git a/Readme.md b/Readme.md
--- a/Readme.md
+++ b/Readme.md
@@ -57,6 +57,8 @@ Default: `msg`.
 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.
++ `--search` (`-s`): Specifiy a search pattern according to
+  [jmespath](http://jmespath.org/).
 
 <a id="api"></a>
 ## API
@@ -76,6 +78,7 @@ in [CLI Arguments](#cliargs):
   localTime: false, // --localTime
   messageKey: 'msg', // --messageKey
   translateTime: false // --translateTime
+  search: 'foo == `bar`' // --search
 }
 ```
 
diff --git a/bin.js b/bin.js
--- a/bin.js
+++ b/bin.js
@@ -18,12 +18,14 @@ args
   .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(['s', 'search'], 'specifiy a search pattern according to jmespath')
 
 args
   .example('cat log | pino-pretty', 'To prettify logs, simply pipe a log file through')
   .example('cat log | pino-pretty -m fooMessage', 'To highlight a string at a key other than \'msg\', use')
   .example('cat log | pino-pretty -t', 'To convert Epoch timestamps to ISO timestamps use the -t option')
   .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\'')
 
 const opts = args.parse(process.argv)
 const pretty = prettyFactory(opts)
diff --git a/index.js b/index.js
--- a/index.js
+++ b/index.js
@@ -2,7 +2,9 @@
 
 const chalk = require('chalk')
 const dateformat = require('dateformat')
+// remove jsonParser once Node 6 is not supported anymore
 const jsonParser = require('fast-json-parse')
+const jmespath = require('jmespath')
 
 const CONSTANTS = require('./lib/constants')
 
@@ -84,6 +86,8 @@ module.exports = function prettyFactory (options) {
 
   pretty.asMetaWrapper = asMetaWrapper
 
+  const search = opts.search
+
   return pretty
 
   function pretty (inputData) {
@@ -99,6 +103,10 @@ module.exports = function prettyFactory (options) {
       log = inputData
     }
 
+    if (search && !jmespath.search(log, search)) {
+      return
+    }
+
     const standardKeys = [
       'pid',
       'hostname',
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
     "chalk": "^2.3.2",
     "dateformat": "^3.0.3",
     "fast-json-parse": "^1.0.3",
+    "jmespath": "^0.15.0",
     "pump": "^3.0.0",
     "split2": "^2.2.0",
     "through2": "^2.0.3"


Test patch:
diff --git a/test/basic.test.js b/test/basic.test.js
--- a/test/basic.test.js
+++ b/test/basic.test.js
@@ -375,5 +375,29 @@ test('basic prettifier tests', (t) => {
     log.info('foo')
   })
 
+  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.end()
 })
diff --git a/test/cli.test.js b/test/cli.test.js
--- a/test/cli.test.js
+++ b/test/cli.test.js
@@ -42,5 +42,16 @@ test('cli', (t) => {
     t.tearDown(() => child.kill())
   })
 
+  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()
 })