SpringBoot日志模块分析

  • 日志是了解系统运行的显示器,了解系统的指示牌,问题追踪器,数据运营分析的基础。

1、日志框架的发展

  • log4j (log for java):最早的日志组件是Apache基金会提供的 log4j,但是不是Apache写的,捐献给apache后,apache开源了:很长的一段时间成为类 java 社区的日志标准;
  • JUL ( Java Util Logging ) Apache公司建议sun将log4j收到java的标准库,但是sun拒绝了,可能为了日志市场,sun自己在jdk1.4提供的日志框架: JUL;
  • JCL (Jakarta C ommons logging) 对于log4j和JUL两个日志框架的出现,Apache觉得开发有点混乱,没有统一的标准也没有关联,有兼容问题,于是乎开发了个 Java  Commons logging: 接口抽象层进行适配,完成了日志的兼容,并且也提供了默认的日志实现为 S im ple-Log:但可以兼容整合log4j和JUL;
  • slf4j ( sample l ogging facade for java ) : Log4j的原作者觉得apache 的Commons logging不够优秀,又使开发出了: slf4j (日志门面接口) + logback (日志的实现,是log4j的升级版),如果想自定义实现日志,只需要添加一个logback.xml文件就可以了。 
  • lg4j2 (log for j ava2): sun公司升级log4j- >log4j2 由于slf4j和logback出来后,Apache感觉快超越了log4j的体系,所以就升级了log4j为log4j2;

2、日志框架的选择

在日志框架的发展历程可以看出,其中JCL和slf4j都是简单的日志门面,不是具体的日志解决方案,它只服务于各种各样的日志系统,用于提供统一的接口标准。日志通过这个门面接口被分为两个阵营:JCL(Jakarta Commons Logging)和 slf4j(sample logging facade for java),总的来说日志的体系分为日志门面和日志的实现:
  • 日志门面:
    • JCL(2014年之后就不升级了)
    • slf4j( 推荐)
  • 日志实现: 
    • Log4j, logback是其升级版- 推荐(  和 slf4j都是同一个作者,兼容强);
    • JUL ,jdk工具包自带的一个简单的日志工具;
    • Log4j2 ,Apache开发的优秀日志实现, 推荐;
推荐使用搭配-日志门面 + 日志实现
推荐:slf4j作为门面:然后搭配logback 或者 log4j2的日志系统:
  • 方案一:Slf4j + logback(springboot的默认日志框架);
  • 方案二:Slf4j + log4j2;

3、日志框架的使用

官网日志使用参考: http://www.slf4j.org/manual.html
有了日志的门面接口,我们就有了统一的日志调用接口,直接去掉日志抽象层的接口方法,避免了调用日志的实现类,经典的面向接口编程的思想,类似于 JDBC 和  数据库驱动的关系,让日志的实现和调用解耦,大大提高了日志的兼容性和灵活性,使用起来也极其方便,只需要给系统导入slf4j和logback的实现jar包就OK了。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

这样我们就可以使用日志了,这里springboot的日志使用的是logback,如果想要用其他的也是OK的,只需要导入相应的jar包即可,日志框架组合依赖包关系如下(资料参考)

上图完美的介绍了slf4j和其他日志实现的依赖关系,使用起来也很方便。
    例如我们使用slf4j和logback的组合只需要导入相应的包就可以了,完美契合;但是如果想使用slf4和log4j,或者JUL就相对多一个适配步骤,因为在log4j出来的时候根本就没有slf4j抽象层,所以为了兼容log4j,这里又多了一个slf4j-log412.jar适配层,用来适配slf4j和log4j接口层的抽象,然后调用slf4j门面接口,就是调用log4j的接口从而调用了log4j的实现。
注意 每个日志框架都有自己的日志实现,所以日志的配置文件还是需要设置成日志实现的配置文件即可;

4、SpringBoot日志遗留问题-框架的切换

如果说每个系统使用着不同的日志框架实现,现在要把它统一套日志框架使用,即使是别的日志框架也要和我一起使用slf4j的日志框架;
比如:A系统的各个组件日志依赖情况如下:
  • 开发系统A: 使用slf4j + logback;
  • 依赖的Spring框架使用commons-logging
  • 依赖的Mybaties使用JUL等等;
思考:SpringBoot如何让系统中其他的日志框架统一到一种日志框架slf4j+logback呢?
  • 1、将系统中其他日志框架先排除出去;
  • 2、导入中间包来替换原有的日志框架包进行适配转换,偷天换日;
  • 3、导入我们需要的日志实现类,比如:日志门面slf4j + 日志实现log4j2;
遗留问题解决资料参考Legacy APIS:  http://www.slf4j.org/legacy.html
 
日志框架适配图
上图完美的展示了怎么解决日志遗留问题,比如我们需要把上图1中的JCL统一到slf4j + logback。
  • 第一步:排除Spring的commons-logging.jar包;
  • 第二步:导入jcl-over-slf4j.jar适配转换包,将Commons-logging API桥接转换为slf4j-api的接口;
  • 第三步:导入我们需要的slf4j和logbackjar包就OK了;
上图将解决办法展示的一目了然,十分清晰。

5、SpringBoot底层的日志框架

Springboot中依赖了很多的starter,其中有两个很重要的starter,选择其中一个starter即可。

方案一:slf4j + log4j2的日志组合框架


<dependencies>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
<dependencies>
 
方案二:默认的框架:slf4j + logback的日志组合框架
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-logging</artifactId>
</dependency>

但是你会发现这两个jar包里什么文件都没有,只是导入了其他的几种日志包的实现和转换包,这也是非常典型的面向接口编程思想,让使用和实现解耦,大大提高了程序的可扩展性和灵活性。通过maven依赖树分析其底层的日志包依赖关系如下:

