如何使用 stringToMatch 过滤器将消息与 log4net 中的换行符进行匹配?

发布于 2024-11-05 08:19:42 字数 2131 浏览 2 评论 0原文

我在配置 StringMatchFilter< 时遇到问题/a> 匹配 a 消息中带有换行符的字符串。我想跳过一些消息并且我 添加了一个像这样的过滤器并且它可以工作。

<filter type="log4net.Filter.StringMatchFilter">
  <param name="AcceptOnMatch" value="false" />
  <stringToMatch value="Unexpected exception in SocketThreadWorker" />
</filter>

但是,如果我将 stringToMatch 更改为“现有连接是 被远程主机强行关闭”,发生在第二行 过滤器不起作用的消息。是因为换行吗 消息还是我在这里做错了什么?

典型的消息可能如下所示:

------ 示例消息 ----------------------------------------

2011-05-04 16:22:24,078 [Client (connected from "127.0.0.1:4076" at 16:22)] ERROR - Unexpected exception in SocketThreadWorker System.Net.Sockets.SocketException:
An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)

------结束示例消息 ---------------------------

“SocketThreadWorker 中出现意外异常”位于消息的第一行,并且“现有连接已发生”强制关闭”位于第二行。

编辑

附加程序如下所示:

<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
  <filter type="log4net.Filter.StringMatchFilter">
    <param name="AcceptOnMatch" value="false" /> 
    <stringToMatch value="An existing connection was forcibly closed by the remote host" />        
  </filter>
  <to value="..." />
  <from value="..." />
  <subject value="[... ${COMPUTERNAME}] An Error occurred" />
  <smtpHost value=".." />
  <bufferSize value="1024" />
  <lossy value="true" />
  <evaluator type="log4net.Core.LevelEvaluator">
     <threshold value="ERROR"/>
  </evaluator>
  <layout type="log4net.Layout.PatternLayout">
     <conversionPattern value="%newline%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
  </layout>
</appender>

我不想通知任何人此错误消息,因为它确实没有那么严重。该消息不是由我自己的代码生成的,而是来自我使用的库。

I'm having trouble with configuring a StringMatchFilter to match a
string in a message with newlines. I want to skip some messages and I
have added a filter like this and it works.

<filter type="log4net.Filter.StringMatchFilter">
  <param name="AcceptOnMatch" value="false" />
  <stringToMatch value="Unexpected exception in SocketThreadWorker" />
</filter>

But if I change the stringToMatch to "An existing connection was
forcibly closed by the remote host" which occurs on the second row of
the message the filter does not work. Is it because of the newline in
the message or am I doing anything wrong here?

A typical message can look like this:

------ Example message ----------------------------

2011-05-04 16:22:24,078 [Client (connected from "127.0.0.1:4076" at 16:22)] ERROR - Unexpected exception in SocketThreadWorker System.Net.Sockets.SocketException:
An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)

------ End example message ---------------------------

"Unexpected exception in SocketThreadWorker" is on the first row of the message and "An existing connection was forcibly closed" is on the second row.

Edit

The appender looks like this:

<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
  <filter type="log4net.Filter.StringMatchFilter">
    <param name="AcceptOnMatch" value="false" /> 
    <stringToMatch value="An existing connection was forcibly closed by the remote host" />        
  </filter>
  <to value="..." />
  <from value="..." />
  <subject value="[... ${COMPUTERNAME}] An Error occurred" />
  <smtpHost value=".." />
  <bufferSize value="1024" />
  <lossy value="true" />
  <evaluator type="log4net.Core.LevelEvaluator">
     <threshold value="ERROR"/>
  </evaluator>
  <layout type="log4net.Layout.PatternLayout">
     <conversionPattern value="%newline%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
  </layout>
</appender>

I don't want to notify anybody about this error message since it is really not that serious. The message is not produced by my own code but it comes from a library that I use.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

星軌x 2024-11-12 08:19:42

log4net 追加的说明

SocketThreadWorker 抛出 SocketException。异常消息“现有连接被远程主机强制关闭”由 错误代码

throw new SocketException(10054);

生成日志语句的代码看起来像一个未处理的异常处理程序(通过打印的消息“意外异常...”)。但是,对于这个答案,想象一下它看起来像这样

try
{
    ...
}
catch (Exception e)
{
    _log.Error("Unexpected exception in SocketThreadWorker", e);
}

log4net 在幕后产生的是 LoggingEvent。它包含提供的日志消息和异常对象(分别)。每个附加程序可以决定如何将这两个项目写入其最终目的地(以及其他属性、布局参数等)。

