项目过程中, 不可避免的, 需要使用到日志功能. 在我接触过的项目中, 也有自己弄一套日志的, 但是更多的, 还是使用别人成熟的dll, 比如log4.
log4相关的文档, 真是非常的多, 也非常的全, 但是本着温故而知新的目的, 还是想把这个过一遍.
先放一个小Demo在上面
<appender name="TraceLogFileAppender" type="log4net.Appender.RollingFileAppender"> <file value="Logs race.txt" /> <MaxSizeRollBackups value="20" /> <StaticLogFileName value="false" /> <DatePattern value="yyyyMMdd'.txt'" /> <RollingStyle value="Size" /> <MaximumFileSize value="10MB"/> <appendToFile value="true" /> <layout type="log4net.Layout.PatternLayout"> <header value="[BEGIN LOGGING AT %date]%newline" type="log4net.Util.PatternString" /> <footer value="[END LOGGING AT %date]%newline%newline" type="log4net.Util.PatternString" /> <ConversionPattern value="%d [%t] %-5p %c - %m%n" /> </layout> <filter type="log4net.Filter.LevelRangeFilter,log4net"> <levelMin value="DEBUG" /> <levelMax value="INFO" /> </filter> </appender>
主要有五个组成部分: Appenders, Filters, Layouts, Loggers, Object Renders
1. Appenders
用来定义日志的输出方式. 可以通过配置Filters和Layout来实现日志的过滤和输出格式.
他的输出方式有很多种, 这里主要介绍几种项目中最常用的.
AdoNetAppender | 将日志记录到数据库中 |
FileAppender | 将日志输出到文件 |
RollingFileAppender | 将日志以回滚文件的形式写到文件中 |
SmtpAppender | 将日志写到邮件中 |
2. Filters
过滤器可以过滤掉Appender输出的内容.
DenyAllFilter | 阻止所有的日志事件被记录 |
LevelMatchFilter | 只有指定等级的日志事件才被记录 |
LevelRangeFilter | 日志等级在指定范围内的事件才被记录 |
LoggerMatchFilter | Logger名称匹配,才记录 |
PropertyFilter | 消息匹配指定的属性值时才被记录 |
StringMathFilter | 消息匹配指定的字符串才被记录 |
3. Layouts
用于控制Appender的输出格式, 可以使线性的, 也可以使Xml. 但是一个Appender只能有个一个Layout. 配置了这个之后, 可以不用在程序中再去自定义一个格式了.
最常用的, 应该还是自定义格式的PatternLayout. 接下来看一下 ConversionPattern 里面的格式和意义
<ConversionPattern value="%d [%t] %-5p %c - %m%n" />
a appdomain |
引发日志事件的应用程序域的名称 |
c (小写) logger |
记录日志事件的Logger对象的名字 可以使用精度说明符控制Logger的名字的输出层级, 默认输出全名 注意,精度符的控制是从右开始的。例如:logger 名为 "a.b.c", 输出模型为 %logger{2} ,将输出"b.c" |
C (大写) class type |
引发日志请求的类的全名 可以使用精度控制符. 例如: 类名是 "log4net.Layout.PatternLayout", 格式模型是 %type{1}将输出"PatternLayout"。(也是从右开始的。) 警告:会影响性能。 |
d date |
记录当前本地时间. 如 %d{HH:mm:ss,fff} 或 %d{dd MMM yyyy HH:mm:ss,fff} 建议还是使用自定义格式的时间吧. |
exception |
异常信息 日志中必须存一个异常对象, 如果日志事件不包含没有异常对象, 那么什么也输出不了. 异常输出完毕后, 会跟一个换行. 一般会在输出异常前加一个换行, 并将异常放在最后. |
F file |
发生日志请求的源代码文件的名字 警告:只在调试的时候有效。调用本地信息会影响性能。 |
U identity |
当前活动用户的名字(Principal.Identity.Name). 警告:会影响性能。(我测试的时候%identity返回都是空的。) |
l (L的小写) location |
引发日志事件的方法(包括命名空间和类名),以及所在的源文件和行号。 警告:会影响性能。没有pdb文件的话,只有方法名,没有源文件名和行号。 |
L p level |
日志等级 |
line | 引发日志的行号 |
m message |
由应用程序提供给日志的消息 |
M method |
发生日志请求的方法名(只有方法名而已)。 警告:会影响性能。 |
X mdc P property propertites |
输出事件的特殊属性。例如: %property{user} 输出user属性。 属性是由loggers或appenders添加到时间中的。 有一个默认的属性"DE<log4net:HostName"总是会有。 DE<%property将输出所以的属性 。 |
n newline |
换行符 |
r timestamp |
从程序启动到事件发生所经过的毫秒数。 |
t thread |
引发日志事件的线程,如果没有线程名就使用线程号。 |
w username |
当前用户的WindowsIdentity。(类似:HostNameUsername) 警告:会影响性能。 |
utcdate |
发生日志事件的UTC时间。DE<后面还可以跟一个日期格式,用大括号括起来。 DE<例如:%utcdate{HH:mm:ss,fff}或者%utcdate{dd MMM yyyy HH:mm:ss,fff}。 如果utcdate后面什么也不跟,将使用ISO8601 格式 。 日期格式和.Net中DateTime类的ToString方法中使用的格式是一样。 另外log4net还有3个自己的格式Formatter。 它们是 "ABSOLUTE", "DATE"和"ISO8601"分别代表AbsoluteTimeDateFormatter,DateTimeDateFormatter和Iso8601DateFormatter。 例如: %date{ISO8601}或%date{ABSOLUTE}。 它们的性能要好于ToString。 |
x ndc |
NDC (nested diagnostic context) |
% |
%%输出一个百分号 |
上面demo中的-5是什么意思呢? 接着看
Format modifier | left justify | minimum width | maximum width | comment |
---|---|---|---|---|
%20logger | false | 20 | none |
如果logger名不足20个字符,就在左边补空格。 |
%-20logger | true | 20 | none |
如果logger名不足20个字符,就在右边补空格。 |
%.30logger | NA | none | 30 |
超过30个字符将截断。 |
%20.30logger | false | 20 | 30 |
logger名要在20到30之间,少了在左边补空格,多了截断。 |
%-20.30logger | true | 20 | 30 |
logger名要在20到30之间,少了在右边补空格,多了截断。 |
4. Loggers
Logger是直接和应用程序交互的组件. Logger只是产生日志, 然后由它引用的Appender记录到指定的地方, 并有Layout控制输出格式.
Logger提供了多种方式来记录一个日志消息, 也可以有多个Logger同时存在. 每个实例化的Logger对象被log4net作为命名实体来维护.
log4net使用继承体系, 两个Logger, a 和 a.b, a是a.b的祖先. 每个Logger都继承了它祖先的属性.
日志的等级有如下几级:
OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL.
5. Object Renders
我对Object Renders的理解是这样的。它将告诉logger如何把一个对象转化为一个字符串记录到日志里。(你可能注意到了,ILog中定义的接口接收的参数是Object,而不是String。)
例如你想把Orange对象记录到日志中,但此时logger只会调用Orange默认的ToString方法而已。所以要定义一个OrangeRender类实现log4net.ObjectRender.IObjectRender接口,然后注册它。这时logger就会知道如何把Orange记录到日志中了。
不过我没有测试过,具体怎么做还是看文档吧。
参考:
log4net使用手册 (这一篇都是从这里拷贝过来的, 链接里面更加详细)