Comparing version 2.15.0 to 3.0.0
{ | ||
"name": "pino", | ||
"version": "2.15.0", | ||
"version": "3.0.0", | ||
"description": "super fast, all natural json logger", | ||
@@ -13,3 +13,11 @@ "main": "pino.js", | ||
"test": "standard && tap --no-cov test/*test.js", | ||
"ci": "standard && tap --cov test/*test.js" | ||
"ci": "standard && tap --cov test/*test.js", | ||
"bench-all": "node benchmarks/runbench all", | ||
"bench-basic": "node benchmarks/runbench basic", | ||
"bench-object": "node benchmarks/runbench object", | ||
"bench-deepobject": "node benchmarks/runbench deepobject", | ||
"bench-multiarg": "node benchmarks/runbench multiarg", | ||
"bench-child": "node benchmarks/runbench child", | ||
"bench-grandchild": "node benchmarks/runbench grandchild", | ||
"bench-conception": "node benchmarks/runbench conception" | ||
}, | ||
@@ -44,5 +52,8 @@ "precommit": "test", | ||
"pre-commit": "^1.1.2", | ||
"pump": "^1.0.1", | ||
"standard": "^8.0.0", | ||
"tap": "^7.0.0", | ||
"steed": "^1.1.3", | ||
"tap": "^8.0.0", | ||
"tape": "^4.6.2", | ||
"through2": "^2.0.1", | ||
"winston": "^2.1.1", | ||
@@ -57,3 +68,2 @@ "zuul": "^3.11.1" | ||
"flatstr": "^1.0.0", | ||
"object.assign": "^4.0.4", | ||
"once": "^1.3.3", | ||
@@ -60,0 +70,0 @@ "quick-format": "^2.0.4", |
197
pino.js
@@ -7,2 +7,3 @@ 'use strict' | ||
var os = require('os') | ||
var fs = require('fs') | ||
var flatstr = require('flatstr') | ||
@@ -13,6 +14,17 @@ var once = require('once') | ||
var baseLog = flatstr('{"pid":' + pid + ',"hostname":"' + hostname + '",') | ||
var extend = require('object.assign').getPolyfill() | ||
var LOG_VERSION = 1 | ||
var defaultOptions = { | ||
safe: true, | ||
name: undefined, | ||
serializers: {}, | ||
timestamp: true, | ||
slowtime: false, | ||
extreme: false, | ||
level: 'info', | ||
levelVal: undefined, | ||
enabled: true | ||
} | ||
var levels = { | ||
@@ -27,8 +39,2 @@ fatal: 60, | ||
// private property | ||
Object.defineProperty(levels, 'silent', { | ||
value: 100, | ||
enumerable: false | ||
}) | ||
var nums = Object.keys(levels).reduce(function (o, k) { | ||
@@ -39,2 +45,29 @@ o[levels[k]] = k | ||
function defineLevelsProperty (onObject) { | ||
Object.defineProperty(onObject, 'levels', { | ||
value: { | ||
values: copy({}, levels), | ||
labels: copy({}, nums) | ||
}, | ||
enumerable: true | ||
}) | ||
Object.defineProperty(onObject.levels.values, 'silent', {value: 100}) | ||
Object.defineProperty(onObject.levels.labels, '100', {value: 'silent'}) | ||
} | ||
// IIFE so the keys are cached at module load | ||
var isStandardLevel = (function () { | ||
var keys = Object.keys(levels) | ||
return function (level) { | ||
return keys.indexOf(level) > -1 | ||
} | ||
}()) | ||
var isStandardLevelVal = (function () { | ||
var keys = Object.keys(nums) | ||
return function (val) { | ||
return keys.indexOf(val + '') > -1 | ||
} | ||
}()) | ||
// level string catch | ||
@@ -46,8 +79,2 @@ var lscache = Object.keys(nums).reduce(function (o, k) { | ||
// private property | ||
Object.defineProperty(nums, '100', { | ||
value: 'silent', | ||
enumerable: false | ||
}) | ||
function streamIsBlockable (s) { | ||
@@ -60,28 +87,27 @@ if (s.hasOwnProperty('_handle') && s._handle.hasOwnProperty('fd') && s._handle.fd) return true | ||
function pino (opts, stream) { | ||
if (opts && (opts.writable || opts._writableState)) { | ||
stream = opts | ||
opts = null | ||
var iopts = opts | ||
var istream = stream | ||
if (iopts && (iopts.writable || iopts._writableState)) { | ||
istream = iopts | ||
iopts = defaultOptions | ||
} | ||
stream = stream || process.stdout | ||
opts = opts || {} | ||
var timestamp = (opts.hasOwnProperty('timestamp')) ? opts.timestamp : true | ||
var slowtime = opts.slowtime | ||
var safe = opts.safe !== false | ||
var stringify = safe ? stringifySafe : JSON.stringify | ||
var formatOpts = safe ? null : {lowres: true} | ||
var name = opts.name | ||
var level = opts.level || 'info' | ||
var serializers = opts.serializers || {} | ||
var end = ',"v":' + LOG_VERSION + '}\n' | ||
var cache = !opts.extreme ? null : { | ||
istream = istream || process.stdout | ||
iopts = Object.assign({}, defaultOptions, iopts) | ||
// internal options | ||
iopts.stringify = iopts.safe ? stringifySafe : JSON.stringify | ||
iopts.formatOpts = iopts.safe ? null : {lowres: true} | ||
iopts.end = ',"v":' + LOG_VERSION + '}\n' | ||
iopts.cache = !iopts.extreme ? null : { | ||
size: 4096, | ||
buf: '' | ||
} | ||
iopts.chindings = '' | ||
if (opts.enabled === false) { | ||
level = 'silent' | ||
if (iopts.enabled === false) { | ||
iopts.level = 'silent' | ||
} | ||
var logger = new Pino(level, stream, serializers, stringify, end, name, timestamp, slowtime, '', cache, formatOpts) | ||
if (cache) { | ||
var logger = new Pino(iopts, istream) | ||
if (iopts.cache) { | ||
// setImmediate is causing a very weird crash: | ||
@@ -91,3 +117,3 @@ // Assertion failed: (cb_v->IsFunction()), function MakeCallback... | ||
setTimeout(function () { | ||
if (!streamIsBlockable(stream)) { | ||
if (!streamIsBlockable(istream)) { | ||
logger.emit('error', new Error('stream must have a file descriptor in extreme mode')) | ||
@@ -98,8 +124,9 @@ } | ||
onExit(function (code, evt) { | ||
if (cache.buf) { | ||
var buf = iopts.cache.buf | ||
if (buf) { | ||
// We need to block the process exit long enough to flush the buffer | ||
// to the destination stream. We do that by forcing a synchronous | ||
// write directly to the stream's file descriptor. | ||
var fd = (stream.fd) ? stream.fd : stream._handle.fd | ||
require('fs').writeSync(fd, cache.buf) | ||
var fd = (istream.fd) ? istream.fd : istream._handle.fd | ||
fs.writeSync(fd, buf) | ||
} | ||
@@ -119,29 +146,30 @@ if (!process._events[evt] || process._events[evt].length < 2 || !process._events[evt].filter(function (f) { | ||
Object.defineProperty(pino, 'levels', { | ||
value: { | ||
values: copy({}, levels), | ||
labels: copy({}, nums) | ||
}, | ||
enumerable: true | ||
}) | ||
defineLevelsProperty(pino) | ||
function Pino (level, stream, serializers, stringify, end, name, timestamp, slowtime, chindings, cache, formatOpts) { | ||
function Pino (opts, stream) { | ||
this.stream = stream | ||
this.serializers = serializers | ||
this.stringify = stringify | ||
this.end = end | ||
this.name = name | ||
this.timestamp = timestamp | ||
this.slowtime = slowtime | ||
this.chindings = chindings | ||
this.cache = cache | ||
this.formatOpts = formatOpts | ||
this._setLevel(level) | ||
this.serializers = opts.serializers | ||
this.stringify = opts.stringify | ||
this.end = opts.end | ||
this.name = opts.name | ||
this.timestamp = opts.timestamp | ||
this.slowtime = opts.slowtime | ||
this.chindings = opts.chindings | ||
this.cache = opts.cache | ||
this.formatOpts = opts.formatOpts | ||
if (opts.level && opts.levelVal) { | ||
var levelIsStandard = isStandardLevel(opts.level) | ||
var valIsStandard = isStandardLevelVal(opts.levelVal) | ||
if (valIsStandard) throw new Error('level value is already used: ' + opts.levelVal) | ||
if (levelIsStandard === false && valIsStandard === false) this.addLevel(opts.level, opts.levelVal) | ||
} | ||
this._setLevel(opts.level) | ||
this._baseLog = flatstr(baseLog + | ||
(this.name === undefined ? '' : '"name":' + stringify(this.name) + ',')) | ||
(this.name === undefined ? '' : '"name":' + this.stringify(this.name) + ',')) | ||
if (timestamp === false) { | ||
if (opts.timestamp === false) { | ||
this.time = getNoTime | ||
} else if (slowtime) { | ||
} else if (opts.slowtime) { | ||
this.time = getSlowTime | ||
@@ -154,2 +182,3 @@ } else { | ||
Pino.prototype = new EventEmitter() | ||
defineLevelsProperty(Pino.prototype) | ||
@@ -163,4 +192,2 @@ Pino.prototype.fatal = genLog(levels.fatal) | ||
Object.defineProperty(Pino.prototype, 'levels', {value: pino.levels}) | ||
Object.defineProperty(Pino.prototype, 'levelVal', { | ||
@@ -174,3 +201,3 @@ get: function getLevelVal () { | ||
if (this.emit) { | ||
this.emit('level-change', nums[num], num, nums[this._levelVal], this._levelVal) | ||
this.emit('level-change', this.levels.labels[num], num, this.levels.labels[this._levelVal], this._levelVal) | ||
} | ||
@@ -180,8 +207,8 @@ | ||
for (var key in levels) { | ||
if (num > levels[key]) { | ||
for (var key in this.levels.values) { | ||
if (num > this.levels.values[key]) { | ||
this[key] = noop | ||
continue | ||
} | ||
this[key] = Pino.prototype[key] | ||
this[key] = isStandardLevel(key) ? Pino.prototype[key] : genLog(num) | ||
} | ||
@@ -192,12 +219,12 @@ } | ||
Pino.prototype._setLevel = function _setLevel (level) { | ||
if (typeof level === 'number') { level = nums[level] } | ||
if (typeof level === 'number') { level = this.levels.labels[level] } | ||
if (!levels[level]) { | ||
if (!this.levels.values[level]) { | ||
throw new Error('unknown level ' + level) | ||
} | ||
this.levelVal = levels[level] | ||
this.levelVal = this.levels.values[level] | ||
} | ||
Pino.prototype._getLevel = function _getLevel (level) { | ||
return nums[this.levelVal] | ||
return this.levels.labels[this.levelVal] | ||
} | ||
@@ -300,14 +327,17 @@ | ||
return new Pino( | ||
bindings.level || this.level, | ||
this.stream, | ||
bindings.hasOwnProperty('serializers') ? extend(this.serializers, bindings.serializers) : this.serializers, | ||
this.stringify, | ||
this.end, | ||
this.name, | ||
this.timestamp, | ||
this.slowtime, | ||
data, | ||
this.cache, | ||
this.formatOpts) | ||
var opts = { | ||
level: bindings.level || this.level, | ||
levelVal: isStandardLevelVal(this.levelVal) ? undefined : this.levelVal, | ||
serializers: bindings.hasOwnProperty('serializers') ? Object.assign(this.serializers, bindings.serializers) : this.serializers, | ||
stringify: this.stringify, | ||
end: this.end, | ||
name: this.name, | ||
timestamp: this.timestamp, | ||
slowtime: this.slowtime, | ||
chindings: data, | ||
cache: this.cache, | ||
formatOpts: this.formatOpts | ||
} | ||
return new Pino(opts, this.stream) | ||
} | ||
@@ -338,2 +368,11 @@ | ||
Pino.prototype.addLevel = function addLevel (name, lvl) { | ||
if (this.levels.values.hasOwnProperty(name)) return false | ||
if (this.levels.labels.hasOwnProperty(lvl)) return false | ||
this.levels.values[name] = lvl | ||
this.levels.labels[lvl] = name | ||
lscache[lvl] = flatstr('"level":' + Number(lvl)) | ||
return true | ||
} | ||
function mapHttpRequest (req) { | ||
@@ -340,0 +379,0 @@ return { |
@@ -25,2 +25,3 @@ ![banner](pino-banner.png) | ||
* [Team](#team) | ||
* [Contributing](#contributing) | ||
* [Acknowledgements](#acknowledgements) | ||
@@ -206,2 +207,3 @@ * [License](#license) | ||
* <a href="#flush"><code>logger.<b>flush()</b></code></a> | ||
* <a href="#addLevel"><code>logger.<b>addLevel(name, lvl)</b></code></a> | ||
* <a href="#levelVal"><code>logger.<b>levelVal</b></code></a> | ||
@@ -230,3 +232,4 @@ * <a href="#level-change"><code>logger.on(<b>'level-change'</b>, fn)</code></a> | ||
* `extreme`: Enables extreme mode, yields an additional 60% performance (from 250ms down to 100ms per 10000 ops). There are trade-off's should be understood before usage. See [Extreme mode explained](#extreme). default `false` | ||
* `level`: one of `'fatal'`, `'error'`, `'warn'`, `'info`', `'debug'`, `'trace'`; also `'silent'` is supported to disable logging. | ||
* `level`: one of `'fatal'`, `'error'`, `'warn'`, `'info`', `'debug'`, `'trace'`; also `'silent'` is supported to disable logging. Any other value defines a custom level and requires supplying a level value via `levelVal`. | ||
* `levelVal`: when defining a custom log level via `level`, set to an integer value to define the new level. Defaults to `undefined`. | ||
* `enabled`: enables logging, defaults to `true`. | ||
@@ -421,2 +424,30 @@ | ||
<a name="addLevel"></a> | ||
### logger.addLevel(name, lvl) | ||
Defines a new level on the logger instance. | ||
Returns `true` on success and `false` if there was a conflict (level name or number already exists). | ||
Example: | ||
```js | ||
var pino = require('pino') | ||
var log = pino() | ||
log.addLevel('myLevel', 35) | ||
log.level = 'myLevel' | ||
log.myLevel('a message') | ||
``` | ||
Notice that `addLevel` does *not* change the current level of the logger. | ||
If you need a custom level at construction, you can supply the `level` and `levelVal` options: | ||
```js | ||
var pino = require('pino') | ||
var log = pino({level: 'myLevel', levelVal: 35}) | ||
log.myLevel('a message') | ||
``` | ||
Notice that the level is set to the custom level on construction, i.e. `log.level` does not need to be set. | ||
<a name="levelVal"></a> | ||
@@ -1017,3 +1048,2 @@ ### logger.levelVal | ||
### David Mark Clements | ||
@@ -1039,2 +1069,10 @@ | ||
## Contributing | ||
Pino is an **OPEN Open Source Project**. This means that: | ||
> Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project. | ||
See the [CONTRIBUTING.md](https://github.com/pinojs/pino/blob/master/CONTRIBUTING.md) file for more details. | ||
<a name="acknowledgements"></a> | ||
@@ -1041,0 +1079,0 @@ ## Acknowledgements |
@@ -140,1 +140,7 @@ 'use strict' | ||
}) | ||
test('flush does nothing without stream mode', function (t) { | ||
var instance = require('..')() | ||
instance.flush() | ||
t.end() | ||
}) |
@@ -29,2 +29,10 @@ 'use strict' | ||
test('the wrong level throws', function (t) { | ||
t.plan(1) | ||
var instance = pino() | ||
t.throws(function () { | ||
instance.level = 'kaboom' | ||
}) | ||
}) | ||
test('set the level by number', function (t) { | ||
@@ -31,0 +39,0 @@ t.plan(4) |
@@ -113,1 +113,30 @@ 'use strict' | ||
}) | ||
test('pino transform prettifies properties', function (t) { | ||
t.plan(1) | ||
var pretty = pino.pretty() | ||
var first = true | ||
pretty.pipe(split(function (line) { | ||
if (first) { | ||
first = false | ||
} else { | ||
t.equal(line, ' a: "b"', 'prettifies the line') | ||
} | ||
return line | ||
})) | ||
var instance = pino(pretty) | ||
instance.info({ a: 'b' }, 'hello world') | ||
}) | ||
test('pino transform treats the name with care', function (t) { | ||
t.plan(1) | ||
var pretty = pino.pretty() | ||
pretty.pipe(split(function (line) { | ||
t.ok(line.match(/\(matteo\/.*$/), 'includes the name') | ||
return line | ||
})) | ||
var instance = pino({ name: 'matteo' }, pretty) | ||
instance.info('hello world') | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
612820
8
38
2904
1085
18
17
3
- Removedobject.assign@^4.0.4
- Removedcall-bind@1.0.7(transitive)
- Removeddefine-data-property@1.1.4(transitive)
- Removeddefine-properties@1.2.1(transitive)
- Removedes-define-property@1.0.0(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedget-intrinsic@1.2.4(transitive)
- Removedgopd@1.0.1(transitive)
- Removedhas-property-descriptors@1.0.2(transitive)
- Removedhas-proto@1.0.3(transitive)
- Removedhas-symbols@1.0.3(transitive)
- Removedhasown@2.0.2(transitive)
- Removedobject-keys@1.1.1(transitive)
- Removedobject.assign@4.1.5(transitive)
- Removedset-function-length@1.2.2(transitive)