StringToMatch 过滤器仅适用于日志消息。不就异常信息了!查看下面的代码,我们将构建一个系统和一个测试来帮助我们调试问题

复制和深入研究

这是一个简单的套接字异常抛出类

public class SocketThreadWorker
{
    public void DoWork()
    {
        throw new SocketException(10054);
    }
}

我们将配置 log4net 以使用 ConsoleAppender使用字符串匹配过滤器,匹配异常消息字符串。

public static class LocalLoggingConfiguration
{
    public static void Configure()
    {
        var filter = new StringMatchFilter
        {
            StringToMatch = "An existing connection was forcibly closed by the remote host",
            AcceptOnMatch = false,
        };

        var appender = new ConsoleAppender
        {
            Layout = new SimpleLayout()
        };

        appender.AddFilter(filter);

        BasicConfigurator.Configure(appender);
    }
}

我们配置 log4net,获取记录器,并在测试中进行失败的调用。您会注意到其他级别的一些日志语句和 Error 处的另一个日志语句与我们的过滤器不匹配(如果它有效)。这样,我们就可以确保我们不会意外丢失所有消息。

[TestClass]
public class SocketLibraryTest
{
    private readonly ILog _log = LogManager.GetLogger(typeof(SocketLibraryTest));

    public SocketLibraryTest()
    {
        LocalLoggingConfiguration.Configure();
    }

    [TestMethod]
    public void CatchThatPeskyException()
    {
        _log.Debug("Testing...");

        try
        {
            new SocketThreadWorker().DoWork();
        }
        catch (Exception e)
        {
            _log.Info("An exception!");
            _log.Error("Unexpected exception in SocketThreadWorker", e);
            _log.Error("It wasn't that bad.");
        }
    }
}

在我的环境中,此测试的输出包括与消息分开的单独行上的异常,因为默认情况下,附加程序将以这种方式打印异常对象。

DEBUG - Testing...  
INFO - An exception!  
ERROR - Unexpected exception in SocketThreadWorker  
System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host  
   at SO5894291.SocketThreadWorker.DoWork() in d:\users\anthony.mastrean\documents\Projects\SO5894291\SO5894291\SocketLibraryTest.cs:line 16  
   at SO5894291.SocketLibraryTest.CatchThatPeskyException() in d:\users\anthony.mastrean\documents\Projects\SO5894291\SO5894291\SocketLibraryTest.cs:line 58  
ERROR - It wasn't that bad.

如果您修改附加器过滤器以匹配不同消息的一部分,您将看到它配置正确并且确实有效。更改字符串以匹配“Testing”,您将看到 DEBUG 语句从控制台输出中消失!

建议

您不想匹配通用日志消息“意外的异常...”。这有机会丢失消息。即使引入记录器匹配过滤器也无济于事,因为套接字工作人员可能会抛出其他异常(同样,可能会丢失消息)。

我能想到的唯一选择是实现您自己的 ExceptionMessageToMatchFilter 。我复制了 StringToMatchFilter 的实现,替换了异常消息的呈现消息字符串。

public class ExceptionMessageToMatchFilter : StringMatchFilter
{
    public override FilterDecision Decide(LoggingEvent loggingEvent)
    {
        if (loggingEvent == null)
            throw new ArgumentNullException("loggingEvent");

        if (loggingEvent.ExceptionObject == null)
            return FilterDecision.Neutral;

        var exceptionMessage = loggingEvent.GetExceptionString();

        if (m_regexToMatch != null)
        {
            if (!m_regexToMatch.Match(exceptionMessage).Success)
                return FilterDecision.Neutral;

            return m_acceptOnMatch ? FilterDecision.Accept : FilterDecision.Deny;
        }

        if (m_stringToMatch == null || exceptionMessage.IndexOf(m_stringToMatch) == -1)
        {
            return FilterDecision.Neutral;
        }

        return m_acceptOnMatch ? FilterDecision.Accept : FilterDecision.Deny;
    }
}

我会小心 GetExceptionString() 调用,我不知道它是否可以返回 null。或者如果没有消息你想做什么(是空的吗?应该返回中性还是继续匹配?)。

在 log4net 配置中进行配置非常容易(特别是因为它具有从字符串到匹配过滤器的所有属性)。

<filter type="MyNamespace.ExceptionMessageToMatchFilter, MyAssembly">
    <stringToMatch value="An existing connection was forcibly closed by the remote host" />
    <acceptOnMatch value="false" />
</filter>

Explanation of log4net Appending

The SocketThreadWorker is throwing a SocketException. The exception message, "An existing connection was forcibly closed by the remote host", is mapped by the error code.

throw new SocketException(10054);

