Quant Beat Logger
Quant Beat
is a simple logger that wraps around lugg which is in itself, a simple wrapper
around bunyan (a powerful logging framework). Quant Beat
adds additional super powers to lugg
and in effect bunyan by providing Mapper Diagnostic Context (MDC) features
using continuation local storage.
According to the documentation of continuation local storage, "Continuation-local storage works like thread-local storage in threaded programming, but is based on chains of Node-style callbacks instead of threads. The standard Node convention of functions calling functions is very similar to something called "continuation-passing style" in functional programming, and the name comes from the way this module allows you to set and get values that are scoped to the lifetime of these chains of function calls".
In simple terms, the continuation local storage provides a
storage area (i.e. a map) that allows asynchronous calls to store data in the map and to retrieve that data at some later point in another asynchronous
call as though the data was added in the local context of the retrieving the asynchronous call. As an example, anything that could
be put on the req
object so that it can be retrieved later can and should be put in the continuation local storage
to stop the req
object being passed around unnecessarily or being passed to every method that needs the data
that was put on the req
object
The continuation local storage allows
us to do some very powerful things in logging in an asynchronous system like node.
In quant-beat
, continuation local storage is
used for among other things, storing a traceId
that is added to the response headers (as X-TraceId
header) if you are
using the quant-beat express middleware
. The traceId
can be used to trace requests through
distributed systems such as microservices which perform distributed logging
Install
npm install quant-beat
Usage
Usage
Normal Usage
Note
quant beat
depends on lugg which takes inspiration from debug
but is not dependent on debug hence if you want to see logs at debug
or trace
level, you must set the DEBUG
environment
variable to the name of your application e.g. DEBUG=MYAPP
In the example usage below of the quant-beat
logger, traceId
will be automatically added to all log lines
'use strict'const Logger = logger// Notethe we specify the mainMethod option in the options object as we are not using the express middlewareconst logger = mainMethod: myMainMethod // this will automatically add traceId to the log entry if it does not exist already exits// If traceId exists, it will be used in subseguent log entries as though the traceId was created // in the subsequent async call const logPoint1 = { // traceId will be created here and added to the log line if does not exist logger return Promise} const logPoint2 = { // traceId will be created here and added to the log line if does not exist logger return Promise} const myMainMethod = { // traceId will be created here and added to the log line if does not exist // The traceId created at log point 1 will be used here automatically and added to the log line }
Throwing and logging exception
One of the most annoying things (for me at least) about logging is dealing with throwing and logging exception. In most cases, when exceptions are thrown, the exception should be logged before throwing. In most cases, developers do something like below
'use strict'const Logger = loggerconst logger = // this will automatically add traceId to the log entry if it does not exist already const log = { try const err = "dude!! this is the wrong type" logger throw err catch e // ... }
With quant-beat
, the boiler plate has been made simpler. The code below will log and throw the
the error passed to it.
traceId
will also be automatically added to all log lines
'use strict'const Logger = loggerconst logger = mainMethod: log // this will automatically add traceId to the log entry if it does not exist already const log = { const err = "dude!! this is the wrong type" // traceId will also be automatically added to all log lines logger}
Express Usage
To use the express middleware, simply use loggerExpress
middleware of quant-beat
as described below
The X-TraceId
header will be automatically added to the response header.
traceId
will also be automatically added to all log lines
//service-1.jsconst logPoint1 = { logger return Promise} moduleexports = logPoint1
//service-2.js const logPoint2 = { logger return Promise} moduleexports = logPoint2
// controller.js'use strict'const express = const router = const middleware = loggerExpressconst Logger = loggerconst service1 = const service2 = const logger = useUuidAsTraceId: true // Will set the Java Spring Cloud Sleuth headers`X-B3-TraceId` router router moduleexports = router
Quant Beat API
constructor([options])
-
options.mainMethod
- This ismain
method / entry point method of an application. This is required if you want to use the MDC / continuation local storage in a an application / module that does not use the express middleware (i.e this is optional even in a non-express context because the logger can still be used without the MDC but thetraceId
will not be automatically propagated). In such applications / modules,
quant-beat
uses themain
method specified byoptions.mainMethod
to determine the root of the continuation local storage context. This mainMethod option should not be set if you are using the express middleware -
options.mdcNamespace
- The namespce name that is used when the continuation local storage is created -
options.name
- The name that is passed to lugg and in effect bunyan -
{boolean} options.useBunyanFormat
- if true, uses bunyan-format module to format the output -
options.bunyanFormatOpts
- The options that are passed to bunyan-format module if{boolean} options.useBunyanFormat
is true -
options.useUuid4AsTraceId
- if true UUIDV4 will be used as the traceId else otherweise a hexadecimal of length 19 will be generated and used if using the mdc
See bunyan and lugg for more information about options
throwing(Error)
Logs and throws the supplied exception / error
getMdc
Returns the MDC (i.e. continuation local storage) associated with the current call chain. Users can add their own data to this MDC i.e (continuation local storage)
For example
'use strict'const Logger = loggerconst logger = mainMethod: myMainMethod // this will automatically add traceId to the log entry if it does not exist already const myMainMethod = { const mdc = logger mdc } const testMethod = { const someKeyValue = logger logger return Promise} const someMethodThatEventuallyCallsTestMethod = { // Doing lots of processing... // This method or one of the methods that someMethodThatEventuallyCallsTestMethod calls can retrieve the value of someKey in from the cls / mdc return }
getLoggingFramework
Returns the underlying logging framework (bunyan in this case).
The underlying framework may change in the future but that should not affect the quant-beat
interface
Methods trace, debug, info, warn, error, fatal
Calling any of the Level methods will
add traceId
to the MDC i.e (continuation local storage)
associated with logger in the current call chain
See bunyan and lugg for more information
Express Middleware API
options.setSpringCloudSleuthHeaders
- if true, the Java spring cloud sleuth headers X-B3-TraceId
will be set