Repository: pinojs/pino-http
Pull request #153 (2021-08-20 02:37:33)

add autologging ignore option
solves #107 via a generic `autologging.ignore` function 

I get errors locally when trying to test: `Unexpected var, use let or const instead.`, linting fixes it (`npm run fix`) but have reverted the linting as requested

naseemkullah: > Can you please restore all the spurious changes? There is a lot of var -> const/let migration here.

linting reverted, but tests fail locally (and in CI)
mcollina: CI is failing because:

```
  /home/runner/work/pino-http/pino-http/logger.js:122:11: 'autoLoggingIgnore' is not defined.
61
  /home/runner/work/pino-http/pino-http/logger.js:123:27: 'autoLoggingIgnore' is not defined.
62
  /home/runner/work/pino-http/pino-http/logger.js:123:57: 'autoLoggingIgnore' is not defined.
```
naseemkullah: > CI is failing because:
> 
> ```
>   /home/runner/work/pino-http/pino-http/logger.js:122:11: 'autoLoggingIgnore' is not defined.
> 61
>   /home/runner/work/pino-http/pino-http/logger.js:123:27: 'autoLoggingIgnore' is not defined.
> 62
>   /home/runner/work/pino-http/pino-http/logger.js:123:57: 'autoLoggingIgnore' is not defined.
> ```

Oops thanks, removed it when i reverted the linting, added back.

> CI is failing because:
> 
> ```
>   /home/runner/work/pino-http/pino-http/logger.js:122:11: 'autoLoggingIgnore' is not defined.
> 61
>   /home/runner/work/pino-http/pino-http/logger.js:123:27: 'autoLoggingIgnore' is not defined.
> 62
>   /home/runner/work/pino-http/pino-http/logger.js:123:57: 'autoLoggingIgnore' is not defined.
> ```

Oops, thanks. Fixing now.

Patch:
diff --git a/README.md b/README.md
index a875bb7..2ca1aad 100644
--- a/README.md
+++ b/README.md
@@ -98,6 +98,7 @@ $ node example.js | pino-pretty
 * `useLevel`: the logger level `pino-http` is using to log out the response. default: `info`
 * `customLogLevel`: set to a `function (res, err) => { /* returns level name string */ }`. This function will be invoked to determine the level at which the log should be issued. This option is mutually exclusive with the `useLevel` option. The first argument is the HTTP response. The second argument is an error object if an error has occurred in the request.
 * `autoLogging`: set to `false`, to disable the automatic "request completed" and "request errored" logging. Defaults to `true`. If set to an object, you can provide more options.
+* `autoLogging.ignore`: set to a `function (req) => { /* returns boolean */ }`. Useful for defining logic based on req properties (such as a user-agent header) to ignore successful requests.
 * `autoLogging.ignorePaths`: array that holds one or many paths that should not autolog on completion. Paths will be matched exactly to the url path `req.url` (using Node class `URL.pathname`). This is useful for ignoring e.g. health check paths that get called every X seconds, and would fill out the logs unnecessarily. If the path matches and succeeds (http 200), it will not log any text. If it fails, it will log the error (as with any other path).
 * `autoLogging.getPath`: set to a `function (req) => { /* returns path string */ }`. This function will be invoked to return the current path as a string. This is useful for checking `autoLogging.ignorePaths` against a path other than the default `req.url`. e.g. An express server where `req.originalUrl` is preferred.
 * `stream`: same as the second parameter
@@ -192,7 +193,7 @@ server.listen(3000)
 
 The `pinoHttp` instance has a property `logger`, which references to an actual logger instance, used
 by pinoHttp. This instance will be a child of an instance, passed as `opts.logger`, or a fresh one,
-if no `opts.logger` is passed. It can be used, for example, for doing most of the things, possible 
+if no `opts.logger` is passed. It can be used, for example, for doing most of the things, possible
 to do with any `pino` instance, for example changing logging level in runtime, like so:
 
 ```js
diff --git a/logger.js b/logger.js
index b347984..8b3723b 100644
--- a/logger.js
+++ b/logger.js
@@ -47,6 +47,7 @@ function pinoLogger (opts, stream) {
   delete opts.stream
 
   var autoLogging = (opts.autoLogging !== false)
+  var autoLoggingIgnore = opts.autoLogging && opts.autoLogging.ignore ? opts.autoLogging.ignore : null
   var autoLoggingIgnorePaths = (opts.autoLogging && opts.autoLogging.ignorePaths) ? opts.autoLogging.ignorePaths : []
   var autoLoggingGetPath = opts.autoLogging && opts.autoLogging.getPath ? opts.autoLogging.getPath : null
   delete opts.autoLogging
@@ -108,13 +109,20 @@ function pinoLogger (opts, stream) {
           url = URL.parse(req.url)
         }
 
-        shouldLogSuccess = !autoLoggingIgnorePaths.find(ignorePath => {
+        const isPathIgnored = autoLoggingIgnorePaths.find(ignorePath => {
           if (ignorePath instanceof RegExp) {
             return ignorePath.test(url.pathname)
           }
 
           return ignorePath === url.pathname
         })
+
+        shouldLogSuccess = !isPathIgnored
+      }
+
+      if (autoLoggingIgnore !== null && shouldLogSuccess === true) {
+        const isIgnored = autoLoggingIgnore !== null && autoLoggingIgnore(req)
+        shouldLogSuccess = !isIgnored
       }
 
       if (shouldLogSuccess) {


Test patch:
diff --git a/test.js b/test.js
index 9f48dba..9c2e627 100644
--- a/test.js
+++ b/test.js
@@ -401,6 +401,34 @@ test('no auto logging with autoLogging set to use regular expressions. result is
   })
 })
 
+test('no auto logging with autoLogging set to true and ignoring a specific user-agent', function (t) {
+  const dest = split(JSON.parse)
+  const logger = pinoHttp({
+    autoLogging: {
+      ignore: function (req) {
+        return req.headers['user-agent'] === 'ELB-HealthChecker/2.0'
+      }
+    }
+  }, dest)
+
+  setup(t, logger, function (err, server) {
+    t.error(err)
+
+    const { address, port } = server.address()
+    http.get({
+      protocol: 'http:',
+      hostname: address,
+      port,
+      path: '/',
+      headers: { 'User-Agent': 'ELB-HealthChecker/2.0' }
+    }, function () {
+      const line = dest.read()
+      t.equal(line, null)
+      t.end()
+    })
+  })
+})
+
 test('support a custom instance', function (t) {
   var dest = split(JSON.parse)
   var logger = pinoHttp({