The code producing the log statement looks like an unhandled exception handler (by the message printed "Unexpected exception... "). But, for this answer, imagine it looks like this

try
{
    ...
}
catch (Exception e)
{
    _log.Error("Unexpected exception in SocketThreadWorker", e);
}

What log4net produces under the covers is a LoggingEvent. It contains the provided log message and the exception object (separately). Each appender can decide how to write these two items to their final destinations (along with other properties, layout parameters, etc).

The StringToMatch filter works only on the log message. Not on the exception message! Check out this code below, we'll construct a system and a test that will help us debug the problem

Reproduction and Deep Dive

Here is a simple socket exception throwing class

public class SocketThreadWorker
{
    public void DoWork()
    {
        throw new SocketException(10054);
    }
}

We'll configure log4net to use a ConsoleAppender with a string match filter, matching the exception message string.

public static class LocalLoggingConfiguration
{
    public static void Configure()
    {
        var filter = new StringMatchFilter
        {
            StringToMatch = "An existing connection was forcibly closed by the remote host",
            AcceptOnMatch = false,
        };

        var appender = new ConsoleAppender
        {
            Layout = new SimpleLayout()
        };

        appender.AddFilter(filter);

        BasicConfigurator.Configure(appender);
    }
}

We configure log4net, get a logger, and make a failing call in the test. You'll notice a few log statements at other levels and another one at Error that won't match our filter (if it works). This way, we can be sure that we're not accidentally losing all messages.

[TestClass]
public class SocketLibraryTest
{
    private readonly ILog _log = LogManager.GetLogger(typeof(SocketLibraryTest));

    public SocketLibraryTest()
    {
        LocalLoggingConfiguration.Configure();
    }

    [TestMethod]
    public void CatchThatPeskyException()
    {
        _log.Debug("Testing...");

        try
        {
            new SocketThreadWorker().DoWork();
        }
        catch (Exception e)
        {
            _log.Info("An exception!");
            _log.Error("Unexpected exception in SocketThreadWorker", e);
            _log.Error("It wasn't that bad.");
        }
    }
}

The output of this test, in my environment, includes the exception on a separate line from the message, because, by default, an appender will print the exception object that way.

DEBUG - Testing...  
INFO - An exception!  
ERROR - Unexpected exception in SocketThreadWorker  
System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host  
   at SO5894291.SocketThreadWorker.DoWork() in d:\users\anthony.mastrean\documents\Projects\SO5894291\SO5894291\SocketLibraryTest.cs:line 16  
   at SO5894291.SocketLibraryTest.CatchThatPeskyException() in d:\users\anthony.mastrean\documents\Projects\SO5894291\SO5894291\SocketLibraryTest.cs:line 58  
ERROR - It wasn't that bad.

If you modify the appender filter to match on a part of a different message, you'll see that it is configured properly and does work. Change the string to match to "Testing" and you'll see the DEBUG statement disappear from the Console output!

Recommendations

You do not want to match on the generic log message "An unexpected exception... ". That has the chance to lose messages. Even introducting a logger match filter won't help, because that socket worker probably can and will throw other exceptions (again, potentially losing messages).

The only option I can think of is to implement your own ExceptionMessageToMatchFilter. I've copied the implementation of StringToMatchFilter, replacing the rendered message string for the exception message.

public class ExceptionMessageToMatchFilter : StringMatchFilter
{
    public override FilterDecision Decide(LoggingEvent loggingEvent)
    {
        if (loggingEvent == null)
            throw new ArgumentNullException("loggingEvent");

        if (loggingEvent.ExceptionObject == null)
            return FilterDecision.Neutral;

        var exceptionMessage = loggingEvent.GetExceptionString();

        if (m_regexToMatch != null)
        {
            if (!m_regexToMatch.Match(exceptionMessage).Success)
                return FilterDecision.Neutral;

            return m_acceptOnMatch ? FilterDecision.Accept : FilterDecision.Deny;
        }

        if (m_stringToMatch == null || exceptionMessage.IndexOf(m_stringToMatch) == -1)
        {
            return FilterDecision.Neutral;
        }

        return m_acceptOnMatch ? FilterDecision.Accept : FilterDecision.Deny;
    }
}

I would be careful around the GetExceptionString() call, I don't know if it can return null. Or what you want to do if there is no message (is it empty? should you return neutral or continue matching?).

It's quite easy to rig up in your log4net configuration (especially because it has all the properties from the string to match filter).

<filter type="MyNamespace.ExceptionMessageToMatchFilter, MyAssembly">
    <stringToMatch value="An existing connection was forcibly closed by the remote host" />
    <acceptOnMatch value="false" />
</filter>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文