Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No slowdown when logging through child loggers. #8

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ node_modules

# Optional REPL history
.node_repl_history

# 0x
.__browserify_string_empty.js
profile-*
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ Into this:
## API

* <a href="#constructor"><code><b>pino()</b></code></a>
* <a href="#child"><code>logger.<b>child()</b></code></a>
* <a href="#level"><code>logger.<b>level</b></code></a>
* <a href="#fatal"><code>logger.<b>fatal()</b></code></a>
* <a href="#error"><code>logger.<b>error()</b></code></a>
Expand Down Expand Up @@ -153,6 +154,25 @@ var instance = pino({
}
```

<a name="child"></a>
### logger.child(bindings)

Creates a child logger, setting all key-value pairs in `bindings` as
properties in the log lines. All serializers will be applied to the
given pair.

Example:

```js
logger.child({ a: 'property' }).info('hello child!')
// generates
// {"pid":46497,"hostname":"MacBook-Pro-di-Matteo.local","level":30,"msg":"hello child!","time":1458124707120,"v":0,"a":"property"}
```

It leverage the output stream of the parent and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be leverages shouldn't it?

its log level. These settings are immutable and pulled out during the
instantiation of the child logger.

<a name="level"></a>
### logger.level

Expand Down
55 changes: 55 additions & 0 deletions benchmarks/basic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict'

var bench = require('fastbench')
var pino = require('../')
var bunyan = require('bunyan')
var bole = require('bole')('bench')
var winston = require('winston')
var fs = require('fs')
var dest = fs.createWriteStream('/dev/null')
var plog = pino(dest)
var max = 10
var blog = bunyan.createLogger({
name: 'myapp',
streams: [{
level: 'trace',
stream: dest
}]
})

require('bole').output({
level: 'info',
stream: dest
})

winston.add(winston.transports.File, { filename: '/dev/null' })
winston.remove(winston.transports.Console)

var run = bench([
function benchBunyan (cb) {
for (var i = 0; i < max; i++) {
blog.info('hello world')
}
setImmediate(cb)
},
function benchWinston (cb) {
for (var i = 0; i < max; i++) {
winston.info('hello world')
}
setImmediate(cb)
},
function benchBole (cb) {
for (var i = 0; i < max; i++) {
bole.info('hello world')
}
setImmediate(cb)
},
function benchPino (cb) {
for (var i = 0; i < max; i++) {
plog.info('hello world')
}
setImmediate(cb)
}
], 10000)

run(run)
45 changes: 45 additions & 0 deletions benchmarks/child.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict'

var bench = require('fastbench')
var pino = require('../')
var bunyan = require('bunyan')
var bole = require('bole')('bench')('child')
var fs = require('fs')
var dest = fs.createWriteStream('/dev/null')
var plog = pino(dest).child({ a: 'property' })
var max = 10
var blog = bunyan.createLogger({
name: 'myapp',
streams: [{
level: 'trace',
stream: dest
}]
}).child({ a: 'property' })

require('bole').output({
level: 'info',
stream: dest
})

var run = bench([
function benchBunyanObj (cb) {
for (var i = 0; i < max; i++) {
blog.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchPinoChild (cb) {
for (var i = 0; i < max; i++) {
plog.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchBoleChild (cb) {
for (var i = 0; i < max; i++) {
bole.info({ hello: 'world' })
}
setImmediate(cb)
}
], 10000)

run(run)
48 changes: 48 additions & 0 deletions benchmarks/childCreation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict'

var bench = require('fastbench')
var pino = require('../')
var bunyan = require('bunyan')
var bole = require('bole')('bench')
var fs = require('fs')
var dest = fs.createWriteStream('/dev/null')
var plog = pino(dest)
var max = 10
var blog = bunyan.createLogger({
name: 'myapp',
streams: [{
level: 'trace',
stream: dest
}]
})

require('bole').output({
level: 'info',
stream: dest
})

var run = bench([
function benchPinoCreation (cb) {
var child = plog.child({ a: 'property' })
for (var i = 0; i < max; i++) {
child.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchBunyanCreation (cb) {
var child = blog.child({ a: 'property' })
for (var i = 0; i < max; i++) {
child.info({ hello: 'world' })
}
setImmediate(cb)
},
function benchBoleCreation (cb) {
var child = bole('child')
for (var i = 0; i < max; i++) {
child.info({ hello: 'world' })
}
setImmediate(cb)
}
], 10000)

run(run)
26 changes: 1 addition & 25 deletions benchmark.js → benchmarks/object.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

var bench = require('fastbench')
var pino = require('./')
var pino = require('../')
var bunyan = require('bunyan')
var bole = require('bole')('bench')
var winston = require('winston')
Expand All @@ -26,30 +26,6 @@ winston.add(winston.transports.File, { filename: '/dev/null' })
winston.remove(winston.transports.Console)

var run = bench([
function benchBunyan (cb) {
for (var i = 0; i < max; i++) {
blog.info('hello world')
}
setImmediate(cb)
},
function benchWinston (cb) {
for (var i = 0; i < max; i++) {
winston.info('hello world')
}
setImmediate(cb)
},
function benchBole (cb) {
for (var i = 0; i < max; i++) {
bole.info('hello world')
}
setImmediate(cb)
},
function benchPino (cb) {
for (var i = 0; i < max; i++) {
plog.info('hello world')
}
setImmediate(cb)
},
function benchBunyanObj (cb) {
for (var i = 0; i < max; i++) {
blog.info({ hello: 'world' })
Expand Down
2 changes: 2 additions & 0 deletions example.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ info({ obj: 42, b: 2 }, 'hello world')
info({ obj: { aa: 'bbb' } }, 'another')
setImmediate(info, 'after setImmediate')
error(new Error('an error'))

pino.child({ a: 'property' }).info('hello child!')
90 changes: 67 additions & 23 deletions pino.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function pino (opts, stream) {
var slowtime = opts.slowtime
var stringify = opts.safe !== false ? stringifySafe : JSON.stringify
var name = opts.name
var level
var level = opts.level
var funcs = {}
var result = {
fatal: null,
Expand All @@ -36,33 +36,24 @@ function pino (opts, stream) {
trace: null
}
var serializers = opts.serializers || {}
var end = '}\n'

for (var key in levels) {
funcs[key] = genLogFunction(key)
}

Object.defineProperty(result, 'level', {
enumerable: false,
get: function () {
return level
},
set: function (l) {
level = levels[l]
if (!level) {
throw new Error('unknown level ' + l)
if (opts.meta) {
end = ',' + opts.meta + end
Object.keys(levels).forEach(function (key) {
if (level <= levels[key]) {
result[key] = funcs[key]
} else {
result[key] = noop
}

Object.keys(levels).forEach(function (key) {
if (level <= levels[key]) {
result[key] = funcs[key]
} else {
result[key] = noop
}
})
}
})

result.level = opts.level || 'info'
})
} else {
setup(result, funcs, level, stream, opts, serializers, stringify)
}

return result

Expand Down Expand Up @@ -113,7 +104,7 @@ function pino (opts, stream) {
}
}
}
return data + '}\n'
return data + end
}

// returns string json with final brace omitted
Expand All @@ -129,6 +120,59 @@ function pino (opts, stream) {
}
}

function setup (result, funcs, level, stream, opts, serializers, stringify) {
var safe = opts.safe

Object.defineProperty(result, 'level', {
enumerable: false,
get: function () {
return level
},
set: function (l) {
level = levels[l]
if (!level) {
throw new Error('unknown level ' + l)
}

Object.keys(levels).forEach(function (key) {
if (level <= levels[key]) {
result[key] = funcs[key]
} else {
result[key] = noop
}
})
}
})

result.level = opts.level || 'info'
result.child = child

function child (bindings) {
if (!opts) {
throw new Error('missing bindings for child logger')
}

var data = ''
var value
for (var key in bindings) {
value = bindings[key]
if (bindings.hasOwnProperty(key) && value !== undefined) {
value = serializers[key] ? serializers[key](value) : value
data += '"' + key + '":' + stringify(value)
}
}

var toPino = {
safe: safe,
meta: data,
level: level,
serializers: serializers
}

return pino(toPino, stream)
}
}

function noop () {}

function mapHttpRequest (req) {
Expand Down
Loading