如何使用log4net的登录正确的上下文与线程池的主题? [英] How to log correct context with Threadpool threads using log4net?

查看:144
本文介绍了如何使用log4net的登录正确的上下文与线程池的主题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到一种方法,从一堆线程登录有益的参考。问题是,大量的代码是(据我可以告诉),所以他们的名字都没有就任何方面处理上是通过线程池线程到达活动。这个问题可以用下面的代码来说明:



<预类=郎-CS prettyprint-覆盖> 类节目
{
私人静态只读log4net.ILog日志= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod()DeclaringType);
静态无效的主要(字串[] args)
{
新的Thread(TestThis)。开始(的ThreadA);
新的Thread(TestThis)。开始(ThreadB);
到Console.ReadLine();
}

私有静态无效TestThis(对象名称)
{
VAR nameStr的=(字符串)名称;
Thread.CurrentThread.Name = nameStr的;
log4net.ThreadContext.Properties [ThreadContext] = nameStr的;
log4net.LogicalThreadContext.Properties [LogicalThreadContext] = nameStr的;
log.Debug(从线程本身);
ThreadPool.QueueUserWorkItem(X => log.Debug(从线程池主题:+ nameStr的));
}
}

的转换模式为:

$ B %讯息%换行符
<! -
$ b

 %日[%线程]%-5level%记录[%属性] / pre> 

输出是像这样:

  2010-05 -21 15:08:02357 [ThreadA中] DEBUG LogicalContextTest.Program [{LogicalThreadContext = ThreadA中,log4net的:主机名= XXX,ThreadContext = ThreadA中}]  - 从线程本身
2010-05-21 15:08:02357 [ ThreadB] DEBUG LogicalContextTest.Program [{LogicalThreadContext = ThreadB,log4net的:主机名= XXX,ThreadContext = ThreadB}] - 从线程本身
2010-05-21 15:08:02404 [7] DEBUG LogicalContextTest.Program [{ log4net的:主机名= XXX}] - 从线程池线程:ThreadA中
2010-05-21 15:08:02420 [16] DEBUG LogicalContextTest.Program [{log4net的:主机= XXX}] - 从线程池主题:ThreadB

正如你所看到的最后两行没有任何有用的信息名来区分2个线程,比其他手动添加名称,将邮件(我想避免)。我怎样才能得到名称/上下文入日志线程池线程,而在每次调用它添加到邮件或需要在每一个回调重新设置该属性。


解决方案

在log4net的上下文信息是每个线程,所以每次你开始你有你的上下文信息添加到一个新的线程。您可以使用属性,或者您可以使用NDC。 NDC的是每个线程,所以你仍然要它在某些时候,这可能是也可能不是你要找的内容添加到每个线程的上下文。这将节省您将它添加到消息本身虽然。在你的榜样,这将是这样的:

  ThreadPool.QueueUserWorkItem(X => NDC.Push(nameStr的) ); log.Debug(从线程池主题:+ nameStr的)); 

下面是对的为NDC 文档。



所有的一切的效果类似于使用属性,就像你在你的例子。唯一的区别是,NDC可以堆叠,使得每次您在栈上推一个值时,将得到的级联到消息。它还支持using语句,这使得更清晰的代码。


I am trying to find a way to log useful context from a bunch of threads. The problem is that a lot of code is dealt with on Events that are arriving via threadpool threads (as far as I can tell) so their names are not in relation to any context. The problem can be demonstrated with the following code:

class Program
{
    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    static void Main(string[] args)
    {
        new Thread(TestThis).Start("ThreadA");
        new Thread(TestThis).Start("ThreadB");
        Console.ReadLine();
    }

    private static void TestThis(object name)
    {
        var nameStr = (string)name;
        Thread.CurrentThread.Name = nameStr;
        log4net.ThreadContext.Properties["ThreadContext"] = nameStr;
        log4net.LogicalThreadContext.Properties["LogicalThreadContext"] = nameStr;
        log.Debug("From Thread itself");
        ThreadPool.QueueUserWorkItem(x => log.Debug("From threadpool Thread: " + nameStr));
    }
}

The Conversion pattern is:

%date [%thread] %-5level %logger [%property] - %message%newline

The output is like so:

2010-05-21 15:08:02,357 [ThreadA] DEBUG LogicalContextTest.Program [{LogicalThreadContext=ThreadA, log4net:HostName=xxx, ThreadContext=ThreadA}] - From Thread itself
2010-05-21 15:08:02,357 [ThreadB] DEBUG LogicalContextTest.Program [{LogicalThreadContext=ThreadB, log4net:HostName=xxx, ThreadContext=ThreadB}] - From Thread itself
2010-05-21 15:08:02,404 [7] DEBUG LogicalContextTest.Program [{log4net:HostName=xxx}] - From threadpool Thread: ThreadA
2010-05-21 15:08:02,420 [16] DEBUG LogicalContextTest.Program [{log4net:HostName=xxx}] - From threadpool Thread: ThreadB

As you can see the last two rows have no Names of useful information to distinguish the 2 threads, other than manually adding the name to the message (which I want to avoid). How can I get the Name/Context into the log for the threadpool threads without adding it to the message at every call or needing to set the property again in every callback.

解决方案

The context information in log4net is per thread, so every time you start a new thread you have to add your context information to it. You can use properties, or you can use the NDC. The NDC is per thread too, so you would still have to add it to each thread's context at some point, which might or might not be what you're looking for. It would save you from adding it to the message itself though. In your example it would be something like this:

ThreadPool.QueueUserWorkItem(x => NDC.Push("nameStr")); log.Debug("From threadpool Thread: " + nameStr));

Here's a link to the documentation for NDC.

All in all the effect is similar to using properties, just like what you have in your example. The only difference is that the NDC can be stacked so that every time that you push a value on the stack it will get concatenated to the message. It also supports the using statement, which makes for cleaner code.

这篇关于如何使用log4net的登录正确的上下文与线程池的主题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