简单Demo
- 新建一个C# framework console project
- 通过Nuget添加log4net引用
- 新建一个配置文件log4net.config
-
修改配置文件,将属性改成
Copy Always, 添加如下配置信息1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
<configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </configSections> <log4net> <root> <level value="WARN" /> <appender-ref ref="LogFileAppender" /> <appender-ref ref="ConsoleAppender" /> </root> <logger name="testApp.Logging"> <level value="DEBUG"/> </logger> <appender name="LogFileAppender" type="log4net.Appender.FileAppender" > <param name="File" value="log_file.txt" /> <param name="AppendToFile" value="true" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" /> </layout> </appender> <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" > <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" /> </layout> </appender> </log4net> </configuration> -
修改AssemblyInfo.cs,添加如下配置
1
[assembly: log4net.Config.XmlConfigurator(ConfigFile="log4net.config", Watch = true)]
-
修改main函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
static void Main(string[] args) { log4net.ILog log = log4net.LogManager.GetLogger("testApp.Logging"); string assemblyFilePath = Assembly.GetExecutingAssembly().Location; string assemblyDirPath = Path.GetDirectoryName(assemblyFilePath); DirectoryInfo pathInfo = new DirectoryInfo(assemblyDirPath); string configFilePath = pathInfo.Parent.Parent.FullName + "//log4net.config"; log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(configFilePath)); Thread.CurrentThread.Name = "main"; log.Debug("initial connection"); log.Warn("test"); log.Info(DateTime.Now.ToString() + ": login success"); Console.ReadKey(); }
结构
log4net 有四种主要的组件,分别是Logger(记录器), Repository(库), Appender(附着器)以及 Layout(布局).
Logger
Logger接口
Logger是应用程序需要交互的主要组件,它用来产生日志消息。产生的日志消息并不直接显示,还要预先经过Layout的格式化处理后才会输出。
Logger提供了多种方式来记录一个日志消息,你可以在你的应用程序里创建多个Logger,每个实例化的Logger对象都被log4net框架作为命名实体(named entity)来维护。这意味着为了重用Logger对象,你不必将它在不同的类或对象间传递,只需要用它的名字为参数调用就可以了。
Log4net框架定义了一个叫做LogManager的类,用来管理所有的logger对象。它有一个GetLogger()静态方法,用我们提供的名字参数来检索已经存在的Logger对象。如果框架里不存在该Logger对象,它也会为我们创建一个Logger对象。代码如下所示:
1
log4net.ILog log = log4net.LogManager.GetLogger("logger-name");
通常来说,我们会以类(class)的类型(type)为参数来调用GetLogger(),以便跟踪我们正在进行日志记录的类。传递的类(class)的类型(type)可以用typeof(Classname)方法来获得
日志的级别
有七个日志记录级别,其中五个可以在代码中调用。 它们如下(最高的位于列表顶部):
从高到低分别为:OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL
Repository
Repository主要用于负责日志对象组织结构的维护。
如果你是个log4net框架的使用者,而非扩展者,那么你几乎不会在你的代码里用到Repository的类。相反的,你需要用到LogManager类来自动管理库和日志对象。
Appender
一个好的日志框架应该能够产生多目的地的输出。比如说输出到控制台或保存到一个日志文件。log4net 能够很好的满足这些要求。它使用一个叫做Appender的组件来定义输出介质。正如名字所示,这些组件把它们附加到Logger日志组件上并将输出传递到输出流中。你可以把多个Appender组件附加到一个日志对象上。
Appender Filters
一个Appender 对象缺省地将所有的日志事件传递到输出流。Appender的过滤器(Appender Filters) 可以按照不同的标准过滤日志事件。
记录日志等级为“FATAL”和“ERROR”的日志信息:
1
2
3
4
5
6
7
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="FATAL"/>
</filter>
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="ERROR"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter"/>
记录日志等级范围从“ERROR”到“INFO”的日志信息:
1
2
3
4
5
<filter type="log4net.Filter.LevelRangeFilter">
<levelMax value="ERROR"/>
<levelMin value="INFO"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter"/><!--不加这个过滤器也可以-->
Layout
Layout 组件用于向用户显示最后经过格式化的输出信息。输出信息可以以多种格式显示,主要依赖于我们采用的Layout组件类型。可以是线性的或一个XML文件。Layout组件和一个Appender组件一起工作。API帮助手册中有关于不同Layout组件的列表。一个Appender对象,只能对应一个Layout对象。
配置文件
设置 log4net的标准方法是使用app.config 文件或 web.config文件。 为了使其与 log4net 正常工作,需要将一些信息放入配置文件中。 这些部分将告诉 log4net 如何配置自身。 无需重新编译应用程序即可更改设置
Root
Root用来记录所有顶级记录器引用。 这些记录器从root继承信息。root节点还包含一个level属性,用来记录log的最低级别。 由于所有内容都继承自root,因此任何子记录器都不会记录低于此lelve的日志信息。 这是快速控制应用程序中的日志记录级别的简单方法。
下面的例子中,Debug信息将不会被记录。
1
2
3
4
5
<root>
<level value="INFO"/>
<appender-ref ref="FileAppender"/>
<appender-ref ref="ConsoleAppender" />
</root>
Additional Loggers
log4net 允许指定除root之外的其他记录器引用。
1
2
3
4
<logger name="Log4NetTest.OtherClass">
<level value="DEBUG"/>
<appender-ref ref="ConsoleAppender"/>
</logger>
请注意,logger的name是包含命名空间的类的全名。
ConfigSections
在配置文件中,除了 log4net 配置信息之外,还可能放了其他信息,因此需要指定一个部分来标识 log4net 配置的存放位置。 下面是一个示例,指定配置信息将存储在 XML 标签log4net下:
1
2
3
4
5
6
7
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
...
</log4net>
Appender
Appender指定log的位置、记录方式以及在什么情况下记录信息。 下面是一个Appender的示例:
1
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
Layout
每个appender必须有一个Layout。 根据所使用的appender的类型,这可能会有所不同,但基本原理是相同的。 需要指定一个数据写入方式的类型。 有多种选项,但建议使用的选项是pattern类型。 这将允许指定如何将数据写入数据存储库。 如果指定pattern,则需要一个指定转换模式的子标签conversionPattern。 这是将数据写入数据存储库的模式。
1
2
3
4
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%ndc]
- %message%newline"/>
</layout>
Conversion Patterns
1
2
3
4
5
6
7
8
9
10
%m(message):输出的日志消息;
%n(newline):换行;
%d(datetime):输出当前语句运行的时刻;
%r(runtime):输出程序从运行到执行到当前语句时消耗的毫秒数;
%t(threadid):当前语句所在的线程ID ;
%p(priority): 日志的当前日志级别;
%c(class):当前日志对象的名称;
%L:输出语句所在的行号;
%F:输出语句所在的文件名;
%-10:表示最小长度为10,如果不够,则用空格填充;
Filters
filter是 appender 的另一个重要部分。 使用过滤器,您可以指定要记录的级别,甚至可以在消息中查找关键字。 过滤器可以混合和匹配,但这样做时需要小心。
StringMatchFilter
字符串匹配过滤器会查找log信息中的特定字符串。 可以指定多个字符串匹配过滤器。 它们的工作方式类似于查询中的 OR 语句。 过滤器将查找第一个字符串,然后查找第二个字符串,依此类推,直到找到匹配项。 然而,这里要注意的重要一点是,未找到与指定字符串的匹配并不排除该条目(因为它可能会继续到下一个字符串匹配过滤器)。 然而,这意味着您可能会遇到找不到匹配项的情况。 在这种情况下,默认操作是记录该条目。 因此,在字符串匹配过滤器集的末尾,有必要包含一个拒绝所有过滤器,以在未进行匹配的情况下拒绝记录条目。
1
2
3
4
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="test" />
</filter>
<filter type="log4net.Filter.DenyAllFilter"/>
LevelRangeFilter
LevelRangeFilter告诉系统仅记录指定范围内的log。 在下面的示例中,级别为 INFO、WARN、ERROR 或 FATAL 的事件将被记录,但 DEBUG 事件将被忽略。 不需要在此条目后添加DenyAll过滤器,因为拒绝是隐含的。
1
2
3
4
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
LevelMatchFilter
LevelMatchFilter指定一个且仅一个要捕获的级别。 但是,它没有内置拒绝功能,因此需要在列出此过滤器后添加DenyAll过滤器。
1
2
3
4
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="ERROR"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter"/>
DenyAllFilter
如果忘记了这个filter,可能会导致程序无法按预期工作。 此filter的唯一目的是指定不应创建任何log条目。 如果这是唯一的filter,则log4net不会记录任何内容。 然而,它的真正目的是指定不再记录任何内容(记住,任何已经匹配的内容都已被记录)。
1
<filter type="log4net.Filter.DenyAllFilter" />
Appender demo
Console Appender
1
2
3
4
5
6
7
8
9
<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>
File Appender
File Appender将log写入文本文件。 这里需要注意的最大区别是必须指定文本文件的名称,指定我们应该 附加到文件(而不是覆盖它),并且指定 FileAppender 应使用最小锁定,这样文件可供多个附加程序使用。
1
2
3
4
5
6
7
8
9
10
11
12
<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>
Rolling File Appender
应尽可能使用Rolling File Appender来代替File Appender。 滚动文件追加器的目的是执行与文件追加器相同的功能,但具有附加选项,即在启动新的日志文件之前仅存储一定量的数据。 这样,就不必担心日志文件大小会随着时间的推移而增长的太大。 在此示例中,指定日志文件的上限应为 10MB,并且在开始删除它们之前最多保留 5 个存档文件(首先删除最旧的文件)。 存档将以与文件相同的名称命名,但带有一个点和数字。 staticLogFileName 条目确保当前日志文件始终以文件标记中指定的名称(mylogfile.txt)命名。
1
2
3
4
5
6
7
8
9
10
11
<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>
rollingStyle有四种模式:
| Name | Description |
|---|---|
| Once | Roll files once per program execution |
| Size | Roll files based only on the size of the file |
| Date | Roll files based only on the date |
| Composite | Roll files based on both the size and date of the file |