【问题标题】:log4net pure code configuration with filter in c#c# 中带过滤器的 log4net 纯代码配置
【发布时间】:2009-05-19 22:41:47
【问题描述】:

我试图纯粹通过代码配置 Log4Net,但是当我使用最小配置时,我被来自 NHibernate 和流畅界面的日志消息淹没了。

所以,我想做的很简单。告诉 Log4Net 只显示我的单个班级的日志消息。我玩弄了一点,但无法弄清楚...

谁能帮忙,我想下面的代码说明了我的想法:

var filter = new log4net.Filter.LoggerMatchFilter();
filter.LoggerToMatch = typeof(DatabaseDirectory).ToString();
filter.AcceptOnMatch = false;

var x = new log4net.Appender.ConsoleAppender();
x.Layout = new log4net.Layout.SimpleLayout();
x.AddFilter(filter);

log4net.Config.BasicConfigurator.Configure(x);

好的,感谢您的帮助,但这里肯定有问题。但我越来越近了。我尝试了 XML 配置,它有更多的文档。我设法使用以下 XML 配置实现了预期的结果。上面的“纯代码”版本肯定有一些配置错误。

以下 XML 配置提供了“正确”的输出,这与上面代码中的配置不同。有人看出区别了吗?

<log4net>
<root>
  <level value="DEBUG" />
  <appender-ref ref="ConsoleAppender" />
</root>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
  <filter type="log4net.Filter.LoggerMatchFilter">
    <loggerToMatch value="Examples.FirstProject.Entities.DatabaseDirectory"/>
  </filter>
  <filter type="log4net.Filter.DenyAllFilter" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="[%C.%M] %-5p %m%n" />
  </layout>
</appender>

【问题讨论】:

  • 最初您的设置看起来非常好。您是否尝试过在不使用 NHibernate 的情况下进行日志记录,只使用您自己的两个记录器,看看一个被接受,一个被拒绝?这样你至少可以排除 NHibernate。

标签: c# configuration log4net


【解决方案1】:

我想通了.. 有时,只是写下来让你大开眼界...

        var filter = new log4net.Filter.LoggerMatchFilter();
        filter.LoggerToMatch = typeof(DatabaseDirectory).ToString();
        filter.AcceptOnMatch = true;

        var filterDeny = new log4net.Filter.DenyAllFilter();


        var x = new log4net.Appender.ConsoleAppender();
        x.Layout = new log4net.Layout.SimpleLayout();
        x.AddFilter(filter);
        x.AddFilter(filterDeny);

        log4net.Config.BasicConfigurator.Configure(x);

看看缺少什么 :-)denyALL 过滤器!!

更多代码示例:

    public static void AllToConsoleSetup()
    {
        var x = new log4net.Appender.ConsoleAppender { Layout = new log4net.Layout.SimpleLayout() };
        log4net.Config.BasicConfigurator.Configure(x);
        SetupDone = true;
    }


    public static void ShowOnlyLogOf(Type t)
    {
        var filter = new log4net.Filter.LoggerMatchFilter {LoggerToMatch = t.ToString(), AcceptOnMatch = true};
        var filterDeny = new log4net.Filter.DenyAllFilter();
        var x = new log4net.Appender.ConsoleAppender {Layout = new log4net.Layout.SimpleLayout()};
        x.AddFilter(filter);
        x.AddFilter(filterDeny);

        log4net.Config.BasicConfigurator.Configure(x);
        SetupDone = true;
    }

