Under the hood

Logging Levels

Each log record holds a level to represent its importance to the workflow. Although you could use any custom number value, oddlog provides some predefined standard levels:

0 - SILENT
1 - TRACE
2 - DEBUG
3 - VERBOSE
4 - INFO
5 - WARN
6 - ERROR
7 - FATAL

It is best practice to scatter logging messages over as many levels as there are distinct levels of significance within a module. If the module has some messages to tell that are more relevant than INFO but less relevant than WARN it's completely fine to use a level like 4.5.

We chose the ascending level in contrast to some popular logging libraries due to two reasons:

  1. exit codes of programs being 0 is fine, >=1 is error; thus ascending to error.
  2. there is no possible severity level below silent, but one could imagine an open range upwards.

Raw log record

At least @oddlog/cli@1.0.0 is required for the current schema.

[
  {Number}  SCHEMA_VERSION, // 3
  {?String} typeKey,        // default: "_type"
  {?Object} meta,           // default: [ os.release(), os.hostname(), process.pid ]
  {String}  loggerName,
  {Number}  timestamp,
  {Number}  severity,
  {?Array}  source: [
    {String} file,
    {Number} row,
    {Number} col
  ],
  {?String} message,
  {?Object} [payload],
]

Example:

[3,"_type",["4.17.8-1-ARCH","zerg",31522],"my-app:http",1533429331401,4,["lib/index.js",42,21],"hello world",{"lorem":"ipsum",answer:42}]

The Array syntax has been chosen due to high parsing performance and compactness. The actual record gets written part by part instead of a single JSON.stringify on an actual array object; this provides the highest possible record stringify speed as only the meta and payload fields need to be stringified generically. The order of the fields is chosen to use the order of specificity according to SCHEMA < PROCESS < LOGGER < LOG. Thus building the prefix string of the schema, process and logger does not have to happen for each log record; saving quite some computation time.

The typeKey allows customization regarding how to handle attributes of the payload within the interpreting tool (e.g. cli). By default, everything within the payload has the default type "plain"; except for the top-level attributes "err" and "error", they have the default type "error". Types can be overwritten for any object that is (part of) the payload by setting the value of its typeKey attribute (e.g. {"_type":"error"}).

Last Updated: 11/7/2018, 7:26:06 PM