我正在使用log4net和log4net.Elasticsearch插件(这个问题很重要,问题一般是关于log4net缓冲),我正在尝试使用缓冲区。我不希望每个日志事件都单独发送给Elasticsearch。这是我的appender配置:
<appender name="ElasticSearchAppender" type="log4net.ElasticSearch.ElasticSearchAppender, log4net.ElasticSearch">
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n" />
</layout>
<connectionString value="Server=xxx.xxx.xxx.xxx;Index=api_actions_log;Port=9200"/>
<lossy value="false" />
<bufferSize value="100" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="INFO"/>
</evaluator>
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="My.Namespace.LoggingFilterAttribute" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
</appender>
正如您所看到的,我指定bufferSize = 100,但即使每条消息都立即发送到Elasticsearch。
我正在深入研究并试图找出代码中真正发生的事情。当调用Log方法时,在ES appender类上调用Append方法。方法继承自base log4net BufferingAppenderSkeleton,如下所示:
protected override void Append(LoggingEvent loggingEvent)
{
if (this.m_cb == null || this.m_bufferSize <= 1)
{
if (this.m_lossy && (this.m_evaluator == null || !this.m_evaluator.IsTriggeringEvent(loggingEvent)) && (this.m_lossyEvaluator == null || !this.m_lossyEvaluator.IsTriggeringEvent(loggingEvent)))
return;
if (this.m_eventMustBeFixed)
loggingEvent.Fix = this.Fix;
this.SendBuffer(new LoggingEvent[1]
{
loggingEvent
});
}
else
{
loggingEvent.Fix = this.Fix;
LoggingEvent loggingEvent1 = this.m_cb.Append(loggingEvent);
if (loggingEvent1 != null)
{
if (!this.m_lossy)
{
this.SendFromBuffer(loggingEvent1, this.m_cb);
}
else
{
if (this.m_lossyEvaluator == null || !this.m_lossyEvaluator.IsTriggeringEvent(loggingEvent1))
loggingEvent1 = (LoggingEvent) null;
if (this.m_evaluator != null && this.m_evaluator.IsTriggeringEvent(loggingEvent))
this.SendFromBuffer(loggingEvent1, this.m_cb);
else if (loggingEvent1 != null)
this.SendBuffer(new LoggingEvent[1]
{
loggingEvent1
});
}
}
else if (this.m_evaluator != null && this.m_evaluator.IsTriggeringEvent(loggingEvent))
this.SendFromBuffer((LoggingEvent) null, this.m_cb);
}
}
在方法的开头,它首先检查我们是否使用缓冲区。答案是肯定的,所以它进入了外部If的其他块。然后它将事件添加到缓冲区并检查是否已从缓冲区返回任何事件:
LoggingEvent loggingEvent1 = this.m_cb.Append(loggingEvent);
if (loggingEvent1 != null)
如果评估为false,则代码继续使用else if:
else if (this.m_evaluator != null && this.m_evaluator.IsTriggeringEvent(loggingEvent))
this.SendFromBuffer((LoggingEvent) null, this.m_cb);
条件被评估为true,因为我在log4net配置(级别评估程序)中有评估程序,并且消息处于适当级别。 SendFromBuffer方法立即向存储发送消息(在我的情况下是Elasticsearch)。
在分解为log4net代码之后,我不明白缓冲如何工作或我需要设置什么。在我看来总会有一些评估器(至少是级别评估器),因此总是会调用SendFromBuffer方法,导致每条消息分别发送到存储器。我想知道如何设置log4net来真正使用缓冲区。
答案 0 :(得分:3)
log4net工作正常as documented:评估者属性&#34;获取或设置ITriggeringEventEvaluator 导致缓冲区立即发送。&#34;
Evaluator是一个可插入的对象,由 BufferingAppenderSkeleton确定是否不应该记录日志事件 被缓冲,但是立即写入/发送。如果是评估员 决定事件是重要的,然后是整个内容 当前缓冲区将与事件一起发送。
通常会设置SmtpAppender以缓冲事件 发送电子邮件的费用可能相对较高。如果 重要的事件到了,比如一个错误,我们希望这样 立即交付,而不是等待缓冲区成为 充分。这是评估员进来的地方,因为它允许我们说: &#34;当一个重要事件到来时,不要担心缓冲,只是 发送你现在拥有的所有东西&#34;。
因此,每个日志级别为Info
或更高的邮件都会触发您的LevelEvaluator
并导致缓冲区被发送。