Logback过滤器是基于Ternary Logic,允许过滤器可以组合或串连在一直形成更复杂的过滤策略。这个设计很大程度上受到Linux的iptables影响。
关于logback自带过滤器
logback提供了两种过滤器:正则过滤器与turbo过滤器。
正则过滤器
正则过滤器继承于抽象类Filter,Filter本质上只包含以ILoggingEvent为入参的一个方法decide()。
基于Ternary Logic,过滤器以排序列表的形式组合在一起。系统按照这个顺序调用每个过滤器的decide(ILoggingEvent event)方法。decide方法返回结果是枚举类FilterReply(DENY, NEUTRAL, ACCEPT其中一个)。返回值为DENY时,日志事件直接丢弃这条日志,不会再传递给剩下的过滤器。返回值为NEUTRAL时,则传递给下面的过滤器。返回值为ACCEPT时,日志事件立即处理这条日志,跳过调用其它过滤器。
在logback中,过滤器可以添加到Appender上。通过添加一个或多个过滤器到Appender,你可以通过任意条件,比如:日志内容、MDC内容、时间等等日志的任何部分,过滤日志事件。
实现你自己的过滤器
创建你自己的过滤器很简单,你只需要继承Filter抽象类并实现decide方法。
下面,提供了一个例子SampleFilter。过滤器只处理日志内容饱含"sample"关键字的日志。
package chapters.filters; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.filter.Filter; import ch.qos.logback.core.spi.FilterReply; public class SampleFilter extends Filter<ILoggingEvent> { @Override public FilterReply decide(ILoggingEvent event) { if (event.getMessage().contains("sample")) { return FilterReply.ACCEPT; } else { return FilterReply.NEUTRAL; } } }
下面的配置文件展示了将SampleFillter添加到ConsoleAppender上。
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="chapters.filters.SampleFilter" /> <encoder> <pattern> %-4relative [%thread] %-5level %logger - %msg%n </pattern> </encoder> </appender> <root> <appender-ref ref="STDOUT" /> </root> </configuration>
通过Joran,logback配置框架,可以很简单地指定属性或子模块到过滤器。向过滤器中添加属性的setter方法后,可以通过<property>指定属性值,嵌套到<filter>里。
我们想要的过滤器常常包含match与mismatch种情况,并通过是否匹配返回结果。例如:日志中需要根据是否为"foobar",一个过滤器可能匹配时返回ACCEPT,不匹配时返回NEUTRAL;另一个过滤器可能匹配时返回NEUTRAL不匹配时返回DENY。
考虑到上面情况,logback提供了AbstractMatcherFilter类,通过OnMatch与OnMismatch属性,可以根据是否匹配指定合适响应值。logback中大部分正则过滤器都继承于AbstractMatcherFilter。
级别过滤器
级别过滤器(LevelFilter)是基于准确匹配日志级别。如果日志级别等于配置的级别,过滤器通过配置中的OnMatch与OnMismatch属性决定是接受还是拒绝事件。下面是一个配置文件的例子:
<configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <encoder> <pattern> %-4relative [%thread] %-5level %logger{30} - %msg%n </pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="CONSOLE" /> </root> </configuration>
阀值过滤器
阀值过滤器(ThresholdFilter)过滤低于指定阀值的事件。当事件中的日志级别大于等于指定阀值时,过滤器的decide方法返回NEUTRAL。然而,拒绝日志级别小于阀值的事件。下面是配置文件的例子:
<configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <!-- deny all events with a level below INFO, that is TRACE and DEBUG --> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <encoder> <pattern> %-4relative [%thread] %-5level %logger{30} - %msg%n </pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="CONSOLE" /> </root> </configuration>
条件过滤器
条件过滤器(EvaluatorFilter)是一种封装了EventEvaluator的通过过滤器。像名字代表的,条件过滤器是根据判断事件是否符合指定条件来分别返回OnMatch与OnMismatch属性里的值。
注意EventEvaluator是一个抽象类,通过继承它,你可以实现你自己的条件逻辑。
Groovy事件判断类
Groovy条件过滤器(GEventEvaluator)是一种以任何Groovy语言的布尔表达式作为判断条件的EventEvaluator的具体实现。我们称这种Groovy布尔表达式为"groovy evaluation expression"。groovy判断表达式是现在过滤器中最灵活的。Groovy事件判断类需要Groovy的运行环境,请将参考指定文档,将Groovy的运行环境添加到你的运行环境中。
判断表达式是在解析配置文件时进行编译的。作为用户,你不用担心实际的内存泄漏。然而,你需要保证你的groovy语言表达式合法。
判断表达式管理当前日志事件。Logback自动添加一个ILoggingEvent的变量'event'(也可以是短名字'e')代表当前日志事件。TRACE、DEBUG、INFO、WARN和ERROR也引入到当前表达式范畴内。因此,"event.level == DEBUG" 与 "e.level == DEBUG"是等价的,都是当前日志事件的级别为DEBUG时,返回true。对于其它比较操作,level变量需要通过toInt()转换成整数。
给你一个更全面的例子:
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> <evaluator class="ch.qos.logback.classic.boolex.GEventEvaluator"> <expression> e.level.toInt() >= WARN.toInt() && <!-- Stands for && in XML --> !(e.mdc?.get("req.userAgent") =~ /Googlebot|msnbot|Yahoo/ ) </expression> </evaluator> <OnMismatch>DENY</OnMismatch> <OnMatch>NEUTRAL</OnMatch> </filter> <encoder> <pattern> %-4relative [%thread] %-5level %logger - %msg%n </pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
上面的过滤器会让日志级别高于WARN的事件继续传递,或者错误是由Google、MSN、Yahoo爬虫产生的。这样做是为了判断事件的MDC中"req.userAgent"值是否匹配"/Googlebot|msnbot|Yahoo/"正则式。注意由于MDC的map可以为null,我们也使用了Groovy的未引用安全操作符"?."。这个表达逻辑如果通过Java实现会很长。
如果你想知道用户代理值是如何以"req.userAgent"键值插入到MDC中的,logback通过一个servlet过滤器MDCInsertingServletFilter实现的,显然,这已经超出了这篇文章的范围。它将在以后的章节中讲到。
Java事件判断类
Logback带了另一个叫做JaninoEventEvaluator的EventEvaluator实现,将任何返回布尔值的Java代码块作为判断条件。我们将这个Java布尔表达式称作"判断表达式"。判断表达式在事件过滤中有很强的灵活性。JaninoEventEvaluator需要Janino jar。相关依赖请参考其它章节。
和JaninoEventEvaluator比较,由于是Groovy的优点,GEventEvaluator更便于使用,但,相同的表达式,JaninoEventEvaluator一般运行快很多。
判断表达式是在解决配置文件时编译的。作为用户,你不需要担心内存问题。但,你需要保证Java语言表达式返回一个布尔值,例如,结果为true或false
判断表达式是判断当前的日志事件。判断表达式可以获取到Logback自动导入的各种变量。导入变更中字母大小写敏感的变更展示如下:
Name | Type | Description |
event | LoggingEvent | 关联日志请求的原始日志事件。下面全部变量都可以在event中取得。例如:event.getMessage()与message变量返回一样的String。 |
message | String | 日志请求中原始信息。像某些日志/,当你写l.info("Hello {}", name),name关联的值为"Alice",然后message为"Hello {}"。 |
formattedMessage | String | 日志请求中的格式化消息。像某些日志/,当你写l.info("Hello {}", name),name关联值为"Allice",格式化消息为"Hello Alice"。 |
logger | String | 日志的名字 |
loggerContext | LoggerContextVO | 日志事件所属日志上下文的一个限制视图对象 |
level | int | 日志级别的int值。用于简化创建关于level的表达式。默认值DEBUG、INFO、WARN和ERROR也可以获得。因此,使用level>INFO是正确的 |
timeStamp | long | 日志事件创建时间。 |
marker | Marker | 日志请求中的Marker对象。注意这个对象可能为空。 |
mdc | Map |
包含日志事件创建时的全部MDC值的map对象。可能通过后面表达式获取值:mdc.get("myKey").从0.9.30,"mdc"变量永远不为空 由于Janino不支持泛型,java.util.Map不包含参数类型。mdc.get()返回的对象是Object而不是String。为了调用返回值的String方法,你需要强转成String。例如: |
throwable | java.lang.Throwable |
如果无异常关联到事件中,则throwable变量为null。 不幸的是,"throwable"不支持serialization。因此,对于远程系统,它的值永远为null。对于本地独立表达式,使用下面的throwableProxy |
throwableProxy | IThrowableProxy | 日志事件异常的代理。如果无异常关联到事件上,"throwableProxy"变量值为空。与throwable不同的是,throwableProxy值不为空,即使是经过序列化的远程系统上 |
给你一个具体例子:
<configuration> <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> <root level="INFO"> <appender-ref ref="STDOUT" /> </root> </configuration>
上面配置中将EvaluatorFilter添加到ConsoleAppender。然后将JaninoEventEvaluator添加到EvaluatorFilter中。如果用户未指定<evaluator>,Logback默认使用JaninoEventEvaluator。 这是Joran很少发生的不明确指推断组件类型的一种情况。
由于OnMismatch属性设置为NEUTRAL,OnMatch属性设置为DENY,这个条件过滤器将丢掉全部内容包含"billing"的事件。
FilterEvents应用程序发出10个日志请求,从0到9。首先,让我们跑不包含任何过滤器的FilterEvent:
java chapters.filters.FilterEvents src/main/java/chapters/filters/basicConfiguration.xml
全部请求会向下面展示的一样:
0 [main] INFO chapters.filters.FilterEvents - logging statement 1
0 [main] INFO chapters.filters.FilterEvents - logging statement 2
0 [main] DEBUG chapters.filters.FilterEvents - logging statement 3
0 [main] INFO chapters.filters.FilterEvents - logging statement 4
0 [main] INFO chapters.filters.FilterEvents - logging statement 5
0 [main] ERROR chapters.filters.FilterEvents - billing statement 6
0 [main] INFO chapters.filters.FilterEvents - logging statement 7
0 [main] INFO chapters.filters.FilterEvents - logging statement 8
0 [main] INFO chapters.filters.FilterEvents - logging statement 9
假如我们想处理"billing statement"。上面讲到的basicEventEvaluator.xml过滤包含"billing",这是我们想要的准确结果。
运行basicEventEvaluator.xml:
java chapters.filters.FilterEvents src/main/java/chapters/filters/basicEventEvaluator.xml
我们将得到:
0 [main] INFO chapters.filters.FilterEvents - logging statement 1
0 [main] INFO chapters.filters.FilterEvents - logging statement 2
0 [main] DEBUG chapters.filters.FilterEvents - logging statement 3
0 [main] INFO chapters.filters.FilterEvents - logging statement 4
0 [main] INFO chapters.filters.FilterEvents - logging statement 5
0 [main] INFO chapters.filters.FilterEvents - logging statement 7
0 [main] INFO chapters.filters.FilterEvents - logging statement 8
0 [main] INFO chapters.filters.FilterEvents - logging statement 9
判断表达式可以是java代码块。例如,下面是一个合法的表达式:
<evaluator> <expression> if(logger.startsWith("org.apache.http")) return true; if(mdc == null || mdc.get("entity") == null) return false; String payee = (String) mdc.get("entity"); if(logger.equals("org.apache.http.wire") && <!-- & encoded as & --> payee.contains("someSpecialValue") && !message.contains("someSecret")) { return true; } return false; </expression> </evaluator>
Matchers
有可能调用String类的matches()方法进行正则匹配,但,这会造成每一次调用filter的时候进行一次编译并生成一个类型对象。为了避免这个问题,你可以提前定义一个或多个Matcher对象。定义完matcher后,你可以在判断表达式中通过名字重复使用对象。
下面例子讲了这种情况:
<configuration debug="true"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> <evaluator> <matcher> <Name>odd</Name> <!-- filter out odd numbered statements --> <regex>statement [13579]</regex> </matcher> <expression>odd.matches(formattedMessage)</expression> </evaluator> <OnMismatch>NEUTRAL</OnMismatch> <OnMatch>DENY</OnMatch> </filter> <encoder> <pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
如果你需要定义更多的matcher,你可以参考上面添加更多的<matcher>元素。
参考文档:https://logback.qos.ch/manual/filters.html
相关推荐
标题"Logback的使用和logback.xml详解"暗示了我们要讨论的是一个日志管理框架——Logback,以及它的配置文件`logback.xml`。Logback是Java社区广泛使用的日志处理系统,由Ceki Gülcü创建,作为Log4j的后继者。它...
logback 配置详解 logback 是由 log4j 创始人设计的另一个开源日志组件,它当前分为三个模块:logback-core、logback-classic 和 logback-access。logback-classic 是 log4j 的一个改良版本,同时它完整实现了 slf4...
其中包含logback.xml配制详解,所配制的jar包,maven配制,我们项目的配制,里面还包含日志打包等
"Spring如何动态自定义logback日志目录详解" 本文主要介绍了如何在Spring框架中动态自定义logback日志目录的相关知识点。 一、日志输出格式的重要性 在日常开发中,日志输出格式的指定是非常重要的。一般情况下,...
Logback 是一个在Java应用程序中用于日志记录的开源框架,它是Log4j的后继者,由Ceki Gülcü(Log4j 的创始人)设计。Logback 提供了比Log4j 更高效、更灵活的日志记录解决方案,旨在提高开发人员的生产力并降低...
"logback-filters" 是 Logback 的一个扩展模块,专门设计用于处理特定的过滤需求,如获取事务信息、身份验证数据等。在日志系统中,过滤器允许我们根据预定义的条件筛选和处理日志事件,从而提高日志的有效性和安全...
1.2. 第一步 ........................................................................................................ 2 1.2.1. 必要条件.....................................................................
slf4j日志demo项目 logback.xml配置详解,slf4j日志demo项目 logback.xml配置详解,slf4j日志demo项目 logback.xml配置详解,slf4j日志demo项目 logback.xml配置详解
LogBack是一款广泛应用于Java开发中的日志记录框架,由Ceki Gülcü(也是Log4j的创始人)设计。它提供了高效、灵活的日志记录功能,适用于各种规模的应用程序。LogBack是作为Log4j的替代品而创建的,旨在提供更好的...
logback的使用,内附所需要的jar包以及使用步骤,希望给个为带来帮助
SLF4J作为一个抽象层,允许开发者选择底层的日志实现,而Logback则是一个优秀的SLF4J实现。在这里,我们关注的是SLF4J的API库`slf4j-api-1.7.26.jar`,以及Logback的两个核心组件`logback-core-1.2.3.jar`和`logback...
**日志系统的重要性** ...通过深入理解和熟练使用Logback,我们可以优化日志记录,提升问题排查效率,为软件系统的稳定运行保驾护航。`logback-advance-demo`压缩包可能包含了上述功能的实践示例,供学习和参考。
Logback 是一款广泛使用的日志记录框架,它提供高效的日志记录功能,并允许灵活的配置。在本文中,我们将深入探讨 logback 的配置,重点放在配置文件中的关键元素上。 首先,配置文件的根节点是 `<configuration>`...
【Spring Boot异步输出Logback日志方法详解】 在Spring Boot中,日志记录是一个重要的功能,用于跟踪应用程序的行为和调试问题。Logback是广泛使用的日志框架,由log4j的创始人Ceki Gülcü设计,提供了高效、灵活...
Logback 是一个高效、模块化的日志框架,它在日志处理领域提供了诸多优势,使得开发者有充分的理由选择它作为日志解决方案。以下是使用Logback的十个主要理由: 1. **性能优化**:Logback 相比于其他日志框架(如...
Logback 是一个开源的日志框架,由 Ceki Gülcü(也是 Log4j 的创建者)设计。它旨在提供高效、灵活的日志记录解决方案,支持日志输出、日志级别管理和日志过滤等功能。在本示例中,我们将会探讨如何使用 Maven ...
Logback 是一个高效、灵活的日志框架,由 Ceki Gülcü 创建,它是 Log4j 的后继者,旨在提供更好的性能和更低的内存消耗。本文将深入探讨如何使用 Logback 实现日志打印和输出到指定位置。** 首先,我们需要理解 ...