Skip to content

Instantly share code, notes, and snippets.

@voxpelli
Created August 2, 2017 09:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save voxpelli/7685137e41c76574e898d789ba3ee411 to your computer and use it in GitHub Desktop.
Save voxpelli/7685137e41c76574e898d789ba3ee411 to your computer and use it in GitHub Desktop.
Part of custom Bunyan setup with Logstash output, as used by HD-Sydsvenskan
const bunyan = require('bunyan');
const bunyanExpressSerializer = require('bunyan-express-serializer');
const LogstashStream = require('./logstash-stream');
const streams = [
{
level: 'trace',
type: 'raw',
stream: new LogstashStream(outStream)
}
];
const logger = bunyan.createLogger({
name: 'app-name',
streams,
serializers: {
err: bunyan.stdSerializers.err,
req: bunyanExpressSerializer
}
});
'use strict';
const bunyan = require('bunyan');
const safeCycles = bunyan.safeCycles;
const levels = {
10: 'trace',
20: 'debug',
30: 'info',
40: 'warn',
50: 'error',
60: 'fatal'
};
const LogstashConverter = function (stream) {
this.stream = stream;
};
LogstashConverter.prototype.write = function (rec) {
const logstashEntry = {
'@timestamp': rec.time,
'@version': 1,
level: levels[rec.level],
message: rec.msg,
type: 'log',
application: rec.name,
job: rec.name
};
let skipLogPoint;
if (rec.req) {
const req = rec.req;
const res = rec.res || {};
const headers = req.headers || {};
const status = res.statusCode;
logstashEntry.method = req.method;
logstashEntry.host = headers.host;
logstashEntry.path = req.url;
logstashEntry.status = status;
logstashEntry.user_agent = headers['user-agent'];
logstashEntry.content_length = headers['content-length'];
logstashEntry.content_type = headers['content-type'];
logstashEntry.xff = headers['x-forwarded-for'];
logstashEntry.referer = headers['referer'];
if (!status || typeof status !== 'number' || ['error', 'fatal'].includes(logstashEntry.level)) {
// Leave alone
} else if (status < 400 && logstashEntry.level === 'info') {
skipLogPoint = true;
} else if (status < 500) {
logstashEntry.level = 'warn';
} else {
logstashEntry.level = 'error';
}
delete rec.req;
delete rec.res;
}
const output = Object.assign({}, rec, logstashEntry);
// remove duplicate fields
delete output.name;
delete output.time;
delete output.msg;
// Remove internal bunyan fields that won't mean anything outside of
// a bunyan context.
delete output.v;
if (!skipLogPoint) {
const str = JSON.stringify(output, safeCycles()) + '\n';
this.stream.write(str);
}
};
module.exports = LogstashConverter;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment