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

Posted

技术标签:

【中文标题】如何将 Winston 限制为每个日志文件只有 1 个文件描述符【英文标题】:How to limit Winston to only 1 file descriptor per log file 【发布时间】:2019-12-24 03:28:21 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

我们有方法来检索设置为静态的记录器,所以我开始认为这是问题所在。

这仅意味着不必实例化该类即可运行该方法。它与返回值的生命周期无关。

我处理这个问题的方法是使用一个简单的脚本来导出 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() 的结果,因此无论您导出什么,都保证在需要模块的任何地方都是完全相同的实例

如果您愿意,可以将此方法调整为您的类和静态方法。只需在类之外(在同一个文件中)进行所有 Winston 设置,然后让静态方法返回实例。

【讨论】:

Winston 提供了 loggers.get 方法,所以我们甚至不必这样做,它应该简单地将文件存储在 Winston 容器中,并带有一个打开的文件描述符。我们遇到的问题是,使用相同记录器的各种类的日志消息应该只为该类中的任何日志语句以不同的东西作为前缀。我们一直在使用子记录器来处理这个问题,由于如上所述的明显原因,它无法工作,因为它会耗尽我们的文件描述符。 @Evan 嗯,该子记录器中可能存在错误。您可能会发现这很有用:npmjs.com/package/winston-annotate 这有点过时了,但仍然有效。 哦酷,这看起来很有趣。我一定会看看并报告 - 谢谢! @Evan 听起来不错。我在这里的某个地方构建了它,它支持元数据,用于记录类别以及不支持结构化数据的记录器,例如 Elasticsearch。我会看看我能挖掘出什么......我真的应该更新那个包,我不知道有人在使用它! :-) 我实际上并不完全确定我是否能够尽可能多地使用它......它几乎完全符合我的要求,但我也需要一些特定于记录器的漂亮自定义设置,包括颜色主题、传输(使用自定义格式化程序)和类 -> 日志文件映射策略。我将不得不查看代码,看看它是否能够处理所有这些,但我想我会先在这里提到它,以防你有任何有用的提示。问题是我们如何创建记录器以及每个记录器的所有自定义属性 - 如果我发布整个 LogService 会有帮助吗?【参考方案2】:

现在我只是觉得自己很愚蠢。这个问题根本与子记录器无关,创建子记录器肯定不会打开新的文件描述符。问题是我们总是将记录器选项传递给我们的 loggers.get(id, options) 方法,而不是在记录器已经存在的情况下只传递没有选项的 id。该修复程序占用了所有几行代码,现在每个日志文件只打开了 1 个文件描述符。哦!

【讨论】:

以上是关于如何将 Winston 限制为每个日志文件只有 1 个文件描述符的主要内容,如果未能解决你的问题,请参考以下文章

Winston:多进程日志记录

如何将我的节点 winston JSON 输出更改为单行

如何使用 Node.js 库 Winston 为日志添加时间戳?

除第一天外,如何使用 Winston 每天轮换日志

Winston 的多个日志文件?

如何更改 winston 日志格式?