log4net - 配置忽略来自特定线程的消息

时间:2012-09-26 16:25:13

标签: c# logging nunit log4net log4net-filter

是否有可能从特定线程中过滤掉日志条目?

我使用nunit运行测试(c#):

using System;
using NUnit.Core;
using log4net;

namespace Main
{
    public class Program
    {
        public static readonly ILogger log = LogManager.GetLogger(typeof(Program));

        static void Main(string[] args)
        {
            log.Info("start");

            TestPackage package = new TestPackage(@"C:\Test\Main.Tests.dll");
            RemoteTestRunner remoteTestRunner = new RemoteTestRunner();
            remoteTestRunner.Load(package);
            TestResult result = remoteTestRunner.Run(new NullListener(), TestFilter.Empty, true, LoggingThreshold.All);

            log.Info("end");
        }
    }
}

这是我得到的记录:

INFO  17:57:24 [1] Main.Program - start
ERROR 17:57:25 [TestRunnerThread] Main.TestedClass - Exception! Relevant for production / okay in test
INFO  17:57:26 [1] Main.Program - end
每次记录错误时,

log4net都会向我发送邮件。如果我运行测试,我不想收到那些邮件。 nunit将thread-name设置为:“TestRunnerThread”。我怎么能忽略这个帖子?

我读过这个:How to log into separate files per thread with Log4Net?并试过这个过滤器(根本没有记录):

<filter type="log4net.Filter.PropertyFilter">
    <key value="threadId" />
    <stringToMatch value="TestRunnerThread" />
    <acceptOnMatch value="false" />
</filter>

2 个答案:

答案 0 :(得分:0)

一些事情:

  • 如您所链接的the answerthe question中所述,您必须使用ThreadContext注册一个键值对,以便过滤键生效:ThreadContext.Properties["threadId"] = "1"
  • 过滤订单很重要。来自docs

      

    过滤器形成事件必须通过的链。沿途的任何过滤器都可以接受事件并停止处理,拒绝事件并停止处理,或允许事件进入下一个过滤器。如果事件到达过滤器链的末尾而没有被拒绝,则会被隐式接受并将被记录。

    确保过滤顺序如下:

    1. 过滤想要的主题
      • 如果匹配,则消息被拒绝且传递给下一个过滤器(由于<acceptOnMatch value="false" />
      • 如果不匹配,则会将消息传递给链中的下一个过滤器
    2. 记录器过滤器
      • 如果匹配,则接受消息并且传递给下一个过滤器
      • 如果不匹配,则会将消息传递给链中的下一个过滤器
    3. 拒绝全部
      • 消息被拒绝

完整示例:

<?xml version="1.0" encoding="utf-8"?>
<log4net>
    <appender type="log4net.Appender.ConsoleAppender" name="consoleApp">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%message%newline" />
        </layout>       
        <filter type="log4net.Filter.PropertyFilter">
            <key value="threadId" />
            <stringToMatch value="3" />
            <acceptOnMatch value="false" />
        </filter>
        <filter type="log4net.Filter.LoggerMatchFilter">
            <loggerToMatch value="sandbox" />
        </filter>
        <filter type="log4net.Filter.DenyAllFilter" />
    </appender>
    <root>
        <level value="ALL" />
        <appender-ref ref="consoleApp" />
    </root>
</log4net>
static void Main(string[] args)
{
    XmlConfigurator.Configure(new FileInfo("config.xml"));

    ILog log = LogManager.GetLogger("sandbox");

    ThreadPool.QueueUserWorkItem(a =>
    {
        ThreadContext.Properties["threadId"] = "1";
        log.Debug("one");
    });

    ThreadPool.QueueUserWorkItem(a =>
    {
        ThreadContext.Properties["threadId"] = "2";
        log.Debug("two");
    });

    ThreadPool.QueueUserWorkItem(a =>
    {
        ThreadContext.Properties["threadId"] = "3";
        log.Debug("three");
    });

    Console.Read();
}

将记录:

one
two

(可能以不同的顺序,取决于首先完成的线程)

答案 1 :(得分:-2)

我没有使用过log4net,但是一个简单的建议就是在你指定电子邮件ID的地方将id更改为fake@fake.com,以便接收登录电子邮件......

同意应该配置一些东西,以便不是每次都发送电子邮件,但这可能是一种解决方法,直到找到一个合适的解决方案

在使用日志记录时,我还建议您查看Microsoft Enterprise库日志记录应用程序块。在您的应用程序中配置和使用非常容易。

链接http://msdn.microsoft.com/en-us/library/ff664569(v=pandp.50).aspx