如何使用log4net记录跟踪消息?


75

我正在使用log4net将写入日志消息记录到滚动日志文件中。

现在,我还将所有跟踪消息从重定向System.Diagnostics.Trace到该日志文件。我该如何配置?我试图在log4net文档中找到有关此内容的任何内容,但均未成功。有可能吗?

我想要这样做的原因是因为我对第三方库的跟踪消息感兴趣。

<log4net>
    <appender name="R1" type="log4net.Appender.RollingFileAppender">
      <file value="C:\Logs\MyService.log" />
      <appendToFile value="true" />
      <rollingStyle value="Date" />
      <maxSizeRollBackups value="10" />
      <datePattern value="yyyyMMdd" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>
</log4net>

Answers:


73

根据Rune的建议,我实现了一个基本的TraceListener,输出到log4net:

public class Log4netTraceListener : System.Diagnostics.TraceListener
{
    private readonly log4net.ILog _log;

    public Log4netTraceListener()
    {
        _log = log4net.LogManager.GetLogger("System.Diagnostics.Redirection");
    }

    public Log4netTraceListener(log4net.ILog log)
    {
        _log = log;
    }

    public override void Write(string message)
    {
        if (_log != null)
        {
            _log.Debug(message);
        }
    }

    public override void WriteLine(string message)
    {
        if (_log != null)
        {
            _log.Debug(message);
        }
    }
}

14
+1以上的答案。如果将log4net也设置为可写入TraceAppender,我会小心。我尚未实际测试过,但是您可能最终会遇到以下情况:Trace正在写入log4net,而log4net正在写入Trace导致无限循环。例如,以上面的示例为例,您可以通过在记录器'System.Diagnostics.Redirection'的附加程序中不包括TraceAppender来缓解这种情况。
Jimit 2011年

1
因为这是一个跟踪侦听器,所以您应该在Write方法中实现try / catch块,以确保Write尝试不会使主机失败。我提交了代码编辑,可纠正对象构造并使代码更具可读性,并减少失败的可能性。
肖恩·威尔逊

@JYL这是该博客文章的更新链接。但是,此举似乎使某些事情丢失了。该帖子中的XML代码现在不正确,并且Log4netTraceListener的链接不起作用。希望作者能复活代码。
2014年

3
log4net中是否有任何内置的监听器可以监听跟踪事件?
Manjay_TBAG 2015年

4
看一下log4net.Util.LogLog类的源代码。默认情况下,这会记录到Trace,@ Jimit通常是正确的-如果发生附加程序错误,您最终将陷入僵局。在您的TraceListener的实现中,我将确保在实现的构造函数中设置log4net.Util.LogLog.EmitInternalMessages = false,并可能处理LogLog.LogReceived事件并以其他方式记录这些消息。可悲的是,由于此设置,某些追加器错误将不会记录。消息来源是您的朋友。
史蒂文·伯恩

26

我不知道log4net是否支持此功能,但是您可以实现自己的跟踪侦听器来执行此操作。

TraceListener没有太多需要实现的方法,您所要做的就是将值转发到log4net,因此这应该很容易做到。

要添加自定义跟踪侦听器,您可以修改app.config / web.config或使用以下代码将其添加到代码中 Trace.Listeners.Add(new Log4NetTraceListener());


1

根据上面的答案,这里有一个实现(此链接很不稳定,但是我确实找到了源代码):

https://code.google.com/archive/p/cavity/

为了粗略地处理从LogLog类发出的内部log4net跟踪的问题(在上一个答案的注释中进行了描述),我通过检查堆栈框架(此实现已实现)来检查此类是否为跟踪的源,并且忽略那些跟踪消息:

    public override void WriteLine(object o, string category)
    {
        // hack to prevent log4nets own diagnostic trace getting fed back
        var method = GetTracingStackFrame(new StackTrace()).GetMethod();
        var declaringType = method.DeclaringType;
        if (declaringType == typeof(LogLog))
        {
            return;
        }
        /* rest of method writes to log4net */
    }

使用TraceAppender仍会产生上述注释中描述的问题。


1

谢谢,

我同意了Dirk的答案。

public class Log4netTraceListener : System.Diagnostics.TraceListener
{
    private readonly log4net.ILog _log;

    public Log4netTraceListener()
        : this(log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType))
    {

    }

    public Log4netTraceListener(log4net.ILog log)
    {
        _log = log;
    }

    public override void Write(string message) => _log?.Debug(message);

    public override void WriteLine(string message) => _log?.Debug(message);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.