为什么使用log4net
有些日志语句只是在开发中用于调试的,不应该在Release版本中输出,log4net通过配置文件可以为Debug和Release不同的模式设置不同的输出级别来控制,而且如果已经发布了,在Release下遇到一些问题,想要查看某些本来在Debug模式下才会输出的日志,可以修改配置文件就会即时生效了(重启程序不是必要的)
代码中使用log4net
先了解log4net定义的日志级别,从上到下,级别由高到低,在配置文件中将可以控制输出级别,低于该级别的日志不会输出。cannot be called表示并非在代码中调用的,而是用于配置文件。
- OFF - nothing gets logged (cannot be called)
- FATAL 严重的错误,程序应该退出
- ERROR 错误,程序无法完成某一个操作
- WARN 警告,虽然程序可以完成操作,但是有一些需要留意的事件
- INFO 信息,用于跟踪某一流程,仅仅用于关键位置
- DEBUG 调试,仅仅用于调试时使用,在完成历史任务后应该从代码中移除
- ALL - everything gets logged (cannot be called)
应该遵守这些级别约定,而不能总使用ERROR或者其它的级别。
调用的方法,以Info为例:
0
1
2
logger.Info("hello, world")
logger.InfoFormat("hello, {0}", word)
logger.Info("hello, world", ex) //ex表示异常
一般而言,写日志的时候最好提供某个tag,来表示某些日志属于这一个过程,例如以下日志语句:
0
1
2
[tag0] hello, world
[tag1] I'm handsome
[tag0] world, hello
在跟踪的时候,就可以仅仅查看tag0的日志。在log4net的基础上做了一点小小的封装:
0
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
public class Logger
{
public static ILog GetLogger(object o)
{
return log4net.LogManager.GetLogger(o.GetType());
}
public static ILog GetLogger(Type type)
{
return log4net.LogManager.GetLogger(type);
}
public static ILog GetLogger(string name)
{
return log4net.LogManager.GetLogger(name);
}
}
...
//用于实例方法中
Logger.Logger.GetLogger(this).Info("install begin");
//用于静态类的方法中
Logger.Logger.GetLogger(typeof(AdbUtil)).Info("获取IMEI:" + (errno as NIErrno).IMEI);
//显性命名
Logger.Logger.GetLogger("UI").Debug(text);
使用GetLogger(this)虽然很方便,但是并不是最好的做法,应该以跟踪的过程来作为tag,而这个过程往往会跨越多个类的实例。
配置文件示例
使用这种配置方式,在Release模式下无法输出日志:
使用XML配置文件,首先添加以下语句(在using语句块后):
0
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
改为使用这种方式:
0
1
2
3
4
5
6
public class Bar
{
static Bar()
{
XmlConfigurator.Configure();
}
}
看这里:Log4net works in Debug but fails in Release build
不过使用app.config也不能监测配置文件变化:
The System.Configuration API is only available if the configuration data is in the application's config file; the file named MyApp.exe.config or Web.config. Because the System.Configuration API does not support reloading of the config file the configuration settings cannot be watched using the log4net.Config.XmlConfigurator.ConfigureAndWatch methods. The main advantage of using the System.Configuration APIs to read the configuration data is that it requires less permissions than accessing the configuration file directly.
下面的App.config中定义了一个回滚文件日志,包括log.txt本身,还最多会有19个以数字命名的备份文件,而log.txt.1总是时间最近的备份。由于同时限制了单文件大小为1MB,所以日志最多占20MB。生成的文件名没有以日期为文件名,因为RollingFileAppender的Composite的rollingStype,只能针对某一日期,限制这一日期之内的日志大小,而不能限制全部的日志的大小。
0
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
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="Logger" type="log4net.Appender.RollingFileAppender">
<file value="4SLOG/log.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="20" />
<maximumFileSize value="1MB" />
<staticLogFileName value="true" />
<encoding value="utf-8" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%thread] %logger %date %-5level - %message %location %newline" />
</layout>
</appender>
<root>
<level key="log_level" value="ALL" />
<appender-ref ref="Logger" />
</root>
</log4net>
</configuration>
Debug和Release下不同的配置
与Web.config不同,VS是不支持在Debug和Release中使用不同的App.config,需要安装插件:SlowCheetah。一个简单的XML Transform的App.Release.config如下:
0
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8" ?>
<!-- For more information on using transformations
see the web.config examples at http://go.microsoft.com/fwlink/?LinkId=214134. -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<log4net>
<root>
<level key="log_level" xdt:Transform="Replace" value="INFO" />
</root>
</log4net>
</configuration>
查看log4net的日志
推荐使用LogViewer