老板下了死命令,要把日志系统切换到Logback
Log4j 介绍过了,SLF4J 也介绍过了,那接下来,你懂的,Logback 就要隆重地登场了,毕竟它哥仨有一个爹,那就是巨佬 Ceki Gulcu。
就在昨天,老板听我说完 Logback 有多牛逼之后,彻底动心了,对我下了死命令,“这么好的日志系统,你还不赶紧点,把它切换到咱的项目当中!”
我们项目之前用的 Log4j,在我看来,已经足够用了,毕竟是小公司,性能上的要求没那么苛刻。
01、Logback 强在哪
1)非常自然地实现了 SLF4J,不需要像 Log4j 和 JUL 那样加一个适配层。
2)Spring Boot 的默认日志框架使用的是 Logback。一旦某款工具库成为了默认选项,那就说明这款工具已经超过了其他竞品。
注意看下图(证据找到了,来自 Spring Boot 官网):
也可以通过源码的形式看得到:
3)支持自动重新加载配置文件,不需要另外创建扫描线程来监视。
4)既然是巨佬的新作,那必然在性能上有了很大的提升,不然呢?
02、Logback 使用示例
第一步,在 pom.xml 文件中添加 Logback 的依赖:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
Maven 会自动导入另外两个依赖:
logback-core 是 Logback 的核心,logback-classic 是 SLF4J 的实现。
第二步,来个最简单的测试用例:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author 微信搜「沉默王二」,回复关键字 PDF
*/
public class Test {
static Logger logger = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
logger.debug("logback");
}
}
Logger 和 LoggerFactory 都来自 SLF4J,所以如果项目是从 Log4j + SLF4J 切换到 Logback 的话,此时的代码是零改动的。
运行 Test 类,可以在控制台看到以下信息:
12:04:20.149 [main] DEBUG com.itwanger.Test - logback
在没有配置文件的情况下,一切都是默认的,Logback 的日志信息会输出到控制台。可以通过 StatusPrinter 来打印 Logback 的内部信息:
LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
在 main 方法中添加以上代码后,再次运行 Test 类,可以在控制台看到以下信息:
12:59:22.314 [main] DEBUG com.itwanger.Test - logback
12:59:22,261 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
12:59:22,262 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
12:59:22,262 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
12:59:22,268 |-INFO in ch.qos.logback.classic.BasicConfigurator@5e853265 - Setting up default configuration.
也就是说,Logback 会在 classpath 路径下先寻找 logback-test.xml 文件,没有找到的话,寻找 logback.groovy 文件,还没有的话,寻找 logback.xml 文件,都找不到的话,就输出到控制台。
一般来说,我们会在本地环境中配置 logback-test.xml,在生产环境下配置 logback.xml。
第三步,在 resource 目录下增加 logback-test.xml 文件,内容如下所示:
<configuration debug="true">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %relative [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Logback 的配置文件非常灵活,最基本的结构为 <configuration>
元素,包含 0 或多个 <appender>
元素,其后跟 0 或多个 <logger>
元素,其后再跟最多只能存在一个的 <root>
元素。
1)配置 appender,也就是配置日志的输出目的地,通过 name 属性指定名字,通过 class 属性指定目的地:
- ch.qos.logback.core.ConsoleAppender:输出到控制台。
- ch.qos.logback.core.FileAppender:输出到文件。
- ch.qos.logback.core.rolling.RollingFileAppender:文件大小超过阈值时产生一个新文件。
除了输出到本地,还可以通过 SocketAppender 和 SSLSocketAppender 输出到远程设备,通过 SMTPAppender 输出到邮件。甚至可以通过 DBAppender 输出到数据库中。
encoder 负责把日志信息转换成字节数组,并且把字节数组写到输出流。
pattern 用来指定日志的输出格式:
%d
:输出的时间格式。%thread
:日志的线程名。%-5level
:日志的输出级别,填充到 5 个字符。比如说 info 只有 4 个字符,就填充一个空格,这样日志信息就对齐了。
反例(没有指定 -5 的情况):
%logger{length}
:logger 的名称,length 用来缩短名称。没有指定表示完整输出;0 表示只输出 logger 最右边点号之后的字符串;其他数字表示输出小数点最后边点号之前的字符数量。%msg
:日志的具体信息。%n
:换行符。%relative
:输出从程序启动到创建日志记录的时间,单位为毫秒。
2)配置 root,它只支持一个属性——level,值可以为:TRACE、DEBUG、INFO、WARN、ERROR、ALL、OFF。
appender-ref 用来指定具体的 appender。
3)查看内部状态信息。
可以在代码中通过 StatusPrinter 来打印 Logback 内部状态信息,也可以通过在 configuration 上开启 debug 来打印内部状态信息。
重新运行 Test 类,可以在控制台看到以下信息:
13:54:54,718 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml] at [file:/Users/maweiqing/Documents/GitHub/JavaPointNew/codes/logbackDemo/target/classes/logback-test.xml]
13:54:54,826 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
13:54:54,828 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
13:54:54,833 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
13:54:54,850 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to DEBUG
13:54:54,850 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
13:54:54,850 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
13:54:54,851 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@f8c1ddd - Registering current configuration as safe fallback point
13:54:54.853 [main] DEBUG com.itwanger.Test - logback
4)自动重载配置。
之前提到 Logback 很强的一个功能就是支持自动重载配置,那想要启用这个功能也非常简单,只需要在 configuration 元素上添加 scan=true
即可。
<configuration scan="true">
...
</configuration>
默认情况下,扫描的时间间隔是一分钟一次。如果想要调整时间间隔,可以通过 scanPeriod 属性进行调整,单位可以是毫秒(milliseconds)、秒(seconds)、分钟(minutes)或者小时(hours)。
下面这个示例指定的时间间隔是 30 秒:
<configuration scan="true" scanPeriod="30 seconds"
...
</configuration>
注意:如果指定了时间间隔,没有指定时间单位,默认的时间单位为毫秒。
当设置 scan=true
后,Logback 会起一个 ReconfigureOnChangeTask 的任务来监视配置文件的变化。
03、把 log4j.properties 转成 logback-test.xml
如果你的项目以前用的 Log4j,那么可以通过下面这个网址把 log4j.properties 转成 logback-test.xml:
http://logback.qos.ch/translator/
把之前 log4j.properties 的内容拷贝一份:
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=debug.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = debug.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
粘贴到该网址的文本域:
点击「Translate」,可以得到以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!-- For assistance related to logback-translator or configuration -->
<!-- files in general, please contact the logback user mailing list -->
<!-- at http://www.qos.ch/mailman/listinfo/logback-user -->
<!-- -->
<!-- For professional support please see -->
<!-- http://www.qos.ch/shop/products/professionalSupport -->
<!-- -->
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<Target>System.out</Target>
<encoder>
<pattern>[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n</pattern>
</encoder>
</appender>
<appender name="D" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--See http://logback.qos.ch/manual/appenders.html#RollingFileAppender-->
<!--and http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy-->
<!--for further documentation-->
<Append>true</Append>
<File>debug.log</File>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<appender name="E" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--See http://logback.qos.ch/manual/appenders.html#RollingFileAppender-->
<!--and http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy-->
<!--for further documentation-->
<File>error.log</File>
<Append>true</Append>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<root level="debug">
<appender-ref ref="stdout"/>
<appender-ref ref="D"/>
<appender-ref ref="E"/>
</root>
</configuration>
可以确认一下内容,发现三个 appender 都在。
但是呢,转换后的文件并不能直接使用,需要稍微做一些调整,因为:
第一,日志的格式化有细微的不同,Logback 中没有 %l
。
第二,RollingFileAppender 需要指定 RollingPolicy 和 TriggeringPolicy,前者负责日志的滚动功能,后者负责日志滚动的时机。如果 RollingPolicy 也实现了 TriggeringPolicy 接口,那么只需要设置 RollingPolicy 就好了。
TimeBasedRollingPolicy 和 SizeAndTimeBasedRollingPolicy 是两种最常用的滚动策略。
TimeBasedRollingPolicy 同时实现了 RollingPolicy 与 TriggeringPolicy 接口,因此使用 TimeBasedRollingPolicy 的时候就可以不指定 TriggeringPolicy。
TimeBasedRollingPolicy 可以指定以下属性:
fileNamePattern,用来定义文件的名字(必选项)。它的值应该由文件名加上一个
%d
的占位符。%d
应该包含java.text.SimpleDateFormat
中规定的日期格式,缺省是yyyy-MM-dd
。滚动周期是通过 fileNamePattern 推断出来的。maxHistory,最多保留多少数量的日志文件(可选项),将会通过异步的方式删除旧的文件。比如,你指定按月滚动,指定
maxHistory = 6
,那么 6 个月内的日志文件将会保留,超过 6 个月的将会被删除。totalSizeCap,所有日志文件的大小(可选项)。超出这个大小时,旧的日志文件将会被异步删除。需要配合 maxHistory 属性一起使用,并且是第二条件。
来看下面这个 RollingFileAppender 配置:
<appender name="D" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天滚动 -->
<fileNamePattern>debug.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 保存 30 天的历史记录,最大大小为 30GB -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%relative [%thread] %level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
基于按天滚动的文件策略,最多保留 30 天,最大大小为 30G。
SizeAndTimeBasedRollingPolicy 比 TimeBasedRollingPolicy 多了一个日志文件大小设定的属性:maxFileSize,其他完全一样。
基于我们对 RollingPolicy 的了解,可以把 logback-test.xml 的内容调整为以下内容:
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<Target>System.out</Target>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="D" class="ch.qos.logback.core.rolling.RollingFileAppender">
<Append>true</Append>
<File>debug.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天轮转 -->
<fileNamePattern>debug.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 保存 30 天的历史记录,最大大小为 30GB -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<appender name="E" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天轮转 -->
<fileNamePattern>error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 保存 30 天的历史记录,最大大小为 30GB -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<root level="debug">
<appender-ref ref="stdout"/>
<appender-ref ref="D"/>
<appender-ref ref="E"/>
</root>
</configuration>
修改 Test 类的内容:
public class Test {
static Logger logger = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
logger.debug("logback");
logger.error("logback");
}
}
运行后,可以在 target 目录下看到两个文件:debug.log 和 errror.log。
到此为止,项目已经从 Log4j 切换到 Logback 了,过程非常的丝滑顺畅,嘿嘿。
04、Logback 手册
Logback 的官网上是有一份手册的,非常详细,足足 200 多页,只不过是英文版的。小伙伴们可以看完我这篇文章入门实操的 Logback 教程后,到下面的地址看官方手册。
http://logback.qos.ch/manual/index.html
如果英文阅读能力有限的话,可以到 GitHub 上查看雷锋翻译的中文版:
https://github.com/itwanger/logback-chinese-manual
当然了,还有一部分小伙伴喜欢看离线版的 PDF,我已经整理好了:
链接:https://pan.baidu.com/s/16FrbwycYUUIfKknlLhRKYA 密码:bptl
实话实话吧,白嫖的感觉就是舒服,赶紧去下载吧!日常求个三连,谢谢你勤劳的手指,嘿嘿。
老板下了死命令,要把日志系统切换到Logback的更多相关文章
- 精尽Spring Boot源码分析 - 日志系统
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- java的几个日志框架log4j、logback、common-logging
开发工作中每个系统都需要记录日志,常见的日志工具有log4j(用的最多),slf4j,commons-loging,以及最近比较流行的logback 以前只是在项目中用log4j,更多的是参考下配置文 ...
- Java日志体系(七)日志框架切换
通过 SLF4J 统一日志 在实际的日志转换过程中,SLF4J其实是充当了一个中介的角色.例如当我们一个项目原来是使用LOG4J进行日志记录,但是我们要换成LogBack进行日志记录. 此时我们需要先 ...
- dos下的edit命令使用详解
dos下的edit命令使用详解 来源:网络 作者:未知 edit命令是一个简单的编辑软件,我们经常用它来编辑一些程序和批处理文件. 比如,我想在c盘根目录下编辑一个简单的批处理文件,要求无论当前盘和当 ...
- 布式实时日志系统(三) 环境搭建之centos 6.4下hadoop 2.5.2完全分布式集群搭建最全资料
最近公司业务数据量越来越大,以前的基于消息队列的日志系统越来越难以满足目前的业务量,表现为消息积压,日志延迟,日志存储日期过短,所以,我们开始着手要重新设计这块,业界已经有了比较成熟的流程,即基于流式 ...
- mysq在命令行模式下执行shell命令
mysql可以在命令行模式下执行shell命令 mysql> help For information about MySQL products and services, visit: htt ...
- Mac下各种网络命令的使用
Mac下各种网络命令的使用(http://blog.51yip.com/linux/745.html) pingwww.baidu.com 会一直ping下去,和windows不一样, windows ...
- Linux下一个简单的日志系统的设计及其C代码实现
1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息, 包括:变量名称及其值.消息结构定义.函数返回 ...
- Windows常用的一些DOS下的CMD命令整理
Windows常用的一些DOS下的CMD命令整理... -------------- 正斜杠--/////-----向右倒--网址正斜杠反斜杠--\\\\------向左倒--文件路径反斜杠 DOS命 ...
随机推荐
- 使用IBMMQ时的那些事
之前项目一直使用的是ActiveMQ,突然要变更成IBMMQ,整理了一些搭建MQ和代码连接MQ是遇到的问题,记录一下. (1)三个系统之内部使用IBMMQ交互,所以应设立两个本地接收队列和两个发送队列 ...
- 题目:写出一条SQL语句,查询工资高于10000,且与他所在部门的经理年龄相同的职工姓名。
create table Emp( eid char(20) primary key, ename char(20), age integer check (age > 0), did char ...
- java转python代码
今天发现一个好玩的工具:可以直接将java转成python 1. 安装工具(windows 环境下面) 先下载antlr: http://www.antlr3.org/download/antlr-3 ...
- Arduino - 串口操作函数与示例代码大全
来源:https://blog.csdn.net/iracer/article/details/50334041 Arduino - 串口操作函数与示例代码大全 本文总结了Arduino常用串口操作函 ...
- JavaScript动态生成表格
要求: HTML标签只写一行表头 通过JS来写动态的表格(有多少组数据,就自动创建多少行表格) 为学习和演示,采用固定的数据,不涉及调用后台数据 代码实现: HTML内容: <table cel ...
- P4107 [HEOI2015]兔子与樱花 贪心
题目描述 传送门 分析 一道贪心题 首先我们可以证明最优的贡献一定是从下依次合并到上的 不会出现一个节点不能合并到父亲节点,却能合并到父亲节点的祖先节点的情况 我们设当前的节点为 \(u\),\(u\ ...
- 关于IPA文件重签名后如何跟踪管理APP的技术探讨和实践演示
前言:开发iOS的朋友都知道,在功能开发完成后,我们就会用申请的苹果账号在后台做证书配置,然后提交到AppStore,但是也有部分APP我们不需要提交到AppStore,比如内部测试用的APP.定制给 ...
- GCC编译选项笔记
警告选项 -Wall:开启大多数的警告信息 -Wextra:开启额外的警告信息,比如参数未使用警告(-Wunused-parameter) -Werror:将警告当作错误,中断编译 优化选项 -O,- ...
- 利用Docker搭建开发环境
一. 前言 随着平台的不断壮大,项目的研发对于开发人员而言,对于外部各类环境的依赖逐渐增加,特别是针对基础服务的依赖.这些现象导致开 发人员常常是为了简单从而直接使用公有的基础组件进行协同开发,在出现 ...
- c++数组的替代品