简体   繁体   English

Log4net LogicalThreadContext未按预期工作

[英]Log4net LogicalThreadContext not working as expected

I've been trying to use Log4nets LogicalThreadContext to provide context to each of my log entries. 我一直在尝试使用Log4nets LogicalThreadContext为我的每个日志条目提供上下文。 My application uses async/await quite heavily, but from reading various articles the LogicalThreadContext should work properly with asynchronous code, from .NET 4.5 onwards. 我的应用程序非常重视async / await,但是从阅读各种文章开始,LogicalThreadContext应该可以与.NET 4.5以后的异步代码一起正常工作。 I'm using .NET 4.5.1 and log4net 2.0.3 我正在使用.NET 4.5.1和log4net 2.0.3

I came across a great article by Stephen Cleary about logging and the .NET CallContext, and as a result I decided to take his code and adapt it to use log4net, in an attempt to see if there was something wrong in my code that may have been causing the issue. 我遇到了Stephen Cleary关于日志记录和.NET CallContext的一篇很棒的文章 ,结果我决定采用他的代码并使其适应log4net,试图看看我的代码中是否有错误可能有一直在引发这个问题。

Firstly, I ran Stephens code exactly as is and got the expected output like so 首先,我完全按原样运行Stephens代码并得到预期的输出

Main 1: <SomeWork>
Main 1 A: <MoreWork>
Main 2: <SomeWork>
Main 2 A: <MoreWork>
Main 1 A: </MoreWork>
Main 1 B: <MoreWork>
Main 2 A: </MoreWork>
Main 2 B: <MoreWork>
Main 2 B: </MoreWork>
Main 2: </SomeWork>
Main 1 B: </MoreWork>
Main 1: </SomeWork>

Next, I modified the code to use log4net rather than Stephens custom MyStack 接下来,我修改了代码以使用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("<SomeWork>");
            await MoreWork("A");
            await MoreWork("B");
            Log.Info("</SomeWork>");
        }
    }

    private static async Task MoreWork(string stackName)
    {
        using (LogicalThreadContext.Stacks[StackName].Push(stackName))
        {
            Log.Info("<MoreWork>");
            await Task.Delay(10);
            Log.Info("</MoreWork>");
        }
    }
}

I expected to get a similar output as before, but instead this time I got the following 我希望得到与以前类似的输出,但这次我得到了以下内容

Main 1: <SomeWork>
Main 1 A: <MoreWork>
Main 1 A 2: <SomeWork>
Main 1 A 2 A: <MoreWork>
Main 1 A 2 A: </MoreWork>
Main 1 B: <MoreWork>
Main 1 B: </MoreWork>
Main 1 B B: <MoreWork>
Main 1 B B: </MoreWork>
Main 1 B: </MoreWork>
Main 1: </SomeWork>
Main 1: </SomeWork>

Notice the separate logical thread contexts start to overlap. 请注意,单独的逻辑线程上下文开始重叠。 This indicates to me the log4net isn't using the CallContext correctly but from everything I can find it looks like they've already fixed any issues around this. 这向我表明log4net没有正确使用CallContext但是从我能找到的所有内容看起来他们已经解决了这个问题。

Has anyone else encountered this or know why this might be happening? 有没有其他人遇到这个或知道为什么会发生这种情况?

Unfortunately, it looks like log4net still does not work with async logical stacks. 不幸的是,看起来log4net 仍然无法与async逻辑堆栈一起使用。

The log4net NuGet package 2.0.3 is log4net 1.2.13 (the current version as of today). log4net NuGet包2.0.3是log4net 1.2.13(截至今天的当前版本)。 There was a bug reported ( LOG4NET-317 ) because at that time LogicalThreadContext used CallContext instead of LogicalCallContext . 报告了一个错误( LOG4NET-317 ),因为当时LogicalThreadContext使用CallContext而不是LogicalCallContext

The current version of LogicalThreadContext does use LogicalThreadContext , but the current version of ThreadContextStacks does not correctly use an immutable stack. 当前版本的LogicalThreadContext确实使用LogicalThreadContext ,但当前版本的ThreadContextStacks 没有正确使用不可变堆栈。

Interestingly, Andrew Arnott correctly pointed out in the original bug report that they had to use an immutable stack . 有趣的是, Andrew Arnott在原始错误报告中正确地指出他们必须使用不可变堆栈 In 2011. 在2011年。

Feel free to write up a minimal repro and report it as a log4net bug. 随意编写一个最小的repro并将其报告为log4net错误。 The key scenario is using the stack within multiple tasks that are combined using Task.WhenAll . 关键场景是在使用Task.WhenAll组合的多个任务中使用Task.WhenAll

I just ran into this on one of our projects. 我刚刚在我们的一个项目中碰到了这个问题。 This should fix it: https://github.com/apache/log4net/pull/12 . 这应该解决它: https//github.com/apache/log4net/pull/12

The code basically obeys to the shallow-copy-on-write and immutable rules described by @StephenCleary and the accompanied test case withstands the Task.WhenAll scenario. 代码基本上遵循@StephenCleary描述的shallow-copy-on-writeimmutable规则,并且伴随的测试用例可以承受Task.WhenAll场景。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM