nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: pinojs/pino
Pull request #174 (2017-01-16 22:16:13)

changed "silent" level to Infinity
enforced silent level to be the highest possible value so no custom levels can be set higher than it.


Patch:
diff --git a/pino.js b/pino.js
index 1e05648..f123c85 100644
--- a/pino.js
+++ b/pino.js
@@ -48,14 +48,17 @@ function defineLevelsProperty (onObject) {
     },
     enumerable: true
   })
-  Object.defineProperty(onObject.levels.values, 'silent', {value: 100})
-  Object.defineProperty(onObject.levels.labels, '100', {value: 'silent'})
+  Object.defineProperty(onObject.levels.values, 'silent', {value: Infinity})
+  Object.defineProperty(onObject.levels.labels, Infinity, {value: 'silent'})
 }
 
 // IIFE so the keys are cached at module load
 var isStandardLevel = (function () {
   var keys = Object.keys(levels)
   return function (level) {
+    if (Infinity === level) {
+      return true
+    }
     return keys.indexOf(level) > -1
   }
 }())
@@ -63,6 +66,9 @@ var isStandardLevel = (function () {
 var isStandardLevelVal = (function () {
   var keys = Object.keys(nums)
   return function (val) {
+    if (!isFinite(val)) {
+      return true
+    }
     return keys.indexOf(val + '') > -1
   }
 }())
@@ -211,10 +217,15 @@ Object.defineProperty(Pino.prototype, 'levelVal', {
 })
 
 Pino.prototype._setLevel = function _setLevel (level) {
-  if (typeof level === 'number') { level = this.levels.labels[level] }
+  if (typeof level === 'number') {
+    if (!isFinite(level)) {
+      throw Error('unknown level ' + level)
+    }
+    level = this.levels.labels[level]
+  }
 
   if (!this.levels.values[level]) {
-    throw new Error('unknown level ' + level)
+    throw Error('unknown level ' + level)
   }
   this.levelVal = this.levels.values[level]
 }


Test patch:
diff --git a/test/addlevel.test.js b/test/addlevel.test.js
index bbcbf5e..fd9ceab 100644
--- a/test/addlevel.test.js
+++ b/test/addlevel.test.js
@@ -113,6 +113,13 @@ test('reject already known values', function (t) {
   }
 })
 
+test('reject values of Infinity', function (t) {
+  t.plan(1)
+  t.throws(function () {
+    pino({level: 'foo', levelVal: Infinity})
+  }, /.*level value is already used.*/)
+})
+
 test('level numbers are logged correctly after level change', function (t) {
   t.plan(1)
   var log = pino({level: 'foo', levelVal: 25}, sink(function (chunk, enc, cb) {
diff --git a/test/levels.test.js b/test/levels.test.js
index 1e37775..16bae8b 100644
--- a/test/levels.test.js
+++ b/test/levels.test.js
@@ -146,19 +146,6 @@ test('silent level', function (t) {
   t.end()
 })
 
-test('setting level to 100', function (t) {
-  var instance = pino({
-    level: 100
-  }, sink(function (chunk, enc, cb) {
-    t.fail('no data should be logged')
-  }))
-
-  Object.keys(pino.levels.values).forEach(function (level) {
-    instance[level]('hello world')
-  })
-  t.end()
-})
-
 test('exposed levels', function (t) {
   t.plan(1)
   t.deepEqual(Object.keys(pino.levels.values), [
Repository: pinojs/pino
Pull request #176 (2017-01-17 17:02:18)

Fix http response filtering
@mcollina In order to distinguish http response I have also tried to use `instanceof`. I decided to go for `setHeader` as you suggested because it seems slightly faster.

I would be happy to improve the PR and integrate your comments.

Fixes https://github.com/pinojs/pino/issues/175


Patch:
diff --git a/pino.js b/pino.js
index f099e0f..74f5374 100644
--- a/pino.js
+++ b/pino.js
@@ -402,7 +402,7 @@ function genLog (z) {
 
       if (m.method && m.headers && m.socket) {
         m = mapHttpRequest(m)
-      } else if (m.statusCode) {
+      } else if (typeof m.setHeader === 'function') {
         m = mapHttpResponse(m)
       }
     } else {


Test patch:
diff --git a/test/error.test.js b/test/error.test.js
index cc932a3..005017c 100644
--- a/test/error.test.js
+++ b/test/error.test.js
@@ -105,3 +105,26 @@ test('err serializer', function (t) {
   instance.level = name
   instance[name]({ err })
 })
+
+test('an error with statusCode property is not confused for a http response', function (t) {
+  t.plan(2)
+  var err = Object.assign(new Error('StatusCodeErr'), { statusCode: 500 })
+  var instance = pino(sink(function (chunk, enc, cb) {
+    t.ok(new Date(chunk.time) <= new Date(), 'time is greater than Date.now()')
+    delete chunk.time
+    t.deepEqual(chunk, {
+      pid: pid,
+      hostname: hostname,
+      level: level,
+      type: 'Error',
+      msg: err.message,
+      stack: err.stack,
+      statusCode: err.statusCode,
+      v: 1
+    })
+    cb()
+  }))
+
+  instance.level = name
+  instance[name](err)
+})
Repository: pinojs/pino
Pull request #199 (2017-03-04 02:56:47)

Make silent level a noop function
This PR is an implementation of @davidmarkclements proposal in https://github.com/pinojs/express-pino-logger/issues/9

Basically, the "silent" level is now a no operation function so that invocations of it behave the way people think it would.


Patch:
diff --git a/pino.js b/pino.js
index d42cb41..98c4361 100644
--- a/pino.js
+++ b/pino.js
@@ -110,6 +110,7 @@ Pino.prototype.warn = tools.genLog(levels.levels.warn)
 Pino.prototype.info = tools.genLog(levels.levels.info)
 Pino.prototype.debug = tools.genLog(levels.levels.debug)
 Pino.prototype.trace = tools.genLog(levels.levels.trace)
+Pino.prototype.silent = tools.noop
 
 Object.defineProperty(Pino.prototype, 'levelVal', {
   get: function getLevelVal () {


Test patch:
diff --git a/test/levels.test.js b/test/levels.test.js
index 16bae8b..99904f8 100644
--- a/test/levels.test.js
+++ b/test/levels.test.js
@@ -146,6 +146,35 @@ test('silent level', function (t) {
   t.end()
 })
 
+test('silent is a noop', function (t) {
+  var instance = pino({
+    level: 'silent'
+  }, sink(function (chunk, enc, cb) {
+    t.fail('no data should be logged')
+  }))
+
+  instance['silent']('hello world')
+  t.end()
+})
+
+test('silent stays a noop after level changes', function (t) {
+  var noop = require('../lib/tools').noop
+  var instance = pino({
+    level: 'silent'
+  }, sink(function (chunk, enc, cb) {
+    t.fail('no data should be logged')
+  }))
+
+  instance.level = 'trace'
+  t.notEqual(instance[instance.level], noop)
+
+  instance.level = 'silent'
+  instance['silent']('hello world')
+  t.is(instance[instance.level], noop)
+
+  t.end()
+})
+
 test('exposed levels', function (t) {
   t.plan(1)
   t.deepEqual(Object.keys(pino.levels.values), [
Repository: pinojs/pino
Pull request #235 (2017-04-17 00:15:57)

Add property to expose Pino version
This PR exposes the current version as a property on the logger. Since we don't expose the actual prototype, and it really can't be exposed, we can't use `pinoPrototype.isPrototypeOf(instance)` to check if a logger instance is an instance of Pino. This PR gives a rudimentary way to validate instances.


Patch:
diff --git a/docs/API.md b/docs/API.md
index 0dd8c6a..332cad7 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -3,6 +3,7 @@
 + [pino](#constructor)
 + [pino.pretty](#pretty)
 + [Logger Instance](#logger)
+  * [.pino](#version)
   * [.child](#child)
   * [.level](#level)
   * [.fatal](#fatal)
@@ -61,7 +62,7 @@
     it is up to you to terminate the process; you **must** perform only synchronous operations at this point.
     See [Extreme mode explained](extreme.md) for more detail.
   * `enabled` (boolean): enables logging. Default: `true`
-  * `browser` (Object): browser only, may have `asObject` and `write` keys, see [Pino in the Browser](../readme.md#browser) 
+  * `browser` (Object): browser only, may have `asObject` and `write` keys, see [Pino in the Browser](../readme.md#browser)
 + `stream` (Writable): a writable stream where the logs will be written.
   Default: `process.stdout`
 
@@ -120,6 +121,17 @@ in this section.
 <a id="logger"></a>
 # Logger
 
+<a id="version"></a>
+## .pino
+
+Exposes the current version of Pino.
+
+### Example:
+```js
+var log = require('pino')()
+if ('pino' in child) conosole.log(`pino version: ${log.pino}`)
+```
+
 <a id="child"></a>
 ## .child(bindings)
 
diff --git a/pino.js b/pino.js
index ac98c2e..38f7843 100644
--- a/pino.js
+++ b/pino.js
@@ -38,6 +38,10 @@ var pinoPrototype = Object.create(EventEmitter.prototype, {
   stream: {
     value: process.stdout,
     writable: true
+  },
+  pino: {
+    value: require('./package.json').version,
+    enumerable: true
   }
 })
 


Test patch:
diff --git a/test/basic.test.js b/test/basic.test.js
index 6cd79ff..750fa42 100644
--- a/test/basic.test.js
+++ b/test/basic.test.js
@@ -9,6 +9,19 @@ var check = require('./helper').check
 var pid = process.pid
 var hostname = os.hostname()
 
+test('pino version is exposed', function (t) {
+  t.plan(2)
+  var instance = pino()
+  t.ok(instance.pino)
+  t.is(instance.pino, require('../package.json').version)
+})
+
+test('child exposes pino version', function (t) {
+  t.plan(1)
+  var child = pino().child({foo: 'bar'})
+  t.ok(child.pino)
+})
+
 function levelTest (name, level) {
   test(name + ' logs as ' + level, function (t) {
     t.plan(2)
Repository: pinojs/pino
Pull request #292 (2017-09-13 20:12:08)

unixTime
Epoch, also known as Unix timestamps, is the number of seconds (not milliseconds!) that have elapsed since January 1, 1970 at 00:00:00 GMT (1970-01-01 00:00:00 GMT).
taken from https://www.freeformatter.com/epoch-timestamp-to-date-converter.html

See [PR](https://github.com/pinojs/pino/pull/291)

@jsumners 

doron2402: √ update 

Patch:
diff --git a/docs/API.md b/docs/API.md
index effe567..22eb5b2 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -25,6 +25,7 @@
     + [.err](#errSerializer)
   + [.stdTimeFunctions](#stdTimeFunctions)
     + [.epochTime](#epochTimeFunction)
+    + [.unixTime](#unixTimeFunction)
     + [.slowTime](#slowTimeFunction)
     + [.nullTime](#nullTimeFunction)
 + [Metadata Support](#metadata)
@@ -41,7 +42,7 @@
   * `name` (string): the name of the logger. Default: `undefined`.
   * `serializers` (object): an object containing functions for custom serialization
     of objects. These functions should return an JSONifiable object and they
-    should never throw. When logging an object, each top-level property matching the exact key of a serializer 
+    should never throw. When logging an object, each top-level property matching the exact key of a serializer
     will be serialized using the defined serializer.
   * `timestamp` (boolean|function): Enables or disables the inclusion of a timestamp in the
     log message. If a function is supplied, it must synchronously return a JSON string
@@ -566,6 +567,11 @@ a string like `,"time":1493426328206`.
 
 The default time function for Pino. Returns a string like `,"time":1493426328206`.
 
+<a id="unixTimeFunction"></a>
+### .unixTime
+
+Returns a unix time in seconds, like `,"time":1493426328`.
+
 <a id="slowTimeFunction"></a>
 ### .slowTime
 
diff --git a/lib/time.js b/lib/time.js
index 66f0744..62b67b8 100644
--- a/lib/time.js
+++ b/lib/time.js
@@ -8,6 +8,10 @@ function epochTime () {
   return ',"time":' + Date.now()
 }
 
+function unixTime () {
+  return ',"time":' + Math.round(Date.now() / 1000.0)
+}
+
 function slowTime () {
   return ',"time":"' + (new Date()).toISOString() + '"'
 }
@@ -15,5 +19,6 @@ function slowTime () {
 module.exports = {
   nullTime: nullTime,
   epochTime: epochTime,
+  unixTime: unixTime,
   slowTime: slowTime
 }


Test patch:
diff --git a/test/timestamp.test.js b/test/timestamp.test.js
index 8e4d06d..8997add 100644
--- a/test/timestamp.test.js
+++ b/test/timestamp.test.js
@@ -5,9 +5,10 @@ var pino = require('../')
 var sink = require('./helper').sink
 
 test('pino exposes standard time functions', function (t) {
-  t.plan(4)
+  t.plan(5)
   t.ok(pino.stdTimeFunctions)
   t.ok(pino.stdTimeFunctions.epochTime)
+  t.ok(pino.stdTimeFunctions.unixTime)
   t.ok(pino.stdTimeFunctions.slowTime)
   t.ok(pino.stdTimeFunctions.nullTime)
 })
Repository: pinojs/pino
Pull request #321 (2017-10-29 04:15:35)

Throws error when prettyPrint specified with stream
Implements #298 


Patch:
diff --git a/pino.js b/pino.js
index 5b09b5d..8eb42ac 100644
--- a/pino.js
+++ b/pino.js
@@ -259,6 +259,7 @@ function pino (opts, stream) {
   }
   iopts = Object.assign({}, defaultOptions, iopts)
   if (iopts.extreme && iopts.prettyPrint) throw Error('cannot enable pretty print in extreme mode')
+  if (stream && iopts.prettyPrint) throw Error('cannot enable pretty print when stream specified')
   istream = istream || process.stdout
   if (iopts.prettyPrint) {
     var prettyOpts = Object.assign({ messageKey: iopts.messageKey }, iopts.prettyPrint)


Test patch:
diff --git a/test/pretty.test.js b/test/pretty.test.js
index fbb40d5..d120afb 100644
--- a/test/pretty.test.js
+++ b/test/pretty.test.js
@@ -249,3 +249,12 @@ test('works without time', function (t) {
 
   instance.info('hello world')
 })
+
+test('throws error when enabled with stream specified', function (t) {
+  t.plan(1)
+  var logStream = writeStream(function (s, enc, cb) {
+    cb()
+  })
+
+  t.throws(() => pino({prettyPrint: true}, logStream), {})
+})
Repository: pinojs/pino
Pull request #332 (2017-11-14 15:27:33)

Do not throw if the passed stream is stdout
improvement on https://github.com/pinojs/pino/pull/321


Patch:
diff --git a/pino.js b/pino.js
index f9ba9a3..0ea01d2 100644
--- a/pino.js
+++ b/pino.js
@@ -273,13 +273,13 @@ function pino (opts, stream) {
   }
   iopts = Object.assign({}, defaultOptions, iopts)
   if (iopts.extreme && iopts.prettyPrint) throw Error('cannot enable pretty print in extreme mode')
-  if (stream && iopts.prettyPrint) throw Error('cannot enable pretty print when stream specified')
   istream = istream || process.stdout
+  var isStdout = istream === process.stdout
+  if (!isStdout && iopts.prettyPrint) throw Error('cannot enable pretty print when stream is not process.stdout')
   if (iopts.prettyPrint) {
     var prettyOpts = Object.assign({ messageKey: iopts.messageKey }, iopts.prettyPrint)
     var pstream = pretty(prettyOpts)
-    var origStream = istream
-    pump(pstream, origStream, function (err) {
+    pump(pstream, process.stdout, function (err) {
       if (err) instance.emit('error', err)
     })
     istream = pstream


Test patch:
diff --git a/test/pretty.test.js b/test/pretty.test.js
index 2a5d8c2..ae4ae1d 100644
--- a/test/pretty.test.js
+++ b/test/pretty.test.js
@@ -265,3 +265,8 @@ test('throws error when enabled with stream specified', function (t) {
 
   t.throws(() => pino({prettyPrint: true}, logStream), {})
 })
+
+test('does not throw error when enabled with stream specified', function (t) {
+  pino({prettyPrint: true}, process.stdout)
+  t.end()
+})
Repository: pinojs/pino
Pull request #335 (2017-11-28 22:11:08)

Fix typo in `withSpaces` function
I wondered why using the "pretty" feature didn't make my logs look that pretty.

Then I looked at the code and found out why: It looks like someone passed a string to `value.split()` when they clearly meant to pass a regex.

Tested this fix with my project, and it looks much better.

Before fix:
```
[2017-11-28T21:45:08.685Z] INFO (16172 on MIS7501): incoming request
    reqId: 1
    req: {
  "id": 1,
  "method": "GET",
  "url": "/api/auth/getCurrentUser",
  "remoteAddress": "::1",
  "remotePort": 58871
}
```

After fix:
```
[2017-11-28T21:46:25.319Z] INFO (15812 on MIS7501): incoming request
    reqId: 1
    req: {
      "id": 1,
      "method": "GET",
      "url": "/api/auth/getCurrentUser",
      "remoteAddress": "::1",
      "remotePort": 58881
    }
```


Patch:
diff --git a/pretty.js b/pretty.js
index 018a799..6cc8a54 100755
--- a/pretty.js
+++ b/pretty.js
@@ -24,7 +24,7 @@ var standardKeys = [
 ]
 
 function withSpaces (value, eol) {
-  var lines = value.split('\r?\n')
+  var lines = value.split(/\r?\n/)
   for (var i = 1; i < lines.length; i++) {
     lines[i] = '    ' + lines[i]
   }


Test patch:
diff --git a/test/pretty.test.js b/test/pretty.test.js
index 0b7efe9..1ab11bf 100644
--- a/test/pretty.test.js
+++ b/test/pretty.test.js
@@ -239,6 +239,27 @@ test('pino transform prettifies properties', function (t) {
   instance.info({ a: 'b' }, 'hello world')
 })
 
+test('pino transform prettifies nested properties', function (t) {
+  t.plan(5)
+  var expectedLines = [
+    undefined,
+    '    a: {',
+    '      "b": {',
+    '        "c": "d"',
+    '      }',
+    '    }'
+  ]
+  var prettier = pretty()
+  prettier.pipe(split(function (line) {
+    var expectedLine = expectedLines.shift()
+    if (expectedLine !== undefined) {
+      t.equal(line, expectedLine, 'prettifies the line')
+    }
+  }))
+  var instance = pino(prettier)
+  instance.info({ a: { b: { c: 'd' } } }, 'hello world')
+})
+
 test('pino transform treats the name with care', function (t) {
   t.plan(1)
   var prettier = pretty()
Repository: pinojs/pino
Pull request #383 (2018-04-02 06:50:09)

Issue #382, pretty print error with null stack
I have added checking for null for matches of error stack regexp. it was throw an error in the case when stack is null.


Patch:
diff --git a/pretty.js b/pretty.js
index a00b737..6d8c2d8 100755
--- a/pretty.js
+++ b/pretty.js
@@ -84,12 +84,16 @@ function filter (value, messageKey, eol, errorLikeObjectKeys, excludeStandardKey
         if (/^\s*"stack"/.test(line)) {
           var matches = /^(\s*"stack":)\s*"(.*)",?$/.exec(line)
 
-          if (matches.length === 3) {
-            var indentSize = /^\s*/.exec(line)[0].length + 4
-            var indentation = Array(indentSize + 1).join(' ')
+          if (matches) {
+            if (matches.length === 3) {
+              var indentSize = /^\s*/.exec(line)[0].length + 4
+              var indentation = Array(indentSize + 1).join(' ')
 
-            result += matches[1] + '\n' + indentation +
-              matches[2].replace(/\\n/g, '\n' + indentation)
+              result += matches[1] + '\n' + indentation +
+                matches[2].replace(/\\n/g, '\n' + indentation)
+            }
+          } else {
+            result += line
           }
         } else {
           result += line


Test patch:
diff --git a/test/pretty.test.js b/test/pretty.test.js
index 85f7152..2933161 100644
--- a/test/pretty.test.js
+++ b/test/pretty.test.js
@@ -563,3 +563,32 @@ test('pino pretty errorProps flag with "*" (print all nested props)', function (
 
   instance.error(error)
 })
+
+test('pino pretty handles errors with a null stack', function (t) {
+  t.plan(6)
+  var prettier = pretty()
+
+  var expectedLines = [
+    undefined,
+    '    message: "foo"',
+    '    stack: null',
+    undefined,
+    '    error: {',
+    '      "message": "foo",',
+    '      "stack": null',
+    '    }'
+  ]
+
+  prettier.pipe(split(function (line) {
+    var expectedLine = expectedLines.shift()
+    if (expectedLine !== undefined) {
+      t.equal(line, expectedLine, 'prettifies the line')
+    }
+  }))
+
+  var instance = pino(prettier)
+  const error = {message: 'foo', stack: null}
+  const objectWithError = {error: error}
+  instance.error(error)
+  instance.error(objectWithError)
+})
Repository: pinojs/pino
Pull request #407 (2018-05-01 01:03:47)

Skip writing log when prettifier says to
Resolves issue #395.


Patch:
diff --git a/docs/pretty.md b/docs/pretty.md
index 6c165b7..925d8ef 100644
--- a/docs/pretty.md
+++ b/docs/pretty.md
@@ -52,6 +52,9 @@ The reference implementation of such a module is the [`pino-pretty`][pp] module.
 To learn more about creating your own prettifier module, learn from the
 `pino-pretty` source code.
 
+Note: if the prettifier returns `undefined`, instead of a formatted line, nothing
+will be written to the destination stream.
+
 ### API Example
 
 > #### NOTE:
diff --git a/lib/tools.js b/lib/tools.js
index 23dfbcf..f41bd02 100644
--- a/lib/tools.js
+++ b/lib/tools.js
@@ -57,6 +57,7 @@ function asMetaWrapper (pretty, dest) {
       }, chindings, this.lastObj)
 
       const formatted = pretty(obj)
+      if (formatted === undefined) return
       dest.write(formatted)
     }
   }


Test patch:
diff --git a/test/fixtures/pretty/skippedOutput.js b/test/fixtures/pretty/skippedOutput.js
new file mode 100644
index 0000000..048905a
--- /dev/null
+++ b/test/fixtures/pretty/skippedOutput.js
@@ -0,0 +1,13 @@
+global.process = { __proto__: process, pid: 123456 }
+Date.now = function () { return 1459875739796 }
+require('os').hostname = function () { return 'abcdefghijklmnopqr' }
+var pino = require(require.resolve('./../../../'))
+var log = pino({
+  prettyPrint: true,
+  prettifier: function () {
+    return function () {
+      return undefined
+    }
+  }
+})
+log.info('h')
diff --git a/test/pretty.test.js b/test/pretty.test.js
index 0f00848..c742567 100644
--- a/test/pretty.test.js
+++ b/test/pretty.test.js
@@ -57,7 +57,7 @@ test('does not throw error when enabled with stream specified', function (t) {
   t.end()
 })
 
-test('can send pretty print to custom stream', (t) => {
+test('can send pretty print to custom stream', function (t) {
   t.plan(1)
 
   var dest = new Writable({
@@ -76,3 +76,18 @@ test('can send pretty print to custom stream', (t) => {
   }, dest)
   log.info('foo')
 })
+
+test('ignores `undefined` from prettifier', function (t) {
+  t.plan(1)
+  var actual = ''
+  var child = fork(path.join(__dirname, 'fixtures', 'pretty', 'skippedOutput.js'), {silent: true})
+
+  child.stdout.pipe(writeStream(function (s, enc, cb) {
+    actual += s
+    cb()
+  }))
+
+  child.on('close', function () {
+    t.is(actual, '')
+  })
+})
Repository: pinojs/pino
Pull request #422 (2018-05-29 00:49:00)

fix: formatOpts typo
search and replace gone awry

So the impact of this not saying `formatOpts` means that `{lowres: true}` was not being passed to `quick-format-unescape` which means any log messages that interpolate an object with a circular will say 'text content "[Circular]"' instead of 'text content {"path": {"to": "[Circular]"}}'


Patch:
diff --git a/pino.js b/pino.js
index 697b15f..d7ad5b7 100644
--- a/pino.js
+++ b/pino.js
@@ -297,7 +297,7 @@ function pino (opts, stream) {
 
   // internal options
   iopts.stringify = iopts.safe ? stringifySafe : JSON.stringify
-  iopts.formatOpts = {lowres: true}
+  iopts.formatOpts = {lowres: !iopts.safe}
   iopts.messageKeyString = `,"${iopts.messageKey}":`
   iopts.end = ',"v":' + LOG_VERSION + '}' + (iopts.crlf ? '\r\n' : '\n')
   iopts.cache = !iopts.extreme ? null : {
@@ -320,7 +320,7 @@ function pino (opts, stream) {
   instance.timestamp = iopts.timestamp
   instance.slowtime = iopts.slowtime
   instance.cache = iopts.cache
-  instance.formatiopts = iopts.formatiopts
+  instance.formatOpts = iopts.formatOpts
   instance.onTerminated = iopts.onTerminated
   instance.messageKey = iopts.messageKey
   instance.messageKeyString = iopts.messageKeyString


Test patch:
diff --git a/test/basic.test.js b/test/basic.test.js
index fed25f7..d5c37e2 100644
--- a/test/basic.test.js
+++ b/test/basic.test.js
@@ -506,3 +506,25 @@ test('when safe is true it should ONLY use `fast-safe-stringify`', function (t)
   })
   t.end()
 })
+
+test('when safe is true, fast-safe-stringify must be used when interpolating', function (t) {
+  var instance = pino({safe: true}, sink(function (chunk, enc, cb) {
+    const { msg } = chunk
+    t.is(msg, 'test {"a":{"b":{"c":"[Circular]"}}}')
+    t.end()
+  }))
+  var o = { a: { b: {} } }
+  o.a.b.c = o.a.b
+  instance.info('test', o)
+})
+
+test('when safe is false, interpolation output circulars at the root', function (t) {
+  var instance = pino({safe: false}, sink(function (chunk, enc, cb) {
+    const { msg } = chunk
+    t.is(msg, 'test "[Circular]"')
+    t.end()
+  }))
+  var o = { a: { b: {} } }
+  o.a.b.c = o.a.b
+  instance.info('test', o)
+})