由日志框架的异常处理引发的思考

400 阅读1分钟

1. 背景

最近在写新的基于SPI日志框架时,起初当判断当前没有Appender实例时,我会抛出异常来阻断系统。阳哥Review后建议“捕获日志框架的所有异常,不要影响应用的正常逻辑”。

2. 解决方案

  1. 参考Slf4j的实现,没有找到Appender实例时,只打印error日志。
  2. SessionLogger设置动态代理,来catch其所有的方法,避免异常上浮。
private static final ThreadLocal<ISessionLogger> loggerThreadLocal = new ThreadLocal() {
        private final IAppender appender = AppenderFactory.getAsyncAppender();

        @Override
        protected ISessionLogger initialValue() {
            ISessionLogger sessionLogger = new SessionLoggerImpl();
            sessionLogger.setAppender(appender);
            return (ISessionLogger) Proxy.newProxyInstance(getClass().getClassLoader(),
                    new Class[]{ISessionLogger.class},
                    (proxy, method, args) -> {
                        try {
                            Object ret = method.invoke(sessionLogger, args);
                            return ret;
                        } catch (Throwable throwable) {
                            return null;
                        }
                    });
        }
    };

3. 反思

一个系统的异常处理逻辑要分模块的去考虑,考虑该模块在系统的所处的位置。

  1. 日志框架是系统的辅助模块。它的异常不能上浮到应用逻辑里,即不能因为日志记录异常而影响整个系统的业务处理。
  2. 不久前开发的Maven插件用来编译生成线上的运行包。如果执行异常,则其生成的代码大概率是错误的。此时一定要抛出异常来中断Maven打包过程,避免运行错误的代码。