logback filters使用详解(二)

TurboFilters

TurboFilter对象全部继承于TurboFilter抽象类。像正则过滤器一样,它们都使用三进制逻辑返回对日志事件的判断。

它们的工作试类似于前面提到的过滤器。但,Filter与TurboFilter存在两点不一样。

TurboFilter对象绑定到日志上下文。因此,它们不光指定的appender被使用时触发,每一次日志请求也会触发。它们的应用范围远远大于appender附属的过滤器。

更重要的,它们会在LoggingEvent对象创建前被调用。TurboFilter对象过滤日志请求,不需要一个日志事件的实例化。因此,turboFilters用于高性能地过滤日志事件,即使在日志事件对象创建前。

实现自定义TruboFilter

只压根继承TurboFilter抽象类就可以创建自定义TurboFilter对象。像前面实现自定义过滤器一样,实现自定义过滤器只要实现decide()方法。下面的例子中,我们创建了一个稍微复杂的过滤器:

package chapters.filters;

import org.slf4j.Marker;
import org.slf4j.MarkerFactory;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.core.spi.FilterReply;

public class SampleTurboFilter extends TurboFilter {

  String marker;
  Marker markerToAccept;

  @Override
  public FilterReply decide(Marker marker, Logger logger, Level level,
      String format, Object[] params, Throwable t) {

    if (!isStarted()) {
      return FilterReply.NEUTRAL;
    }

    if ((markerToAccept.equals(marker))) {
      return FilterReply.ACCEPT;
    } else {
      return FilterReply.NEUTRAL;
    }
  }

  public String getMarker() {
    return marker;
  }

  public void setMarker(String markerStr) {
    this.marker = markerStr;
  }

  @Override
  public void start() {
    if (marker != null && marker.trim().length() > 0) {
      markerToAccept = MarkerFactory.getMarker(marker);
      super.start(); 
    }
  }
}

 上面的TurboFilter接收饮食特殊标识的事件。如果未找到指定标识,过滤器则将责任传递给连上下一个过滤器。

为了增加灵活性,通过getter与setter,测试标识可能在配置文件中指定。我们也通过实现start()方法去验证在处理配置过程中选项是否已指定。

<configuration>
  <turboFilter class="chapters.filters.SampleTurboFilter">
    <Marker>sample</Marker>
  </turboFilter>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>
        %-4relative [%thread] %-5level %logger - %msg%n
      </pattern>
    </encoder>
  </appender>

  <root>
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

 Logback提供了一些TurboFilter类。MDCFilter用于验证是否存在指定值;DynamicThresholdFilter基于MDC的key与level阀值过滤。另一个方面,MarkerFilter用于验证日志请求中包含指定标识。

下面是应用MDCFilter与MarkerFilter的一个例子:

<configuration>

  <turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
    <MDCKey>username</MDCKey>
    <Value>sebastien</Value>
    <OnMatch>ACCEPT</OnMatch>
  </turboFilter>
        
  <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
    <Marker>billing</Marker>
    <OnMatch>DENY</OnMatch>
  </turboFilter>

  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%date [%thread] %-5level %logger - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="INFO">
    <appender-ref ref="console" />
  </root>  
</configuration>

DuplicateMessageFilter

DuplicateMessageFilter优点在与众不同。这个过滤器会监测重复的消息,超过一定数量后,会丢弃掉重复的消息。

为了监控重复,过滤器在消息中使用简单的String相等性。它不会监测到只有一些字符差异的非常相近的消息。例如:

logger.debug("Hello "+name0);
logger.debug("Hello "+name1);

 假设name0与name1有不同的值,则认为这两条"Hello"消息不相关。依赖于用户的使用,以后的发布版本有可能添加验证string相似性功能。

注意包含参数的日志情况,只有考虑到原始消息。例如:下面两个请求,原始消息为"Hello {}"一样,因此,它被视为重复。

重复的数量可能通过AllowedRepetitions属性配置。例如,如果属性值为1,则第2条及以后的相同消息会被丢弃。类似,如果属性值为2,则第3条及以后的相同消息会被丢弃。AllowedRepetitions默认值为5。

为了监测重复性,这个过滤器需要在内部缓存中保持旧消息的引用。这个缓存的大小取决于属性CacheSize。默认,属性值为100。

