首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >日志那些事儿——谈谈需要日志输出的client jar应该如何设计

日志那些事儿——谈谈需要日志输出的client jar应该如何设计

作者头像
LNAmp
发布2018-09-05 15:34:42
5950
发布2018-09-05 15:34:42
举报

前言

上篇文章提到了应该如何设计需要输出日志的client jar,大概有三个比较重要的点。

  • 缩小jar包依赖范围,如果是基于maven,可以把client工程中依赖的日志相关jar scope设置为provided.
  • “感知”应用系统所使用的日志框架,匹配相应的日志框架
  • 不使用配置文件,改用编码配置logger

其中第一点非常好实现。本文着重分析第二点与第三点的思路和关键代码。

如何“感知”日志框架

记得很早之前第一次和彭老师喝咖啡的时候,彭老师问我最近在干啥,我说在做公司的权限平台。彭老师问我要设计的时候最开始想到的方案是啥,我说看了看网上的设计好像能满足项目的需求。彭老师说道你一开始其实应该想到像windows操作是怎么考虑权限问题的,看看它的设计说不定能找到灵感有更好地设计方案。 当然彭老师只是提供了一种思路,当面对问题的时候可以想想看有没有人已经很好得解决了这个问题。所以当我要在client jar中“感知”日志框架时,我会先想想在哪些场景下别人和我会有同样的需求。很明显,在一些中间件或者一些框架中会有这种需要,很多中间件会需要输出日志供调试和排错等。 所以,关于如何“感知”日志框架,我在某中间件中找到了答案,该中间件和我有同样的需求场景。对于我们平常使用来说,最重要的两种日志框架是log4j、logback,最重要的日志门面是slf4j、common-logging等,在本文场景中,暂不考虑log4j2。 “感知”日志框架,某中间件中是这么做的。

static {
        try {
            setLoggerFactory(new Slf4jLoggerFactory());
        } catch (Throwable var3) {
            try {
                setLoggerFactory(new Log4jLoggerFactory());              
            } catch (Throwable var2) {
                setLoggerFactory(new NopLoggerFactory());
            }
        } 
    }

public Slf4jLoggerFactory() throws ClassNotFoundException {    Class.forName("org.slf4j.impl.StaticLoggerBinder");
}

看见没,就是如此的简单粗暴,要判断系统中是否使用了slf4j,只需要判断“org.slf4j.impl.StaticLoggerBinder”是否存在。这种做法勉强可以算是对的吧,因为如果不使用slf4j,那引入slf4j的相关jar干嘛。这种做法简单粗暴,但是确实可行。

不使用配置文件,改用编码配置logger

前文提到了,如果要适配多种日志框架,那么就需要在client jar的classpath下准备多种不同的日志配置文件。使用配置文件不灵活,那么是否存在不使用配置文件的方式对Logger进行相关设置呢。答案肯定是有,那就是使用代码进行动态配置。 在对logback和log4j的源码进行分析的过程中提到,在logger.info过程中,会调用logger中所有的appender,那么我们要配置日志输出的路径,pattern等,只需要设置相应的appender就行,下文就将分别介绍如何使用代码设置logger的Appender

普通log4j appender设置

    public void configureAppender(org.apache.log4j.Logger logger, String name, String pattern,String fileName){
            DailyRollingFileAppender appender = new DailyRollingFileAppender();
        appender.setName(name);
        appender.setLayout(new PatternLayout(pattern)));
        appender.setAppend(true);
        appender.setFile(fileName);
        appender.setEncoding(encoding);
        appender.activateOptions();
        logger.removeAllAppenders();
        logger.addAppender(appender);
    }

以上代码为logger设置了一个DailyRollingFileAppender

slf4j+logback appender设置

public void configureAppender(ch.qos.logback.classic.Logger logger, String name, String pattern,String fileName){ 

        RollingFileAppender appender = new RollingFileAppender();
        appender.setContext(LogbackLoggerContextUtil.getLoggerContext());
        appender.setName(name);
        appender.setAppend(true);
        appender.setFile(fileName);
        TimeBasedRollingPolicy rolling = new TimeBasedRollingPolicy();
        rolling.setParent(appender);
        rolling.setFileNamePattern(fileName + ".%d{yyyy-MM-dd}");
        rolling.setContext(LogbackLoggerContextUtil.getLoggerContext());
        rolling.start();
        appender.setRollingPolicy(rolling);
        PatternLayout layout = new PatternLayout();
        layout.setPattern(pattern);
        layout.setContext(LogbackLoggerContextUtil.getLoggerContext());
        layout.start();
        appender.setLayout(layout);
        appender.start();
        this.logger.detachAndStopAllAppenders();
        this.logger.addAppender(appender);
        }

以上代码为logback设置了RollingFileAppender

需要注意的是,当使用slf4j的日志门面时,通过LoggerFactory.getLogger得到的logger实例实际类型不尽相同,当使用slf4j+log4j时为org.slf4j.impl.Log4jLoggerAdapter,当使用slf4j+logback时为ch.qos.logback.classic.Logger,前者需要通过反射的手段取得org.apache.log4j.Logger对其设置Appender。

关键代码已经列在上面了,很多代码其实出自官网,官方有提供使用代码进行logger的配置。最后上一张类图来说明整个设计,该类图完整地展示了如何设计一个能自适应多种日志类型的日志工具。

适配logback/log4j的日志类结构图.jpg

总结

大体的步骤就是识别日志框架,使用相应日志框架得到对应的logger,例如org.apache.log4j.Logger等,根据logger的实际类型将其包装成统一的logger类型并且配置相应的Appender。类图完整地展示了整个设计。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.09.03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 如何“感知”日志框架
  • 不使用配置文件,改用编码配置logger
    • 普通log4j appender设置
      • slf4j+logback appender设置
      • 总结
      相关产品与服务
      消息队列 TDMQ
      消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档