Security News
The Push to Ban Ransom Payments Is Gaining Momentum
Ransomware costs victims an estimated $30 billion per year and has gotten so out of control that global support for banning payments is gaining momentum.
koa-bunyan-logger
Advanced tools
Readme
NOTE that you're reading the README of the version which targets Koa v2.x, if you want to read the current version read the README in master branch
Flexible log context and request logging middleware for koa using bunyan.
Inspired by koa-bunyan, koa-json-logger, bunyan-request, and others.
A primary goal of this module is to be as flexible as possible, while remaining relatively lightweight, leaving advanced functionality and customization the app.
var koa = require('koa');
var koaBunyanLogger = require('koa-bunyan-logger');
var app = koa();
app.use(koaBunyanLogger());
app.use(function (ctx, next) {
ctx.log.info({'Got a request from %s for %s', ctx.request.ip, ctx.path);
return next();
});
app.listen(8000);
Server:
node examples/simple.js | ./node_modules/.bin/bunyan -o short`
Client:
curl http://localhost:8000/
Server output:
07:50:14.014Z INFO koa: Got a request from ::1 for /
app.use(koaBunyanLogger());
app.use(koaBunyanLogger.requestIdContext());
app.use(koaBunyanLogger.requestLogger());
Server:
node examples/requests.js | ./node_modules/.bin/bunyan -o short
Client:
curl -H "X-Request-Id: 1234" http://localhost:8000/
Server output:
20:19:24.526Z INFO koa: --> GET / (req_id=1234)
GET / HTTP/1.1
--
req.header: {
"user-agent": "curl/7.30.0",
"host": "localhost:8000",
"accept": "*/*",
"x-request-id": "1234"
}
20:19:24.527Z INFO koa: <-- GET / 1ms (req_id=1234, duration=1, res.status=200, res.message=OK)
GET / HTTP/1.1
--
x-powered-by: koa
content-type: text/plain; charset=utf-8
content-length: 11
--
req.header: {
"user-agent": "curl/7.30.0",
"host": "localhost:8000",
"accept": "*/*",
"x-request-id": "1234"
}
It is possible to skip logs from some endpoints with ignorePath
option.
app.use(koaBunyanLogger.requestLogger({ ignorePath: ['/ping'] }))
To ensure that stack traces from request handling don't get logged in their raw non-JSON forms, you can disable the app's default error handler:
app.on('error', function () {});
Parameters:
Use an existing logger:
var bunyan = require('bunyan');
var koaBunyanLogger = require('koa-bunyan-logger');
var appLogger = bunyan.createLogger({
name: 'myapp',
level: 'debug',
serializers: bunyan.stdSerializers
});
app.use(koaBunyanLogger(appLogger));
Shortcut to create a new logger:
var koaBunyanLogger = require('koa-bunyan-logger');
app.use(koaBunyanLogger({
name: 'myapp',
level: 'debug'
}));
Options:
durationField: Name of field to store request duration in ms
levelFn: Function which will be called with (status, err) and should return the name of a log level to be used for the response log entry. The default function will log status 400-499 as warn, 500+ as error, and all other responses as info.
updateLogFields: Function which will be called with a single argument, an object containing the fields (req, res, err) to be logged with the request and response message.
The function has the opportunity to add or remove fields from the object, or return a different object to replace the default set of fields. The function will be called using the koa 'this' context, once for the request and again for the response.
updateRequestLogFields: Function which will be called with a request fields object when logging a request, after processing updateLogFields.
updateResponseLogFields: Function which will be called with a response fields object when logging a response, after processing updateLogFields. It also receives a second argument, err, if an error was thrown.
formatRequestMessage: Function which will be called to generate a log message for logging requests. The function will be called in the context of the koa 'this' context and passed the request fields object. It should return a string.
formatResponseMessage: Same as formatRequestLog, but for responses.
Basic usage:
app.use(koaBunyanLogger());
app.use(koaBunyanLogger.requestLogger());
Add custom fields to include in request and response logs:
app.use(koaBunyanLogger.requestLogger({
// Custom fields for both request and response
updateLogFields: function (fields) {
fields.authorized_user = this.user.id;
fields.client_version = this.request.get('X-Client-Version');
},
// Custom fields for response only
updateResponseLogFields: function (fields, err) {
if (err) {
fields.last_db_query = this.db.lastDbQuery();
}
}
}));
Get X-Request-Id header, or if the header does not exist, generates a random unique id for each request.
Options:
var koaBunyanLogger = require('koa-bunyan-logger');
app.use(koaBunyanLogger());
app.use(koaBunyanLogger.requestIdContext());
Or use a different header:
var koaBunyanLogger = require('koa-bunyan-logger');
app.use(koaBunyanLogger());
app.use(koaBunyanLogger.requestIdContext({
header: 'Request-Id'
}));
By default, the request id will be accessible as this.reqId and this.request.reqId:
var koaBunyanLogger = require('koa-bunyan-logger');
app.use(koaBunyanLogger());
app.use(koaBunyanLogger.requestIdContext());
app.use(function (ctx) {
ctx.response.set('X-Server-Request-Id', ctx.reqId);
ctx.body = "Hello world";
});
Adds time(label)
and timeEnd(label)
methods to the koa
context, which records the time between the time() and
timeEnd() calls for a given label.
Calls to time() and timeEnd() can be nested or interleaved as long as they're balanced for each label.
Options:
var koaBunyanLogger = require('koa-bunyan-logger');
app.use(koaBunyanLogger());
app.use(koaBunyanLogger.requestIdContext());
app.use(koaBunyanLogger.timeContext());
app.use(function (ctx) {
ctx.time('get data');
return getUser()
.then(u => {
return getFriend(u)
.then(f => [u, f]);
})
.then(data => {
let user = data[0];
let friends = data[1];
ctx.timeEnd('get data');
ctx.time('serialize');
ctx.body = serialize(user, friends);
ctx.timeEnd('serialize');
});
});
The same but using async functions
var koaBunyanLogger = require('koa-bunyan-logger');
app.use(koaBunyanLogger());
app.use(koaBunyanLogger.requestIdContext());
app.use(koaBunyanLogger.timeContext());
app.use(async function (ctx) {
ctx.time('get data');
let user = await getUser();
let friends = await getFriend(user);
ctx.timeEnd('get data');
ctx.time('serialize');
ctx.body = serialize(user, friends);
ctx.timeEnd('serialize');
});
Example output:
{"name":"koa","hostname":"localhost","pid":9228,"level":10,"label":"get data","duration":102,"msg":"","time":"2014-11-07T01:45:53.711Z","v":0}
{"name":"koa","hostname":"localhost","pid":9228,"level":10,"label":"serialize","duration":401,"msg":"","time":"2014-11-07T01:45:54.116Z","v":0}
To return different fields, such as nesting the data under
a single field, add a updateLogFields
function to the options:
var koaBunyanLogger = require('koa-bunyan-logger');
app.use(koaBunyanLogger());
app.use(koaBunyanLogger.requestIdContext());
app.use(koaBunyanLogger.timeContext({
updateLogFields: function (fields) {
return {
request_trace: {
name: fields.label,
time: fields.duration
}
};
}
}));
The internal copy of bunyan is exported as .bunyan
:
var koaBunyanLogger = require('koa-bunyan-logger');
var bunyan = koaBunyanLogger.bunyan;
FAQs
Koa middleware for logging requests using bunyan
We found that koa-bunyan-logger demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Ransomware costs victims an estimated $30 billion per year and has gotten so out of control that global support for banning payments is gaining momentum.
Application Security
New SEC disclosure rules aim to enforce timely cyber incident reporting, but fear of job loss and inadequate resources lead to significant underreporting.
Security News
The Python Software Foundation has secured a 5-year sponsorship from Fastly that supports PSF's activities and events, most notably the security and reliability of the Python Package Index (PyPI).