使用 ELK 堆栈的应用程序日志记录

Application logging with ELK stack

将 NLog 与 Elasticsearch target to forward logs to AWS Elasticsearch as a Service 集群一起用于 Kibana 中的可视化。

这很好用,但我担心在生产中使用它,因为 ES 集群可用性和集群故障转移的影响,当日志使用 elasticsearch-net client 通过 HTTP 发送时。

我正在考虑为 NLog 使用不同的目标,将日志发送到更可靠的目的地(文件、S3?),然后让其他东西(Logstash、AWS Lambda)接收它们并将它们发送到 ES,这最小化应用程序本身风险的方法。

想听听你的想法

更新

主要关注的是应用可用性,为防止丢失日志,使用了次要目标。

使用最新的 NLog 并将 throwExceptions 设置为 false,此时不使用异步目标,但考虑到这一点,因为我们有很多异步代码。

为了提供更多上下文,"app" 是一组 API(WebAPI 和 WCF),每分钟转速为 10 - 15K。

场景

请求来了,ES集群不可用

案例 1 - 没有异步目标的 NLog

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
        autoReload="true"
        throwExceptions="false"
        internalLogLevel="Off"
        internalLogFile="c:\temp\nlog-internal.log">

    <targets>
      <target name="elastic"
              xsi:type="BufferingWrapper"
              flushTimeout="5000">
        <target xsi:type="ElasticSearch"
                layout="${logger} | ${threadid} | ${message}"
                index="logstash-${date:format=yyyy.MM.dd}"
                includeAllProperties="true"
                uri="...">

          <field name="user"
                 layout="${windows-identity:userName=True:domain=False}"/>
          <field name="host"
                 layout="${machinename}"/>
          <field name="number"
                 layout="1"
                 layoutType="System.Int32"/>

        </target>
      </target>
    </targets>
    <rules>
      <logger name="*"
              minlevel="Debug"
              writeTo="elastic" />
    </rules>
  </nlog>

问:

案例 2 - 带有异步目标的 NLog

对 queueLimit="10000" batchSize="100" 的弹性搜索目标使用异步包装器

问:

问得好。

没什么可担心的,但正确配置 NLog 很重要。

不确定什么应该是可靠的,运行 程序或没有丢失日志消息,所以对于那些情况:

  • 如果你害怕丢失一些日志信息

    • 写入多个目标(来自 NLog),例如文件 Elasticsearch。
    • 可选,使用 fallbackgroupwrapper(以防写入目标时出错)
    • 如果启用异步,check the overflow/queue settings - 默认启用丢弃(以防止 CPU 或内存过载)
  • 如果您担心日志记录会破坏您的应用程序:

    • 使用最新稳定版的NLog
    • 不启用 throwExceptions(默认禁用)
    • 如果启用 async,错误将写入另一个线程中的目标,因此它不会破坏您的应用程序。
    • 同样在使用 asynccheck the overflow and queue settings

更新

案例一,

what happens with the main thread when target can't be reached?

没有。主队列将消息放入缓冲区。另一个 (Timer) 线程正在处理这些消息。如果失败,并且 throwException 未启用,则只会将错误写入 internalLog(启用时)。所有异常都将被捕获。当写入目标失败时,您将丢失消息。

案例二,

is another thread[B] created ?

将创建一个 Timer。这将创建一个线程来处理消息。

will subsequent requests reuse thread [B] and queue the logging requests?

是的,但不能保证它会是同一个线程。计时器将从池中创建一个线程。注意:只有一个线程会同时存在。

what happens when the queueLimit is reached?

取决于您的配置。默认情况下,它将默认丢弃,如上所述。参见 check the overflow/queue settings。就内存和 CPU 而言,这是最安全的选择。您可以选择丢弃、阻塞(停止主线程)或增加队列(通过了解内存使用情况)。

will additional threads [B1 ... Bn] be started? (this will flood connection pool)

没有。 1 个定时器,1 个线程池。有关详细信息,请查看 MSDN page for Timer, or the reference source.