【问题标题】:Node request/connection-specific variables节点请求/连接特定变量
【发布时间】:2016-01-22 21:36:52
【问题描述】:

上下文:

我正在尝试将日志条目链接到与这些条目的生成相关联的请求。我喜欢 bunyan 的 child 记录器的概念,它允许我将请求 ID 附加到子记录器生成的任何后续条目中。我希望这个记录器可以在其他模块中使用,所以我 require 一个带有 getter 的文件来获取子记录器。这允许将其他孤立的事件(例如 getting widgets)链接到导致该条目的请求

人为的例子:

index.js

var widget = require('./widget');
var logging = require('./logging');
//...
app.use('*', function(req, res, next) {
    var logger = logging.getLogger();
    var child = logger.child({requestId: req.id}); //req.id set in earlier middleware
    logging.setLogger(child);
};
app.get('/widgets', function(req, res, next) { 
    res.json(widgets.getAll());
};
//...

widget.js

var logging = require('./logging');
//...
exports = module.exports = {
    getAll: function () {
        logging.getLogger().info("getting widgets");
        return widgets;
    }
}

问题在于状态在请求(单例?)之间共享,因此如果几乎同时发出两个请求,“获取小部件”日志条目会将requestId 属性设置为第二个请求的 id。

问题:

有没有办法让变量的范围附加到请求,而不必注入和传递req 对象(例如new widget() 和/或widget.setRequest(req)),或实例化为注入@987654332 @ 目的?将这样的对象传递给其他模块感觉就像违反了关注点分离

换句话说,为了实现我想要实现的目标,为请求而不是跨请求共享状态的最佳方式是什么?

【问题讨论】:

  • logging.setLogger(logging.getLogger().... 我的眼睛开始发烫。在 x.x 之前我从未见过如此冗长的 node.js
  • @PatrickRoberts 这是一个非常人为的例子,只是为了让大家明白这一点。建议?更多的行会有帮助吗?
  • 我找不到任何引用 req.id 的文档。这是从哪里来的?
  • 它本身并不存在,它是在之前的中间件中生成并添加到req对象中(在//...行某处)
  • 为了确保我理解总体目标,控制台日志的前缀是唯一的请求 ID?

标签: javascript node.js logging


【解决方案1】:

您可以将代码更改为:

app.use('*', function(req, res, next) { 
    req.fooBarLogger = logging.getLogger().child({requestId: req.id});
});
app.get('/widgets', function(req, res, next) { 
    res.json(widgets.getAll(req));
});

module.exports = {
    getAll: function(req) {
        req.fooBarLogger.info("getting widgets");
        return widgets;
    }
};

【讨论】:

  • 该死,打败我......我解释了一半。这是我的逻辑:我的想法是,如果您需要与特定请求对象关联的控制台日志,而不是将引用存储在 logging 模块中,您可以将其直接附加到 req 对象,因为任何控制台日志与该 req 关联的用户很可能拥有对该 req 对象的范围访问权限。
  • 我的问题中有这个“无需注入和传递 req 对象”。当小部件的依赖关系有更多的依赖关系时,它会变得更加复杂,这也需要req 对象,或者当小部件不需要它,但它的依赖关系需要它时。这就是为什么它似乎违反了 SoC 原则。如果将其注入所有依赖项和子依赖项是获得我希望的功能的唯一方法,我想我只需要接受它
  • 您不必将其附加到req。例如,您可以直接传递它。但是,这将需要 all 需要进行日志记录的函数现在采用另一个参数——这甚至更复杂,而且并不总是可能的。将记录器挂在req 对象上通常是获得所需内容的最便宜的方法。已经通过req 对象的函数可以免费获取记录器。
猜你喜欢
  • 1970-01-01
  • 2017-10-23
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多