Repository: pinojs/hapi-pino
Pull request #184 (2023-06-19 10:32:29)

Allow specifying level for request start/complete logging
Fixes https://github.com/pinojs/hapi-pino/issues/183 .

I couldn't find a way to do this with any existing `options` so here's a PR that allows specifying the log level for request start, request complete and request error events.

It can be useful to log the request start/complete messages on a lower level, such as `debug`. For example, if there is too much traffic to log every single request, and you wish to log on `debug` level by default, and later in the pipeline decide to drop or keep those log entries.


Patch:
diff --git a/README.md b/README.md
index f56d47b..2465b29 100644
--- a/README.md
+++ b/README.md
@@ -149,7 +149,7 @@ events"](#hapievents) section.
 
 ### `options.customRequestCompleteMessage`
 
-  **Default**: '[response] ${request.method} ${request.path} ${request.raw.res.statusCode} (${responseTime}ms)'
+  **Default**: `` `[response] ${request.method} ${request.path} ${request.raw.res.statusCode} (${responseTime}ms)` ``
 
   Set to a `function (request, responseTime) => { /* returns message string */ }`. This function will be invoked at each completed request, setting "msg" property to returned string. If not set, default value will be used.
 
@@ -159,6 +159,24 @@ events"](#hapievents) section.
 
   Set to a `function (request, err) => { /* returns message string */ }`. This function will be invoked at each failed request, setting "msg" property to returned string. If not set, default value will be used.
 
+### `options.customRequestStartLevel:  pino.Level`
+
+  **Default**: 'info'
+
+  The log level to use for `request start` events.
+
+### `options.customRequestCompleteLevel:  pino.Level`
+
+**Default**: 'info'
+
+  The log level to use for `request complete` events.
+
+### `options.customRequestErrorLevel:  pino.Level`
+
+**Default**: 'error'
+
+  The logging level to use for `request-error` events.
+
 ### `options.stream` Pino.DestinationStream
 
   **Default**: `process.stdout`
diff --git a/index.d.ts b/index.d.ts
index 9a9fc03..2da02f2 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -27,6 +27,9 @@ declare namespace HapiPino {
     customRequestStartMessage?: ((req: Request) => string) | undefined;
     customRequestCompleteMessage?: ((req: Request, responseTime: number) => string) | undefined;
     customRequestErrorMessage?: ((req: Request, error: Error) => string) | undefined;
+    customRequestStartLevel?: pino.Level | undefined;
+    customRequestCompleteLevel?: pino.Level | undefined;
+    customRequestErrorLevel?: pino.Level | undefined;
     tags?: { [key in pino.Level]?: string } | undefined;
     stream?: NodeJS.WriteStream | undefined;
     allTags?: pino.Level | undefined;
diff --git a/index.js b/index.js
index f98f250..dd570d0 100644
--- a/index.js
+++ b/index.js
@@ -103,6 +103,10 @@ async function register (server, options) {
   const requestCompleteMessage = options.customRequestCompleteMessage || function (request, responseTime) { return `[response] ${request.method} ${request.path} ${request.raw.res.headersSent ? request.raw.res.statusCode : '-'} (${responseTime}ms)` }
   const requestErrorMessage = options.customRequestErrorMessage || function (request, error) { return error.message } // Will default to `Internal Server Error` by hapi
 
+  const requestStartLevel = options.customRequestStartLevel || 'info'
+  const requestCompleteLevel = options.customRequestCompleteLevel || 'info'
+  const requestErrorLevel = options.customRequestErrorLevel || 'error'
+
   // expose logger as 'server.logger'
   server.decorate('server', 'logger', logger)
 
@@ -117,7 +121,7 @@ async function register (server, options) {
     request.logger = logger.child(childBindings)
 
     if (shouldLogRequestStart(request)) {
-      request.logger.info({
+      request.logger[requestStartLevel]({
         req: childBindings.req ? undefined : request
       }, requestStartMessage(request))
     }
@@ -151,7 +155,7 @@ async function register (server, options) {
     }
 
     if (event.error && isEnabledLogEvent(options, 'request-error')) {
-      request.logger.error(
+      request.logger[requestErrorLevel](
         {
           tags: event.tags,
           err: event.error
@@ -179,7 +183,7 @@ async function register (server, options) {
 
       // If you want `req` to be added either use the default `getChildBindings` or make sure `req` is passed in your custom bindings.
       const responseTime = (info.completed !== undefined ? info.completed : info.responded) - info.received
-      request.logger.info(
+      request.logger[requestCompleteLevel](
         {
           payload: options.logPayload ? request.payload : undefined,
           queryParams: options.logQueryParams ? request.query : undefined,


Test patch:
diff --git a/test.js b/test.js
index d72a136..e7c1ab4 100644
--- a/test.js
+++ b/test.js
@@ -1559,6 +1559,32 @@ experiment('options.logRequestComplete', () => {
     await server.inject('/something')
     await finish
   })
+
+  test('when options.logRequestComplete is true and options.customRequestCompleteLevel is set', async () => {
+    const server = getServer()
+    let done
+    const finish = new Promise(function (resolve, reject) {
+      done = resolve
+    })
+    const stream = sink(data => {
+      expect(data.msg).to.startWith('[response]')
+      expect(data.level).to.equal(20)
+      done()
+    })
+    const plugin = {
+      plugin: Pino,
+      options: {
+        stream,
+        level: 'debug',
+        logRequestComplete: true,
+        customRequestCompleteLevel: 'debug'
+      }
+    }
+
+    await server.register(plugin)
+    await server.inject('/something')
+    await finish
+  })
 })
 
 experiment('logging with mergeHapiLogData option enabled', () => {