Log For log4net (一) — 配置概述

Friday, April 27, 2007

最近在写程序时,觉得对程序进行log很有必要。比如一个程序试运行时,可以通过log了解程序的运行情况等。.NET 框架下有很多开源的log工具,log4net就是其中的代表。

以前学习英语的东西,都是只了解了一个大概。这次决定试试通过翻译英文文档来学习log4net,看看能不能有更多的收获。学习的过程就叫Log For log4net吧,好像有一点绕口:-)

第一部分选取了log4net手册的Configuration节。这一节比较长,打算分两次看完。

注:1. 代码中的英文注释将保留

         2. log译为“记录”;logger译为“记录器”

原文地址:log4net Manual - Configuration

配置

对应用程序进行记录需要一定量的规划和工作。观察说明大约4成的代码是用来完成记录工作,即使中等规模的程序也需要在代码中嵌入上千行的记录语句。因此有必要自动维护记录代码。

log4net环境是完全可程序化配置的,但是使用XML格式的配置文件对它进行配置将会更灵活方便。

让我们看看是怎样在例子程序MyApp中使用log4net来完成记录。
译注:这里的MyApp为控制台应用程序。

   1: using Com.Foo;
   2:  
   3: // Import log4net classes.
   4: using log4net;
   5: using log4net.Config;
   6:  
   7: public class MyApp 
   8: {
   9:     // Define a static logger variable so that it references the
  10:     // Logger instance named "MyApp".
  11:     private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
  12:  
  13:     static void Main(string[] args) 
  14:     {
  15:         // Set up a simple configuration that logs on the console.
  16:         BasicConfigurator.Configure();
  17:  
  18:         log.Info("Entering application.");
  19:         Bar bar = new Bar();
  20:         bar.DoIt();
  21:         log.Info("Exiting application.");
  22:     }
  23: }

MyApp首先声明导入log4net的相关类,然后定义了一个静态记录器变量,传入参数是该类的类名。

在MyApp中使用了下面的Bar类

   1: using log4net;
   2:  
   3: namespace Com.Foo
   4: {
   5:     public class Bar
   6:     {
   7:         private static readonly ILog log = LogManager.GetLogger(typeof(Bar));
   8:  
   9:         public void DoIt()
  10:         {
  11:             log.Debug("Did it again!");
  12:         }
  13:     }
  14: }

BasicConfigurator.Configure()方法创建了一个简单的log4net配置,这个方法增加了一个到控制台的根记录器,输入格式可以使用PatternLayout来设置,例如"%-4timestamp [%thread] %-5level %logger %ndc - %message%newline".

默认情况下,根记录器被分配到Level.DEBUG

上述代码的输出如下

   1: 0    [main] INFO  MyApp  - Entering application.
   2: 36   [main] DEBUG Com.Foo.Bar  - Did it again!
   3: 51   [main] INFO  MyApp  - Exiting application.

我们注意到在log4net中,子记录器只会连接到他们存在的上级。这里,名为Com.Foo.Bar的记录器直接连接到根记录器,因而将忽略未使用的Com或者Com.Foo的记录器。这种方法明显改进了性能和降低了log4net的内存使用。

MyApp类通过调用BasicConfigurator.Configure()方法来配置log4net,其他类只需要导入log4net命名空间,获取他们需要的记录器进行记录。

上面的例子总是输入相同的记录信息。当然,可以简单的修改MyApp使之在运行时刻控制记录。下面是一个轻微修改版本。

   1: using Com.Foo;
   2:  
   3: // Import log4net classes.
   4: using log4net;
   5: using log4net.Config;
   6:  
   7: public class MyApp 
   8: {
   9:     private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
  10:  
  11:     static void Main(string[] args) 
  12:     {
  13:         // BasicConfigurator replaced with XmlConfigurator.
  14:         XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));
  15:  
  16:         log.Info("Entering application.");
  17:         Bar bar = new Bar();
  18:         bar.DoIt();
  19:         log.Info("Exiting application.");
  20:     }
  21: }

