UNPKG

lumberjill

Version:
142 lines (123 loc) 3.79 kB
'use strict'; // external modules const assert = require('assert-plus'); const bunyan = require('bunyan'); const _ = require('lodash'); const restifyErrs = require('restify-errors'); // internal files const stringify = require('./stringify'); const CONSTANTS = require('./constants'); /** * a formatted stream so we don't have to force user to send the log * back out to bunyan binary again. * @class * @param {Object} options an options object */ function SimpleStream(options) { const self = this; /** * when true, emits logs in raw JSON. * @type {Boolean} */ self.raw = options.raw; /** * when true, prepends all logs with timestamps. * @type {Boolean} */ self.timestamp = options.timestamp; /** * when true, prepends all logs with timestamps. * @type {Boolean} */ self.forcestdout = options.forcestdout; } /** * stream's write impl. rolling our own write stream formatter. * @method write * @param {Object} record a log record * @return {undefined} */ SimpleStream.prototype.write = function(record) { const self = this; const log = this.forcestdout === true ? console.log : console.warn; // log in raw JSON format if (self.raw === true) { log(stringify(record, true)); } else { // write to stderr const timeString = record.time.toTimeString(); let out = []; if (self.timestamp === true) { out.push( '[' + timeString.slice(0, timeString.indexOf(' ')) + ']' + '[' + record.name + ']' ); } else { out.push('[' + record.name + ']'); } out = out.concat([ CONSTANTS.COLORS_MAPPING[record.level]( bunyan.nameFromLevel[record.level] ), record.msg ]); // first log contextual object // clean up the object of bunyan internal fields, clean log it. const cleanedObj = _.omit(record, CONSTANTS.BUNYAN_BLACKLIST_FIELDS); if (!_.isEmpty(cleanedObj)) { out.push(stringify(cleanedObj)); } // then log any errors if (record.err) { out.push('\n' + record.err.stack); } log(out.join(' ')); } }; /** * creates a bunyan logger using the passed in options. * @function create * @param {Object} options an option sobject * @param {Object} options.name name of the logger * @param {Boolean} [options.raw] if true, log in raw JSON * @param {Boolean} [options.level] level of the logger. defaults to info/30 * @return {Object} a bunyan logger */ function create(options) { assert.object(options, 'options'); assert.string(options.name, 'options.name'); assert.optionalBool(options.raw, 'options.raw'); assert.optionalBool(options.timestamp, 'options.timestamp'); assert.optionalNumber(options.level, 'options.level'); assert.optionalBool(options.forcestdout, 'options.forcestdout'); // backfill default options const opts = _.defaults({}, options, { level: bunyan.INFO, timestamp: false, forcestdout: false }); return bunyan.createLogger({ name: opts.name, serializers: _.assign({}, bunyan.stdSerializers, { err: restifyErrs.bunyanSerializer }), streams: [ { level: opts.level, stream: new SimpleStream(opts), type: 'raw' } ] }); } // re-export bunyan levels for convenience. module.exports = _.assign( { create: create }, _.pick(bunyan, ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL']) );