Log4j2 Filter配合ACM(Nacos)实现日志降级

原有日志降级实现方式为使用LogUtil工具类,在工具类中判断ACM(Nacos)状态实现日志降级,缺点很明显,打印日志中的行号是LogUtil方法的行号,而不是原始代码的行号。

@Slf4j
public class LogUtil {

    public static void logInfo(String format, Object... arguments){
        if(!AcmSwitch.logInfoSwitchON){
            return;
        }
        log.info(format,arguments);
    }

    public static void logWarn(String format, Object... arguments){
        if(!AcmSwitch.logWarnSwitchON){
            return;
        }
        log.warn(format,arguments);
    }

    public static void logError(String format, Object... arguments){
        if(!AcmSwitch.logErrorSwitchON){
            return;
        }
        log.error(format,arguments);
    }

}

改造后通过Log4j2的Filter机制实现ACM(Nacos)动态日志降级,打印日志时,直接使用Logger,日志的行号保留原始的代码行号。

Log4j2 Filter实现ACM日志降级

1. 扩展Filter接口(或者AbstractFilter),实现Filter接口的方法

@Plugin(name = "AcmLogFilter", category = "Core", elementType = "filter", printObject = false)
public class AcmLogFilter extends AbstractFilter {

    public AcmLogFilter() {
        super(null, null);
    }

    public AcmLogFilter(Result onMatch, Result onMismatch) {
        super(onMatch, onMismatch);
    }

    @Override
    public Result filter(final LogEvent event) {
        return filterSub(event.getLevel());
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
                         final Throwable t) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
                         final Throwable t) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object... params) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0, final Object p1) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0, final Object p1, final Object p2) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0, final Object p1, final Object p2, final Object p3) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0, final Object p1, final Object p2, final Object p3,
                         final Object p4) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0, final Object p1, final Object p2, final Object p3,
                         final Object p4, final Object p5) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0, final Object p1, final Object p2, final Object p3,
                         final Object p4, final Object p5, final Object p6) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0, final Object p1, final Object p2, final Object p3,
                         final Object p4, final Object p5, final Object p6,
                         final Object p7) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0, final Object p1, final Object p2, final Object p3,
                         final Object p4, final Object p5, final Object p6,
                         final Object p7, final Object p8) {
        return filterSub(level);
    }

    @Override
    public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
                         final Object p0, final Object p1, final Object p2, final Object p3,
                         final Object p4, final Object p5, final Object p6,
                         final Object p7, final Object p8, final Object p9) {
        return filterSub(level);
    }


    private Result filterSub(Level level) {
        if (Level.INFO.equals(level)) {
            if (!AcmServiceSwitch.logInfoSwitchON) {
                return onMismatch;
            }
        } else if (Level.WARN.equals(level)) {
            if (!AcmServiceSwitch.logWarnSwitchON) {
                return onMismatch;
            }
        } else if (Level.ERROR.equals(level)) {
            if (!AcmServiceSwitch.logErrorSwitchON) {
                return onMismatch;
            }
        }
        return onMatch;
    }

    @PluginFactory
    public static AcmLogFilter createFilter(@PluginAttribute(value = "onMatch", defaultString = "NEUTRAL") Result onMatch,
                                               @PluginAttribute(value = "onMismatch", defaultString = "DENY") Result onMismatch) {
        return new AcmLogFilter(onMatch, onMismatch);
    }
}

关键代码为filterSub方法中,会调用下面的方法,方法中根据ACM配置决定是否log日志。

private Result filterSub(Level level) {
        if (Level.INFO.equals(level)) {
            if (!AcmProductServiceSwitch.logInfoSwitchON) {
                return onMismatch;
            }
        } else if (Level.WARN.equals(level)) {
            if (!AcmProductServiceSwitch.logWarnSwitchON) {
                return onMismatch;
            }
        } else if (Level.ERROR.equals(level)) {
            if (!AcmProductServiceSwitch.logErrorSwitchON) {
                return onMismatch;
            }
        }
        return onMatch;
    }

2. 配置log4j2.xml

Filter可以配置在多个位置:

  • Context-wide(全局)
  • Logger
  • Appender
  • Appender Reference

例如,全局配置可以在 `<Configuration>`元素下增加以下内容,即可对全局的log进行过滤。

  <Filters>
        <AcmLogFilter></AcmLogFilter>
    </Filters>

3. log

log时,不需要使用LogUtil,直接使用slf4j或log4j2的Logger方法即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值