这个版本的MyApp使用XmlConfigurator来解析配置文件和建立记录环境,配置文件的路径通过命令行制定。
译注:不知道怎么赋值给命令行参数,我是直接传递log4net的配置文件的名称。

下面是一个简单的配置文件,它的效果与上面的基于BasicConfigurator的例子完全相同。

   1: <log4net>
   2:     <!-- A1 is set to be a ConsoleAppender -->
   3:     <appender name="A1" type="log4net.Appender.ConsoleAppender">
   4:  
   5:         <!-- A1 uses PatternLayout -->
   6:         <layout type="log4net.Layout.PatternLayout">
   7:             <conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" />
   8:         </layout>
   9:     </appender>
  10:     
  11:     <!-- Set root logger level to DEBUG and its only appender to A1 -->
  12:     <root>
  13:         <level value="DEBUG" />
  14:         <appender-ref ref="A1" />
  15:     </root>
  16: </log4net>

如果我们不再想记录任何Com.Foo命名空间中类的记录输出,可以参照下面的配置文件

   1: <log4net>
   2:     <!-- A1 is set to be a ConsoleAppender -->
   3:     <appender name="A1" type="log4net.Appender.ConsoleAppender">
   4:  
   5:         <!-- A1 uses PatternLayout -->
   6:         <layout type="log4net.Layout.PatternLayout">
   7:             <!-- Print the date in ISO 8601 format -->
   8:             <conversionPattern value="%date [%thread] %-5level %logger %ndc - %message%newline" />
   9:         </layout>
  10:     </appender>
  11:     
  12:     <!-- Set root logger level to DEBUG and its only appender to A1 -->
  13:     <root>
  14:         <level value="DEBUG" />
  15:         <appender-ref ref="A1" />
  16:     </root>
  17:     
  18:     <!-- Print only messages of level WARN or above in the package Com.Foo -->
  19:     <logger name="Com.Foo">
  20:         <level value="WARN" />
  21:     </logger>
  22: </log4net>

输出将会是这样:

   1: 2000-09-07 14:07:41,508 [main] INFO  MyApp - Entering application.
   2: 2000-09-07 14:07:41,529 [main] INFO  MyApp - Exiting application.

因为记录器Com.Foo.Bar没有分配级别,它将继承配置文件中已分配为Warn级别的Com.Foo的级别,Bar.DoIt方法中记录语句的级别为DEBUG,低于WARN,因此DoIt方法的记录请求将被禁止。

下面是使用多记录方式的配置文件

   1: <log4net>
   2:     <appender name="Console" type="log4net.Appender.ConsoleAppender">
   3:         <layout type="log4net.Layout.PatternLayout">
   4:             <!-- Pattern to output the caller's file name and line number -->
   5:             <conversionPattern value="%5level [%thread] (%file:%line) - %message%newline" />
   6:         </layout>
   7:     </appender>
   8:     
   9:     <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
  10:         <file value="example.log" />
  11:         <appendToFile value="true" />
  12:         <maximumFileSize value="100KB" />
  13:         <maxSizeRollBackups value="2" />
  14:  
  15:         <layout type="log4net.Layout.PatternLayout">
  16:             <conversionPattern value="%level %thread %logger - %message%newline" />
  17:         </layout>
  18:     </appender>
  19:     
  20:     <root>
  21:         <level value="DEBUG" />
  22:         <appender-ref ref="Console" />
  23:         <appender-ref ref="RollingFile" />
  24:     </root>
  25: </log4net>

运行它控制台将会出现如下输出

   1: INFO [main] (MyApp.cs:16) - Entering application.
   2: EBUG [main] (Bar.cs:12) - Doing it again!
   3: INFO [main] (MyApp.cs:19) - Exiting application.

指的注意的是,因为根记录器有第二个记录方式,记录也会被输出到example.log文件,文件将会被回滚当他达到100KB,当回滚发生时,旧版本的example.log将会被重命名为example.log.1

注意,实现这些不同的记录行为并不需要重新编译程序。我们可以轻松的将记录输出到Email地址、Windows的事件记录器,或者远程的log4net服务器。

更多的使用XmlConfigurator实现多输出方式的例子 点击这里

0 COMMENTS: