Roarr
JSON logger for Node.js.
Usage
Roarr logging is disabled by default. To enable logging, you must start program with an environment variable ROARR_LOG
set to true
, e.g.
ROARR_LOG=true node ./index.js
roarr
package exports a function that accepts the following API:
export type LoggerType =
(
context: MessageContextType,
message: string,
c?: SprintfArgumentType,
d?: SprintfArgumentType,
e?: SprintfArgumentType,
f?: SprintfArgumentType,
g?: SprintfArgumentType,
h?: SprintfArgumentType,
i?: SprintfArgumentType,
k?: SprintfArgumentType
) => void |
(
message: string,
b?: SprintfArgumentType,
c?: SprintfArgumentType,
d?: SprintfArgumentType,
e?: SprintfArgumentType,
f?: SprintfArgumentType,
g?: SprintfArgumentType,
h?: SprintfArgumentType,
i?: SprintfArgumentType,
k?: SprintfArgumentType
) => void;
Put it into words:
- First parameter can be either a string (message) or an object.
- If first parameter is an object (context), the second parameter must be a string (message).
- Arguments after the message parameter are used to enable printf message formatting.
- Printf arguments must be of a primitive type (
string | number | boolean | null
). - There can be up to 9 printf arguments (or 8 if the first parameter is the context object).
import log from 'roarr';
log('foo');
log('bar %s', 'baz');
const debug = log.child({
level: 'debug'
});
debug('qux');
debug({
quuz: 'corge'
}, 'quux');
Produces output:
{"context":{},"message":"foo","sequence":0,"time":1506776210001,"version":"1.0.0"}
{"context":{},"message":"bar baz","sequence":1,"time":1506776210002,"version":"1.0.0"}
{"context":{"level":"debug"},"message":"qux","sequence":2,"time":1506776210003,"version":"1.0.0"}
{"context":{"level":"debug","quuz":"corge"},"sequence":3,"message":"quux","time":1506776210004,"version":"1.0.0"}
Prepending context using the global state
Prepending context using the global state will affect all roarr
logs.
import log from 'roarr';
log('foo');
global.ROARR.prepend = {
taskId: 1
};
log('bar');
global.ROARR.prepend = {};
log('baz');
Produces output:
{"context":{},"message":"foo","sequence":0,"time":1506776210001,"version":"1.0.0"}
{"context":{"taskId":1},"message":"bar","sequence":1,"time":1506776210002,"version":"1.0.0"}
{"context":{},"message":"baz","sequence":2,"time":1506776210003,"version":"1.0.0"}
Prepending context using the global state is useful when the desired result is to associate all logs with a specific context for a duration of an operation, e.g. to correlate the main process logs with the dependency logs.
import log from 'roarr';
import foo from 'foo';
const taskIds = [
1,
2,
3
];
for (const taskId of taskIds) {
global.ROARR = global.ROARR || {};
global.ROARR.prepend = {
taskId
};
log('starting task ID %d', taskId);
foo(taskId);
log('successfully completed task ID %d', taskId);
global.ROARR.prepend = {};
}
Produces output:
{"context":{"taskId":1},"message":"starting task ID 1","sequence":0,"time":1506776210001,"version":"1.0.0"}
{"context":{"taskId":1},"message":"foo","sequence":1,"time":1506776210002,"version":"1.0.0"}
{"context":{"taskId":1},"message":"successfully completed task ID 1","sequence":2,"time":1506776210003,"version":"1.0.0"}
[...]
Filtering logs
Roarr is designed to print all or none logs (refer to the ROARR_LOG
environment variable documentation).
To filter logs you need to use a JSON processor, e.g. jq.
jq primer
jq
allows you to filter JSON messages using select(boolean_expression)
, e.g.
ROARR_LOG=true node ./index.js | jq 'select(.context.level == "warning" or .context.level == "error")'
Transports
A transport in most logging libraries is something that runs in-process to perform some operation with the finalised log line. For example, a transport might send the log line to a standard syslog server after processing the log line and reformatting it.
Roarr does not support in-process transports.
Roarr does not support in-process transports because Node processes are single threaded processes (ignoring some technical details). Given this restriction, Roarr purposefully offloads handling of the logs to external processes so that the threading capabilities of the OS can be used (or other CPUs).
Depending on your configuration, consider one of the following log transports:
- Beats for aggregating at a process level (written in Go).
- logagent for aggregating at a process level (written in JavaScript).
- Fluentd for aggregating logs at a container orchestration level (e.g. Kubernetes) (written in Ruby).
Environment variables
When running the script in a Node.js environment, use environment variables to control roarr
behaviour.
Name | Type | Function | Default |
---|
ROARR_LOG | Boolean | Enables/ disables logging. | false |