<configuration>

  <turboFilter class="ch.qos.logback.classic.turbo.DuplicateMessageFilter"/>

  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%date [%thread] %-5level %logger - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="INFO">
    <appender-ref ref="console" />
  </root>  
</configuration>

 因此,配置了上面过滤器的FilterEvents输出为:

 
2008-12-19 15:04:26,156 [main] INFO chapters.filters.FilterEvents - logging statement 0
2008-12-19 15:04:26,156 [main] INFO chapters.filters.FilterEvents - logging statement 1
2008-12-19 15:04:26,156 [main] INFO chapters.filters.FilterEvents - logging statement 2
2008-12-19 15:04:26,156 [main] INFO chapters.filters.FilterEvents - logging statement 4
2008-12-19 15:04:26,156 [main] INFO chapters.filters.FilterEvents - logging statement 5
2008-12-19 15:04:26,171 [main] ERROR chapters.filters.FilterEvents - billing statement 6

 “logging statement 0”是第一个"logging statement {}"的发生。"logging statement 1"是第1个重复,"logging statement 2"是第2个重复。有趣的是,虽然基本规则被丢弃了,DEBUG级别的"logging statement 3"是第3个重复。通过这个可以看出TurboFilter早于其它过滤器调用,包含基本规则。因此,DuplicateMessageFilter认为"logging statement 3"为重复。由于它被后面的连上的规则丢弃造成它常常被忘记。"logging statement 4"是第4个重复,"logging statement 5"第5个。由于默认只允许5个重复,Statements6以及之后的都将被丢弃。

logback-access

Logback-access提供了logback-classic里的大部分特点。特别是,除了一点不一样,Logback-access过滤器与Logback-classic采用一样的方式获得与工作。Logback-access通过AccessEvent取代LoggingEvent实例。现在,logback-access提供了下面介绍有限的过滤器。如果你想要建议增加过滤器,请联系logback邮件列表。

CountingFilter

通过CountingFilter,logback-access可以提供web-server的访问统计数据。初始化时,CountingFilter以MBean的形式将自己注册到JMX服务器。你可以通过访问那个MBean获取统计数据,如,每分钟、小时、天、星期、月平均值。其它统计,如,上周、前天、上一个小时、上个月的数量,以及获得的总数量。

下面的lobback-access.xml声明了一个CountingFilter:

<configuration>
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

  <filter class="ch.qos.logback.access.filter.CountingFilter">
    <name>countingFilter</name>
  </filter>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%h %l %u %t \"%r\" %s %b</pattern>
    </encoder>
  </appender>

  <appender-ref ref="STDOUT" />
</configuration>

 你可以通过jconsole查看JMX服务器上的任何统计数据

console使用界面

 

EvaluatorFilter

EvaluatorFilter是封装了EventEvaluator的泛型过滤器。就如名字介绍的,EventEvaluator判断指定事件是否满足条件。匹配与否,Evaluator会返回OnMatch与OnMismatch属性配置的值。EvaluatorFilter与前面类似,参考上一篇文章。

判断表达式用于处理当前访问事件。Logback-access自动将以event变量名,导入AccessEvent实例。你可以读取关于HTTP请求与响应的各种数据。

下面配置文件展示了过滤响应编码为404的,每个请求为404的都会打印到console中。

<configuration>
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      <evaluator>
        <expression>event.getStatusCode() == 404</expression>
      </evaluator>
      <onMismatch>DENY</onMismatch>
    </filter>
   <encoder><pattern>%h %l %u %t %r %s %b</pattern></encoder>
  </appender>

  <appender-ref ref="STDOUT" />
</configuration>

 下面一个鸽子,我们过滤结果为404错误与请求CSS类型文件:

<configuration>
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      <evaluator name="Eval404">
        <expression>
         (event.getStatusCode() == 404)
           &amp;&amp;  <!-- ampersand characters need to be escaped -->
         !(event.getRequestURI().contains(".css"))
        </expression>
      </evaluator>
      <onMismatch>DENY</onMismatch>
    </filter>

   <encoder><pattern>%h %l %u %t %r %s %b</pattern></encoder>
  </appender>

  <appender-ref ref="STDOUT" />
</configuration>

 

 

参考文档:https://logback.qos.ch/manual/filters.html 

猜你喜欢

转载自dongmj.iteye.com/blog/2359558