Log4j2分析与实践-Filters

    Filters可以用来对日志事件进行过滤,过滤器会返回一个枚举类型的值,枚举值包含三个:ACCEPT、DENY和NEUTRAL。当返回结果为ACCEPT时会跳过这一级别的其它过滤器,进入下个级别的过滤器;为DENY时会直接终止事件的传递;为NEUTRAL时会继续交给同级别的其它过滤器处理(若已经是同级别最后一个过滤器,那么将日志事件传递给下个级别)。
    可以在以下四个位置配置过滤器:
(1)上下文范围有效的过滤器直接在<Configuration>标签里配置,被这种过滤器拒绝的日志事件不再会向后传递。一旦日志事件被一个上下文范围有效的过滤器判定为ACCEPT时,其它上下文有效的过滤器将不会对日志事件进行过滤,日志事件将会继续呗Logger和Appender的过滤器过滤。
(2)Logger过滤器配置在一个特定的Logger上面。这些过滤器会在上下文范围有效的过滤器之后发挥作用,被这些过滤器拒绝的日志事件将会被丢弃,也不管additivity的配置如何,不会将日志传递给父亲Logger。
(3)Appender过滤器用于决定一个指定的Appender是否应该处理和发布日志事件。
(4)Appender引用过滤器用于决定Logger是否应该将日志事件路由到一个Appender。

BurstFilter

    BurstFilter用于控制日志事件的处理速率,它会在日志事件达到最大限制时默默地丢弃日志事件。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <!-- level表示用于过滤的日志级别,rate表示每秒平均事件数目,maxBurst表示每秒最大事件数目,onMatch表示 --匹配过滤器结果时处理方式,onMismatch表示不匹配过滤器结果时的处理方式>
      <BurstFilter level="INFO" rate="16" maxBurst="100" onMatch="ACCEPT" onMismatch="DENY"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>

CompositeFilter

    CompositeFilter提供了一种指定多个Filter的方式。只需要在<Configuration>标签中添加一个<Filters>标签,然后在<Filters>中添加其它过滤器。<Filters>没有其它参数。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Filters>
    <MarkerFilter marker="EVENT" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
    <DynamicThresholdFilter key="loginId" defaultThreshold="ERROR"
                            onMatch="ACCEPT" onMismatch="NEUTRAL">
      <KeyValuePair key="User1" value="DEBUG"/>
    </DynamicThresholdFilter>
  </Filters>
  <Appenders>
    <File name="Audit" fileName="logs/audit.log">
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
    </File>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <BurstFilter level="INFO" rate="16" maxBurst="100"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Logger name="EventLogger" level="info">
      <AppenderRef ref="Audit"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>


ThresholdFilter

    若日志事件的级别跟配置的级别相同,或者比配置的级别更低(日志打印范围更小),那么ThresholdFilter就会返回一个onMatch结果,否则会返回一个onMismatch结果。比如,如果ThresholdFilter配置的级别为ERROR,日志事件级别为DEBUG,那么onMismatch值就会返回。只有ERROR或级别更低的FATAL级别到日志事件的到来,才会返回onMatch。
    以下示例表示仅在日志级别匹配时才让appender写日志:


<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>

DynamicThresholdFilter

    DynamicThresholdFilter可以基于指定属性并通过日志级别来进行过滤,跟ThresholdFilter的主要区别在于它能够动态地修改日志事件的级别。比如,如果用户的loginId在ThreadContext Map中被捕获了,那么就可以仅针对这个用户更改日志级别。比如Filter的日志级别为ERROR,那么就可以把这个用户的日志级别改为DEBUG。具体看以下示例:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <!-- 过滤器要过滤的日志级别为ERROR -->
  <DynamicThresholdFilter key="loginId" defaultThreshold="ERROR"
                          onMatch="ACCEPT" onMismatch="NEUTRAL">
	<!-- 对loginId为User1的用户启用DEBUG日志级别 -->
    <KeyValuePair key="User1" value="DEBUG"/>
  </DynamicThresholdFilter>
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <BurstFilter level="INFO" rate="16" maxBurst="100"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>


MapFilter

    MapFilter对MapMessage中的数据元素进行过滤。


<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <!-- operator为or,表示里面两个KeyValuePair其中有一个匹配时均可返回onMatch;若为and时,需要两个都匹配时才返回onMatch -->
  <MapFilter onMatch="ACCEPT" onMismatch="NEUTRAL" operator="or">
    <KeyValuePair key="eventId" value="Login"/>
    <KeyValuePair key="eventId" value="Logout"/>
  </MapFilter>
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <BurstFilter level="INFO" rate="16" maxBurst="100"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
 </Configuration>


MarkerFilter

    MarkerFilter会比较配置的标记值和日志事件中的标记值,当它们匹配时就会返回onMatch。


<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <MarkerFilter marker="FLOW" onMatch="ACCEPT" onMismatch="DENY"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>


RegexFilter

    RegexFilter使用正则表达式来比较日志消息。以下示例表示仅让Appender打印包含单词"test"的日志事件:


<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <RegexFilter regex=".* test .*" onMatch="ACCEPT" onMismatch="DENY"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>


ScriptFilter

    ScriptFilter用于执行脚本并返回true或者false,参考Log4j2分析与实践-配置详解 中脚本相关内容了解如何定义脚本。


<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="ERROR">
  <Scripts>
    <ScriptFile name="filter.js" language="JavaScript" path="src/test/resources/scripts/filter.js" charset="UTF-8" />
  </Scripts>
  <Appenders>
    <List name="List">
      <PatternLayout pattern="[%-5level] %c{1.} %msg%n"/>
    </List>
  </Appenders>
  <Loggers>
    <Logger name="TestJavaScriptFilter" level="trace" additivity="false">
      <AppenderRef ref="List">
	    <!-- 用于执行filter.js中定义的脚本 -->
        <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
          <ScriptRef ref="filter.js" />
        </ScriptFilter>
      </AppenderRef>
    </Logger>
    <Root level="trace">
      <AppenderRef ref="List" />
    </Root>
  </Loggers>
</Configuration>

StructuredDataFilter

    StructuredDataFilter继承自MapFilter,它可以根据事件ID、type和message进行过滤。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <!-- 匹配ID为Login或者Logout的日志事件 -->
  <StructuredDataFilter onMatch="ACCEPT" onMismatch="NEUTRAL" operator="or">
    <KeyValuePair key="id" value="Login"/>
    <KeyValuePair key="id" value="Logout"/>
  </StructuredDataFilter>
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <BurstFilter level="INFO" rate="16" maxBurst="100"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>


ContextMapFilter

    ContextMapFilter对当前上下文中的数据元素进行过滤。


<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <!-- 匹配上下文中的User1和User2参数 -->
  <ContextMapFilter onMatch="ACCEPT" onMismatch="NEUTRAL" operator="or">
    <KeyValuePair key="User1" value="DEBUG"/>
    <KeyValuePair key="User2" value="WARN"/>
  </ContextMapFilter>
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <BurstFilter level="INFO" rate="16" maxBurst="100"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>


TimeFilter

    TimeFilter可用于将时间限制到一天的某一区间。示例表示仅打印每天处于5:00-5:30的日志事件:


<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="DENY"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>