zoukankan      html  css  js  c++  java
  • [翻译]log4net教程

    原文:log4net Tutorial

    一、基础

      log4net分为三部分:配置、设置和调用。配置通常是在app.webconfig或web.config文件中;为了增加灵活性,我们也可以使用单独的配置文件。设置通常是几行代码,作用是设置和实例化一个logger连接。最后一部分是调用。

    二、日志级别

      有7个日志级别,其中5个可以在代码中调用。下面是日志级别列表,按照优先级排列:

    1. OFF - nothing gets logged (cannot be called)
    2. FATAL
    3. ERROR
    4. WARN
    5. INFO
    6. DEBUG
    7. ALL - everything gets logged (cannot be called)

      这些级别会在代码和配置文件中多次使用。除了第一个和最后一个外,其他的级别没有指明代表什么含义。

    三、配置

      在app.webconfig或web.config文件中配置log4net logger是标准做法。

    1.Root

      我们需要一个root节点来覆盖最高级别的logger引用,这些是logger的继承信息。root节点唯一的其他作用就是定义日志的最低级别。因为所有logger均继承自root,因此低于指定级别的不会被记录为日志。这是控制程序中日志级别的简单方式,例如下面的例子中使用默认的INFO级别(这样DEBUG消息将会被忽略),并且应该启用root下面的两个appender的引用:

    <root>
      <level value="INFO"/>
      <appender-ref ref="FileAppender"/>
      <appender-ref ref="ConsoleAppender" />
    </root>

    2.Additional Logger

      有时我们希望知道程序特定一部分的更多信息。log4net允许我们在root logger之外指定额外的logger。例如,下面的例子中指定了一个额外的logger,记录在OtherClass类对象内的控制台日志:

    <logger name="Log4NetTest.OtherClass">
      <level value="DEBUG"/>
      <appender-ref ref="ConsoleAppender"/>
    </logger>

      需要注意的是logger name的值为包含命名空间的类名。如果我们想要监控整个命名空间,就只要使用需要监控的命名空间填充即可。我(作者)建议不要在多个logger中重复使用日志输出目的地。我们可以这样做,但会有一些 不可预知的结果。

    3.CofigSections

      在一个配置文件中除了log4net外通常还会有其他配置信息,我们需要定义一个节点来标识log4net配置的位置。下面的例子,表示log4net的配置信息在“log4net”标签下面:

    <configSections>
      <section name="log4net" 
        type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    </configSections>

    4.通用的Appender

      appender是记录信息的名字。它用来指定信息被记录在哪里,怎样被记录以及在什么情况下被记录。虽然每个appender都有不同的参数来确定信息被记录在哪里,但是还是有一些通用的元素。第一个是name和type。必须为每个appender命名,并为他分配一个类型。例如:

    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">

    4.1.Layout:

      在每个appender内部必须有一个layout节点。尽管根据不同的appender类型会有不同,但是基础的是相同的。我们需要一个类型来指定数据如何被写入。有多个选项,但是我(作者)推荐的是使用模式布局(pattern layout)类型。因为这样允许我们指定数据如何被写入数据存储。如果我们指定模式布局类型,我们还需要一个子标签来指定转换模式(conversion pattern)。我们的数据使用这种模式写入的到数据存储。例如:

    <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%date [%thread] %-5level %logger [%ndc] 
        - %message%newline"/>
        </layout>

    4.2.Conversion Pattern:

      正如上面提到的,转换模式实体是模式布局用来告诉appender如何存储信息的。在这些模式中可以使用很多不同的关键词和字符串。在这里列出我(作者)认为最有用和最重要的。所有的可以可以查看log4net文档:

    • %date - 使用本地时区信息输出日期。也可以使用花括号和布局模式格式化日期,例如%date{MMMM DD,yyyy HH:mm:ss,fff}会输出"January 01,2011 14:15:43,767"。但是建议使用log4net的日期格式(ABSOLUTE,DATE或ISO8601)这样性能会比较好。
    • %utcdate - 与%date相同,只是它输出世界时。
    • %exception - 如果传递过来一个异常,它将会被使用,并在异常信息后插入新的一行。如果没有异常传递过来,这个实体会被忽略并且不会产生新的一行。这个转换模式通常放在日志实体的最后,并且在异常前面通常也会插入一行。
    • %level - 这是我们指定的事件级别(DEBUG,INFO,WARN等)。
    • %message - 我们传递到日志事件的消息。
    • %newline - 这是新行实体。根据我们程序的平台翻译成新行字符。这是换行的首选方法,并且相对于特定的平台供应商没有性能问题。
    • %timestamp - 程序运行以来的毫秒数。
    • %thread - 实体产生的线程名(如果线程没有命名则是线程的编号)。

      下面几个也非常有用,但是使用时要特别注意,因为它们会对性能造成影响:

    • %identity - 使用Principal.Identity.Name方法获取的当前用户的用户名。
    • %location - 在调试时特别有用,它将告诉我们日志方法是否被调用(行号、方法等)。然而 ,在Release模式下信息的数量将会减少,这取决于系统访问编译后的代码。
    • %line - 代码的行号(即上面location的行号)。
    • %method - 调用日志实体的方法(即上面location的方法)。
    • %username - 输出WindowsIdentity属性的值。

      有些配置文件使用的是字母而不是名字。这有利于整个实体。我(作者)在这里不会深度介绍,我们只要知道这些实体可以被格式化为合适的宽度。可以在两边添加空格,也可以将值截断来适应内部固定宽度的列。基本的语法是将数字或值放在%号和名字之间:

    • X - 指定了字符的最小长度。如果字符的长度小于此值,将会在左侧填充空格。例如,%10message将会输出" hi"。
    • -X - 和上面相同,不同的是在右侧填充空格。例如,%-10message将会输出"hi "。
    • .X - 指定字符的最大长度。如果超出长度将会从左侧开始截取。例如,%.10message如果字符串为"Error entry"将会输出"rror entry"。

      我们可以将上面的组合使用,例如"%10.20message",如果长度不足10则在左侧填充空格,如果超过20将会截取。

    4.3.Filter:

      Filter是appender的一部分。使用filter我们可以指定哪个(或哪些)级别被记录,甚至可以在消息中寻找关键字。Filter可以混合和匹配,当时当我们这样做的时候要特别注意。当消息符合filter的内部标准,它将会被记录并且filter的过程结束。这是Filter最大的缺陷,因此当我们处理复杂的filter时,filter的排序就变得非常重要。

    4.3.1.StringMatchFilter:

      字符串匹配filter在被记录的信息中寻找指定的字符串。我们可以知道多个字符串匹配filter。它们在一个查询语句中类似OR组合。需要注意的是不要试图匹配一个指定的字符串不排除一个实体(因为它可以继续下一个字符串匹配filter)。这意味着,我们可能会遇到没有匹配的情况。这种情况下,默认的行为是记录这个实体。因此,在字符串匹配filter设置的最后,包含一个否认所有filter(下面会介绍)在没有匹配时组织实体被记录是非常必要的。下面是字符串匹配filter的例子:

    <filter type="log4net.Filter.StringMatchFilter">
      <stringToMatch value="test" />
    </filter>

    4.3.2.LevelRangeFilter:

      级别范围filter告诉系统只有在指定范围内的实体才会被记录。下面的例子中INFO、WARN、ERROR级别的事件会被记录,但是DEBUG事件不会被记录。我们在这个实体后面不需要定义否认所有filter,因为否定所有filter是默认的。

    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="INFO" />
      <levelMax value="FATAL" />
    </filter>

    4.3.3.LevelMatchFilter:

      级别匹配filter与级别范围filter类似,不同的是它只捕获指定的一种级别。它没有默认的否定所有filter,因此要在级别匹配filter之后添加否定所有filter。

    <filter type="log4net.Filter.LevelMatchFilter">
      <levelToMatch value="ERROR"/>
    </filter>

    4.3.4.DenyAllFilter:

      如果被忘记,appender通常不会按照所期望的工作。指定这个条目的唯一目的是指定不产生日志实体。如果只定义了这个条目,将不会有日志产生。

    <filter type="log4net.Filter.DenyAllFilter" />

    5.Appender

      每个类型的appender都有它自己的语法定义数据存储到哪里。最不寻常的是把日志存储到数据库。

    5.1.Console Appender:

      我(作者)通常使用这个appender来测试,但是它在产品上同样有用。它写入到输出窗口,如果我们使用的是console程序它会写入到命令窗口。下面的filter输出的值类似"2010-12-26 15:41:03,581 [10] WARN Log4NetTest.frmMain - This is a WARN test.",在它的末尾将会换行。

    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{ABSOLUTE} 
        [%thread] %level %logger - %message%newline"/>
      </layout>
      <filter type="log4net.Filter.StringMatchFilter">
        <stringToMatch value="test" />
      </filter>
      <filter type="log4net.Filter.DenyAllFilter" />
    </appender>

    5.2.File Appender:

      这个appender将会写入一个文本文件。该appender必须指定文件名(下面的例子中文件名为mylogfile.txt,将会存储在与可执行文件相同的路径),我们指定在文件末尾添加(而不是覆盖),并且指定FileAppender使用最小锁这样该文件可以被多个appender使用。

    <appender name="FileAppender" type="log4net.Appender.FileAppender">
      <file value="mylogfile.txt" />
      <appendToFile value="true" />
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <levelMin value="INFO" />
        <levelMax value="FATAL" />
      </filter>
    </appender>

    5.3.Rolling File Appender:

      应该尽量使用该Appender代替file appender。Rolling file appender的目的是与file appender执行相同的功能,但是每个文件只存储一定量的数据。这样就不用担心日志耗尽存储空间。如果没有使用滚动选项,在足够时间的情况下,即使是一个小的应用程序也会耗尽存储空间。在下面的例子中使用于上面例子类似的方式记录日志,但是指定了每个文件的大小为10MB,并且在删除之前有5个存档文件(从最之前的文件开始删除)。存档文件具有相同的名字,只是在每个文件名字后添加一个点和数组(例如,第二个存档的文件名为mylogfile.txt.2).staticLogFileName确保日志文件与指定的文件名相同(本例中为mylogfile.txt)。

    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="mylogfile.txt" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="5" />
      <maximumFileSize value="10MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
      </layout>
    </appender>

    5.4.ADO.NET Appender:

      下面的例子是写入SQL Server数据库,但是我们可以使用这种模式写入任意数据库。

      注意:如果我们发现ADO.NET appender没有反应,查看bufferSize的值。这个值定义的是将日志写入数据库之前log4
    net缓存的语句数量。

      更多信息请参考:http://logging.apache.org/log4net/release/config-examples.html

    <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
      <bufferSize value="100" />
      <connectionType value="System.Data.SqlClient.SqlConnection, 
       System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <connectionString value="data source=[database server];
        initial catalog=[database name];integrated security=false;
        persist security info=True;User ID=[user];Password=[password]" />
      <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="255" />
        <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="255" />
        <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>
    </appender>

    四、代码

      在我们的程序中引入log4net的dll时,有三行代码是我们需要知道的。第一个是需要一次性放置在我们的类中。我(作者)通常它放在Program.cs文件的using语句下面:

    [assembly: log4net.Config.XmlConfigurator(Watch = true)]

      第二个是需要在每个类中用到的,定义一个变量用来调用log4net的方法。它使用System.Reflection调用后去当前类的信息:

    private static readonly log4net.ILog log = log4net.LogManager.GetLogger
        (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

      最后的代码块是实际调用来记录一些信息。例如:

    log.Info("Info logging");

      注意,我们可以在后面添加一个可选参数包含异常信息。与下面的非常类似:

    log.Error("This is my error", ex);

      ex是异常对象。我们需要使用%exception来捕获异常信息。

    五、记录额外的数据

      通常使用log4net的基本配置就可以为应用程序提供足够的信息。但是,有时我们想要使用标准方法记录更多的信息。例如,在ADO.NET appender中,我们可能想要添加用户名字段而不仅仅是信息字段。没有一种转换模式与应用程序中的用户名匹配。然而,我们可以使用上下文属性来自定义可以被appender访问的属性。例如:

    log4net.GlobalContext.Properties["testProperty"] = "This is my test property information";

      需要注意几点:1.自定义属性可以任意命名,但是如果命名与已经存在的命名相同,将会把原来的覆盖。2.本例中使用的是Global上下文,但是有四个上下文可以被利用。它们是基于线程的。Global定义的可以应用在程序进程、逻辑继承和进一步限制时间范围的任何地方。如果两个属性具有相同的名字,将会取窄范围的那个的值。

      捕获自定义属性的例子:

    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date{ABSOLUTE} [%thread] %level 
                                %logger - %message%newlineExtra Info: %property{
                                testProperty}%newline%exception"/>
    </layout>

      更多信息请查看:http://logging.apache.org/log4net/release/manual/contexts.html

    六、不使用app.config/web.config

      有时我们需要单独的文件存储log4net的配置信息。实际上这是存储配置信息最好的方法,因为我们可以有不同的配置副本应用于项目。这可以减少开发时间并且允许我们记录标准化的日志信息。如果要单独存储配置文件,我们需要更改程序的两个地方。第一件是将配置文件保存在另一个文件。第二件是修改调用设置,例如:

    [assembly: log4net.Config.XmlConfigurator(ConfigFile = 
                    "MyStandardLog4Net.config", Watch = true)]  

      还可以使用另一种方法,这种方法需要把配置文件命名为程序集名称(包括扩展名):

    [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "mylogger", Watch = true)]

      在上面的例子中如果我们的程序是test.exe,log4net的配置文件需要命名为test.exe.mylogger。

    七、配置文件模板

    <!--This is the root of your config file-->
    <configuration> <!-- Level 0 -->
      <!--This specifies what the section name is-->
      <configSections> <!-- Level 1 -->
        <section name="log4net" 
          type="log4net.Config.Log4NetConfigurationSectionHandler, 
                log4net"/> <!-- Level 2 -->
      </configSections>
      <log4net> <!-- Level 1 -->
        <appender>  <!-- Level 2 -->
          <layout>  <!-- Level 3 -->
            <conversionPattern />  <!-- Level 4 -->
          </layout>
          <filter>  <!-- Level 3 -->
          </filter>
        </appender>
        <root> <!-- Level 2 -->
          <level /> <!-- Level 3 -->
          <appender-ref /> <!-- Level 3 -->
        </root>
        <logger> <!-- Level 2 -->
          <level /> <!-- Level 3 -->
          <appender-ref /> <!-- Level 3 -->
        </logger>
      </log4net>
    </configuration>

      发现已经有园友翻译过这篇文章,而且比我翻译的好很多:Log4Net指南

  • 相关阅读:
    关联规则算法---Eclat算法
    Apriori算法第二篇----详细分析和代码实现
    scrapy框架初识
    git入门
    phantomjs的和谷歌浏览器的简单使用
    selenium模块的而简单使用
    代理ip的使用以及多进程爬取
    爬虫之re块解析
    爬虫初识和request使用
    xpath的基础使用
  • 原文地址:https://www.cnblogs.com/walden1024/p/4613928.html
Copyright © 2011-2022 走看看