2015-06-27 2 views
4

Я создал службу Node JS REST с помощью Express. Каждый запрос, который приземляется на эту службу, имеет заголовки, такие как «X-org-ReqId» & «X-org-Tid», в котором мне нужно войти во все строки журнала, которые написаны во время выполнения этого запроса. В основном мне нужно записывать некоторую контекстуальную информацию в каждую строку журнала, чтобы помочь мне отслеживать транзакции/запросы через несколько служб.Как регистрировать запрос и идентификатор транзакции в каждой строке журнала, используя winston для Node JS?

Я использую Winston регистратор инициализирован так:

var winston = require('winston'); 
var appLogger = new(winston.Logger)({ 
    transports: [ 
    new(winston.transports.Console)({ 
     level: 'info', //TODO: Should be changed to Error in prod 
     colorize: true 
    }), 
    new(winston.transports.DailyRotateFile)({ 
     filename: '/var/log/org/my-service.log', 
     datePattern: '.yyyy-MM-dd', 
     tailable: true, 
     // handleExceptions: true, 
     json: true, 
     logstash: true 
    }) 
    ], 
    exitOnError: false 
}); 

appLogger.on('error', function(err) { 
    console.error("Logger in error", err); 
}); 

module.exports.logger = function() { 
    return appLogger; 
}; 

и в отдельных классах, где я хочу, чтобы использовать его, я так:

var logger = require('../config/logger').logger(); 

myObject.on("error", function (err) { 
       logger.error("Error connecting bucket=" + bucketId , err); 
}); 

Это произведет журнал, как это:

{"level":"info","message":"Error connecting bucket=2.....","timestamp":"2015-06-10T06:44:48.690Z"} 

Winston по умолчанию добавить timestamp в этот оператор журнала, но я также хочу регистрировать такие вещи, как req.headers ['X-org-ReqId'] & req.headers ['X-org-Tid'], чтобы я знал, какая транзакция была неудачной и какова была ошибка.

Я хочу, чтобы войти, как это:

{"level":"info","message":"Error connecting bucket=2....","timestamp":"2015-06-10T06:44:48.690Z", "tid":"a3e8b380-1caf-11e5-9a21-1697f925ec7b", "reqid":"aad28806-1caf-11e5-9a21-1697f925ec7b"} 

В Java мире мы привыкли иметь NDC, есть эквивалент в узле JS мире?

ответ

0

Я столкнулся с той же проблемой, что и вы. Это может быть не лучший способ сделать что-то, потому что вам нужно распространять объект «req», но он работает.

Я желаю, чтобы получить какое-либо улучшение :)

Frist Я перезаписать методы журналирования Уинстона в моем 'log.js':

// MyLogger definition 
function MyLogger() { 
    this.__proto__.__proto__.constructor.apply(this, arguments); 
} 

// Inheritance 
MyLogger.prototype.__proto__ = winston.Logger.prototype; 

// Overwriting methods 
MyLogger.prototype.log = function() { 
    var args = []; 
    // Copying arguments not to modify them 
    for (var i = 0; i < arguments.length; i++) { 
     args[i] = arguments[i]; 
    } 

    // Adding information in logs 
    var lastArg = args[arguments.length - 1]; 
    if (typeof lastArg === 'object' 
     && lastArg.headers) { 
     args[arguments.length - 1] = { 
      // Liste des infos ajoutées dans les logs 
      requestId: lastArg.headers['x-request-id'] ? lastArg.headers['x-request-id'] : arguments[arguments.length - 1].id, 
      host: arguments[arguments.length - 1].headers.host, 
      pId: process.pid 
     }; 
    } 

    // Calling super 
    this.__proto__.__proto__.log.apply(this, args); 
} 

MyLogger.prototype.error = function() { 
    var args = ["error"]; 
    for (var i = 0; i < arguments.length; i++) { 
     args[i + 1] = arguments[i]; 
    } 
    this.__proto__.log.apply(this, args); 
} 
MyLogger.prototype.warn = function() { 
    var args = ["warn"]; 
    for (var i = 0; i < arguments.length; i++) { 
     args[i + 1] = arguments[i]; 
    } 
    this.__proto__.log.apply(this, args); 
} 
MyLogger.prototype.info = function() { 
    var args = ["info"]; 
    for (var i = 0; i < arguments.length; i++) { 
     args[i + 1] = arguments[i]; 
    } 
    this.__proto__.log.apply(this, args); 
} 
MyLogger.prototype.verbose = function() { 
    var args = ["verbose"]; 
    for (var i = 0; i < arguments.length; i++) { 
     args[i + 1] = arguments[i]; 
    } 
    this.__proto__.log.apply(this, args); 
} 
MyLogger.prototype.debug = function() { 
    var args = ["debug"]; 
    for (var i = 0; i < arguments.length; i++) { 
     args[i + 1] = arguments[i]; 
    } 
    this.__proto__.log.apply(this, args); 
} 
MyLogger.prototype.silly = function() { 
    var args = ["silly"]; 
    for (var i = 0; i < arguments.length; i++) { 
     args[i + 1] = arguments[i]; 
    } 
    this.__proto__.log.apply(this, args); 
} 

var logger = new MyLogger({ 
    transports: [ 
     new winston.transports.File({ 
      level: config.LOG_LEVEL, 
      filename: config.LOG_FILE, 
      handleExceptions: true, 
      json: true, 
      maxsize: 5242880, //5MB 
      maxFiles: 5, 
      colorize: false 
     }), 
     new winston.transports.Console({ 
      level: config.LOG_LEVEL, 
      handleExceptions: true, 
      json: false, 
      colorize: true 
     }) 
    ], 
    exitOnError: false 
}); 

module.exports     = logger; 

Затем в каждом модуле, который нуждается в протоколирования:

var logger   = require("../log.js"); 

... 

logger.debug("My message", req); 

Создает консоль журнала и файл журнала журнала JSON с каждой информацией, необходимой для отслеживания потока.

Следующим шагом будет не распространение «req» и ​​получение необходимой информации из контекста или сеанса.

Надеюсь, что помогло :)