如何将 Winston 限制为每个日志文件只有 1 个文件描述符

How to limit Winston to only 1 file descriptor per log file

我目前在我的项目中使用 Winston 来记录一些日志文件——确切地说是 4 个不同的文件。每个文件都被大量 classes 用来对特定功能进行分组——这是一个非常典型的应用程序用例。我的问题是,到目前为止,Winston 正在为每个 class 的同一个日志文件打开一个单独的文件描述符,甚至每次使用 class 时。我 运行 使用最新版本的 Amazon Linux,我的基准是使用 470 个文件描述符。一旦启动我的应用程序,我就会跳到 1700 多个。从那里开始,当应用程序运行并实例化使用记录器的新 classes 时,会使用数千个额外的文件描述符。我们所有的日志都是使用 Winston 的容器提取的(请参见下面的代码)。

更新:我刚刚创建了一个只有 winston 的准系统应用程序,我用它创建了 1 个父记录器和成千上万的子记录器。我还使用子记录器在创建时记录消息。整个过程只需要 OS 上的 1 个文件描述符,所以很明显我们在我们的应用程序中做的事情(它要复杂得多)导致 Winston 打开一个单独的 FD...但这不是默认行为。谁看过这个吗?我正在努力向测试应用程序添加越来越多的内容,只是为了看看我是否能找到它实际开始使用更多文件描述符的时间点。

We have the method to retrieve a logger set up to be static, and so I'm starting to think that is the issue.

这仅意味着 class 不必实例化为 运行 该方法。它与 return 值的生命周期无关。

我处理这个问题的方法是使用导出 Winston 实例的简单脚本。例如:

const winston = require('winston');

const applog = winston.createLogger({
  transports: [
    new (winston.transports.Console)({ 
      level: 'debug',
      handleExceptions: true
    })
  ],
  format: winston.format.simple()
});

module.exports = applog;

然后,在我想要记录器的任何模块中,如下所示:

const applog = require('./lib/applog');

Node.js 缓存 require() 的结果,因此无论您导出什么,都保证是 完全相同的实例 用于需要模块的任何地方。

如果您愿意,可以将此方法修改为您的 class 和静态方法。只需在 class 之外(在同一个文件中)进行所有 Winston 设置,并让静态方法 return 成为实例。

好吧,现在我只是觉得自己很愚蠢。该问题与子记录器完全无关,创建子记录器绝对不会打开新的文件描述符。问题是我们总是将记录器选项传递给我们的 loggers.get(id, options) 方法,而不是如果记录器已经存在则只传递没有选项的 id。修复只用了几行代码,现在每个日志文件只打开了 1 个文件描述符。哦!