目录

1、日志框架的发展

2、日志框架的选择

3、日志框架的使用

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

5、SpringBoot底层的日志框架

6、SpringBoot日志的配置

6.1、日志参数配置

6.2、日志配置文件

7、 项目中日志收集流程

8、小结


前言

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

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( 推荐)
  • 日志实现: 
  • 推荐(  和 slf4j都是同一个作者,兼容强);
  • JUL ,jdk工具包自带的一个简单的日志工具;
  • 推荐;

推荐使用搭配-日志门面 + 日志实现


推荐: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包即可,日志框架组合依赖包关系如下(资料参考)




springboot log4j2 每天一个日志文件_spring boot


上图完美的介绍了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


 


日志框架适配图



springboot log4j2 每天一个日志文件_slf4j_02


上图完美的展示了怎么解决日志遗留问题,比如我们需要把上图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 log4j2 每天一个日志文件_日志框架_03


slf4j + logback的组合来实现日志的记录;


从这关系也可以看出springboot也考虑到了其他的日志框架,例如JUL,JCL和log4j这些日志框架的适配;


面向接口编程的好处。



springboot log4j2 每天一个日志文件_日志框架_04

SpringBoot日志框架总结:


  • SpringBoot能适配所有的日志,而且底层默认使用slf4j + logback的方式记录日志;
  • 引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉,其他什么都不用做。
  • springboot提供了转换的中间包进行了适配,偷天换日的操作;
<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、日志参数配置


日志文档参考: https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#boot-features-logging


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的高级特性这么办呢?


<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、 项目中日志收集流程


    为了更好的利用日志,我们一般会将日志输出到日志中心,做数据分析,告警和问题的跟踪查询,用户画像的分析等。



springboot log4j2 每天一个日志文件_java_05


 


具体步骤:


  • 1、配置pom.xml中的dependency;
  • 2、配置log4j2.xml中的appender;
  • 3、配置日志名category;
  • 4、打印日志;

之后经过kafka将日志导入数据仓库做数据分析,导入日志中心进行问题定位追踪记录,导入监控平台cat做报警系统等等。


8、小结


在实际的应用中,日志是必不可少的,也是最重要的一个组件。常见 的功能包括:


  • 1、 快速定位分析问题,行为记录跟踪;
  • 2、监控 系统运行情况, 持久化数据
  • 3、数据的统计和分析;
  • 4、当然,在很多大型的互联网应用中,基于日志的收集以及分析可以了解用户画像,比如兴趣爱好/点击行为。

 


 


参考文件:


日志框架参数: https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#boot-features-logging


http://www.slf4j.org/manual.html


https://spring.io/quickstart