.Net魔法堂:log4net详解
一、作用
提供一个记录日志的框架,可以将日志信息记录到文件、控制台、Windows事件日志和数据库(MSSQL、Acess、Oracle、DB2和SQLite等)。
二、先看看示例,感受一下吧
config配置文件
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler"/>
</configSections>
<log4net>
<!-- 定义日志的输出媒介 -->
<root>
<appender-ref ref="ConsoleAppender"/>
<appender-ref ref="R"/>
</root>
<!-- 定义输出到控制台 -->
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
</layout>
</appender>
<!-- 定义输出到日志文件 -->
<appender name="R" type="log4net.Appender.FileAppender" rollingStyle="Date" datePattern="yyyyMMdd-HH:mm:ss">
<file value="logs/log.txt"></file>
<appendToFile value="true"></appendToFile>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-d{yyyy-MM-dd HH:mm:ss} [%L] [%c]-[%p] %m%n"></conversionPattern>
</layout>
</appender>
</log4net>
</configuration>
cs文件
/**
* 指定log4net使用.config文件来读取配置信息
* 若为Winform(假定程序为Demo.exe), 那么配置文件则为Demo.exe.config
* 若为Webform,则为web.config
*/
[assembly:log4net.Config.XmlConfigurator(Watch=true)]
namespace Demo{
public class MainClass{
public static void Main(String[] args){
ILog log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
log.Error("error", new Exception("there is an exception"));
log.Fatal("fatal", new Exception("there is a deadly exception occurs"));
log.Info("info");
log.Debug("debug");
log.Warn("warn");
Console.Read();
}
}
}
三、框架的核心组件
1. Appender
作用:用于定义日志信息的输出介质(文件、控制台、Windows事件日志和数据库(MSSQL、Acess、Oracle、DB2和SQLite等)) 内置的Appdner组件:
ConsoleAppender ,输出介质为控制台
FileAppender ,输出介质为文件,示例如下
<appender name="FileAppender" type="log4net.Appender.FileAppender"
file="logs/log.txt" appendToFile="true">
<layout type="log4net.Layout.PatternLayout">
..........
</layout>
</appender>
RollingFileAppender ,将日志以回滚文件的形式写入文件中。可以指定文件最大容量,当超过就生成一个新文件来记录,且可以指定最多生成日志文件数量,当超过时则覆盖从第一个日志文件开始循环覆盖。
示例1:
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"
file="logs/log.txt" appendToFile="true" rollingStyle="Size" maxSizeRollBackups="10" maximumFileSize="100KB" staticLogFileName="true">
<layout type="log4net.Layout.PatternLayout">
..........
</layout>
</appender>
示例2:
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"
file="logs/log.txt" appendToFile="true" rollingStyle="Date" datePattern="yyyyMMdd">
<layout type="log4net.Layout.PatternLayout">
..........
</layout>
</appender>
EventLogAppender ,输出介质为系统日志
AdoNetAppender ,输出介质为数据库,示例如下
<appender name="AdoNetAppender_Oracle" type="log4net.Appender.AdoNetAppender">
<connectionType value="System.Data.OracleClient.OracleConnection, System.Data.OracleClient" />
<connectionString value="data source=[mydatabase];User ID=[user];Password=[password]" />
<commandText value="INSERT INTO Log (Datetime,Thread,Log_Level,Logger,Message) VALUES (:log_date, :thread, :log_level, :logger, :message)" />
<bufferSize value="128" />
<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>
</appender>
自定义Appender时,需要继承 log4net.Appender.AppenderSkeleton
2. Layout
作用:定义向用户显示最终的经格式化的输出信息。 注意:一个Appender对象仅能对应一个Layout对象 内容的Layout组件:
PatternLayout ,用户自定义格式,内置参数如下
%m
(message),输出的日志消息%n
(newline),换行%d
(datetime),输出当前语句运行的时刻%r
(runtime),输出程序从运行到当前语句时消耗的毫秒数%t
(thread id),输出当前语句运行的线程ID%p
(level),输出日志级别(日志事件)%c
(class),输出当前语句所在的对象名称%M
(method),输出当前语句所在的方法名称%f
(file),输出当前语句所在的文件名称%L
(line),输出当前语句位于所在的文件中的行号%l
(location),输出当前语句位于的全限定类名,以及源文件和行号%数字
,表示该项的最小长度,如果不够则在左边用空格填充。如:%5p
,表示输出日志级别,且长度最小为5个字符%-数字
,表示该项的最小长度,如果不够则在右边用空格填充。如:%-5p
,表示输出日志级别,且长度最小为5个字符%.数字
,表示该项的最大长度,如果超出则截断%数字.数字
,表示该项的必须位于最小和最大长度之间,如果超出则截断, 不够则用空格填充
最佳实践: %-d{yyyy-MM-dd HH:mm:ss} [%L] [%c]-[%p] %m%n
SimpleLayout
ExceptionLayout
,输出时包含Message和Trace信息。Logger方法必须传入Exception对象,否则什么都不输出。
XmlLayout
,中文会有问题。
自定义Layout时,需要继承 log4net.Layout.LayoutSkeleton
3. Appender Filter
作用:默认情况下Appender对象会将所有日志信息都输出到相应的介质中,通过Appender Filter对象(命令空间:log4net.Filter)可以按照不同的标准过滤日志事件或内容。 内置的Filter组件:
DenyAllFilter ,阻止所有的日志事件被记录
LevelMatchFilter ,只有指定等级的日志事件才被记录
LevelRangeFilter ,日志等级在指定范围内的事件才被记录
LoggerMatchFilter , Logger名称匹配才被记录
PropertyFilter ,消息匹配指定的属性值才被记录
StringMatchFilter ,消息匹配指定的字符串才被记录
4. Logger
作用:直接与应用交互的组件,用于触发日志事件
级别(日志事件) |
优先级 |
---|---|
OFF |
6 |
FATAL |
5 |
ERROR |
4 |
WARN |
3 |
INFO |
2 |
DEBUG |
1 |
ALL |
0 |
5. Object Render
作用:输出根据Layout格式化的日志消息。Render必须实现log4net.ObjectRender.IObjectRender接口
6. Repository
作用:负责日志对象组织结构的维护。对于非框架扩展者,几乎不会用到该组件。
四、配置方式
1. 代码中配置
通过 log4net.Config.BasicConfigurator.Configure
配置根日志且只能配置根日志而已。
示例 :
// 和PatternLayout一起使用FileAppender
log4net.Config.BasicConfigurator.Configure(
new log4net.Appender.FileAppender(
new log4net.Layout.PatternLayout("%d
[%t]%-5p %c [%x] - %m%n"),"testfile.log"));
// using a FileAppender with an XMLLayout
log4net.Config.BasicConfigurator.Configure(
new log4net.Appender.FileAppender(
new log4net.Layout.XMLLayout(),"testfile.xml"));
// using a ConsoleAppender with a PatternLayout
log4net.Config.BasicConfigurator.Configure(
new log4net.Appender.ConsoleAppender(
new log4net.Layout.PatternLayout("%d [%t] %-5p %c - %m%n")));
// using a ConsoleAppender with a SimpleLayout
log4net.Config.BasicConfigurator.Configure(
new log4net.Appender.ConsoleAppender(new
log4net.Layout.SimpleLayout()));
2. 配置文件(推荐使用)
log4net框架会在 AppDomain.CurrentDomain.BaseDirectory
指向的目录路径下查找配置文件。
在config文件中配置
在<configuration>
节点下添加<configSections>
节点
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler"/>
</configSections>
只有添加上述节点,log4net.dll才能读取config文件下<log4net>节点
下配置信息
根日志<root>节点
框架中所有日志对象都是根日志的后代,因此日志对象若没有显式配置时则会使用根日志的配置信息。
<root>
<!-- level节点用于定义处理哪个级别的日志事件,缺省值为DEBUG -->
<level>INFO</level>
<!-- appender-ref节点用于定义日志对象所使用的Appender对象 -->
<appender-ref ref="appender节点的name属性值"/>
</root>
日志对象<logger>节点
显式配置日志对象。
<!-- additivity特性设置为false时,日志对象将不继承根日志的appender-ref节点信息。缺省值为true -->
<logger name="test.Logging" additivity="false">
<!-- 覆盖根日志的level设置 -->
<level value="WARN"/>
</logger>
.cs文件中的相应的调用方式
log4net.LogManager.GetLogger("test.Logging");
Appender对象<appender>节点
<appender name="appender1" type="log4net.Appender.FileAppender">
<layout type="log4net.Laytout.PatternLayout">
<conversionPattern value=".........."/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter" levelMin="DEBUG" levelMax="WARN">
</filter>
</appender>
五、关联配置文件
每个可独立执行的程序集均可以关联自己的配置文件。(组件库就使用调用者的配置文件好了) 在 AssemblyInfo.cs文件 中添加
[assembly:log4net.Config.DOMConfigurator([ConfigFile="配置文件名"|ConfigFileExtension="编译后配置文件的扩展名"][Watch=true/false])
参数说明:
ConfigFile :指定配置文件含扩展名的路径,如果为相对路径则以AppDomain.CurrentDomain.BaseDirectory
为当前路径;
ConfigFileExtension :若程序编译后配置文件使用了不同的扩展名,则通过该属性指定,默认值为config
,配置文件的最终名称为"应用程序名.exe.config";
注意:ConfigFile和ConfigFileExtension属性是互斥的,仅能设置其中一个
Watch :设置是否需要运行时监视文件的修改、重命名和删除等事件,若设置为true,则使用FileSystemWatcher来监视配置文件。
六、输出日志的优化方式
/**
* 由于触发日志事件时,会检查日志对象的级别是否满足日志事件的级别
* 先检测日志对象的级别,才触发日志事件
*/
if (log.IsDebugEnabled) log.Debug("message.....");
七、总结
现在我们就不再糊里糊涂地调用log4net了,建议具体使用时再查阅API文档!
八、参考
http://www.cnblogs.com/jams742003/archive/2009/12/10/1620861.html http://zhoufoxcn.blog.51cto.com/792419/429988
- 微信二次开发Java自定义菜单事件实现
- 微信OAuth授权获取用户OpenId-JAVA(个人经验)
- 【手写文字识别】-JavaAPI示例代码
- 【Python3-API】情感倾向分析示例代码
- SpringMVC+Hibernate +MySql+ EasyUI实现CRUD(一)
- 【Python3-API】通用文字识别示例代码
- Python入门教程之安装MyEclipse插件和安装Python环境
- AutoFlowLayout-多功能流式布局与网格布局控件
- RBAC新解:基于资源的权限管理(Resource-Based Access Control)
- 基于开源项目搭建属于自己的技术堆栈
- Redis整合Spring项目搭建实例
- SpringMVC+Hibernate +MySql+ EasyUI实现POI导出Excel(二)
- Nginx+Tomcat+Redis负载均衡Session共享实现超级简单(CentOS6.9系统 Java版本)
- Apache Ignite——新一代数据库缓存系统
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于prometheus的监控方案
- Gin 学习之自定义服务器配置信息
- 经验总结 | 关于 reNgine 自动化网络侦查框架的国内安装与报错的解决方法
- CS学习笔记 | 24、C2lints实例演示
- CS学习笔记 | 23、malleable命令
- ASP.NET Core 基于声明的访问控制到底是什么鬼?
- scATAC-seq建库原理,质控方法和新R包Signac的使用
- R语言可视化学习笔记之ggridges包绘制山峦图
- 06 . ELK Stack + kafka集群
- 使用DockerFile构建运行GoWeb
- windows版gbc:基于enginx的组件服务器系统paas,可用于mixed web与websocket game
- 01 . RPC简介原理及用Go实现一个RPC
- 17 . Go之网络编程
- 01 . Go框架之Beego简介部署及程序流程分析
- 服务器入侵排查流程