UNPKG

cedar

Version:
175 lines (146 loc) 4.33 kB
var doNothing = function () {} /** * The `Base` log defines methods that transports will share. */ var Base = module.exports = function (config, defaults) { var cedar = require('../../cedar') // A log is a shorthand for `log.log`, among other things. var log = function () { log.log.apply(log, arguments) } // Don't run `setMethods` until all config properties are set. var setMethods = doNothing // Define properties that trigger `setMethods`. Base.resetters.forEach(function (property) { var value Object.defineProperty(log, property, { get: function () { return value }, set: function (newValue) { value = newValue setMethods.apply(log) } }) }) // Copy `config` properties to the `log`. Base.decorate(log, config, true) // Apply default properties. Base.decorate(log, defaults || Base.defaults) // Set up logging methods. Base.setMethods.apply(log) // Re-run `setMethods` if `resetters` change. setMethods = Base.setMethods // Return the fully-decorated log function. return log } /** * Some properties will reset methods if changed. */ Base.resetters = ['level', 'prefixes', 'format', 'showTrace'] /** * Cedar supports 7 levels of logging. */ Base.levels = ['trace', 'debug', 'log', 'info', 'warn', 'error', 'fatal'] /** * Share defaults between log objects. */ Base.defaults = { // Show all log messages by default. level: 'trace', // Stream to `stdout` (using `write`). stream: process.stdout, // Don't add any space to JSON. space: '', // Stringify with `JSON.stringify`. stringify: JSON.stringify, // Join arguments together as an array. join: function (args) { var list = [] for (var index = 0, length = args.length; index < length; index++) { var arg = args[index] if (arg instanceof Error) { arg = '"' + (arg.stack || arg.toString()).replace(/\n/, '\\n') + '"' } else { arg = JSON.stringify(arg, null, this.space) } list.push(arg) } return '[' + list.join(',') + ']' }, // Start messages with a prefix for each log method. prefixes: { trace: 'TRACE ', debug: 'DEBUG ', log: 'LOG ', info: 'INFO ', warn: 'WARN ', error: 'ERROR ', fatal: 'FATAL ' }, // Format a log message. format: function (message, type, prefix) { return prefix + message + '\n' } } /** * Decorate an object with the properties of another. */ Base.decorate = function (object, defaults, shouldOverwrite) { object = object || {} for (var key in defaults) { if (shouldOverwrite || (typeof object[key] === 'undefined')) { object[key] = defaults[key] } } return object } /** * Create logging methods based on the configured `level`. */ Base.setMethods = function () { var self = this var found = false if ((Base.levels.indexOf(self.level) < 0) && self.level !== 'nothing') { self.error('Unknown log level: "' + self.level + '".') } else { Base.levels.forEach(function (methodName, index) { if (methodName === self.level) { found = true } var prefix = self.prefixes[methodName] || '' var format = self.format // If this log is an Emitter, we can catch and emit errors. if (self.emit) { self[methodName] = found ? function () { var message = self.join(arguments) message = format.call(self, message, methodName, prefix) try { self.stream.write(message) } catch (e) { self.emit('error', e) } } : doNothing // Otherwise, they'll just throw. } else { self[methodName] = found ? function () { var message = self.join(arguments) message = format.call(self, message, methodName, prefix) self.stream.write(message) } : doNothing } }) // Wrap the trace method with a stack tracer. if (self.trace !== doNothing) { var traceMethod = self.trace self.trace = function () { var e = new Error('') Error.captureStackTrace(e, self.trace) var l = arguments.length arguments[l] = e.stack.split('\n').splice(2).join('\n') arguments.length = ++l traceMethod.apply(self, arguments) } } } }