如何记录 - 12因素应用方式

ala*_*udi 14 logging node.js express

我想知道记录我的节点应用程序背后的最佳实践.我正在https://12factor.net/logs上阅读12因素应用程序指南,并指出应始终将日志发送到stdout.很酷,但那么有人会如何管理生产中的日志?是否有一个应用程序可以获取发送给它的任何内容stdout?另外,是否建议我只登录stdout而不是stderr?我很欣赏这个问题的观点.

Bri*_*ker 12

是否有一个应用程序可以获取发送给它的任何内容stdout

您链接到的页面提供了一些日志管理工具的示例,但最简单的版本只是将应用程序的输出重定向到文件.所以在bash中node app.js > app.out.您也可以分裂你stdoutstderr喜欢node app.js 2> app.err 1> app.out.

您还可以使用某种服务从该文件中收集日志,然后将它们编入索引以便在其他位置进行搜索.

仅登录的建议背后的想法stdout是让环境控制如何处理日志,因为应用程序不一定知道它最终将在其中运行的环境.此外,通过将所有日志视为事件流,您可以选择如何处理此流,直至环境.例如,您可能希望将日志流直接发送到日志聚合服务,或者您可能希望先对其进行预处理,然后将结果流式传输到其他位置.如果您要求特定输出(例如记录到文件),则会降低服务的可移植性.

12因素指南的两个主要目标是"适合在现代云平台上部署"并提供"执行环境之间的最大可移植性".在您的实例上可能有临时存储的云平台上,或者运行相同服务的许多实例,您需要将日志聚合到某个中央存储中.通过提供日志流,您可以将其保留到环境中以协调如何执行此操作.如果将它们直接放入文件中,则必须根据每个应用程序决定放置日志的位置定制环境,然后将它们重定向到中央存储.stdout因此,使用日志主要是一种有用的约定.


pau*_*sm4 6

我认为明确地说“ [Web]应用程序应将日志写入”是一个错误stdout

相反,我建议:

一)专业品质,强大的Web应用程序应该HAVE日志

b)应用程序应将“日志”视为抽象的“流”对象

c)理想情况下,可以将记录器实现配置为写入stdout,stderr,文件,带日期戳的文件,旋转文件,按严重性级别进行过滤等,等等。

我强烈认为,在没有任何中间“记录器”抽象的情况下,对stdout进行硬编码写入是POOR做法。

这是一篇好文章:

https://blog.risingstack.com/node-js-logging-tutorial/

  • -1,因为这似乎并没有真正回答问题,而是提出了矛盾的观点。记录 12FA 的全部目的是分离这些关注点,这似乎也忽略了日志事件、*日志*、船舶和接收器之间的区别。你的“理想”是将所有概念混在一起(这并不罕见),这与 12FA 日志记录实践相反。--“记录器”是将日志事件发送到日志(stdout)的,船是将日志事件发送到日志(stdout)的将该流的内容移动到接收器(文件、splunk 等) (3认同)

Sin*_*tic 5

很酷,但是那么人们将如何管理生产中的日志呢?

原木水槽正是您所寻找的。

是否有一个应用程序可以收集发送到标准输出的所有内容?

是和不是。它是日志船(或日志路由器)。它可能是一个应用程序,但它实际上只是您的应用程序并不真正了解的执行或运行时环境中的某个进程。

另一种看待这个问题的方法是关注点分离。正如在另一个答案中所述,它是让环境拥有日志所发生的事情,并且只期望应用程序完全关心发出日志事件。我认为 12FA 文档中缺少的是,他们不会尝试为您完成这个难题,因为对于从 stdout 去哪里会有不同的意见,所以我将根据我的个人经验添加那些缺失的部分来帮助您以及我在云空间中看到的一切。

记录器将日志事件发送到日志流(也称为“日志”)

不用说,您的应用程序应该具有某种“记录器”抽象,但这实际上只是将日志事件发送到标准输出的入口点。该抽象的职责是以所需的格式将您的日志事件发送到日志流(stdout),然后您的应用程序的职责就完成了。事实上,12FA文档到这里就结束了。

12 Factor App 旨在创建云友好且可移植的应用程序,因此您必须假设您甚至不知道执行/运行时环境是什么。所以我们不知道“环境”是什么,这就是重点。因此,从这里开始,执行/运行时环境有责任处理流并将其移动到接收器。

日志船/路由器实现日志流到日志接收器

因此,我们现在解决这个问题的方法是为 stdout 流提供某种侦听器,该侦听器将获取输出并将其发送到下游的日志接收器。

“船”(也称为日志路由器抓取器)可能是环境或运行时中的某个东西,或者说实话,它可能是运行应用程序后台的东西(流侦听器);它可能是其他一些自定义流程;它甚至可能是 Kafka——我认为 GCP 使用 fluidd 从各种来源收集日志并将它们放入 stackdriver 中。关键是它应该是您的应用程序中的一个单独的“类”,您的应用程序并不真正了解它。它只是监听流并将其发送到接收器。在某些解决方案中,这是您需要构建的东西,在其他解决方案中,它由您的平台处理。简单地说“如何将水流送到水槽?”

“水槽”是目的地。这可以是控制台(你好,它实际上是一个流读取器),它可以是一个文件,它可以是 Splunk、Application Insights、Stack Driver 等。有简单的解决方案,也有更大、更复杂的企业解决方案,但这个概念仍然存在相同。

简而言之,如果我们向标准输出写入“我们如何管理生产中的日志”,这就是您问题的答案。这是您正在寻找的日志接收器日志聚合器。在 12FA 的白话中,“splunk”之类的东西并不是“log”。日志是流本身(stdout)。就 12FA 而言 - 您的应用程序不知道接收器是什么,理想情况下,它不应该知道,因为该接收器可能会发生变化,在这种情况下,您的所有应用程序都会崩溃,或者可能有许多不同的接收器,这可能会让您陷入困境应用程序关闭,特别是如果您直接写入接收器而不是首先写入标准输出。如果没有别的,这只是另一个脱钩练习。

您可以发送到单个接收器,一次发送到多个接收器,或者您可以发送到单个接收器并让其他一些组件将您的日志从该接收器“运送”到另一个接收器(例如写入滚动文件并让路由器将其抓取到斯普兰克)。仅取决于您的需求。

实际上,默认情况下,您可以看到这种情况在云提供商中越来越多地出现。例如,在 GCP 上,所有发送到 stdout 的日志都会自动获取并发送到 stackdriver。在 Azure 中,只要将检测添加到 .NET 应用程序(应用程序诊断包),它就会向 stdout 发出事件,并由 azure 监视器拾取。也有越来越多的包开始实现这种模式,因此在 .NET 中,您可以使用 Serilog 来抽象大多数这些概念。

Logger -> Log Event -> Log [stream] (stdout) -> Sink -> Your eyeballs

  • Logger:用于发出日志的东西,通常是一个抽象(例如 Serilog、NLog、Log4net)
  • 日志事件:单个日志本身
  • 日志流(或“日志”):标准输出,它是所有事件的无缓冲、按时间排序的聚合,没有开始或结束。
  • 日志船/路由器:将流发送到一个或多个接收器的传输。(例如,在进程中,如 log4net,在进程外,如 Fluentd)
  • 日志接收器:您实际上正在查看的东西,例如控制台、文件或索引/搜索引擎或分析/监控平台(例如 splunk、datadog、appinsights、stackdriver 等)

有些软件包和平台提供了其中一个或多个部分,但所有这些部分始终存在。当您了解 12FA 日志记录时,它们会变得更有意义。