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>
4

2 回答 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

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

于 2018-05-18T20:50:30.513 回答
-2

我没有使用 log4net,但一个简单的建议是将 id 更改为 fake@fake.com 在您指定电子邮件 id 以接收日志电子邮件的地方...

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

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

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

于 2012-09-26T17:10:28.333 回答