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

5

是否有可能过滤掉特定线程的日志记录?

我使用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将线程名设置为:“TestRunnerThread”。如何忽略此线程?
我阅读了这篇文章:如何使用Log4Net在不同的文件中记录每个线程的日志?并尝试了该过滤器(但完全没有记录)。
<filter type="log4net.Filter.PropertyFilter">
    <key value="threadId" />
    <stringToMatch value="TestRunnerThread" />
    <acceptOnMatch value="false" />
</filter>

1
为什么不在测试环境中配置另一组附加器? - Wiktor Zychla
你正在尝试的方法需要更多的步骤,不仅需要将线程名称设置为TestRunnerThread,还需要设置log4net属性,例如log4net.ThreadContext.Properties["threadId"] = "TestRunnerThread";,而且Nunit不太可能这样做。 - sgmoore
@WiktorZychla:这将是程序的自我测试。其中一些测试检查配置是否正确。程序特定的配置和log4net配置都在同一个文件(app.config)中。我将尝试在_self-test-mode_下动态禁用附加器。 - dirk
@sgmoore:是的。Nunit做不到这一点。但我想:如果log4net可以通过%threadconversionPattern中显示“TestRunnerThread”,那么过滤也应该是可能的。 - dirk
propertyFilter 只能用于属性,而 %thread 不是属性,而是所谓的“转换模式名称”,我认为没有办法对这些“转换模式名称”进行过滤。 - sgmoore
2个回答

0
一些事情:
  • 如你所链接的问题答案所提到的,你必须在ThreadContext中注册一个键值对才能让过滤器键起作用:ThreadContext.Properties["threadId"] = "1"
  • 过滤器的顺序很重要。请看文档:

    过滤器形成了事件必须通过的链条。沿途的任何过滤器都可以接受事件并停止处理,拒绝事件并停止处理,或将事件传递给下一个过滤器。如果事件到达过滤器链的末尾而没有被拒绝,它就会被默认接受并记录。

    确保过滤器的顺序如下:

    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

(根据哪个线程先完成可能会有不同的顺序)


-2

我没有使用过log4net,但一个简单的建议是在指定接收日志邮件的电子邮件ID的地方将其更改为类似fake@fake.com的内容...

同意应该有一些配置来避免每次发送电子邮件,但这可以是一个解决方法,直到您找到一个合适的解决方案

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接