Log4net LogicalThreadContext未按预期工作

我一直在尝试使用Log4nets LogicalThreadContext为我的每个日志条目提供上下文。 我的应用程序非常重视async / await,但是从阅读各种文章开始,LogicalThreadContext应该可以与.NET 4.5以后的异步代码一起正常工作。 我正在使用.NET 4.5.1和log4net 2.0.3

我找到了Stephen Cleary关于日志记录和.NET CallContext的一篇很棒的文章 ,结果我决定采用他的代码并使其适应使用log4net,试图查看我的代码中是否有错误可能有一直在引发这个问题。

首先,我完全按原样运行Stephens代码并得到预期的输出

Main 1:  Main 1 A:  Main 2:  Main 2 A:  Main 1 A:  Main 1 B:  Main 2 A:  Main 2 B:  Main 2 B:  Main 2:  Main 1 B:  Main 1:  

接下来,我修改了代码以使用log4net而不是Stephens自定义MyStack

 internal class Program { private static readonly ILog Log = LogManager.GetLogger(typeof(Program)); private const string StackName = "test"; private static void Main(string[] args) { XmlConfigurator.Configure(); using (LogicalThreadContext.Stacks[StackName].Push("Main")) { Task.WhenAll(SomeWork("1"), SomeWork("2")).Wait(); } Console.ReadKey(); } private static async Task SomeWork(string stackName) { using (LogicalThreadContext.Stacks[StackName].Push(stackName)) { Log.Info(""); await MoreWork("A"); await MoreWork("B"); Log.Info(""); } } private static async Task MoreWork(string stackName) { using (LogicalThreadContext.Stacks[StackName].Push(stackName)) { Log.Info(""); await Task.Delay(10); Log.Info(""); } } } 

我希望得到与以前类似的输出,但这次我得到了以下内容

 Main 1:  Main 1 A:  Main 1 A 2:  Main 1 A 2 A:  Main 1 A 2 A:  Main 1 B:  Main 1 B:  Main 1 BB:  Main 1 BB:  Main 1 B:  Main 1:  Main 1:  

请注意,单独的逻辑线程上下文开始重叠。 这向我表明log4net没有正确使用CallContext,但从我能找到的所有内容看起来他们已经解决了这个问题。

有没有其他人遇到这个或知道为什么会发生这种情况?

不幸的是,看起来log4net 仍然无法与async逻辑堆栈一起使用。

log4net NuGet包2.0.3是log4net 1.2.13(截至今天的当前版本)。 报告了一个错误( LOG4NET-317 ),因为当时LogicalThreadContext使用CallContext而不是LogicalCallContext

当前版本的LogicalThreadContext确实使用LogicalThreadContext ,但当前版本的ThreadContextStacks 没有正确使用不可变堆栈。

有趣的是, Andrew Arnott在原始的bug报告中正确地指出他们必须使用不可变堆栈 。 在2011年。

随意编写一个最小的repro并将其报告为log4net错误。 关键场景是在使用Task.WhenAll组合的多个任务中使用Task.WhenAll

我刚刚参加了我们的一个项目。 这应该解决它: https : //github.com/apache/log4net/pull/12 。

代码基本上遵循@StephenCleary描述的shallow-copy-on-writeimmutable规则,并且伴随的测试用例可以承受Task.WhenAll场景。