您的位置 首页 java

Java——LogBack实现自定义过滤器

LogBack自定义过滤器实现

问题场景:

在做一个 WebService 项目的开发时,需要对调用服务端的参数进行验证,于是采用了验证框架,在调用参数不满足验证条件时就会产生异常。考虑到生产环境的情况,一定要把这种异常记录到日志中,便于发生问题时便于查找问题。于是开始干吧,加参数验证框架,加LogBack日志框架,等到都加好了做测试时,问题来了。

当调用服务端的参数不符合验证条件时,验证框架确实给出了异常提示,但同时也输出了很多WebService的信息,最要命的是这两种信息来自同一个类,都是DEBUG级别的。假如把这些信息都记到日志中去,将来查找问题估计会比较麻烦,需要人工过滤很多无用的信息。

按照常规的方法,用输出信息的包或类,和信息级别去筛选也无法将这两种信息分开。郁闷了。于是就想能不能靠要记录的日志信息的特征去过滤日志哪,比如要记录的日志是这样的:

 [17:49:41.245][DEBUG][o. apache .cxf.phase.PhaseInterceptorChain][http-nio-8889-exec-1] Application {wsdl.bbzdmws.com}userService#{wsdl.bbzdmws.com}getUserName has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: getUserName.arg0.age: 年龄需要在0和100之间
at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:162)
at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.createFault(AbstractJAXWSMethodInvoker.java:267)  

可以看到,日志是以“Application”开头的一串字符串,就认为其它不是以“Application”开头的都不用记录吧。在网上查找了资料后发现,自定义的过滤器可以实现这个想法,这里记录下实现过程。

实现步骤

  1. 写一个过滤器的实现类
  2. 在LogBack的配置文件中配置上这个类

过滤器的实现类

 package com.bbzd.mws.logfilter;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

/**
 * 自定义过滤器
 * @date 2022/10/11 - 17:23
 */
public class InputCheckFilter  extends  Filter<ILoggingEvent> {

    @Override
    public FilterReply decide(ILoggingEvent iLoggingEvent) {
        //在日志消息中包含"Application"字符串时,会记录消息,否则不记录
        if(iLoggingEvent.getMessage().contains("Application")){
            return FilterReply.ACCEPT;
        }else{
            return FilterReply.DENY;
        }
    }
}
  

LogBack的配置文件片断,其它按LogBack的常规配置就好,%ex{1}是去掉完整的异常调用栈信息,缩短记录的行数

 <appender name="checkError" class="ch.qos.logback.core.rolling.Rolling File Appender">
    <File>${LOG_HOME}checkError.log</File>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${LOG_HOME}checkError.log.%d{yyyy-MM-dd}.gz</fileNamePattern>
        <maxHistory>10</maxHistory>
    </rollingPolicy>
    <encoder>
        <pattern>[%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n %ex{1}</pattern>
    </encoder>
    <!-- 过滤器配置为自定义的过滤器 -->
    <filter class="com.bbzd.mws.logfilter.InputCheckFilter" />
</appender>  

实现效果:

 [17:49:41.245][DEBUG][o.apache.cxf.phase.PhaseInterceptorChain][http-nio-8889-exec-1] Application {wsdl.bbzdmws.com}userService#{wsdl.bbzdmws.com}getUserName has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: getUserName.arg0.age: 年龄需要在0和100之间
at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:162)
at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.createFault(AbstractJAXWSMethodInvoker.java:267)  

总结

  1. WebService框架居然把校验参数异常信息定义为DEBUG级别,我也是无语了
  2. 信息要做判断会影响效率,但这里是把判断的情况限定在由org.apache.cxf.phase包产生的前提下,应该影响不大,使用这种方式更多的是要看具体环境

附录:完整的LogBack的配置文件

 <?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <springProperty scope="context" name="LOG_HOME" source="logging.file.path"/>


    <!-- 彩色日志配置 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){green} %clr([${PID:-}]){magenta} %clr([%25.25t]){yellow} %clr([${LOG_LEVEL_PATTERN:-%5p ]}){red} %clr(%-40.40logger{39}){blue} %clr(:){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                <!-- [%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n -->
                ${CONSOLE_LOG_PATTERN}
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
    </appender>



    <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${LOG_HOME}lmes.error.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}lmes.error.log.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>10</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>[%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>


    <appender name="checkError" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${LOG_HOME}checkError.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}checkError.log.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>10</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>[%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n %ex{1}</pattern>
        </encoder>
        <!-- 过滤器配置为自定义的过滤器 -->
        <filter class="com.bbzd.mws.logfilter.InputCheckFilter" />
    </appender>


    <logger name="org.springframework">
        <level value="INFO"></level>
    </logger>
    <logger name="org.apache.http">
        <level value="INFO"></level>
    </logger>
    <logger name="org.hibernate.validator.internal.engine">
        <level value="ERROR"></level>
    </logger>
    <logger name="org.apache.cxf.jaxb">
        <level value="INFO"></level>
    </logger>
    <logger name="org.hibernate.validator.internal.xml">
        <level value="INFO"></level>
    </logger>
    <logger name="org.apache.cxf.configuration.spring">
        <level value="INFO"></level>
    </logger>
    <logger name="com.bbzd.mws">
        <level value="ERROR"></level>
    </logger>


    <logger name="org.apache.cxf.phase" level="DEBUG" additivity="false">
        <appender-ref ref="checkError"/>
        <appender-ref ref="console"/>
    </logger>


    < root  level="DEBUG">
        <appender-ref ref="console"/>
        <appender-ref ref="error"/>
    </root>

</configuration>  

文章来源:智云一二三科技

文章标题:Java——LogBack实现自定义过滤器

文章地址:https://www.zhihuclub.com/176951.shtml

关于作者: 智云科技

热门文章

网站地图