Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Pino is a very low overhead Node.js logger, which is inspired by Bunyan. It is designed to be as minimal as possible and to perform logging tasks with a very small performance overhead. Pino provides a simple to use API for structured logging and can be easily integrated with different transports for log processing.
Basic Logging
This feature allows you to perform basic logging tasks, such as logging informational messages.
const pino = require('pino');
const logger = pino();
logger.info('Hello, this is an info message!');
Logging with Different Levels
Pino allows you to log messages with different severity levels, such as error, warn, and debug.
const logger = pino();
logger.error('This is an error message');
logger.warn('This is a warning message');
logger.debug('This is a debug message');
Child Loggers
You can create child loggers from a parent logger, which can inherit the configuration of the parent and can also have additional properties.
const parentLogger = pino();
const childLogger = parentLogger.child({ a: 'property' });
childLogger.info('Hello from child logger');
Custom Serializers
Pino allows you to define custom serializers for logging objects in a specific way.
const logger = pino({
serializers: {
req: (req) => ({ method: req.method, url: req.url })
}
});
logger.info({ req: requestObject }, 'Request log message');
Pretty Printing
For development purposes, Pino can be combined with the 'pino-pretty' module to format logs in a more readable way.
const pino = require('pino');
const pretty = require('pino-pretty');
const logger = pino(pretty());
logger.info('This will be pretty printed');
Winston is a multi-transport async logging library for Node.js. It is designed to be a simple and universal logging library with support for multiple transports. Compared to Pino, Winston is more feature-rich and configurable but can be heavier on performance.
Bunyan is a simple and fast JSON logging library for Node.js services. Like Pino, it is inspired by the Unix philosophy and focuses on structured logging. Bunyan is more similar to Pino in terms of philosophy, but Pino claims to be faster and more efficient.
Log4js is a logging framework for Node.js, which provides flexible configuration and supports multiple appenders. It is similar to the Log4j library for Java. Compared to Pino, Log4js offers more traditional logging features but may not be as performance-optimized.
Extremely fast node.js logger, inspired by Bunyan. It also includes a shell utility to pretty-print its log files.
npm install pino --save
'use strict'
var pino = require('./')()
var info = pino.info
var error = pino.error
info('hello world')
error('this is at error level')
info('the answer is %d', 42)
info({ obj: 42 }, 'hello world')
info({ obj: 42, b: 2 }, 'hello world')
info({ obj: { aa: 'bbb' } }, 'another')
setImmediate(info, 'after setImmediate')
error(new Error('an error'))
This produces:
{"pid":13087,"hostname":"MacBook-Pro-3.home","level":30,"msg":"hello world","time":1457531561635,"v":0}
{"pid":13087,"hostname":"MacBook-Pro-3.home","level":50,"msg":"this is at error level","time":1457531561636,"v":0}
{"pid":13087,"hostname":"MacBook-Pro-3.home","level":30,"msg":"the answer is 42","time":1457531561637,"v":0}
{"pid":13087,"hostname":"MacBook-Pro-3.home","level":30,"msg":"hello world","time":1457531561637,"v":0,"obj":42}
{"pid":13087,"hostname":"MacBook-Pro-3.home","level":30,"msg":"hello world","time":1457531561638,"v":0,"obj":42,"b":2}
{"pid":13087,"hostname":"MacBook-Pro-3.home","level":30,"msg":"another","time":1457531561638,"v":0,"obj":{"aa":"bbb"}}
{"pid":13087,"hostname":"MacBook-Pro-3.home","level":50,"msg":"an error","time":1457531561639,"v":0,"type":"Error","stack":"Error: an error\n at Object.<anonymous> (/Users/davidclements/z/nearForm/pino/example.js:14:7)\n at Module._compile (module.js:413:34)\n at Object.Module._extensions..js (module.js:422:10)\n at Module.load (module.js:357:32)\n at Function.Module._load (module.js:314:12)\n at Function.Module.runMain (module.js:447:10)\n at startup (node.js:141:18)\n at node.js:933:3"}
{"pid":13087,"hostname":"MacBook-Pro-3.home","level":30,"msg":"after setImmediate","time":1457531561641,"v":0}
As far as we know, it is the fastest logger in town:
info('hello world')
:
benchBunyan*10000: 1115.193ms
benchWinston*10000: 1722.497ms
benchBole*10000: 1640.052ms
benchPino*10000: 265.622ms
info({'hello': 'world'})
:
benchBunyanObj*10000: 1252.539ms
benchWinstonObj*10000: 1729.837ms
benchBoleObj*10000: 1491.677ms
benchPinoObj*10000: 365.207ms
info('hello %s %j %d', 'world', {obj: true}, 4, {another: 'obj'})
:
benchBunyanInterpolateExtra*10000: 2607.519ms
benchWinstonInterpolateExtra*10000: 2258.154ms
benchBoleInterpolateExtra*10000: 3069.085ms
benchPinoInterpolateExtra*10000: 450.634ms
In multiple cases, pino is 6x faster than alternatives.
To use the command line tool, we can install pino
globally:
npm install -g pino
Then we simply pipe a log file through pino
:
cat log | pino
There's also a transformer flag that converts Epoch timestamps to ISO timestamps.
cat log | pino -t
For instance, pino -t
will transform this:
{"pid":14139,"hostname":"MacBook-Pro-3.home","level":30,"msg":"hello world","time":1457537229339,"v":0}
Into this:
{"pid":14139,"hostname":"MacBook-Pro-3.home","level":30,"msg":"hello world","time":"2016-03-09T15:27:09.339Z","v":0}
pino()
logger.child()
logger.level
logger.fatal()
logger.error()
logger.warn()
logger.info()
logger.debug()
logger.trace()
pino.stdSerializers.req
pino.stdSerializers.res
Returns a new logger. Allowed options are:
safe
: avoid error causes by circular references in the object tree,
default true
name
: the name of the logger, default undefined
serializers
: an object containing functions for custom serialization of objects. These functions should return an JSONifiable object and they should never throwslowtime
: Outputs ISO time stamps ('2016-03-09T15:18:53.889Z'
) instead of Epoch time stamps (1457536759176
). WARNING: This option carries a 25% performance drop, we recommend using default Epoch timestamps and transforming logs after if required. The pino -t
command will do this for you (see CLI)stream
is a Writable stream, defaults to process.stdout
.
Example:
'use strict'
var pino = require('pino')
var instance = pino({
name: 'myapp',
safe: true,
serializers: {
req: pino.stdSerializers.req
res: pino.stdSerializers.res
}
}
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:
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 leverages the output stream of the parent and its log level. These settings are immutable and pulled out during the instantiation of the child logger.
Creating a child logger is fast:
benchPinoCreation*10000: 507ms
benchBunyanCreation*10000: 1473ms
benchBoleCreation*10000: 1648ms
benchPinoCreation*10000: 461ms
benchBunyanCreation*10000: 1448ms
benchBoleCreation*10000: 1621ms
And logging throuh a child logger has little performance penalty:
benchPinoChild*10000: 394ms
benchBoleChild*10000: 1504ms
benchBunyanObj*10000: 1326ms
benchPinoChild*10000: 368ms
benchBoleChild*10000: 1486ms
Set this property to the desired logging level.
In order of priority, available levels are:
Example: logger.level = 'info'
The logging level is a minimum level. For instance if logger.level
is 'info'
then all fatal
, error
, warn
, and info
logs will be enabled.
Log at 'fatal'
level the given msg
. If the first argument is an
object, all its properties will be included in the JSON line.
If more args follows msg
, these will be used to format msg
using
util.format
Log at 'error'
level the given msg
. If the first argument is an
object, all its properties will be included in the JSON line.
If more args follows msg
, these will be used to format msg
using
util.format
Log at 'warn'
level the given msg
. If the first argument is an
object, all its properties will be included in the JSON line.
If more args follows msg
, these will be used to format msg
using
util.format
Log at 'info'
level the given msg
. If the first argument is an
object, all its properties will be included in the JSON line.
If more args follows msg
, these will be used to format msg
using
util.format
Log at 'debug'
level the given msg
. If the first argument is an
object, all its properties will be included in the JSON line.
If more args follows msg
, these will be used to format msg
using
util.format
Log at 'trace'
level the given msg
. If the first argument is an
object, all its properties will be included in the JSON line.
If more args follows msg
, these will be used to format msg
using
util.format
Function to generate a JSONifiable object out of an HTTP request from node HTTP server.
It returns an object in the form:
{
pid: 93535,
hostname: 'your host',
level: 30,
msg: 'my request',
time: '2016-03-07T12:21:48.766Z',
v: 0,
req: {
method: 'GET',
url: '/',
headers: {
host: 'localhost:50201',
connection: 'close'
},
remoteAddress: '::ffff:127.0.0.1',
remotePort: 50202
}
}
Function to generate a JSONifiable object out of an HTTP response from node HTTP server.
It returns an object in the form:
{
pid: 93581,
hostname: 'myhost',
level: 30,
msg: 'my response',
time: '2016-03-07T12:23:18.041Z',
v: 0,
res: {
statusCode: 200,
header: 'HTTP/1.1 200 OK\r\nDate: Mon, 07 Mar 2016 12:23:18 GMT\r\nConnection: close\r\nContent-Length: 5\r\n\r\n'
}
}
You should configure logrotate to rotate your log files, and just redirect the standard output of your application to a file, like so:
node server.js > /var/log/myapp.log
In order to rotate your log files, add in /etc/logrotate.d/myapp
:
/var/log/myapp.log {
su root
daily
rotate 7
delaycompress
compress
notifempty
missingok
copytruncate
}
Transports are not part of Pino. There will never be an API for transports, or support for ObjectMode Writable streams. This library is fast because it does way less than the others. We went to great lengths to make sure this library is really fast, and transports will slow things down.
So, how do you do a transport? With Pino, we create a separate process for our transport and pipe to it. It's the Unix philosophy.
Something like:
var split = require('split2')
var pump = require('pump')
var through = require('through2')
var myTransport = through.obj(function (chunk, enc, cb) {
// do whatever you want here!
console.log(chunk)
cb()
}
pump(process.stdin, split2(JSON.parse), myTransport)
Using transports in the same process causes unnecessary load and slows down Node's single threaded event loop.
If you write a transport, let us know and we will add a link here!
This project was kindly sponsored by nearForm.
MIT
FAQs
super fast, all natural json logger
The npm package pino receives a total of 6,765,178 weekly downloads. As such, pino popularity was classified as popular.
We found that pino demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.