BREAKING CHANGE: Importing modules with extensions is now unsupported, i.e. use `@xen-orchestra/log/configure` instead of `@xen-orchestra/log/configure.js`. Allows ESM modules to import modules without specifying extensions (just like CJS module) which will make migrating this lib to ESM painless in the future.
@xen-orchestra/log
Logging system with decoupled producers/consumer
Install
Installation of the npm package:
> npm install --save @xen-orchestra/log
Usage
Producers
Everywhere something should be logged:
import { createLogger } from '@xen-orchestra/log'
const log = createLogger('my-module')
log.debug('only useful for debugging')
log.info('this information is relevant to the user')
log.warn('something went wrong but did not prevent current action')
log.error('something went wrong')
log.fatal('service/app is going down')
// you can add contextual info
log.debug('new API request', {
method: 'foo',
params: [ 'bar', 'baz' ]
user: 'qux'
})
// by convention, errors go into the `error` field
log.error('could not join server', {
error,
server: 'example.org',
})
Consumer
Then, at application level, configure the logs are handled:
import { createLogger } from '@xen-orchestra/log'
import { configure, catchGlobalErrors } from '@xen-orchestra/log/configure'
import transportConsole from '@xen-orchestra/log/transports/console'
import transportEmail from '@xen-orchestra/log/transports/email'
const transport = transportEmail({
service: 'gmail',
auth: {
user: 'jane.smith@gmail.com',
pass: 'H&NbECcpXF|pyXe#%ZEb',
},
from: 'jane.smith@gmail.com',
to: ['jane.smith@gmail.com', 'sam.doe@yahoo.com'],
})
configure([
{
filter: process.env.DEBUG,
transport: transportConsole(),
},
{
// only levels >= warn
level: 'warn',
transport,
},
{
type: 'email',
service: 'gmail',
auth: {
user: 'jane.smith@gmail.com',
pass: 'H&NbECcpXF|pyXe#%ZEb',
},
from: 'jane.smith@gmail.com',
to: ['jane.smith@gmail.com', 'sam.doe@yahoo.com'],
},
])
// send all global errors (uncaught exceptions, warnings, unhandled rejections)
// to this logger
catchGlobalErrors(createLogger('app'))
A transport as expected by configure(transport) can be:
- a function that will receive emitted logs;
- an object with a
typeproperty and options which will be used to create a transport (see next section); - an object with a nested
transportwhich will be used if one of the following conditions is fulfilled:filter: pattern which is matched against the log namespace (can also be an array of filters);level: the minimal level of accepted logs;
- an array of transports.
Transports
Console
import transportConsole from '@xen-orchestra/log/transports/console'
configure(transportConsole())
Optional dependency:
> yarn add nodemailer pretty-format
Configuration:
import transportEmail from '@xen-orchestra/log/transports/email'
configure(
transportEmail({
service: 'gmail',
auth: {
user: 'jane.smith@gmail.com',
pass: 'H&NbECcpXF|pyXe#%ZEb',
},
from: 'jane.smith@gmail.com',
to: ['jane.smith@gmail.com', 'sam.doe@yahoo.com'],
})
)
Syslog
Optional dependency:
> yarn add split-host syslog-client
Configuration:
import transportSyslog from '@xen-orchestra/log/transports/syslog'
// By default, log to udp://localhost:514
configure(transportSyslog())
// But TCP, a different host, or a different port can be used
configure(transportSyslog({ target: 'tcp://syslog.company.lan' }))
Contributions
Contributions are very welcomed, either on the documentation or on the code.
You may:
- report any issue you've encountered;
- fork and create a pull request.