真的很丑但是工作(它搞砸了突出显示,不要错过最后几行):

        public static void DefaultSetup()
    {
       // AllToConsoleSetup();
        XmlConfigurator.Configure(XmlSetup());
      // DbConfig();

    }


    private static Stream XmlSetup()
    {
        const string x = @" <log4net>
<root>

  <level value=""ALL"" />
  <appender-ref ref=""AdoNetAppender"">

  </appender-ref>
</root>


<appender name=""AdoNetAppender"" type=""log4net.Appender.AdoNetAppender"">
  <bufferSize value=""1"" />
  <connectionType value=""System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"" />
  <connectionString value=""data source=Christian-PC\SQLEXPRESS;initial catalog=log4net_2;integrated security=false;persist security info=True;User ID=log4net;Password=XXXX"" />
  <commandText value=""INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)"" />
  <parameter>
    <parameterName value=""@log_date"" />
    <dbType value=""DateTime"" />
    <layout type=""log4net.Layout.RawTimeStampLayout"" />
  </parameter>
  <parameter>
    <parameterName value=""@thread"" />
    <dbType value=""String"" />
    <size value=""655"" />
    <layout type=""log4net.Layout.PatternLayout"">
      <conversionPattern value=""%thread"" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value=""@log_level"" />
    <dbType value=""String"" />
    <size value=""50"" />
    <layout type=""log4net.Layout.PatternLayout"">
      <conversionPattern value=""%level"" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value=""@logger"" />
    <dbType value=""String"" />
    <size value=""655"" />
    <layout type=""log4net.Layout.PatternLayout"">
      <conversionPattern value=""%logger"" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value=""@message"" />
    <dbType value=""String"" />
    <size value=""4000"" />
    <layout type=""log4net.Layout.PatternLayout"">
      <conversionPattern value=""%message"" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value=""@exception"" />
    <dbType value=""String"" />
    <size value=""2000"" />
    <layout type=""log4net.Layout.ExceptionLayout"" />
  </parameter>
  <filter type=""log4net.Filter.LoggerMatchFilter"">
    <param name=""LoggerToMatch"" value=""Ruppert"" />
  </filter>
  <filter type=""log4net.Filter.DenyAllFilter"">
  </filter>
</appender>
</log4net>";
        return new MemoryStream(ASCIIEncoding.Default.GetBytes(x));
    }

【讨论】:

  • Christian - 您能否指出任何仅使用代码(log4net 新手可以使用)配置 log4net 的资源?
  • 对不起,这里没有真正的链接。尝试搜索部分sn-p,例如Layout.SimpleLayout...我将在上面的帖子中添加更多代码..
  • 感谢 Christian,这对我开始很有用。非常感谢。
  • 通过代码用 XML 配置 log4net 的好例子。我自己一直在研究这个。我添加了一个示例,该示例显示了使用 XmlConfigurator.Configure 重载执行相同操作的稍微简单的方法,该重载将 XmlElement 作为参数。
  • (编辑我的评论为时已晚,所以创建一个新评论)是否更简单可能值得商榷 ;-) 我想我应该说我的示例略有不同!
【解决方案2】:

这是另一种使用 XML 配置 log4net 的方法,通过代码使用 XmlDocument 加载 xml。与 Christian 的示例不同的是,我使用的是 XmlConfigurator.Configure 重载,它以 XmlElement 作为参数。我还使用了单引号而不是双引号。总而言之,我认为它是最小的清洁剂。

  string xml =
  @"<log4net>
    <appender name='file1' type='log4net.Appender.RollingFileAppender'>
      <!-- Log file locaation -->
      <param name='File' value='log4net.log'/>
      <param name='AppendToFile' value='true'/>
      <!-- Maximum size of a log file -->
      <maximumFileSize value='2KB'/>
      <!--Maximum number of log file -->
      <maxSizeRollBackups value='8'/>
      <!--Set rolling style of log file -->
      <param name='RollingStyle' value='Composite'/>
      <param name='StaticLogFileName' value='false'/>
      <param name='DatePattern' value='.yyyy-MM-dd.lo\g'/>
      <layout type='log4net.Layout.PatternLayout'>
        <param name='ConversionPattern' value='%d [%t] %-5p  %m%n'/>
      </layout>
    </appender>

    <!-- Appender layout fix to view in console-->
    <appender name='console' type='log4net.Appender.ConsoleAppender'>
      <layout type='log4net.Layout.PatternLayout'>
        <param name='Header' value='[Header]\r\n'/>
        <param name='Footer' value='[Footer]\r\n'/>
        <param name='ConversionPattern' value='%d [%t] %-5p  %m%n'/>
      </layout>
    </appender>

    <appender name='debug' type='log4net.Appender.DebugAppender'>
      <layout type='log4net.Layout.PatternLayout'>
        <param name='ConversionPattern' value='%d [%t] %logger %-5p %m%n'/>
      </layout>
    </appender>
    <root>
      <level value='INFO'/>
      <!--
            Log level priority in descending order:

            FATAL = 1 show  log -> FATAL 
            ERROR = 2 show  log -> FATAL ERROR 
            WARN =  3 show  log -> FATAL ERROR WARN 
            INFO =  4 show  log -> FATAL ERROR WARN INFO 
            DEBUG = 5 show  log -> FATAL ERROR WARN INFO DEBUG
            -->
      <!-- To write log in file -->
      <appender-ref ref='debug'/>
      <appender-ref ref='file1'/>
    </root>

  </log4net>";

  //
  // Use XmlDocument to load the xml string then pass the DocumentElement to
  // XmlConfigurator.Configure.
  //
  XmlDocument doc = new XmlDocument();
  doc.LoadXml(xml);

  log4net.Config.XmlConfigurator.Configure(doc.DocumentElement);

