slf4j-logback-filter-MDC进阶

Have lots of ideas and throw away the bad ones. You aren't going to have good ideas unless you have lots of ideas and some sort of principle of selection. —LINUS PAULING

logback 其他系列请参考:
[url]http://wangxinchun.iteye.com/blog/2101653[/url]
[url]http://wangxinchun.iteye.com/blog/2094761[/url]
------------------------------------------filter----------------------------------------------------------------------

在logback 中为了对日志做更精细的控制,appender 标签可以配置多个filter标签。

说明:每个自定义的filter 都需要继承ch.qos.logback.core.filter.Filter类,并实现 decide(ILoggingEvent event) 方法。这方法会返回一个FilterReply枚举对象,有三个可选值:DENY, NEUTRAL or ACCEPT。如果返回DENY 那么event直接被抛弃,不被记录也无需参考下一个filter,如果是ACCEPT那么直接记录无需参考下一个filter,如果是NEUTRAL 那么由下一个filter判断,如果没有下一个filter,那么会直接记录。
最基本的一个自定义filter案例:
Filter code:

/**
* 自定义filter 功能:如果日志的内容超过10个字符,抛弃掉
* @author wangxinchun1988@163.com
* @date 2014-8-13上午11:10:25
*/
public class LogFilter extends Filter<ILoggingEvent> {
@Override
public FilterReply decide(ILoggingEvent event) {
if (event.getFormattedMessage().toString().length()< 10 ) {
return FilterReply.ACCEPT;
} else {
return FilterReply.DENY;
}
}
}

logback.xml 配置

<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>rooling.log</file>
<filter class="com.qunar.logback.LogFilter" />
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>rooling-log.%d{yyyy-MM-dd-HH}.log.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>[%thread] %-5level %logger{35} - %msg%n </pattern>
</encoder>
</appender>


测试case:

@Test
public void testLogback() throws InterruptedException {
long l = System.currentTimeMillis();
for(int i=0;i<30;i++){
logger.info("hello {} ", wrapLog(i));
}
System.out.println(System.currentTimeMillis() - l);
Thread.currentThread().sleep(1000);
}

private String wrapLog(int logLength){
StringBuilder sb = new StringBuilder();
for(int i=0;i<logLength;i++){
sb.append("a");
}
return sb.toString();
}

输出:
[main] INFO com.qunar.logback.LogbackTest - hello
[main] INFO com.qunar.logback.LogbackTest - hello a
[main] INFO com.qunar.logback.LogbackTest - hello aa
[main] INFO com.qunar.logback.LogbackTest - hello aaa
[main] INFO com.qunar.logback.LogbackTest - hello aaaa
[main] INFO com.qunar.logback.LogbackTest - hello aaaaa
[main] INFO com.qunar.logback.LogbackTest - hello aaaaaa
[main] INFO com.qunar.logback.LogbackTest - hello aaaaaaa
[main] INFO com.qunar.logback.LogbackTest - hello aaaaaaaa
[main] INFO com.qunar.logback.LogbackTest - hello aaaaaaaaa
[main] INFO com.qunar.logback.LogbackTest - hello aaaaaaaaaa
[main] INFO com.qunar.logback.LogbackTest - hello aaaaaaaaaaa
[main] INFO com.qunar.logback.LogbackTest - hello aaaaaaaaaaaa

结论:日志超过10个字符的都被DENY 了。

同样 logback 默认提供了其他的filter
ch.qos.logback.classic.filter.LevelFilter:级别限制,可以指定某个日志文件只输出某一级别的日志。
ch.qos.logback.classic.filter.ThresholdFilter:级别限制,可以限制不输出低于某一级别的日志。

LevelFilter源代码如下:

public class LevelFilter extends AbstractMatcherFilter<ILoggingEvent> {

Level level;

@Override
public FilterReply decide(ILoggingEvent event) {
if (!isStarted()) {
return FilterReply.NEUTRAL;
}

if (event.getLevel().equals(level)) {
return onMatch;
} else {
return onMismatch;
}
}

public void setLevel(Level level) {
this.level = level;
}

public void start() {
if (this.level != null) {
super.start();
}
}
}


为了灵活支持简单的逻辑判断,以避免创建自定义的filter,logback 提供了EvaluatorFilter 允许逻辑判断代码。
配置的相关变量如下表:
[img]http://dl2.iteye.com/upload/attachment/0100/1338/f029509d-cfa6-3fd1-a305-3cc201d5b6ff.jpg[/img]

xml 配置如下:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
<expression>return message.contains("billing");</expression>
</evaluator>
<OnMismatch>NEUTRAL</OnMismatch>
<OnMatch>DENY</OnMatch>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger - %msg%n
</pattern>
</encoder>
</appender>


以上配置,如果log的内容中有billing 是不会输出的。和日志输出级别没有任何关系

------------------------------------------------MDC----------------------------------------------------------------------
mdc:Mapped Diagnostic Context
mdc 是用来application保存上下文信息的。可以通过mdc的put方法设置kev value信息,然后在日志里面输出value,比如ip或域名,在根据域名来区分业务线的情况来说,对业务的跟踪很有帮助。

case案例如下:

<encoder>
<pattern>[%X{ip} %X{domain}][%thread] %-5level %logger{35} - %msg%n </pattern>
</encoder>


注意通过:%X{key} 来取得MDC put的值。
java use case 如下:

@Test
public void testLogback() throws InterruptedException {
MDC.put("ip", "192.168.1.5");
MDC.put("domain", "wxc.trade.qunar.com");
for(int i=0;i<30;i++){
logger.info("hello {} ", wrapLog(i));
}
}


输出:
[192.168.1.5 wxc.trade.qunar.com][main] INFO com.qunar.logback.LogbackTest - hello
[192.168.1.5 wxc.trade.qunar.com][main] INFO com.qunar.logback.LogbackTest - hello a
[192.168.1.5 wxc.trade.qunar.com][main] INFO com.qunar.logback.LogbackTest - hello aa
[192.168.1.5 wxc.trade.qunar.com][main] INFO com.qunar.logback.LogbackTest - hello aaa
[192.168.1.5 wxc.trade.qunar.com][main] INFO com.qunar.logback.LogbackTest - hello aaaa
。。。
注意:每条日志的前面有了ip 和 domain的信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值