You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

koa-bunyan-logger

Package Overview
Dependencies
Maintainers
2
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

koa-bunyan-logger - npm Package Compare versions

Comparing version

to
2.1.0

.eslintrc.yml

161

index.js

@@ -1,8 +0,21 @@

'use strict';
const bunyan = require('bunyan');
const uuid = require('uuid');
const util = require('util');
const onFinished = require('on-finished');
var bunyan = require('bunyan');
var uuid = require('uuid');
var util = require('util');
var onFinished = require('on-finished');
const updateFields = (ctx, func, data, err) => {
if (!func) return data;
try {
if (err) {
return func.call(ctx, data, err) || data;
}
return func.call(ctx, data) || data;
} catch (e) {
ctx.log.error(e);
return data;
}
};
/*

@@ -12,5 +25,5 @@ * If logger is a bunyan logger instance, return it;

*/
function createOrUseLogger(logger) {
const createOrUseLogger = (logger) => {
if (!logger || !logger.info || !logger.child) {
var loggerOpts = logger || {};
const loggerOpts = logger || {};
loggerOpts.name = loggerOpts.name || 'koa';

@@ -23,3 +36,3 @@ loggerOpts.serializers = loggerOpts.serializers || bunyan.stdSerializers;

return logger;
}
};

@@ -35,6 +48,6 @@ /*

*/
module.exports = function (loggerInstance) {
module.exports = (loggerInstance) => {
loggerInstance = createOrUseLogger(loggerInstance);
return function logger(ctx, next) {
return (ctx, next) => {
ctx.log = loggerInstance;

@@ -60,13 +73,12 @@

*/
module.exports.requestIdContext = function (opts) {
module.exports.requestIdContext = (opts) => {
opts = opts || {};
var header = opts.header || 'X-Request-Id';
var ctxProp = opts.prop || 'reqId';
var requestProp = opts.requestProp || 'reqId';
var logField = opts.field || 'req_id';
var fallbackLogger;
const header = opts.header || 'X-Request-Id';
const ctxProp = opts.prop || 'reqId';
const requestProp = opts.requestProp || 'reqId';
const logField = opts.field || 'req_id';
return function requestIdContext(ctx, next) {
var reqId = ctx.request.get(header) || uuid.v4();
return (ctx, next) => {
const reqId = ctx.request.get(header) || uuid.v4();

@@ -76,3 +88,3 @@ ctx[ctxProp] = reqId;

var logFields = {};
const logFields = {};
logFields[logField] = reqId;

@@ -105,32 +117,34 @@

*/
module.exports.requestLogger = function (opts) {
module.exports.requestLogger = (opts) => {
opts = opts || {};
var levelFn = opts.levelFn || function (status, err) {
const levelFn = opts.levelFn || function (status) {
if (status >= 500) {
return 'error';
} else if (status >= 400) {
} if (status >= 400) {
return 'warn';
} else {
return 'info';
}
return 'info';
};
var durationField = opts.durationField || 'duration';
const durationField = opts.durationField || 'duration';
var formatRequestMessage = opts.formatRequestMessage || function (data) {
const formatRequestMessage = opts.formatRequestMessage || function () {
return util.format(' <-- %s %s',
this.request.method, this.request.originalUrl);
this.request.method, this.request.originalUrl);
};
var formatResponseMessage = opts.formatResponseMessage || function (data) {
const formatResponseMessage = opts.formatResponseMessage || function (data) {
return util.format(' --> %s %s %d %sms',
this.request.method, this.request.originalUrl,
this.status, data[durationField]);
this.request.method, this.request.originalUrl,
this.status, data[durationField]);
};
return function requestLogger(ctx, next) {
var url = ctx.url;
return (ctx, next) => {
if (Array.isArray(opts.ignorePath) && opts.ignorePath.includes(ctx.path)) {
return next();
}
var requestData = {
let requestData = {
req: ctx.req

@@ -144,7 +158,7 @@ };

var startTime = new Date().getTime();
var err;
const startTime = new Date().getTime();
let err;
var onResponseFinished = function () {
var responseData = {
const onResponseFinished = () => {
let responseData = {
req: ctx.req,

@@ -158,12 +172,12 @@ res: ctx.res

responseData[durationField] = new Date().getTime() - startTime;
responseData[durationField] = Date.now() - startTime;
responseData = updateFields(ctx, opts.updateLogFields, responseData);
responseData = updateFields(ctx, opts.updateResponseLogFields,
responseData, err);
responseData, err);
var level = levelFn.call(ctx, ctx.status, err);
const level = levelFn.call(ctx, ctx.status, err);
ctx.log[level](responseData,
formatResponseMessage.call(ctx, responseData));
formatResponseMessage.call(ctx, responseData));

@@ -174,3 +188,3 @@ // Remove log object to mitigate accidental leaks

return next().catch(e => {
return next().catch((e) => {
err = e;

@@ -189,17 +203,2 @@ }).then(() => { // Emulate a finally

function updateFields (ctx, func, data, err) {
if (!func) return data;
try {
if (err) {
return func.call(ctx, data, err) || data;
} else {
return func.call(ctx, data) || data;
}
} catch (e) {
ctx.log.error(e);
return data;
}
}
/**

@@ -218,21 +217,12 @@ * Middleware which adds methods this.time(label) and this.timeEnd(label)

*/
module.exports.timeContext = function (opts) {
module.exports.timeContext = (opts) => {
opts = opts || {};
var logLevel = opts.logLevel || 'trace';
var updateLogFields = opts.updateLogFields;
const logLevel = opts.logLevel || 'trace';
const { updateLogFields } = opts;
return function timeContext(ctx, next) {
ctx._timeContextStartTimes = {};
function time(label) {
/* jshint validthis:true */
const startTimes = this._timeContextStartTimes;
ctx.time = time;
ctx.timeEnd = timeEnd;
return next();
};
function time (label) {
/*jshint validthis:true */
var startTimes = this._timeContextStartTimes;
if (startTimes[label]) {

@@ -245,6 +235,6 @@ this.log.warn('time() called for previously used label %s', label);

function timeEnd (label) {
/*jshint validthis:true */
var startTimes = this._timeContextStartTimes;
var startTime = startTimes[label];
function timeEnd(label) {
/* jshint validthis:true */
const startTimes = this._timeContextStartTimes;
const startTime = startTimes[label];

@@ -256,7 +246,7 @@ if (!startTime) { // whoops!

var duration = new Date().getTime() - startTime;
var fields = {
label: label,
duration: duration,
msg: label + ': ' + duration + 'ms'
const duration = new Date().getTime() - startTime;
let fields = {
label,
duration,
msg: `${label}: ${duration}ms`
};

@@ -269,2 +259,11 @@

}
return (ctx, next) => {
ctx._timeContextStartTimes = {};
ctx.time = time;
ctx.timeEnd = timeEnd;
return next();
};
};

@@ -271,0 +270,0 @@

{
"name": "koa-bunyan-logger",
"version": "2.0.0",
"version": "2.1.0",
"description": "Koa middleware for logging requests using bunyan",

@@ -10,3 +10,5 @@ "main": "index.js",

"scripts": {
"test": "make test"
"test": "mocha",
"test:coverage": "npx istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage",
"lint": "eslint index.js"
},

@@ -30,15 +32,15 @@ "keywords": [

"dependencies": {
"bunyan": "~1.5.0",
"on-finished": "~2.1.1",
"bunyan": "~1.8.12",
"on-finished": "~2.3.0",
"uuid": "^3.0.0"
},
"devDependencies": {
"co-mocha": "~1.1.2",
"co-supertest": "~0.0.10",
"istanbul": "~0.4.0",
"jshint": "~2.5.8",
"coveralls": "^3.0.2",
"eslint": "^5.6.1",
"eslint-config-sexy": "^5.0.0",
"istanbul": "^0.4.5",
"koa": "^2.0.0",
"mocha": "~2.3.3",
"supertest": "~1.1.0"
"mocha": "^5.2.0",
"supertest": "^3.3.0"
}
}

@@ -94,2 +94,10 @@ # bunyan-logger

### Ignoring specific path from logging
It is possible to skip logs from some endpoints with `ignorePath` option.
```js
app.use(koaBunyanLogger.requestLogger({ ignorePath: ['/ping'] }))
```
### Suppressing default error stack traces

@@ -96,0 +104,0 @@

@@ -1,11 +0,8 @@

var Koa = require('koa');
var koaBunyanLogger = require('../');
var supertest = require('supertest');
var assert = require('assert');
var bunyan = require('bunyan');
const Koa = require('koa');
const koaBunyanLogger = require('../');
const supertest = require('supertest');
const assert = require('assert');
const bunyan = require('bunyan');
require('co-mocha');
require('co-supertest');
describe('koaBunyanLogger', function () {
describe('koaBunyanLogger', () => {
var app;

@@ -15,5 +12,5 @@ var server;

beforeEach(function *() {
beforeEach(async () => {
app = new Koa();
app.on('error', function () {}); // suppress errors
app.on('error', () => {}); // suppress errors

@@ -31,3 +28,3 @@ ringBuffer = new bunyan.RingBuffer({limit: 100});

afterEach(function *() {
afterEach(async () => {
if (server) {

@@ -41,3 +38,3 @@ server.close();

var request = function () {
const request = () => {
if (!server) {

@@ -50,3 +47,3 @@ server = app.listen(0);

var record = function (i) {
const record = (i) => {
assert.ok(i >= 0 || i < ringBuffer.records.length);

@@ -56,9 +53,13 @@ return ringBuffer.records[i];

var helloWorld = function (ctx) {
const helloWorld = (ctx) => {
ctx.body = 'Hello world';
};
it('creates a default logger', function *() {
const pingResponse = (ctx) => {
ctx.body = 'ping';
};
it('creates a default logger', async () => {
app.use(koaBunyanLogger());
app.use(function (ctx) {
app.use(ctx => {
assert.ok(ctx.log);

@@ -68,9 +69,9 @@ ctx.body = '';

yield request().get('/').expect(200).end();
await request().get('/').expect(200);
});
it('can log simple requests', function * () {
it('can log simple requests', async () => {
app.use(koaBunyanLogger(ringLogger));
app.use(function (ctx) {
app.use(ctx => {
ctx.log.info('Got request');

@@ -80,3 +81,3 @@ ctx.body = 'Hello world';

yield request().get('/').expect(200).end();
await request().get('/').expect(200);

@@ -86,11 +87,11 @@ assert.equal(record(0).msg, 'Got request');

describe('koaBunyanLogger.requestLogger', function () {
var REQ_MESSAGE = / <-- GET \//;
var RES_MESSAGE = / --> GET \/ \d+ \d+ms/;
describe('koaBunyanLogger.requestLogger', () => {
const REQ_MESSAGE = / <-- GET \//;
const RES_MESSAGE = / --> GET \/ \d+ \d+ms/;
beforeEach(function () {
beforeEach(() => {
app.use(koaBunyanLogger(ringLogger));
});
function checkRequestResponse (status) {
const checkRequestResponse = status => {
assert.equal(ringBuffer.records.length, 2);

@@ -102,7 +103,7 @@ assert.ok(record(0).msg.match(REQ_MESSAGE));

it('logs requests', function *() {
it('logs requests', async () => {
app.use(koaBunyanLogger.requestLogger());
app.use(helloWorld);
yield request().get('/').expect(200).end();
await request().get('/').expect(200);

@@ -112,10 +113,17 @@ checkRequestResponse(200);

it('logs 404 errors', function *() {
it('ignore logs requests', async () => {
app.use(koaBunyanLogger.requestLogger({ ignorePath: ['/ping'] }));
app.use(pingResponse);
await request().get('/ping?t=xxx').expect(200);
assert.equal(ringBuffer.records.length, 0);
});
it('logs 404 errors', async () => {
app.use(koaBunyanLogger.requestLogger());
app.use(function (ctx) {
app.use(ctx => {
ctx.throw(404);
});
yield request().get('/').expect(404).end();
await request().get('/').expect(404);

@@ -125,10 +133,10 @@ checkRequestResponse(404);

it('logs 500 errors', function *() {
it('logs 500 errors', async () => {
app.use(koaBunyanLogger.requestLogger());
app.use(function () {
app.use(() => {
throw new Error('oh no');
});
yield request().get('/').expect(500).end();
await request().get('/').expect(500);

@@ -138,5 +146,5 @@ checkRequestResponse(500);

it('allows adding fields to request/response log data', function *() {
it('allows adding fields to request/response log data', async () => {
app.use(koaBunyanLogger.requestLogger({
updateLogFields: function (fields) {
updateLogFields: fields => {
fields.foo = 'bar';

@@ -147,3 +155,3 @@ fields.baz1 = 'fizz';

updateRequestLogFields: function (fields) {
updateRequestLogFields: fields => {
fields.addedToReq = 'hello';

@@ -153,3 +161,3 @@ delete fields.baz1;

updateResponseLogFields: function (fields, err) {
updateResponseLogFields: (fields, err) => {
fields.addedToRes = 'world';

@@ -164,7 +172,7 @@ delete fields.baz2;

app.use(function () {
app.use(() => {
throw new Error('uh oh');
});
yield request().get('/').expect(500).end();
await request().get('/').expect(500);

@@ -184,5 +192,5 @@ checkRequestResponse(500);

it('logs errors in update methods and then continues', function *() {
it('logs errors in update methods and then continues', async () => {
app.use(koaBunyanLogger.requestLogger({
updateResponseLogFields: function (fields) {
updateResponseLogFields: fields => {
throw new Error('clumsy');

@@ -194,3 +202,3 @@ }

yield request().get('/').expect(200).end();
await request().get('/').expect(200);

@@ -209,13 +217,13 @@ assert.equal(ringBuffer.records.length, 3);

describe('koaBunyanLogger.requestIdContext', function () {
it('throws an exception if this.log is not available', function *() {
describe('koaBunyanLogger.requestIdContext', () => {
it('throws an exception if this.log is not available', async () => {
app.use(koaBunyanLogger.requestIdContext());
yield request().get('/').expect(500).end();
await request().get('/').expect(500);
});
it('adds req_id from X-Request-Header to log messages', function *() {
it('adds req_id from X-Request-Header to log messages', async () => {
app.use(koaBunyanLogger(ringLogger));
app.use(koaBunyanLogger.requestIdContext());
app.use(function (ctx) {
app.use(ctx => {
ctx.log.info('hello world');

@@ -225,3 +233,3 @@ ctx.body = "";

yield request().get('/').set({'X-Request-Id': '1234'}).expect(200).end();
await request().get('/').set({'X-Request-Id': '1234'}).expect(200);

@@ -231,7 +239,7 @@ assert.equal(ringBuffer.records[0].req_id, '1234');

it('adds generated req_id to log messages if there is no header', function *() {
it('adds generated req_id to log messages if there is no header', async () => {
app.use(koaBunyanLogger(ringLogger));
app.use(koaBunyanLogger.requestIdContext());
app.use(function (ctx) {
app.use(ctx => {
ctx.log.info('hello world');

@@ -241,3 +249,3 @@ ctx.body = "";

yield request().get('/').expect(200).end();
await request().get('/').expect(200);

@@ -248,8 +256,8 @@ assert.equal(ringBuffer.records[0].req_id.length, 36);

describe('koaBunyanLogger.timeContext', function () {
it('records the time between time() and timeEnd()', function *() {
describe('koaBunyanLogger.timeContext', () => {
it('records the time between time() and timeEnd()', async () => {
app.use(koaBunyanLogger(ringLogger));
app.use(koaBunyanLogger.timeContext());
app.use(function (ctx) {
app.use(ctx => {
ctx.time('foo');

@@ -260,3 +268,3 @@ ctx.timeEnd('foo');

yield request().get('/').expect(200).end();
await request().get('/').expect(200);
assert.equal(ringBuffer.records[0].label, 'foo');

@@ -266,7 +274,7 @@ assert.equal(typeof ringBuffer.records[0].duration, 'number');

it('handles nested calls to time()', function *() {
it('handles nested calls to time()', async () => {
app.use(koaBunyanLogger(ringLogger));
app.use(koaBunyanLogger.timeContext());
app.use(function (ctx) {
app.use(ctx => {
ctx.time('foo');

@@ -279,3 +287,3 @@ ctx.time('bar');

yield request().get('/').expect(200).end();
await request().get('/').expect(200);
assert.equal(ringBuffer.records[0].label, 'bar');

@@ -287,7 +295,7 @@ assert.equal(typeof ringBuffer.records[0].duration, 'number');

it('warns if time() is called twice for the same label', function *() {
it('warns if time() is called twice for the same label', async () => {
app.use(koaBunyanLogger(ringLogger));
app.use(koaBunyanLogger.timeContext());
app.use(function (ctx) {
app.use(ctx => {
ctx.time('x');

@@ -298,3 +306,3 @@ ctx.time('x');

yield request().get('/').expect(200).end();
await request().get('/').expect(200);
assert.equal(ringBuffer.records[0].level, bunyan.WARN);

@@ -304,7 +312,7 @@ assert.ok(ringBuffer.records[0].msg.match(/called for previously/));

it('warns if timeEnd(label) is called without time(label)', function *() {
it('warns if timeEnd(label) is called without time(label)', async () => {
app.use(koaBunyanLogger(ringLogger));
app.use(koaBunyanLogger.timeContext());
app.use(function (ctx) {
app.use(ctx => {
ctx.timeEnd('blam');

@@ -314,3 +322,3 @@ ctx.body = '';

yield request().get('/').expect(200).end();
await request().get('/').expect(200);
assert.equal(ringBuffer.records[0].level, bunyan.WARN);

@@ -320,6 +328,6 @@ assert.ok(ringBuffer.records[0].msg.match(/called without/));

it('allows returning custom log fields', function *() {
it('allows returning custom log fields', async () => {
app.use(koaBunyanLogger(ringLogger));
app.use(koaBunyanLogger.timeContext({
updateLogFields: function (fields) {
updateLogFields: fields => {
return {

@@ -334,3 +342,3 @@ request_trace: {

app.use(function (ctx) {
app.use(ctx => {
ctx.time('foo');

@@ -341,3 +349,3 @@ ctx.timeEnd('foo');

yield request().get('/').expect(200).end();
await request().get('/').expect(200);
assert.equal(ringBuffer.records[0].request_trace.name, 'foo');

@@ -344,0 +352,0 @@ assert.equal(typeof ringBuffer.records[0].request_trace.time, 'number');

Sorry, the diff of this file is not supported yet