【讨论】:

    【解决方案3】:

    以下代码介绍如何在代码中配置 AdoNetAppender。如果要添加过滤器,则需要在 GetAppender() 方法中的 appender 实例上添加过滤器实例。为了在您的应用程序中使用记录器,建议使用依赖注入来隔离记录器的实现和接口。此外,使用 DI 范围概念使其成为单例以避免对象重新创建。 注意:CrmConfigHelper 类用于访问应用程序配置文件 appSettings 部分。

    代码示例如下所示

    public sealed class SqlLogger:ILogger
    { 
        private ILog _logger;
        public SqlLogger()
        {            
            log4net.Config.BasicConfigurator.Configure(GetAppender());
            this._logger = log4net.LogManager.GetLogger(CrmConfigHelper.GetString(Constants.LOG4NET_LOGGER_NAME));
        }
    
        private log4net.Appender.AdoNetAppender GetAppender()
        {            
            log4net.Appender.AdoNetAppender appender = new log4net.Appender.AdoNetAppender();
            appender.ConnectionType = CrmConfigHelper.GetString(Constants.LOG4NET_CONNECTION_TYPE);
            appender.ConnectionString = CrmConfigHelper.GetString(Constants.LOG4NET_DB_CONNECTION);
            appender.BufferSize = CrmConfigHelper.getInteger(Constants.LOG4NET_BUFFER_SIZE);
            appender.CommandText = "INSERT INTO [EventLog] ([Date],[HostName],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @hostname, @log_level, @logger, @message,@exception)";
            appender.CommandType = System.Data.CommandType.Text;
            appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter() { 
                ParameterName = "@log_date",
                DbType = System.Data.DbType.DateTime,
                Size = 100,
                Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}")) as IRawLayout
            });
            appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter()
            {
                ParameterName = "@hostname",
                DbType = System.Data.DbType.String,
                Size = 50,
                Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%property{log4net:HostName}")) as IRawLayout
            });
            appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter()
            {
                ParameterName = "@log_level",
                DbType = System.Data.DbType.String,
                Size = 50,
                Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%level")) as IRawLayout
            });
            appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter()
            {
                ParameterName = "@logger",
                DbType = System.Data.DbType.String,
                Size = 50,
                Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%logger")) as IRawLayout
            });
            appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter()
            {
                ParameterName = "@message",
                DbType = System.Data.DbType.String,
                Size = 4000,
                Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%message")) as IRawLayout
            });
            appender.AddParameter(new log4net.Appender.AdoNetAppenderParameter()
            {
                ParameterName = "@exception",
                DbType = System.Data.DbType.String,
                Size = 2000,
                Layout = new RawLayoutConverter().ConvertFrom(new ExceptionLayout()) as IRawLayout
            });
    
            appender.ActivateOptions();
            return appender;
        }
    
        public void Error(Message context)
        {
            _logger.Error(context.ToJsonString());
        }
    
        public void Error(Message context, Exception exception)
        {
            _logger.Error(context.ToJsonString(), exception);
        }
    
        public void Warn(Message context)
        {
            _logger.Warn(context.ToJsonString());
        }
    
        public void Warn(Message context, Exception exception)
        {
            _logger.Warn(context.ToJsonString(), exception);
        }
    
        public void Info(Message context)
        {
            _logger.Info(context.ToJsonString());
        }
    
        public void Info(Message context, Exception exception)
        {
            _logger.Info(context.ToJsonString(), exception);
        }
    }
    
    public interface ILogger
    {
        void Error(Message context);
        void Error(Message context, Exception exception);
        void Warn(Message context);
        void Warn(Message context, Exception exception);
        void Info(Message context);
        void Info(Message context, Exception exception);
    }
    
    public sealed class Message
    {
        public string RunDate { get; set; }
        public string RunBy { get; set; }
        public string Message { get; set; }
    
        public string ToJsonString()
        {
            return new JavaScriptSerializer().Serialize(this);
        }
    }
    

    【讨论】:

    • @Phil:看起来它可以从项目的配置文件中检索信息。就个人而言,我可能会将这些信息作为参数传递,这样就不需要 SQLLogger 了解有关该项目的任何信息。然后,您可以将其拆分为一个单独的、自包含的项目,并在您希望为其启用日志记录的任何项目中引用它。
    • @Ellesedil 作者更新了解释 CrmConfigHelper 的答案。不过,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2020-09-03
    • 2010-11-17
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多