【问题标题】:Custom PatternLayout for specific logger get called on GetLogger<T>();在 GetLogger<T>() 上调用特定记录器的自定义 PatternLayout;
【发布时间】:2019-01-10 22:36:12
【问题描述】:

我正在尝试为 W3C 格式的日志创建一个新的附加程序。

我的 appender 布局需要一个自定义标题。所以,我继承 PatternLayout 类是这样的:


    using System;
    using System.Diagnostics;
    using System.Text;
    using log4net.Layout;

    namespace MyApp.Framework.Logging
    {
        public class W3CLayout : PatternLayout
        {
            public override string Header
            {
                get { return buildW3CLogHeader(); }
                set {  }
            }

            private string buildW3CLogHeader()
            {
                var header = new StringBuilder();

                header.AppendLine("#Software: " + ConfigurationSettings.ProductName + " " + ConfigurationSettings.Product + " " + ConfigurationSettings.Version);
                header.AppendLine("#Version: 1.0 // Reference: http://www.w3.org/TR/WD-logfile");
                header.AppendLine("#Date: " + DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"));
                header.AppendLine("#Fields: date time cs-host cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status time-taken");

                return header.ToString();
            }
        }
    }

我在 web.config 中:

...  the rest of the web.config ...

    <log4net>
        <appender name="ServicesLogAppender" type="MyApp.Framework.Logging.ConsumerLoggingAppender, MyApp.Framework">
          <param name="File" value="web-services.log" />
          <param name="MaximumFileSize" value="20MB" />
          <param name="MaxSizeRollBackups" value="3" />
          <param name="StaticLogFileName" value="false" />
          <param name="Threshold" value="ALL" />
          <param name="RollingStyle" value="Size" />
          <param name="appendToFile" value="true" />
          <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread,%a] %-5level %logger - %message%newline" />
          </layout>
        </appender>
        <appender name="OutgoingServicesLogAppender" type="MyApp.Framework.Logging.ConsumerLoggingAppender, MyApp.Framework">
          <param name="File" value="outgoing-web-services.log" />
          <param name="MaximumFileSize" value="21MB" />
          <param name="MaxSizeRollBackups" value="3" />
          <param name="StaticLogFileName" value="false" />
          <param name="Threshold" value="ALL" />
          <param name="RollingStyle" value="Size" />
          <param name="appendToFile" value="true" />
          <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
          <layout type="MyApp.Framework.Logging.W3CLayout, MyApp.Framework">
            <conversionPattern value="%message%newline" />
          </layout>
        </appender>
        <root>
          <level value="WARN" />
          <appender-ref ref="ServicesLogAppender" />
        </root>
        <logger name="ServicesLogger">
          <level value="INFO" />
        </logger>
        <logger name="MyCompany">
          <level value="INFO" />
        </logger>
        <logger name="MyApp">
          <level value="INFO" />
        </logger>
        <logger name="OutgoingServices" additivity="false">
          <level value="INFO" />
          <appender-ref ref="OutgoingServicesLogAppender" />
        </logger>
      </log4net>
    ...  the rest of the web.config ...

我遇到的问题是当程序在程序中调用GetLogger&lt;T&gt;() 时,如下所示,


    namespace MyApp.WebUI
    {
        public class Global : System.Web.HttpApplication
        {
            private static readonly ILog _log = LogManager.GetLogger<Global>();

            private void Application_Start(object sender, EventArgs e)
            {
                // This will write a log to web-services.log
                _log.Info("Starting Application_Start");

            }
       }
    }

不只是调用ServicesLogAppender appender,它还初始化MyApp.Framework.Logging.W3CLayout Header 属性。这导致了一个问题,因为当我即将使用 OutgoingServices appender 时,它会写入两次日志。 见下文:


    namespace MyApp.Domain.WorkOrder
    {
        public abstract class AbstractStatusChangeNotifier
        {
            private static readonly ILog Logger = LogManager.GetLogger("OutgoingServices");

            public void DoWork(){
               Logger.Info("This log will show up twice");
            }
        }
    }

为 web-services.log 生成的日志文件:


    2019-01-10 17:00:51,674 [81,/LM/W3SVC/1/ROOT/MyApp-5-131916312513450449] INFO  Myapp.WebUI.Global - Starting Application_Start

为outgoing-web-services.log 生成的日志文件:


    #Software: MyApp 257.14.0.0 
    #Version: 1.0 // Reference: http://www.w3.org/TR/WD-logfile
    #Date: 2019-01-10 21:46:48
    #Fields: date time cs-host cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status time-taken
    This log will show up twice
    #Software: MyApp 257.14.0.0
    #Version: 1.0 // Reference: http://www.w3.org/TR/WD-logfile
    #Date: 2019-01-10 21:58:54
    #Fields: date time cs-host cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status time-taken
    This log will show up twice

该应用似乎有重复的记录器(因为W3CLayout 调用了两次)并且它两次写入同一个文件。如何防止 GetLogger() 发起W3CLayout PatternLayout?或者我在web.config 上错过了什么?

【问题讨论】:

    标签: c# web-config log4net


    【解决方案1】:
    namespace MyApp.Framework.Logging
        {
            public class W3CLayout : PatternLayout
            {
                public override string Header
                {
                    get { return buildW3CLogHeader(); }
                    set {  }
                }
    
                private string buildW3CLogHeader()
                {
                    var header = new StringBuilder();
    
                    header.AppendLine("#Software: " + ConfigurationSettings.ProductName + " " + ConfigurationSettings.Product + " " + ConfigurationSettings.Version);
                    header.AppendLine("#Version: 1.0 // Reference: http://www.w3.org/TR/WD-logfile");
                    header.AppendLine("#Date: " + DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"));
                    header.AppendLine("#Fields: date time cs-host cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status time-taken");
    
                    return header.ToString();
                }
            }
        }
    

    在上面的类中,我调用了ConfigurationSettings.ProductName,它初始化了log4net 的另一个实例。使用继承类时,我必须小心不要在任何地方调用任何private static ILog _log = LogManager.GetLogger&lt;ClassName&gt;();

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 2016-11-04
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多