all files / pnr-common/lib/node/logging/ winston-fluent.js

81.63% Statements 40/49
57.89% Branches 22/38
100% Functions 4/4
81.63% Lines 40/49
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134                                  209×   209×       209× 209× 570× 19×   551×     551× 551×       209×                                                                                         19× 19×   19×       19× 19× 19× 19×                       19× 19× 19×     19× 19×         19×    
/*
 * 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);
};