从这个依赖关系图可以看出Springboot默认是使用 slf4j + logback的组合来实现日志的记录;
从这关系也可以看出springboot也考虑到了其他的日志框架,例如JUL,JCL和log4j这些日志框架的适配;
例如JCL框架的日志包,表面看似是使用的JCL的日志,但是底层实际上使用的是slf4j的日志,进行了日志的中间转换适配,这也是 面向接口编程的好处。
SpringBoot日志框架总结:
  • SpringBoot能适配所有的日志,而且底层默认使用slf4j + logback的方式记录日志;
  • 引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉,其他什么都不用做。
  • springboot提供了转换的中间包进行了适配,偷天换日的操作;
例如如果Spring使用了commons-loggin日志,想统一使用slf4j + logback的日志框架,SpringBoot只需要把spring的commons-loggin排除掉就可以了。
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <exclusions>
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

6、SpringBoot日志的配置

日志框架
  • SpringBoot默认帮我们配置好了 日志slf4j + logback。
日志级别
  • SpringBoot默认的日志级别: info
  • 日志级别从低到高 :trace < debug<info<warn<error,项目中一般到info级别就够了;设置后高级别生效;
  • 级别规则:只输出级别不低于设定级别的日志信息,例:loggers级别为INFO,则INFO、WARN、ERROR、FATAL级别的日志信息都会输出,而级别比INFO低的DEBUG则不会输出;

6.1、日志参数配置

SpringBoot默认日志输出格式:
2017-06-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2017-06-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext

默认输出格式解析:The following items are output:

  • 时间:Date and Time — Millisecond precision and easily sortable.
  • 日志级别:Log Level —  ERROR WARN INFO DEBUG  or  TRACE .
  • 线程id:Process ID.
  • 分隔符:A  ---  separator to distinguish the start of actual log messages.
  • 线程名字:Thread name — Enclosed in square brackets (may be truncated for console output).
  • 日志的类名:Logger name — This is usually the source class name (often abbreviated).
  • 日志信息:The log message.
参数
描述
Example
result
logging.path
指定日志路径
/var/log
输出到/var/log/spring.log文件中
logging.file
制定日志文件名
my.log
输出日志到my.log文件
logging.pattern.console
终端日志格式
 
 
logging.pattern.file
指定日志文件内容格式
 
 
日志格式参数解析:
这里分析一个日志格式
<Properties>
    <Property name="PATTERN">%d %p [%t] %C{1} (%F:%L) [%marker] - %m%n</Property>
    <Property name="LOG_DIR">/opt/log</Property>
</Properties>

#  %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921

#  %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
#  %t 输出产生该日志事件的线程名
#  %c 输出所属的类目,通常就是所在类的全名
#  %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。
#  %m 输出代码中指定的消息
#  %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
#  %r 输出自应用启动到输出该log信息耗费的毫秒数
 

6.2、日志配置文件

例如项目中使用的log4j2日日志框架,直接使用log4j2.xml配置文件即可被日志框架识别加载了,绕过了spring框架。但是如果想用spring的高级特性这么办呢?
例如想要用到springboot的高级功能<SpringProfile>标签,允许日志按照某种环境来加载生效,例如:
<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

思考:如何定义自己的日志配置文件呢?

Depending on your logging system, the following files will be loaded:
也是非常简单,使用的日志框架和相应的日志配置文件关系如下:
 
Logging System
Customization
Logback
logback-spring.xml logback.xml 
Log4j2
log4j2-spring.xml  or  log4j2.xml
JDK (Java Util Logging)
logging.properties
log4j2-spring.xml:这时候该日志配置文件就会被springboot加载,可以使用springboot的高级功能< springProfile>,然后就可以指定某段配置只在某个指定的环境生效,例如设置在dev环境和不是dev下分别使用不同的日志输出格式:
<!--输出日志的格式,根据环境选择日志配置文件-->
<springProfile name="dev">
    <PatternLayout pattern=" dev-log %d %p [%t] %C{1} (%F:%L) [%marker] - %m%n"/> 
</springProfile>
<springProfile name="!dev">
    <PatternLayout pattern=" non-dev-log %d %p [%t] %C{1} (%F:%L) [%marker] - %m%n"/>
</springProfile>

这里需要在applicaton.properties文件或者命令行中设置激活的日志文件,参数如下:

spring.profiles.active=dev

设置完成之后,日志的输出格式就会是dev环境下的格式了,非常灵活;

如果配置了springProfile但是使用的是logback.xml,则logback日志框架会因为找不到日志配置文件而报错:no applicable action for [springProfile].
 

7、 项目中日志收集流程

    为了更好的利用日志,我们一般会将日志输出到日志中心,做数据分析,告警和问题的跟踪查询,用户画像的分析等。
 
具体步骤:
  • 1、配置pom.xml中的dependency;
  • 2、配置log4j2.xml中的appender;
  • 3、配置日志名category;
  • 4、打印日志;
之后经过kafka将日志导入数据仓库做数据分析,导入日志中心进行问题定位追踪记录,导入监控平台cat做报警系统等等。

8、小结

在实际的应用中,日志是必不可少的,也是最重要的一个组件。常见 的功能包括:
  • 1、 快速定位分析问题,行为记录跟踪;
  • 2、监控 系统运行情况, 持久化数据
  • 3、数据的统计和分析;
  • 4、当然,在很多大型的互联网应用中,基于日志的收集以及分析可以了解用户画像,比如兴趣爱好/点击行为。
 
 
参考文件:
 
 
 
 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值