对于一个web项目来说,日志框架是必不可少的,日志的记录可以帮助我们在开发以及维护过程中快速的定位错误。相信很多人听说过slf4j,log4j,logback,JDK Logging等跟日志框架有关的词语,所以这里也简单介绍下他们之间的关系。
首先slf4j可以理解为规则的制定者,是一个抽象层,定义了日志相关的接口。log4j,logback,JDK Logging都是slf4j的实现层,只是出处不同,当然使用起来也就各有千秋,这里放一张网上的图更明了的解释了他们之间的关系:
我使用这个框架是因为一开始接触的时候就用的这个,后来在网上了解到slf4j+logback也确实当下最流行的日志框架,并且自己用着也确实很顺手,也就一直用了下来。
在Spring boot使用是非常方便的,不需要我们有什么额外的配置,因为Spring boot默认支持的就是slf4j+logback的日志框架,想要灵活的定制日志策略,只需要我们在src/main/resources下添加配置文件即可,只是默认情况下配置文件的命名需要符合以下规则:
其中logback-spring.xml是官方推荐的,并且只有使用这种命名规则,才可以配置不同环境使用不同的日志策略这一功能。
首先介绍配置文件的关键节点:
框架介绍
根节点
在该节点内可以添加子节点
,该节点有一个必填的属性ref,值为我们定义的 节点的name属性的值。
介绍了根节点的三个主要的子节点,下面再介绍两个不那么重要但可以了解的子节点:
好了,介绍了上边的节点我们就已经可以搭建一个简单的配置文件框架了,如下:
<?xml version="1.0" encoding="UTF-8"?>
demo
上面搭建了框架,定义了一个输出到控制台的ConsoleAppender以及输出到文件的FileAppender,下面来细说这两个最基本的日志策略,并介绍最常用的滚动文件策略的RollingFileAppender,这三种类型的日志策略足够我们的日常使用。
输出到控制台的ConsoleAppender的介绍:
先给出一个demo:
[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n
ConsoleAppender的功能是将日志输出到控制台,有一个
该节点主要做两件事:
该节点的子节点
介绍了常用的转换符,我们再看看上边的例子中我们定义的格式:
[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n
日志的格式一目了然,可以看出我们在最前面加了[eran]的字符串,这里是我个人的使用习惯,一般将项目名统一展现在日志前边,而且在每个转换符之间加了空格,这更便于我们查看日志,并且使用了>>字符串来将%msg分割开来,更便于我们找到日志信息中我们关注的内容,这些东西大家可以自己按照自己的喜好来。
输出到文件的FileAppender
先给出一个demo:
D:/test.log
true
[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n
FileAppender表示将日志输出到文件,常用几个子节点:
显而易见,样例中我们的日志策略表示,每次将日志信息追加到D:/test.log的文件中。
滚动文件策略RollingFileAppender介绍
按时间滚动TimeBasedRollingPolicy
demo如下:
D:/logs/test.%d{yyyy-MM-dd}.log
7
1GB
[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n
RollingFileAppender是非常常用的一种日志类型,表示滚动纪录文件,先将日志记录到指定文件,当符合某种条件时,将日志记录到其他文件,常用的子节点:
以上就是关于RollingFileAppender的常用介绍,上面的demo的配置也基本满足了我们按照时间滚动TimeBasedRollingPolicy生成日志的要求,下面再介绍一种常用的滚动类型SizeAndTimeBasedRollingPolicy,即按照时间和大小来滚动。
按时间和大小滚动SizeAndTimeBasedRollingPolicy
demo如下:
D:/logs/test.%d{yyyy-MM-dd}.%i.log
100MB
7
1GB
[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n
仔细观察上边demo中的
上边的demo中多了一个
日志过滤
级别介绍
在说级别过滤之前,先介绍一下日志的级别信息:
上述级别从上到下由低到高,我们开发测试一般输出DEBUG级别的日志,生产环境配置只输出INFO级别甚至只输出ERROR级别的日志,这个根据情况而定,很灵活。
过滤节点
过滤器通常配置在Appender中,一个Appender可以配置一个或者多个过滤器,有多个过滤器时按照配置顺序依次执行,当然也可以不配置,其实大多数情况下我们都不需要配置,但是有的情况下又必须配置,所以这里也介绍下常用的也是笔者曾经使用过的两种过率机制:级别过滤器LevelFilter和临界值过滤器ThresholdFilter。
在此之前先说下
级别过滤器LevelFilter
过滤条件:只处理INFO级别的日志,格式如下:
INFO
ACCEPT
DENY
就如上边的demo中的配置一样,设置了级别为INFO,满足的日志返回ACCEPT即立即处理,不满足条件的日志则返回DENY即丢弃掉,这样经过这一个过滤器就只有INFO级别的日志会被打印出输出。
临界值过滤器ThresholdFilter
过滤条件:只处理INFO级别之上的日志,格式如下:
INFO
当日志级别等于或高于临界值时,过滤器返回NEUTRAL,当日志级别低于临界值时,返回DENY。
带过滤器的
下面给出一个带过滤器的
D:/logs/test.%d{yyyy-MM-dd}.%i.log
100MB
7
1GB
[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n
INFO
INFO
ACCEPT
DENY
上边的demo中,我们给按时间和大小滚动SizeAndTimeBasedRollingPolicy的滚动类型加上了过滤条件。
异步写入日志AsyncAppender
都知道,我们的日志语句是嵌入在程序内部,如果写入日志以及程序执行的处于一个串行的状态,那么日志的记录就必然会阻碍程序的执行,加长程序的响应时间,无疑是一种极为损耗效率的方式,所以实际的项目中我们的日志记录一般都用异步的方式来记录,这样就和主程序形成一种并行的状态,不会影响我们程序的运行,这也是我们性能调优需要注意的一个点。
AsyncAppender并不处理日志,只是将日志缓冲到一个BlockingQueue里面去,并在内部创建一个工作线程从队列头部获取日志,之后将获取的日志循环记录到附加的其他appender上去,从而达到不阻塞主线程的效果。因此AsynAppender仅仅充当事件转发器,必须引用另一个appender来写日志。
0
512
常用节点:
上边花费了很长的篇幅介绍了
上文已经简单介绍了
首先在这里给出项目结构:
下面定义两个
当存在多个
上边我们定义了logger1和logger2,很明显看出logger1是logger2的父级,以本例给出多个
流程图看着一目了然,这里就不再赘述,只是在实际的项目中我们一般都不让
配置profile
profile即根据不同的环境使用不同的日志策略,这里举例开发和生产环境:
可以看到我们只需要在
java -jar xxx.jar --spring.profiles.active=prodspring.profiles.active=prod整合
最后将所有的模块整合在一起形成一个完整的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
[%contextName]%date [%thread %line] %level >> %msg >> %logger{10}%n
D:/test.log
true
[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n
D:/logs/test.%d{yyyy-MM-dd}.log
7
1GB
[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n
D:/logs/test.%d{yyyy-MM-dd}.%i.log
100MB
7
1GB
[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n
INFO
INFO
ACCEPT
DENY
0
512
终于到最后一步了,上边介绍了怎么配置logback-spring.xml配置文件,下面介绍怎么在项目中引入日志对象,以及怎么使用它输出日志,直接上代码:
package com.example.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestLog {
private final static Logger log = LoggerFactory.getLogger(TestLog.class);
@RequestMapping(value="/log",method=RequestMethod.GET)
public void testLog() {
log.trace("trace级别的日志");
log.debug("debug级别日志");
log.info("info级别日志");
log.warn("warn级别的日志");
log.error("error级别日志");
}
}在每一个需要使用日志对象的方法里边都要定义一次private final static Logger log = LoggerFactory.getLogger(xxx.class);其中xxx代指当前类名,如果觉得这样很麻烦,也可以通过@Slf4j注解的方式注入,但是这种方式需要添加pom依赖并且需要安装lombok插件,这里就不概述了,需要了解的朋友可以自己google。
| 留言与评论(共有 0 条评论) “” |