You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							109 lines
						
					
					
						
							3.8 KiB
						
					
					
				
			
		
		
	
	
							109 lines
						
					
					
						
							3.8 KiB
						
					
					
				# Asynchronous Logging
 | 
						|
 | 
						|
In essence, asynchronous logging enables even faster performance by Pino.
 | 
						|
 | 
						|
In Pino's standard mode of operation log messages are directly written to the
 | 
						|
output stream as the messages are generated with a _blocking_ operation.
 | 
						|
Asynchronous logging works by buffering
 | 
						|
log messages and writing them in larger chunks.
 | 
						|
 | 
						|
```js
 | 
						|
const pino = require('pino')
 | 
						|
const logger = pino(pino.destination({
 | 
						|
  dest: './my-file', // omit for stdout
 | 
						|
  minLength: 4096, // Buffer before writing
 | 
						|
  sync: false // Asynchronous logging
 | 
						|
}))
 | 
						|
```
 | 
						|
 | 
						|
* See [`pino.destination`](/docs/api.md#pino-destination)
 | 
						|
* `pino.destination` is implemented on [`sonic-boom` ⇗](https://github.com/mcollina/sonic-boom).
 | 
						|
 | 
						|
## Caveats
 | 
						|
 | 
						|
This has a couple of important caveats:
 | 
						|
 | 
						|
* 4KB of spare RAM will be needed for logging
 | 
						|
* As opposed to the default mode, there is not a one-to-one relationship between
 | 
						|
  calls to logging methods (e.g. `logger.info`) and writes to a log file
 | 
						|
* There is a possibility of the most recently buffered log messages being lost
 | 
						|
  (up to 4KB of logs)
 | 
						|
  * For instance, a power cut will mean up to 4KB of buffered logs will be lost
 | 
						|
 | 
						|
So in summary, use asynchronous logging only when performing an extreme amount of
 | 
						|
logging, and it is acceptable to potentially lose the most recent logs.
 | 
						|
 | 
						|
* Pino will register handlers for the following process events/signals so that
 | 
						|
  Pino can flush the asynchronous logger buffer:
 | 
						|
 | 
						|
  + `beforeExit`
 | 
						|
  + `exit`
 | 
						|
  + `uncaughtException`
 | 
						|
  + `SIGHUP`
 | 
						|
  + `SIGINT`
 | 
						|
  + `SIGQUIT`
 | 
						|
  + `SIGTERM`
 | 
						|
 | 
						|
  In all of these cases, except `SIGHUP`, the process is in a state that it
 | 
						|
  *must* terminate. Thus, if an `onTerminated` function isn't registered when
 | 
						|
  constructing a Pino instance (see [pino#constructor](api.md#constructor)),
 | 
						|
  then Pino will invoke `process.exit(0)` when no error has occurred, or
 | 
						|
  `process.exit(1)` otherwise. If an `onTerminated` function is supplied, it
 | 
						|
  is the responsibility of the `onTerminated` function to manually exit the process.
 | 
						|
 | 
						|
  In the case of `SIGHUP`, we will look to see if any other handlers are
 | 
						|
  registered for the event. If not, we will proceed as we do with all other
 | 
						|
  signals. If there are more handlers registered than just our own, we will
 | 
						|
  simply flush the asynchronous logging buffer.
 | 
						|
 | 
						|
### AWS Lambda
 | 
						|
 | 
						|
On AWS Lambda we recommend to call `dest.flushSync()` at the end
 | 
						|
of each function execution to avoid losing data.
 | 
						|
 | 
						|
## Usage
 | 
						|
 | 
						|
The `pino.destination({ sync: false })` method will provide an asynchronous destination.
 | 
						|
 | 
						|
```js
 | 
						|
const pino = require('pino')
 | 
						|
const dest = pino.destination({ sync: false }) // logs to stdout with no args
 | 
						|
const logger = pino(dest)
 | 
						|
```
 | 
						|
 | 
						|
<a id='log-loss-prevention'></a>
 | 
						|
## Log loss prevention
 | 
						|
 | 
						|
The following strategy can be used to minimize log loss:
 | 
						|
 | 
						|
```js
 | 
						|
const pino = require('pino')
 | 
						|
const dest = pino.destination({ sync: false })
 | 
						|
const logger = pino(dest)
 | 
						|
 | 
						|
// asynchronously flush every 10 seconds to keep the buffer empty
 | 
						|
// in periods of low activity
 | 
						|
setInterval(function () {
 | 
						|
  logger.flush()
 | 
						|
}, 10000).unref()
 | 
						|
 | 
						|
// use pino.final to create a special logger that
 | 
						|
// guarantees final tick writes
 | 
						|
const handler = pino.final(logger, (err, finalLogger, evt) => {
 | 
						|
  finalLogger.info(`${evt} caught`)
 | 
						|
  if (err) finalLogger.error(err, 'error caused exit')
 | 
						|
  process.exit(err ? 1 : 0)
 | 
						|
})
 | 
						|
// catch all the ways node might exit
 | 
						|
process.on('beforeExit', () => handler(null, 'beforeExit'))
 | 
						|
process.on('exit', () => handler(null, 'exit'))
 | 
						|
process.on('uncaughtException', (err) => handler(err, 'uncaughtException'))
 | 
						|
process.on('SIGINT', () => handler(null, 'SIGINT'))
 | 
						|
process.on('SIGQUIT', () => handler(null, 'SIGQUIT'))
 | 
						|
process.on('SIGTERM', () => handler(null, 'SIGTERM'))
 | 
						|
```
 | 
						|
 | 
						|
* See [`pino.destination` api](/docs/api.md#pino-destination)
 | 
						|
* See [`pino.final` api](/docs/api.md#pino-final)
 | 
						|
* See [`destination` parameter](/docs/api.md#destination)
 |