服务化拆分过程中的日志框架选择

 

    背景:

      最近做服务化拆分过程中,因为要把公共的拦截器如登录相关的封装到API包中,很多拦截器中都有日志的打印。按理说api包中不应该有日志的打印,但是如果去掉重要的日志,那么会很难定位线上的问题。

 

    解决方案一:

      原先我们账户提供的API包需要打印一些本地存根的信息,如初始化缓存,本地存根是否取到对象,是否走了dubbo接口。于是参照了下现有的框架的解决方案,写了下面这一段逻辑。让依赖方启动的时候初始化这个bean,然后就可以用这个LogUtil对象来打印日志了。

      

@Component
public class LogUtil implements InitializingBean {

    public static final Logger accountOpt = LoggerFactory.getLogger("accountOpt");

    @Override
    public void afterPropertiesSet() throws Exception {
        Properties p = new Properties();

        p.setProperty("log4j.category.accountOpt", "INFO"  + ",accountOpt");
        p.setProperty("log4j.appender.accountOpt", "org.apache.log4j.DailyRollingFileAppender");
        p.setProperty("log4j.appender.accountOpt.File", "logs/log/accountOpt.log" );
        p.setProperty("log4j.appender.accountOpt.layout", "org.apache.log4j.PatternLayout");
        p.setProperty("log4j.appender.accountOpt.maxFileSize ", "100MB" );
        p.setProperty("log4j.appender.accountOpt.maxBackupIndex ", " 30");
        p.setProperty("log4j.appender.accountOpt.DatePattern ", " '.'yyyy-MM-dd");
        p.setProperty("log4j.appender.accountOpt.layout.ConversionPattern", "%d - accountOpt - %c - %p [%t] %x - %m%n");

        PropertyConfigurator.configure(p);
    }
}

// 使用
LogUtil.accountOpt.info("Account userName:" + userName + " is not in cache");

 

    缺点:

      1)依赖API的服务需要依赖log4j才能打印出日志。

      2)配置写死在代码里了,比较丑。

      3)依赖方需要手动初始化这个bean。

 

    解决方案二:

      slf4j(Simple Logging Facade for Java ), API依赖slf4j, 依赖方只要引入相应的slf4j-adapter和相应的底层实现即可。slf4j 使用了Facade模式,为啥为叫这个模式? 看看Facade模式定义吧,为复杂的子系统定义一套简单的接口,子系统就是下面的各种log实现啊,接口就是slf4j啊。通过slf4j也顺带学习了下Facade模式了。

     架构如下:

      
 

 

    代码实现:

      

// 依赖方只要配置accountOpt 即可
Logger logger = LoggerFactory.getLogger("accountOpt");

 
     优势:

      1)api不关心具体的日志实现,留给依赖方实现,依赖方只要引入自己的适配器jar和底层的实现log即可。

      2)  即使api里面引入了相应的log实现,依赖方依然可以exclude相应的实现,做不同的log实现,而且可以打印出API里面的日志。

      3)如果api已经依赖了具体的实现,如account-api依赖了log4j。那么应用应用依赖account-api的时候直接exclude掉log4j的东西,直接引入slf4j-log4j-adapter,这个包里面定义了与log4j相同的包相同的接口。所以启动不会报错,而且也不用依赖account-api里面log4j的实现。这一点是周会分享的时候波爷补充的,所以经常发现分享的时候别人往往能够看到你的不足,经常分享吧。

 

    最终选择:

      我们的最终选择是API里面使用slf4j,实现里面使用logback,因为据说logback比log4j性能高很多。

    

     

 

 

猜你喜欢

转载自labreeze.iteye.com/blog/2359759