如何在每个请求的每个 winston 日志节点 js 中添加 uuid?
How to add uuid in every winston log node js per request?
我正在使用 winston 记录器。我想在每个请求具有相同 uuid 的每个日志中添加 uuid。
In app.js
var distributorapp = require('./routes/distributorapp');
app.use('/dstapp',distributorapp);
In routes/distributorapp.js(Middleware)
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
}
};
In 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 并将其添加到请求 body.So 我在 Middleware.But 中添加了它如何在 customFileFormatter 格式化程序函数中对 logger.js 可用?
当有人使用此记录器记录任何数据时,我希望通过请求在每个日志的记录器格式化程序中预先添加 uuid。
如果有人需要 logger.js
并执行
logger.info("Hello");
logger.info("Hi");
目前关注我有关注日志
2017-02-24T12:36:23+05:30 [INFO] "Hello"
2017-02-24T12:36:23+05:30 [INFO] "Hi"
但是我想要
2017-02-24T12:36:23+05:30 [INFO] c00d6800-fa5f-11e6-83c2-f531bfc95472 "Hello"
2017-02-24T12:36:23+05:30 [INFO] c00d6800-fa5f-11e6-83c2-f531bfc95472 "Hi"
另外我想根据路由中间件更改记录器文件路径。
当前,当请求来自 /dstapp
时,它使用 distributorapp
中间件,此请求的每个后续日志都会转到路径 dstapp/2017-02-24/test.log
但是当请求来自 /anotherapp
时,它使用 anotherapp
中间件,此请求的后续日志转到路径 anotherapp/2017-02-24/test.log
我找遍了所有地方,但找不到任何解决方案
提前致谢
我对 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)
我已经找到解决方法了。
In app.js
var logger = require('./locallibs/logger');
app.use(logger)
app.use('/dstapp',distributorapp);
My 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()
};
In any file
var logger = require('winston');
logger.info("First Log");
logger.info("Second Log");
Output is
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
我不得不面对同样的问题。
我找到了一个解决方案,使用 node-uuid 库为每个请求生成唯一的 uuid,并使用 continuation-local-storage 库在模块之间共享信息。
1º。我添加了一个中间件功能来为每个请求创建 uuid 并将其添加到我创建的命名空间中:
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 库以打印获取请求的 ID 并将其添加到每个日志中,如下所示:
var winston = require('winston');
var getNamespace = require('continuation-local-storage').getNamespace;
// Wrap Winston logger to print reqId in each log
var formatMessage = function(message) {
var myRequest = getNamespace('my request');
message = myRequest && myRequest.get('reqId') ? message + " reqId: " + myRequest.get('reqId') : message;
return message;
};
var logger = {
log: function(level, message) {
winstonLogger.log(level, formatMessage(message));
},
error: function(message) {
winstonLogger.error(formatMessage(message));
},
warn: function(message) {
winstonLogger.warn(formatMessage(message));
},
verbose: function(message) {
winstonLogger.verbose(formatMessage(message));
},
info: function(message) {
winstonLogger.info(formatMessage(message));
},
debug: function(message) {
winstonLogger.debug(formatMessage(message));
},
silly: function(message) {
winstonLogger.silly(formatMessage(message));
}
};
module.exports = logger;
有了这2段代码你就搞定了。
为了方便起见,我创建了一个实现所有这些的库,您可以像 winston 一样使用它,而不必担心所有这些事情:
https://github.com/davicente/express-logger-unique-req-id
如果你想深入了解一下,可以看看这篇文章:https://solidgeargroup.com/express-logging-global-unique-request-identificator-nodejs
看看 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)
对我帮助很大!
我正在使用 winston 记录器。我想在每个请求具有相同 uuid 的每个日志中添加 uuid。
In app.js
var distributorapp = require('./routes/distributorapp');
app.use('/dstapp',distributorapp);
In routes/distributorapp.js(Middleware)
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
}
};
In 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 并将其添加到请求 body.So 我在 Middleware.But 中添加了它如何在 customFileFormatter 格式化程序函数中对 logger.js 可用?
当有人使用此记录器记录任何数据时,我希望通过请求在每个日志的记录器格式化程序中预先添加 uuid。
如果有人需要 logger.js
并执行
logger.info("Hello");
logger.info("Hi");
目前关注我有关注日志
2017-02-24T12:36:23+05:30 [INFO] "Hello"
2017-02-24T12:36:23+05:30 [INFO] "Hi"
但是我想要
2017-02-24T12:36:23+05:30 [INFO] c00d6800-fa5f-11e6-83c2-f531bfc95472 "Hello"
2017-02-24T12:36:23+05:30 [INFO] c00d6800-fa5f-11e6-83c2-f531bfc95472 "Hi"
另外我想根据路由中间件更改记录器文件路径。
当前,当请求来自 /dstapp
时,它使用 distributorapp
中间件,此请求的每个后续日志都会转到路径 dstapp/2017-02-24/test.log
但是当请求来自 /anotherapp
时,它使用 anotherapp
中间件,此请求的后续日志转到路径 anotherapp/2017-02-24/test.log
我找遍了所有地方,但找不到任何解决方案 提前致谢
我对 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)
我已经找到解决方法了。
In app.js
var logger = require('./locallibs/logger');
app.use(logger)
app.use('/dstapp',distributorapp);
My 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()
};
In any file
var logger = require('winston');
logger.info("First Log");
logger.info("Second Log");
Output is
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
我不得不面对同样的问题。 我找到了一个解决方案,使用 node-uuid 库为每个请求生成唯一的 uuid,并使用 continuation-local-storage 库在模块之间共享信息。
1º。我添加了一个中间件功能来为每个请求创建 uuid 并将其添加到我创建的命名空间中:
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 库以打印获取请求的 ID 并将其添加到每个日志中,如下所示:
var winston = require('winston');
var getNamespace = require('continuation-local-storage').getNamespace;
// Wrap Winston logger to print reqId in each log
var formatMessage = function(message) {
var myRequest = getNamespace('my request');
message = myRequest && myRequest.get('reqId') ? message + " reqId: " + myRequest.get('reqId') : message;
return message;
};
var logger = {
log: function(level, message) {
winstonLogger.log(level, formatMessage(message));
},
error: function(message) {
winstonLogger.error(formatMessage(message));
},
warn: function(message) {
winstonLogger.warn(formatMessage(message));
},
verbose: function(message) {
winstonLogger.verbose(formatMessage(message));
},
info: function(message) {
winstonLogger.info(formatMessage(message));
},
debug: function(message) {
winstonLogger.debug(formatMessage(message));
},
silly: function(message) {
winstonLogger.silly(formatMessage(message));
}
};
module.exports = logger;
有了这2段代码你就搞定了。
为了方便起见,我创建了一个实现所有这些的库,您可以像 winston 一样使用它,而不必担心所有这些事情: https://github.com/davicente/express-logger-unique-req-id
如果你想深入了解一下,可以看看这篇文章:https://solidgeargroup.com/express-logging-global-unique-request-identificator-nodejs
看看 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)
对我帮助很大!