chip-log v1.0.2
Chip-log provides NodeJS with structured logging which includes extended attributes
- module, function name, and line number of the caller
- requestId pulled from async hook in the request (express)
- request logging (express)
- wrapper for Debug for faster debug logs
# Examples below using pino-pretty as formatter
[1611629195127] INFO (17914 on evil.lan): nested
module: "example-appserver"
function: "nestedHandler"
lineNum: 6
requestId: "10279b7c-69fe-4767-b36a-80f6b0b2266c"
payload: {
myData: "example payload"
}
[1611629195128] INFO (17914 on evil.lan): finished
module: "example-appserver"
function: "helloWorldHandler"
lineNum: 12
requestId: "10279b7c-69fe-4767-b36a-80f6b0b2266c"Installation
Requirements
- NodeJS 14+
- optional Express v4+
Use as a general purpose logger
Import chip-log and call the log level with a message, a json object, or both
const log = require('chip-log');
log.info('hello world')
log.error(err.message, { error })Use with Express
See example-app below, or the Chip-Log Repo on Github
Log Levels
- error
- warn
- info
- debug
- trace
- fatal
- silent
Configuration
Envars to configure
Minimum log level to dispatch, default: info
LOG_LEVEL=trace|debug|info|warn|error|fatalNamespace for the async hook context, default: APP_NAMESPACE
APP_NAMESPACE=My_ApplicationPath to the entry directory of the application (defaults to current working directory the node process is started in)
APP_BASE=./srcDisable logging, like during tests
LOG_VOID=trueRedacting specific paths in logs
REDACT='req.body.password,req.params.passwordDebug Wrapping
To wrap debug messages provided from Debug, ensure Chip-Log is the first import of the entry file for your module.
Middleware
requires Express v4+
Context Middleware
Using NodeJS Async Hooks, attach a Request ID to a request. When logging in a function as part of a Express request, the requestId will be one of the attributes on the log
In your application setup for express, when declaring middleware .use(),
aim to add the context middleware as close to being first as possible.
const app = require('express')()
const { context } = require('chip-log').middleware;
app.use(context())# example output using pino-pretty
[1611629195128] INFO (17914 on evil.lan): finished
module: "example-appserver"
function: "helloWorldHandler"
lineNum: 12
requestId: "10279b7c-69fe-4767-b36a-80f6b0b2266c"Request Middleware
Provides details of the request and response from Express for a request. If used with Context middleware, the log will also contain the requestId
In your application setup for express, when declaring middleware .use(),
you can place request anywhere before routes are declared.
If using with the Context middleware, place anywhere after, before the routes
const app = require('express')()
const { context, request } = require('chip-log').middleware;
app.use(context())
app.use(request())# example output using pino-pretty
[1612893183539] INFO (25216 on RR3D-MAC0005.lan): request completed
req: {
"id": "8c276c5d-2717-47b5-8dbf-c4d33964e057",
"method": "GET",
"url": "/favicon.ico",
"headers": {
"host": "localhost:3000",
"connection": "keep-alive",
"sec-ch-ua": "\"Google Chrome\";v=\"87\", \" Not;A Brand\";v=\"99\", \"Chromium\";v=\"87\"",
"sec-ch-ua-mobile": "?0",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36",
"accept": "image/avif,image/webp,image/apng,image/*,*/*;q=0.8",
"sec-fetch-site": "same-origin",
"sec-fetch-mode": "no-cors",
"sec-fetch-dest": "image",
"referer": "http://localhost:3000/",
"accept-encoding": "gzip, deflate, br",
"accept-language": "en-US,en;q=0.9"
},
"remoteAddress": "::1",
"remotePort": 50622
}
requestId: "8c276c5d-2717-47b5-8dbf-c4d33964e057"
res: {
"statusCode": 404,
"headers": {
"x-powered-by": "Express",
"content-security-policy": "default-src 'none'",
"x-content-type-options": "nosniff",
"content-type": "text/html; charset=utf-8",
"content-length": 150
}
}
responseTime: 2Example Application
const app = require('express')()
const log = require('chip-log')
const {
context,
request,
} = log.middleware
const nestedHandler = () => {
log.info('nested')
}
const helloWorldHandler = (req, res) => {
nestedHandler()
log.info('finished', { test: 'one' })
res.send('Hello world')
}
app.use(context())
app.use(request())
app.get('/', helloWorldHandler)
app.listen(3000, () => log.info('Running'))