/*
* winston-fluent.js: Transport for outputting logs to td-agent
*
* (C) 2013 Hironori Takahashi
* MIT LICENCE
*
*/
'use strict';
var util = require('util');
var fluentLogger = require('fluent-logger');
var winston = require('winston');
//
// ### function clone (obj)
// #### @obj {Object} Object to clone.
// Helper method for deep cloning pure JSON objects
// i.e. JSON objects that are either literals or objects (no Arrays, etc)
//
function clone (obj) {
// we only need to clone refrence types (Object)
Iif (!(obj instanceof Object)) {
return obj;
} else Iif (obj instanceof Date) {
return obj;
}
var copy = {};
for (var i in obj) {
if (Array.isArray(obj[i])) {
copy[i] = obj[i].slice(0);
}
else Iif (obj[i] instanceof Buffer) {
copy[i] = obj[i].slice(0);
}
else Eif (typeof obj[i] !== 'function' && obj[i] !== obj) {
copy[i] = obj[i] instanceof Object ? clone(obj[i]) : obj[i];
}
}
return copy;
}
//
// ### function fluent (options)
// #### @options {Object} Options for this instance.
// Constructor function for the fluent transport
//
// options.formatter {function} is an optional winston style log formatter
// callback. It differs from normal winston formatter callbacks in that
// it may return and {Object} as opposed to the {string} normally provided
// by winston formatters.
//
var Fluent = exports.Fluent = function (options) {
options = options || {};
Iif (!options.tag){
throw 'winston-fluent requires "tag" property';
}
Iif (!options.label){
throw 'winston-fluent requires "label" property';
}
// Set transport name
this.name = 'fluent';
//
// Merge the options for the target Fluent server.
//
this.tag = options.tag;
this.label = options.label;
this.options = options.options;
this.formatter = options.formatter;
this.fluentSender = fluentLogger.createFluentSender(this.tag, this.options);
};
//
// Inherit from `winston.Transport`.
//
util.inherits(Fluent, winston.Transport);
//
// Define a getter so that `winston.transports.Fluent`
// is available and thus backwards compatible.
//
winston.transports.Fluent = Fluent;
//
// ### function log (level, msg, [meta], callback)
// #### @level {string} Level at which to log the message.
// #### @msg {string} Message to log
// #### @meta {Object} **Optional** Additional metadata to attach
// #### @callback {function} Continuation to respond to when complete.
// Core logging method exposed to Winston. Metadata is optional.
//
Fluent.prototype.log = function (level, msg, meta, callback) {
var self = this;
var data;
Iif (typeof meta !== 'object' && meta !== null) {
meta = { meta: meta };
}
Eif (typeof this.formatter !== 'function') {
data = clone(meta) || {};
data.level = level;
Iif (msg && msg !== 'null') {
data.message = msg;
}
}
else {
data = this.formatter(clone({
level: level,
message: msg,
meta: meta
}));
}
Eif (data) {
this.fluentSender.emit(this.label, data, function(err) {
Iif (err) {
return self.emit('error', err);
}
Eif (self.fluentSender._sendQueue.length === 0) {
return self.emit('logged');
}
});
}
callback(null, true);
};
|