如何为log4net创建异步包装?

默认情况下,log4net是一种同步日志记录机制,我想知道是否有办法使用log4net进行异步日志记录?

如果你去log4net网站,你可以找到一些例子,其中至少有一个是异步Appender。

http://logging.apache.org/log4net/release/example-apps.html

请注意,我没有使用这些示例中的任何一个,所以我不能以某种方式保证它们。

这是从代码存储库中的log4net Examples区域到实际异步appender的链接:

http://svn.apache.org/viewvc/logging/log4net/trunk/examples/net/2.0/Appenders/SampleAppendersApp/cs/src/Appender/AsyncAppender.cs?view=markup

我简单地看了一眼,它显然是一个或多个“常规”Appender的包装器。 在每个日志记录请求(包含一个或多个LoggingEvent对象)上,使用ThreadPool线程将LoggingEvents转发到包装的Appender列表。

只是想提供我的完整解决方案供参考。 一些重要的项目,FixFlags让你捕获实际进行日志记录的线程。 阻止集合位于ReactiveExtensions中。 这里的要点是你的转发appender处理异步的东西然后只是在LoggingEvent上转发到标准的Log4Net appender,这让Log4Net可以完成它所擅长的所有事情。 没有重新发明轮子。

///  /// Provides an extension for the log4net libraries to provide ansynchronous logging capabilities to the log4net architecture ///  public class AsyncLogFileAppender : log4net.Appender.ForwardingAppender { private static int _asyncLogFileAppenderCount = 0; private readonly Thread _loggingThread; private readonly BlockingCollection _logEvents = new BlockingCollection(); protected override void Append(log4net.Core.LoggingEvent loggingEvent) { loggingEvent.Fix = FixFlags.ThreadName; _logEvents.Add(loggingEvent); } public AsyncLogFileAppender() { _loggingThread = new Thread(LogThreadMethod) { IsBackground = true, Name = "AsyncLogFileAppender-" + Interlocked.Increment(ref _asyncLogFileAppenderCount), }; _loggingThread.Start(); } private void LogThreadMethod() { while (true) { LoggingEvent le = _logEvents.Take(); foreach (var appender in Appenders) { appender.DoAppend(le); } } } } 

然后,在log4net.xml中,您可以设置appender

                   

更新:

如果你想在log4net中使用上下文,比如“ log4net.ThreadContext.Properties["CustomColumn"]

然后你需要更新上面的代码

 loggingEvent.Fix = FixFlags.All; 

我是这样做的:

 Task.Factory.StartNew(() => log.Info("My Info")); 

这样log4net就可以异步执行单独线程的日志记录……

BTW, Task类在System.Threading.Tasks命名空间中。

这里的一些想法是不正确的,导致无效/陈旧数据,乱序记录或非常糟糕的性能。 例如,接受的答案建议使用log4net AsyncAppender ,它使用ThreadPool导致无序条目,这可能不是一些问题,但我当然希望我的日志事件一个接一个,它也可能有可怕的性能,并把太多ThreadPool上的压力也不会批量记录日志条目。 乔纳森提出的答案肯定是一个更好的解决方案,但仍缺乏最佳性能。

这里应该如何实现这一点的一个很好的例子可以在这里找到基准测试结果和解释。

该解决方案的另一个优点是它已经被实现为Forwarder而不是Appender允许用户包含多个Appender并同时登录到每个Appender

我本周遇到了这个问题,但是我不想继续向线程池发送请求,因为它最终会使线程应用程序的其余部分挨饿,所以我想出了一个Asyncronous appender,它运行一个专用的线程来追加哪个通过缓冲区喂养。 请在此处查看: https : //github.com/cjbhaines/Log4Net.Async