使用 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" 的弹性搜索目标使用异步包装器
问:
- 是否创建了另一个线程[B]?
- 后续请求是否会重用线程 [B] 并将日志记录请求排队?
- 达到队列限制时会发生什么?
- 是否会启动其他线程 [B1 ... Bn]? (这会淹没连接池)
问得好。
没什么可担心的,但正确配置 NLog 很重要。
不确定什么应该是可靠的,运行 程序或没有丢失日志消息,所以对于那些情况:
如果你害怕丢失一些日志信息
- 写入多个目标(来自 NLog),例如文件 和 Elasticsearch。
- 可选,使用 fallbackgroupwrapper(以防写入目标时出错)
- 如果启用异步,check the overflow/queue settings - 默认启用丢弃(以防止 CPU 或内存过载)
如果您担心日志记录会破坏您的应用程序:
- 使用最新稳定版的NLog
- 不启用
throwExceptions
(默认禁用)
- 如果启用
async
,错误将写入另一个线程中的目标,因此它不会破坏您的应用程序。
- 同样在使用
async
、check 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.
将 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" 的弹性搜索目标使用异步包装器
问:
- 是否创建了另一个线程[B]?
- 后续请求是否会重用线程 [B] 并将日志记录请求排队?
- 达到队列限制时会发生什么?
- 是否会启动其他线程 [B1 ... Bn]? (这会淹没连接池)
问得好。
没什么可担心的,但正确配置 NLog 很重要。
不确定什么应该是可靠的,运行 程序或没有丢失日志消息,所以对于那些情况:
如果你害怕丢失一些日志信息
- 写入多个目标(来自 NLog),例如文件 和 Elasticsearch。
- 可选,使用 fallbackgroupwrapper(以防写入目标时出错)
- 如果启用异步,check the overflow/queue settings - 默认启用丢弃(以防止 CPU 或内存过载)
如果您担心日志记录会破坏您的应用程序:
- 使用最新稳定版的NLog
- 不启用
throwExceptions
(默认禁用) - 如果启用
async
,错误将写入另一个线程中的目标,因此它不会破坏您的应用程序。 - 同样在使用
async
、check 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.