c#中带过滤器的log4net纯代码配置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/885378/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 08:23:47  来源:igfitidea点击:

log4net pure code configuration with filter in c#

c#configurationlog4net

提问by Christian Ruppert

I am trying to configure Log4Net purely by code, but when I did with a minimal configuration, I was flooded by logging messages from NHibernate and the fluent interface.

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

So, what I am trying to do is simple. Tell Log4Net to show me only log messages of my single class. I toyed around a little bit, but can't figure it out...

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

Can anyone help, I think the following code illustrates my idea:

任何人都可以帮忙,我认为以下代码说明了我的想法:

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);

Ok, thanks for your help, but there must be some issue here. But I get closer. I tried the XML configuration, which has much more documentation. And I managed to achieve the desired result using the following XML configuration. There must be some misconfiguration in the "pure code" version above.

好的,谢谢你的帮助,但这里肯定有问题。但我离得更近了。我尝试了 XML 配置,其中包含更多文档。我设法使用以下 XML 配置实现了预期的结果。上面的“纯代码”版本肯定存在一些配置错误。

The following XML configuration provides the "correct" output, which is not the same than the config in code above. Anybody sees the difference?

以下 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>

采纳答案by Christian Ruppert

I figured it out.. Sometimes, just writing it down opens your eyes...

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

        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);

See what was missing :-) The denyALL filter!!

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

Some more code examples:

更多代码示例:

    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;
    }

Really UGLY but working (it screws up the highlighting, do not miss the last lines):

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

        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));
    }

回答by wageoghe

Here is anohter way to configure log4net with XML via code using XmlDocument to load the xml. The difference from Christian's example is that I am using the XmlConfigurator.Configureoverload that takes an XmlElementas a parameter. I also used single tick marks rather than doubling up the double quotation marks. All in all, I think that it is the tiniest bit cleaner.

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

  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);

回答by David Zhao

The following codes works on how to config AdoNetAppender in codes. If you want to add filter, you need to add filter instance on the appender instance in GetAppender() method. For using logger in your application, Dependency Injection is recommended to be used to isolate logger implementation and interface. In addition, use DI scope concept to make it singleton to avoid object recreation. Note: CrmConfigHelper class is used to get access to application configuration file appSettings section.

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

The codes samples are shown below

代码示例如下所示

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);
    }
}