Repository: pinojs/hapi-pino
Pull request #87 (2019-10-04 18:06:45)

feat: add options.getChildBindings()
Related suggestion issue: https://github.com/pinojs/hapi-pino/issues/86

This PR adds an optional `options.getChildBindings(request) => Pino.Bindings` function to the hapi-pino options object.

This allows you to customize the bindings being passed into `logger.child()`, which was previously hardcoded to always be `{ req: request }`

If omitted, it keeps the old behavior of `{ req: request }`

```javascript
    const plugin = {
      plugin: Pino,
      options: {
        stream: stream,
        level: 'info',
        getChildBindings: (req) => ({ custom: true })
      }
    }

    await server.register(plugin)
```


coveralls: 
[![Coverage Status](https://coveralls.io/builds/26120630/badge)](https://coveralls.io/builds/26120630)

Coverage decreased (-0.02%) to 98.86% when pulling **b356e284722e2fa52e931a39bec383e14a674c09 on devshackio:feat-getChildBindings** into **45ecfec80cccdb273ce77a74ee2539ae730fd1d8 on pinojs:master**.


Patch:
diff --git a/README.md b/README.md
index 39eee20..88cc41a 100644
--- a/README.md
+++ b/README.md
@@ -135,6 +135,7 @@ events"](#hapievents) section.
   // with mergeHapiLogData: false (Default)
   { level: 30, data: { hello: 'world' }}
   ```
+- `[getChildBindings]` - Takes a function with the request as an input, and returns the object that will be passed into pinoLogger.child(). If omitted, then `{ req: request }` will be used for the child bindings, which automatically adds the request to every pino log call
 - `[ignorePaths]` - Takes an array of string routes and disables logging for each.  Useful for health checks or any route that does not need logging. E.g `['/health']`
 - `[level]` - Set the minumum level that Pino should log out. See [Level](https://github.com/pinojs/pino/blob/master/docs/api.md#level). For example, `{level: 'debug'}` would configure Pino to output all `debug` or higher events.
 - `[redact]` - Path to be redacted in the log lines. See the [log redaction](https://getpino.io/#/docs/redaction) docs for more details.
diff --git a/index.js b/index.js
index 4b22a34..407a078 100644
--- a/index.js
+++ b/index.js
@@ -67,6 +67,7 @@ async function register (server, options) {
   }
 
   const mergeHapiLogData = options.mergeHapiLogData
+  const getChildBindings = options.getChildBindings ? options.getChildBindings : (request) => ({ req: request })
 
   // expose logger as 'server.logger()'
   server.decorate('server', 'logger', () => logger)
@@ -77,7 +78,10 @@ async function register (server, options) {
       request.logger = nullLogger
       return h.continue
     }
-    request.logger = logger.child({ req: request })
+
+    const childBindings = getChildBindings(request)
+    request.logger = logger.child(childBindings)
+
     return h.continue
   })
 
@@ -96,7 +100,8 @@ async function register (server, options) {
       return
     }
 
-    request.logger = request.logger || logger.child({ req: request })
+    const childBindings = getChildBindings(request)
+    request.logger = request.logger || logger.child(childBindings)
 
     if (event.error && isEnabledLogEvent(options, 'request-error')) {
       request.logger.error(


Test patch:
diff --git a/test.js b/test.js
index 95d30c9..131d085 100644
--- a/test.js
+++ b/test.js
@@ -776,6 +776,59 @@ experiment('uses a prior pino instance', () => {
   })
 })
 
+experiment('request.logger.child() bindings', () => {
+  test('request.logger.child() bindings are { req: request } by default', async () => {
+    const server = getServer()
+    let done
+    const finish = new Promise(function (resolve, reject) {
+      done = resolve
+    })
+
+    const stream = sink(data => {
+      expect(data.req).to.not.be.undefined()
+      expect(data.req.id).to.not.be.undefined()
+      expect(data.custom).to.be.undefined()
+      done()
+    })
+    const plugin = {
+      plugin: Pino,
+      options: {
+        stream: stream,
+        level: 'info'
+      }
+    }
+
+    await server.register(plugin)
+    await server.inject('/something')
+    await finish
+  })
+
+  test('request.logger.child() bindings can be provided via getChildBindings(request)', async () => {
+    const server = getServer()
+    let done
+    const finish = new Promise(function (resolve, reject) {
+      done = resolve
+    })
+    const stream = sink(data => {
+      expect(data.req).to.be.undefined()
+      expect(data.custom).to.not.be.undefined()
+      done()
+    })
+    const plugin = {
+      plugin: Pino,
+      options: {
+        stream: stream,
+        level: 'info',
+        getChildBindings: (req) => ({ custom: true })
+      }
+    }
+
+    await server.register(plugin)
+    await server.inject('/something')
+    await finish
+  })
+})
+
 experiment('logging with mergeHapiLogData option enabled', () => {
   test("log event data is merged into pino's log object", async () => {
     const server = getServer()