如何在每个请求的每个winston日志节点js中添加uuid?

时间:2017-02-24 07:23:59

标签: node.js express logging winston

我正在使用winston记录器。我想在每个请求中具有相同uuid的每个日志中添加 uuid

  

在app.js

var distributorapp = require('./routes/distributorapp');
app.use('/dstapp',distributorapp);
  

在routes / distributorapp.js(中间件)中

var qs = require('querystring');
var request = require('request');
var logger = require('../locallibs/logger');
var uuid = require('uuid/v1');
module.exports = {
    mddlw: function (req, res, next) {
        req.bodyData = qs.parse(req.body); // parsing body and added to request object
        req.uuid = uuid(); // Adding uuid to request to available every where throught request
        callHsmRest(req, res); // function to do some logic and handle middleware functionality
    }
};
  

在logger.js

var winston = require('winston');
var fs = require('fs');
var moment = require('moment');
var today = moment().format('YYYY-MM-DD');

if (!fs.existsSync(today)) {
    fs.mkdirSync(today);
}


function customFileFormatter(options) {
    console.log(options);
    return options.timestamp() + ' [' + options.level.toUpperCase() + '] ' + (undefined !== options.message ? options.message : '') +
            (options.meta && Object.keys(options.meta).length ? JSON.stringify(options.meta) : '');
}

var logger = new (winston.Logger)({
    transports: [
        new (winston.transports.File)({
            timestamp: function () {
                return moment().format();
            },
            json: false,
            filename: today + '/test.log',
            formatter: customFileFormatter
        })
    ]
});

现在在每个请求中我想生成uuid并将其添加到请求体中。所以我在Middleware中添加了。但是如何在customFileFormatter格式化函数中使用logger.js?

当某人使用此记录器记录任何数据时,我希望通过请求在每个日志中将uuid添加到logger格式化程序中。

如果某人需要logger.js并且

logger.info("Hello");
logger.info("Hi");

目前我有以下日志

  

2017-02-24T12:36:23 + 05:30 [INFO]“你好”
    2017-02-24T12:36:23 + 05:30 [INFO]“嗨”

但我想要

  

2017-02-24T12:36:23 + 05:30 [INFO] c00d6800-fa5f-11e6-83c2-f531bfc95472“你好”
  2017-02-24T12:36:23 + 05:30 [INFO] c00d6800-fa5f-11e6-83c2-f531bfc95472“嗨”

另外,我想根据路由中间件更改记录器文件路径。

当请求来自/dstapp时,它使用distributorapp中间件,此请求的每个后续日志都会转到路径dstapp/2017-02-24/test.log
但是,当请求来自/anotherapp时,它使用anotherapp中间件,此请求的后续日志将转到路径anotherapp/2017-02-24/test.log

我搜索过每一个地方但找不到任何解决方案 在此先感谢

4 个答案:

答案 0 :(得分:7)

我不得不面对同样的问题。 我找到了一个解决方案,使用node-uuid库为每个请求生成一个唯一的uuid,以及continuation-local-storage库,用于在模块之间共享信息。

1°。我添加了一个中间件功能来为每个请求创建uuid并将其添加到我创建的命名空间中:

<script type="text/javascript"> 
jQuery.noConflict();

$(function(){ (<< ERROR IS HERE)

    //clear value when clicked
    $('.clearme').one("focus", function() {
      $(this).val("");
    });

    //fancybox for infoLinks
    $("a.hole-link").fancybox({
                'width'   :900,
      'height'  :800,
            'type': 'iframe',
      'fitToView' : false,
      'autoSize' : false,
      'autoDimensions' : false
        });


    $(".desc-link").click(function () {

        if ( $(".desc-div").hasClass('open') ) {

            $(".desc-div").removeClass('open').animate({
                'width' : '1000',
                'height' : '1000'   
            }, 1000);

            $(".desc-inner-div").css("display","none");

            } else {    

            $(".desc-div").addClass('desc-div-open').animate({
                'width' : '100%',
                'height' : '100%'   
            }, 1000,  function() {

                $(".desc-inner-div").css("display","block");
            });

            $(".desc-link").css("display","none");
        }   
    }); 

    $(".close-link").click(function () {

        $(".desc-div").animate({
                'width' : '0px',
                'height' : '0px'    
            }, 1000, function() {
                $(".desc-div").removeClass('desc-div-open');
                $(".desc-link").css("display","inline");
            });

        $(".desc-inner-div").css("display","none");

    }); 

}); 
</script>

2º。我包装了winston库来打印获取请求的id并将其添加到每个日志中,如下所示:

var uuid = require('node-uuid');
var createNamespace = require('continuation-local-storage').createNamespace;
var myRequest = createNamespace('my request');

// Run the context for each request. Assign a unique identifier to each request
app.use(function(req, res, next) {
    myRequest.run(function() {
        myRequest.set('reqId', uuid.v1());
        next();
    });
});

有了这2段代码,你就可以得到它。

为了更容易,我创建了一个实现所有这一切的库,你可以将它用作winston,而不用担心所有这些: https://github.com/davicente/express-logger-unique-req-id

如果您想进一步了解它,可以查看这篇文章:https://solidgeargroup.com/express-logging-global-unique-request-identificator-nodejs

答案 1 :(得分:4)

我做了与ES6 Proxy类似的事情。在中间件中,我生成唯一的requestId并将其添加到app.locals。然后在logger.js中,我为日志函数添加了代理处理程序:

let logProxyHandler = {
    apply (target, thisArg, args) {
        var app = getApp(),
            id = '';
        // Some requests do not have unique ID  
        if (app && app.locals && app.locals.requestId) {
            id = `[${app.locals.requestId}]`;
        }
        args[0] = `${id} ${args[0]}`;
        return Reflect.apply(target, thisArg, args);
    }
}

然后添加:

logger.info = new Proxy(logger.info, logProxyHandler)

答案 2 :(得分:2)

我已经找到了解决方法。

  

在app.js

var logger = require('./locallibs/logger');
app.use(logger)
app.use('/dstapp',distributorapp);
  

我的logger.js

var winston = require('winston');
var fs = require('fs');
var moment = require('moment');
var today = moment().format('YYYY-MM-DD');
var uuid = require('uuid/v1');
if (!fs.existsSync(today)) {
    fs.mkdirSync(today);
}


function customFileFormatter(options) {
    return options.timestamp() + ' [' + options.level.toUpperCase() + '] ' + uuid() + ' ' + (undefined !== options.message ? options.message : '') +
            (options.meta && Object.keys(options.meta).length ? JSON.stringify(options.meta) : '');
}

winston.remove(winston.transports.Console);
winston.add(winston.transports.File,
        {
            timestamp: function () {
                return moment().format();
            },
            json: false,
            filename: today + '/test.log',
            formatter: customFileFormatter
        }
);

module.exports = function (req, res, next) {
    next()
};
  

在任何文件中

var logger = require('winston');
logger.info("First Log");
logger.info("Second Log");
  

输出

2017-02-24T18:51:39+05:30 [INFO] 2cf92c90-fa94-11e6-83ba-ebaf5a4e7acd First Log
2017-02-24T18:51:39+05:30 [INFO] 2cf9c8d0-fa94-11e6-83ba-ebaf5a4e7acd Second Log

答案 3 :(得分:0)

看看 AsyncLocalStorage (https://nodejs.org/api/async_hooks.html#async_hooks_class_asynclocalstorage),它需要 Node.js 12.17.0+、13.14.0+ 或 14.0.0+。

在幕后使用它的包是:CLS-RTRACER (https://github.com/puzpuzpuz/cls-rtracer)

对我帮助很大!