Repository: pinojs/pino
Pull request #756 (2019-12-28 08:06:21)

fix(redaction): remove undefined entries for removed number and boolean values
This fixes an issue where removing a number or boolean value at a top-level path results in an `undefined` value instead of fully removing the entry.

`hapi-pino` issue for context: https://github.com/pinojs/hapi-pino/issues/94




Patch:
diff --git a/docs/api.md b/docs/api.md
index 6e15ba3..8525a7e 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -807,6 +807,7 @@ The `pino.stdTimeFunctions` object provides a very small set of common functions
 * `pino.stdTimeFunctions.epochTime`: Milliseconds since Unix epoch (Default)
 * `pino.stdTimeFunctions.unixTime`: Seconds since Unix epoch
 * `pino.stdTimeFunctions.nullTime`: Clears timestamp property (Used when `timestamp: false`)
+* `pino.stdTimeFunctions.isoTime`: ISO 8601-formatted time in UTC
 
 * See [`timestamp` option](#opt-timestamp)
 
diff --git a/lib/time.js b/lib/time.js
index 104c440..420a028 100644
--- a/lib/time.js
+++ b/lib/time.js
@@ -6,4 +6,6 @@ const epochTime = () => `,"time":${Date.now()}`
 
 const unixTime = () => `,"time":${Math.round(Date.now() / 1000.0)}`
 
-module.exports = { nullTime, epochTime, unixTime }
+const isoTime = () => `,"time":"${new Date(Date.now()).toISOString()}"` // using Date.now() for testability
+
+module.exports = { nullTime, epochTime, unixTime, isoTime }
diff --git a/lib/tools.js b/lib/tools.js
index 586c84d..d24f8d2 100644
--- a/lib/tools.js
+++ b/lib/tools.js
@@ -105,8 +105,7 @@ function asJson (obj, num, time) {
         // this case explicity falls through to the next one
         case 'boolean':
           if (stringifier) value = stringifier(value)
-          data += ',"' + key + '":' + value
-          continue
+          break
         case 'string':
           value = (stringifier || asString)(value)
           break


Test patch:
diff --git a/test/redact.test.js b/test/redact.test.js
index 5a812cc..be27cc1 100644
--- a/test/redact.test.js
+++ b/test/redact.test.js
@@ -240,7 +240,7 @@ test('redact.remove option – removes both key and value', async ({ is }) => {
   is('cookie' in req.headers, false)
 })
 
-test('redact.remove – top level key', async ({ is }) => {
+test('redact.remove – top level key - object value', async ({ is }) => {
   const stream = sink()
   const instance = pino({ redact: { paths: ['key'], remove: true } }, stream)
   instance.info({
@@ -250,6 +250,26 @@ test('redact.remove – top level key', async ({ is }) => {
   is('key' in o, false)
 })
 
+test('redact.remove – top level key - number value', async ({ is }) => {
+  const stream = sink()
+  const instance = pino({ redact: { paths: ['key'], remove: true } }, stream)
+  instance.info({
+    key: 1
+  })
+  const o = await once(stream, 'data')
+  is('key' in o, false)
+})
+
+test('redact.remove – top level key - boolean value', async ({ is }) => {
+  const stream = sink()
+  const instance = pino({ redact: { paths: ['key'], remove: true } }, stream)
+  instance.info({
+    key: false
+  })
+  const o = await once(stream, 'data')
+  is('key' in o, false)
+})
+
 test('redact.remove – top level key in child logger', async ({ is }) => {
   const stream = sink()
   const opts = { redact: { paths: ['key'], remove: true } }
diff --git a/test/timestamp.test.js b/test/timestamp.test.js
index 89e7843..87bdc09 100644
--- a/test/timestamp.test.js
+++ b/test/timestamp.test.js
@@ -11,6 +11,7 @@ test('pino exposes standard time functions', async ({ ok }) => {
   ok(pino.stdTimeFunctions.epochTime)
   ok(pino.stdTimeFunctions.unixTime)
   ok(pino.stdTimeFunctions.nullTime)
+  ok(pino.stdTimeFunctions.isoTime)
 })
 
 test('pino accepts external time functions', async ({ is }) => {
@@ -101,3 +102,20 @@ test('pino.stdTimeFunctions.unixTime returns seconds based timestamps', async ({
   is(result.time, 1531069920)
   Date.now = now
 })
+
+test('pino.stdTimeFunctions.isoTime returns ISO 8601 timestamps', async ({ is }) => {
+  const opts = {
+    timestamp: pino.stdTimeFunctions.isoTime
+  }
+  const stream = sink()
+  const instance = pino(opts, stream)
+  const ms = 1531069919686
+  const now = Date.now
+  Date.now = () => ms
+  const iso = new Date(ms).toISOString()
+  instance.info('foobar')
+  const result = await once(stream, 'data')
+  is(result.hasOwnProperty('time'), true)
+  is(result.time, iso)
+  Date.now = now
+})