Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/robhaswell/canopi-node
🌴 A simple Node logging library for the cloud
https://github.com/robhaswell/canopi-node
bole cloud error-handler json logger logging logging-library node node-js node-module nodejs
Last synced: 26 days ago
JSON representation
🌴 A simple Node logging library for the cloud
- Host: GitHub
- URL: https://github.com/robhaswell/canopi-node
- Owner: robhaswell
- License: apache-2.0
- Created: 2017-01-29T12:48:44.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2023-01-11T07:55:00.000Z (about 2 years ago)
- Last Synced: 2024-12-14T15:15:21.827Z (about 2 months ago)
- Topics: bole, cloud, error-handler, json, logger, logging, logging-library, node, node-js, node-module, nodejs
- Language: JavaScript
- Homepage:
- Size: 277 KB
- Stars: 0
- Watchers: 1
- Forks: 2
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Canopi [ ![Codeship Status for robhaswell/canopi](https://app.codeship.com/projects/49893e50-c891-0134-6fb0-6ac8e955f005/status?branch=master)](https://app.codeship.com/projects/199046)
🌴 A simple Node logging library for the cloud```js
const log = canopi('app')
log.setOutputStream(process.stdout)log.info('something happened', { thing: value })
// {"timestamp":"...","name":"app","message":"something happened","thing":value}const eventLog = log('events')
log.info({ kind: 'createWidget', widget: widget })
// {"timestamp":"...","name":"app:events","kind":"createWidget","widget":widget}const widgetLog = eventLog({ widget: widget })
log.error(new Error(), { kind: 'widgetFailed' })
// {"timestamp":"...","name":"app:events","kind":"widgetFailed","widget":widget,"err":{ name, message, [code], stack }}canopi.addErrorHandler((err) => { errors.report(err) })
// Call `errors.report` with any logged `log.(err)`
```## Motivation
Canopi was created to support the logging needs of a microservices application deployed to Google Container Engine.
In order to effectively debug a distributed application, it is required to be able to trace logs which relate to a given request, event or entity.
This means that every log message needs to have some sort of context to be useful, usually supplied an object of relevant properties and values.
Additionally, there is no requirement for alternative logging streams or level-based filtering, as logs are processed by log collection tooling.Other logging solutions such as [Bole](https://github.com/rvagg/canopi) or [Bunyan](https://github.com/trentm/node-bunyan) make it difficult to log errors with some context, or are overly burdened with unnecessary functionality, so we created Canopi.
The API for Canopi is heavily inspired by Bole.
## API
### canopi('name')
Create a new **logger** with the supplied `name` to be attached to each output.
If you keep a logger-per module you don't need to pass loggers around, *keep your concerns separated*.### canopi.setOutputStream(process.stdout)
Configure the output stream.
### canopi({ aProperty: 'aValue'})
Create a new **logger** with the fields from the supplied object included in the output.
### canopi('name', { aProperty: 'aValue'})
Create a new **logger** with the supplied `name` and fields to be included in the output.
### logger#debug(), logger#info(), logger#warn(), logger#error()
Loggers have 4 roughly identical log methods, one for each of the supports log-levels.
Log levels are recorded on the output and can be used to determine the level of detail passed to the output.Log methods support the following types of input:
#### logger.\('message')
Providing a message string will output the message under the property `message`.
No substitution is performed.#### logger.\("message", { an: 'object' })
If an object is provided with a message, the behaviour is as above but with additional properties from the object included in the output.
#### logger.\({ an: 'object' })
Providing an object will log all the fields of the object.
#### logger.\(err)
**`Error` objects**: log output will include the error `name`, `message`, complete `stack` and also a `code` where there is one.
#### logger.\(err, { an: 'object' })
The error will be logged as above, but with additional properties from the object included in the output.
#### logger.\(err, 'message')
The error will be logged as above, but with the additional `message` property.
**Note:** Any other call signature will log a `CanopiUsageError` at the requested log level.
### logger()
The `logger` object returned by `canopi()` is also a function that accepts a `name` or `object` argument.
It returns a new logger whose name is the parent logger with the new name appended after a `':'` character.
This is useful for splitting a logger up for grouping events.
Consider the HTTP server case where you may want to group all events from a particular request together:```js
var log = canopi('server')http.createServer(function (req, res) {
req.log = log(uuid.v4()) // make a new sub-logger
req.log.info(req)//...
// log an error against this sub-logger
req.log.error(err)
})
```## Formatters
Canopi supports _formatters_, which are convenience functions the user can defined which format unweildy objects.
A formatting function takes two arguments, a _key_ and a function.
The function will be called with the value of the _key_ if anything is logged under that _key_.```js
canopi.setFormatter('upper', (value) => value.toUpperCase())
log.info({ upper: 'make me uppercase' })
// {"timestamp":"...","upper":"MAKE ME UPPERCASE"}canopi.setFormatter('upper', null)
log.info({ upper: 'make me uppercase' })
// {"timestamp":"...","upper":"make me uppercase"}
```A default formatter for `request` objects is available as `canopi.requestFormatter`.
This can also be set (along with others in the future) with `canopi.defaultFormatters()`.Formatters are not chainable .
## Error handlers
Canopi supports a list of error handlers which are called in turn with each error logged.
Errors are passed to error handlers only if they are the first argument to a log method, they are an instance of `Error`, and the log level is `error`.#### canopi.addErrorHandler(function callback(err) { ... })
Call `callback` with a single argument of the error instance whenever an error is logged as the first argument to a log method.
## Other methods
### canopi.quiet()
Silence the logger output by preventing it from writing to `process.stdout` and removing any error handlers.