);
在log4net中,通过添加节点PropertyFilter来实现属性过滤,如下:
<filter type="log4net.Filter.PropertyFilter">
<key value="" />
<stringToMatch value="" />
<acceptOnMatch value="" />
</filter>
如上key代表需要我们定义的键,而stringToMatch代表我们通过对应键所添加的值,最后acceptOnMatch代表是否接受匹配,为布尔值,默认为true(接收匹配就记录)。若我们在配置文件appender节点小添加如下节点:
<filter type="log4net.Filter.PropertyFilter">
<key value="filter" />
<stringToMatch value="1" />
<acceptOnMatch value="false" />
</filter>
如上设置代表,当我们对应设置属性的键为filter,而值为1时则记录日志,接下来我们在上述控制台基础通过log4net提供的api去设置线程级别的属性,添加如下:
ThreadContext.Properties["filter"] = "1";
log.Info("1......");
ThreadContext.Properties["filter"] = "0";
log.Info("0......");
我们通过设置键filter的值为1和0时都记录下来了,很显然没达到要求,我们只想记录对应值等于1的日志,此时需要在上述节点继续添加如下一行来只记录此属性键对应值的日志:
好了,到此有了对log4net日志过滤的基础铺垫,接下来实现我们的需求:创建两个日志文件,一个记录正常信息(排除审计),一个只记录审计信息 。接下来我们对配置文件修改如下:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<!--只接收auditing日志-->
<appender name="AuditingRollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="auditing.txt" />
<appendToFile value="true" />
<countDirection value="1"/>
<maximumFileSize value="10MB" />
<maxSizeRollBackups value="-1" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
<filter type="log4net.Filter.PropertyFilter">
<key value="filter" />
<stringToMatch value="auditing" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
</appender>
<!--只接收除auditing以外的日志-->
<appender name="ExceptAuditingRollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="non-auditing.txt" />
<appendToFile value="true" />
<countDirection value="1"/>
<maximumFileSize value="10MB" />
<maxSizeRollBackups value="-1" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
<filter type="log4net.Filter.PropertyFilter">
<key value="filter" />
<stringToMatch value="auditing" />
<acceptOnMatch value="false" />
</filter>
</appender>
<level value="DEBUG"/>
<appender-ref ref="AuditingRollingFileAppender" />
<appender-ref ref="ExceptAuditingRollingFileAppender" />
</root>
</log4net>
上述配置文件就不用我多讲,接下来我们将控制台中上述测试打印的日志给移除,我们添加如下代码进行测试:
//只接收auditing日志
ThreadContext.Properties["filter"] = "auditing";
log.Info("auditing.......");
//只接收除了auditing以外日志
ThreadContext.Properties["filter"] = "non-auditing";
log.Info("non-auditing.......");
log.Warn("测试非审计......");
//只接收auditing日志
ThreadContext.Properties["filter"] = "auditing";
log.Info("测试审计.......");
虽然创建一个审计日志文件和一个非审计日志文件,我们的配置也没任何毛病,但是通过上述日志输出发现,非审计文件压根没有日志却全部到了审计文件里,这是为何呢? 经过排查,我开始猜测log4net难道是对值进行模糊匹配吗?为了验证猜想,我将上述对非审计的值(多加一个字母Z)修改成如下:
只要我们将上述非审计日志的值设置时并不包含审计日志里的值(auditing)就没问题,真香,哈哈。上述排除auditing节点以外日志的节点是从反向考虑,当然我们也可以从正向考虑,设置为其他值,还是注意不要包含auditing,并且只记录该值的记录,如下
<!--只接收除auditing以外的日志-->
<appender name="ExceptAuditingRollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="non-auditing.txt" />
<appendToFile value="true" />
<countDirection value="1"/>
<maximumFileSize value="10MB" />
<maxSizeRollBackups value="-1" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
<filter type="log4net.Filter.PropertyFilter">
<key value="filter" />
<stringToMatch value="other" />
<acceptOnMatch value="true" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
</appender>
如上我们在输出非审计日志时,我们设置了INFO和Warn级别日志,要是我们想过滤掉上述Warn以及其他级别,只想保留Info级别日志,那么我们应该肿么办呢?我们添加输出内置INFO级别日志,除此级别外拒绝其他级别的日志,如下:
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="INFO"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter"/>
在log4net中除了设置属性过滤外,还可以比如通过日志中的字符串进行匹配,比如我们添加如下字符串匹配节点,说明包含cache_log的值将不会被记录:
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="cache_log" />
<acceptOnMatch value="false" />
</filter>
log4net运行时创建日志
我们可能会遇到根据什么规则或者需要在运行时创建日志文件,这个时候就不能如上写死日志文件名了,我们通过log4net提供给我们的api【%property】来实现,我们将上述节点file进行如下修改:
<file type="log4net.Util.PatternString" value="D:\logs\%property{LogName}" />
接着添加创建日志文件名代码,注意要将如下第一行放在第二行前面,否则创建的文件名将为null,如下:
ThreadContext.Properties["LogName"] = "runtime.log";
Config.XmlConfigurator.Configure(repo, log4netConfig["log4net"]);
log4net在以前.NET Framework中用到的比较多,但是并未使用过过滤日志这一特性,我们通过业务模块不同来过滤日志,最近要使用时研究发现的问题,看到网上对此资料甚少,所以在此作为备忘录,能够帮到有需要的童鞋当然再好不过啦。
你所看到的并非事物本身,而是经过诠释后所赋予的意义