当使用Windows Azure DiagnosticsMonitor时,log4net traceappender仅记录级别为'verbose'的消息

14

我有一个Azure工作角色,我配置了一个log4net Trace Appender来写入WindowsAzure.Diagnostics。这是通过在工作角色的RoleEntryPoint中进行以下调用来完成的。

using System;
using Microsoft.WindowsAzure.Diagnostics;
using log4net.Config;

namespace XXX
{
    public class WorkerRole : RoleEntryPoint
    {
        public override bool OnStart()
        {
            var config = DiagnosticMonitor.GetDefaultInitialConfiguration();

            config.Logs.ScheduledTransferLogLevelFilter = LogLevel.Warning;
            config.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(5);

            config.WindowsEventLog.DataSources.Add("System!*");
            config.WindowsEventLog.DataSources.Add("Application!*");
            config.WindowsEventLog.ScheduledTransferLogLevelFilter = LogLevel.Error;
            config.WindowsEventLog.ScheduledTransferPeriod = TimeSpan.FromMinutes(5);

            DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", config);

        XmlConfigurator.Configure();
        }
    }
}

App.config文件的配置方式如下:

<log4net>
    <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%logger - %message" />
        </layout>
    </appender>
    <root>
        <level value="ALL" />
        <appender-ref ref="TraceAppender" />
    </root>
</log4net>

<system.diagnostics>
    <trace>
        <listeners>
            <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics">
                <filter type="" />
            </add>
        </listeners>
    </trace>
</system.diagnostics>
这将导致所有消息(即使是错误消息)以“详细”级别记录在表存储中。如何修复?

这个已经过时了,请参考http://blog.kloud.com.au/2014/10/22/logging-with-log4net-and-azure-diagnostics-on-web-and-worker-roles/。 - Rory
你确定吗?人们似乎仍然在使用Microsoft.WindowsAzure.Diagnostics 2.5.0.0时遇到了这个问题。 - Rune Vejen Petersen
嗯嗯 :/ 不,我不确定。 - Rory
1个回答

25

有几篇博客讨论了这个问题:(这里这里)

  • 事实证明,log4net TraceAppender将所有日志消息转换为Trace.Write消息,而DiagnosticMonitorTraceListener将所有Trace.Write消息转换为详细信息。

在我的情况下,解决方案是使用Pete McEvoy的方法,并以以下方式扩展TraceAppender:

using System.Diagnostics;
using log4net.Appender;
using log4net.Core;
namespace XXX.Logging
{
    public class AzureTraceAppender : TraceAppender
    {
        protected override void Append(LoggingEvent loggingEvent)
        {
            var level = loggingEvent.Level;
            var message = RenderLoggingEvent(loggingEvent);

            if (level >= Level.Error)
              Trace.TraceError(message);
            else if (level >= Level.Warn)
              Trace.TraceWarning(message);
            else if (level >= Level.Info)
              Trace.TraceInformation(message);
            else
              Trace.WriteLine(message);
            if (ImmediateFlush)
              Trace.Flush();
        }
    }
}

然后,这个扩展被实现在我的 App.config 文件中:

<log4net>
    <appender name="AzureTraceAppender" type="XXX.Logging.AzureTraceAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%logger - %message" />
        </layout>
    </appender>
    <root>
        <level value="ALL" />
        <appender-ref ref="AzureTraceAppender" />
    </root>
</log4net>

1
非常有用。然而,我无法通过Trace.Write()从log4net获取调试级别的消息。我将代码调整为else if (level >= Level.Debug),现在可以在我的流日志和表存储中看到调试级别的消息了。 - Jonathan Freeland
1
是的,它非常有用。一个评论是:一个简单的Trace.Write(..)不会显示在Azure流日志中,因此最终的else分支什么也不做。我们必须将log4net消息的5个级别显式地投射到3个级别的Trace。 - g.pickardou
我有Microsoft.WindowsAzure.Diagnostics 2.5.0.0,但问题仍然存在。不过你的回答解决了它。 - Jaanus
正如@g.pickardou所指出的那样,Trace.Write()在Azure流日志中不会显示。然而,Trace.WriteLine()会以冗长级别记录下来。将5个log4net级别转换为4个Azure级别比转换为3个Azure级别要容易得多。 - josh
@g.pickardou和josh:TraceAppender代码已更新。感谢指出。 - Rune Vejen Petersen

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