Logback快速入门使用详解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Logback快速⼊门使⽤详解
⼀、简介
Java 开源⽇志框架,以继承改善 log4j 为⽬的⽽⽣,是 log4j 创始⼈ Ceki Gülcü 的开源产品。

它声称有极佳的性能,占⽤空间更⼩,且提供其他⽇志系统缺失但很有⽤的特性。

其⼀⼤特⾊是,在 logback-classic 中本地(native)实现了 SLF4J API(也表⽰依赖 slf4j-api)
⼆、架构 / Logback知识
1. 项⽬分为三个模块:
logback-core:其他俩模块基础模块,作为通⽤模块其中没有 logger 的概念
logback-classic:⽇志模块,完整实现了 SLF4J API
logback-access:配合Servlet容器,提供 http 访问⽇志功能
2. 在 logback 中主要概念(Logger、Appender、Layout、Encoder)
· Logger
⽇志记录器,logback-classic 的部分
每个 Logger 都附加到⼀个 LoggerContext 上,该 Context 负责构造 Logger 以及将其安排在层级结构中。

1. 命名及层级关系
Logger 名称区分⼤⼩写,并遵循层级命名规则。

层级关系⽤ "." 表⽰,如:"com.foo" 是 "com.foo.Bar" 的⽗Logger
且所有 Logger 都可通过LoggerFactory#getlogger(String name)来获取,且相同名称返回的实例相同
2. 根 Logger
是所有层级结构的顶部Logger,可通过名称检索获取
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
3. Level 与继承关系
Logger 可以被分配级别(TRACE、DEBUG、INFO、WARN、ERROR),可在 ch.qos.logback.classic 中查看
若没有给 Logger 分配级别,则它将从最近的分配了等级的祖先处继承等级
例:
Logger name Assigned level Effective level
root DEBUG DEBUG
X INFO INFO
X.Y none INFO
X.Y.Z ERROR ERROR
4. Level 与 log 规则(basic selection rule)
Logger 只会启⽤等级 ≥ Logger等级的⽇志请求
等级排序(严重程度,⽽⾮优先级):TRACE < DEBUG < INFO < WARN < ERROR
如:
Logger logger = LoggerFactory.getLogger("com.foo");
logger.setLevel(Level. INFO);
// 启⽤,因为 WARN >= INFO
logger.warn("Low fuel level.");
// 禁⽤, 因为 DEBUG < INFO.
logger.debug("Starting search for nearest gas station.");
· Appender
Logback 通过Appender#doAppend(E event)将⽇志事件打印到⽬的地(允许附加多个Appender即即多个⽬的地
⽬前官⽅已提供 console、⽂件、远程socket服务、JMS、远程UNIX Syslog进程、MySQL/PostgreSQL/Orcale等数据库的 appender ⽀持.注意:
⼀个 Logger 可以通过Logger#addAppender⽅法可被附加多个 appender
appender 同样适⽤于继承结构,且是以追加的⽅式⽽⾮覆盖;
但继承⾏为可被 Logger 的additivity标志影响是否继承(通过Logger#setAdditive设置)
additivity 标志本⾝也是可继承的
继承⽰例如下:
Logger Name Attached Appenders Additivity Flag Output Targets
root A1not applicable A1
x A-x1, A-x2true A1, A-x1, A-x2
x.y none true A1, A-x1, A-x2
x.y.z A-xyz1true A1, A-x1, A-x2, A-xyz1
security A-sec false A-sec
security.access none true A-sec
· Layout
表⽰⽇志输出格式,其通过接⼝ch.qos.logback.core#doLayout(E event): String将⽇志事件格式化为String 返回。

Logback 官⽅提供 PatternLayout,允许以类似c语⾔printf来指定输出格式。

可通过将 layout 与 appender 关联,来实现⾃定义输出格式和⽬的地;但并不是每个 appender 都需要 layout,⽐如负责序列化的SocketAppender ⾃然不需要 doLayout 转字符串
· Encoder
Encoder的概念在 Logback 0.9.19 中被引⼊,通过Encoder#encode可将 LoggingEvent 转为 byte[]
⽬前 Logback 仅提供了 PatternLayoutEncoder 这⼀个可⽤的实现,其逻辑很简单:内部构造/包装了 PatternLayout 实例,调
⽤PatternLayout#doLayout得到格式化字串后,再调⽤String#getBytes返回 byte[]
引⼊原因:因为Layout#doLayout接⼝只能将 LoggingEvent 转为 String,这在某些情况下不太灵活,⽽现在 Encoder 能完全控制字节格式。

⽐如,在以前的版本中常在FileAppender中嵌套PatternLayout来使⽤,但现在仅需依赖Encoder
三、使⽤
1) 使⽤⽰例
1. 引⼊依赖(logback-classic背后会⾃动引⼊ logback-core、slf4j 等依赖包
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.10</version>
</dependency>
2. 基于slf4j⽤法,获取并使⽤Logger
public class Sample {
private static final Logger LOGGER = LoggerFactory.getLogger(Sample.class);
public static void main(String[] args){
("A Message From LOGGER:{}", "Hello World");
}
}
输出:
16:55:54.091 [main] INFO logbacktest.Sample - A Message From LOGBACK:Hello World
2) logback 配置
Logback 初始化时,根据以下顺序尝试配置:
1. 类路径下尝试寻找 logback-test.xml
2. 若没有,类路径下尝试寻找 logback.groovy
3. 若没有,类路径下尝试寻找 logback.xml
4. 若没有,尝试基于 Java SPI 机制寻找 com.qos.logback.classic.spi.Configurator 接⼝的实现
5. 若以上都没有,Logback 会使⽤最基本的 BasicConfigurator 配置⾃⼰。

这将使⽤ TTLLLayout(类似 PatternLayout)以"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"模式格式化⽇志,并将 ConsoleAppender 附加到 root Logger,这会输出到控制台,且 root 被指定为 DEBUG 等级。

默认配置等效为以下xml配置:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
可通过以下代码打印当前配置:StatusPrinter.print((LoggerContext) LoggerFactory.getILoggerFactory())
输出:
15:25:46,635 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
15:25:46,635 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
15:25:46,636 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
15:25:46,647 |-INFO in ch.qos.logback.classic.BasicConfigurator@5f16132a - Setting up default configuration.
四、log 整体流程
1. 获取 filter 链决策
2. 应⽤ basic selection rule
3. 创建 LoggingEvent 对象
4. 调⽤ appenders
5. 调 Layout 格式化
6. 输出到⽬的地
五、配置详解
1.配置⽂件
⼀些写法/背景知识:
1. 可在值中以 ${KEY:-defaultValue} 的形式引⼊属性,查找顺序如下:
⾸先在本地作⽤域查找(详见<property>)
若没有,在上下⽂作⽤域查找
若没有,在JVM系统属性查找
最后,在系统环境变量中查找
既⽀持名称(KEY)中的嵌套,也⽀持值/默认值的嵌套引⽤
2. 预定义属性:
HOSTNAME:系统hostname,是配置时在 context 域中被定义被定义
CONTEXT_NAME:上下⽂名
3. ⼀些标签涉及到类的标签(如<definer>、<appender>、<encoder>),其⼦标签除了规定之外,还可定义与 JavaBean 属性同名,这将调⽤
相应setter注⼊。

顶级标签
<configuration>
属性:
debug:获知 Logback 内部状态,官⽅推荐在<configuration>上设置debug属性,⽽⾮在代码中调⽤ StatusPrinter。

例:<configuration debug="true">
这也等同于设置状态监听器 OnConsoleStatusListener
例:
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<!-- … -->
</configuration>
scan / scanPeriod:可定期扫描配置⽂件的更改,并在更改时⾃动应⽤。

默认每分钟⼀次
例:<configuration scan="true" scanPeriod="30 seconds" >
packagingData:可令每⼀⾏StackTrace输出其对应jar包。

需注意,其计算成本⾼昂
例:<configuration packagingData="true">
输出⽰例:
14:28:48.835 [btpool0-7] INFO c.q.l.demo.prime.PrimeAction - 99 is not a valid value
ng.Exception: 99 is invalid
at ch.qos.logback.demo.prime.PrimeAction.execute(PrimeAction.java:28) [classes/:na]
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431) [struts-1.2.9.jar:1.2.9]
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236) [struts-1.2.9.jar:1.2.9]
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) [struts-1.2.9.jar:1.2.9]
<configuration>⼦标签
<include>:从另外的⽂件引⼊配置,⽬标⽂件必须将其标签放⼊<included>下。

(SpringBoot基础配置便是如此,可参考spring-boot:2.4.0包中base.xml)
file
resource
url
optional:[true | false],默认若找不到⽬标⽂件,将输出警告;可设置为可选避免该⾏为
<contextName>:设置上下⽂名称,可作为区分不同多个应⽤程序到同⼀target的区分,默认为"default"
⽰例:
<contextName>myAppName</contextName>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %contextName [%t] %level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<property>:配置或引⼊外部属性,别名
name
value
file:引⽤⽂件系统的 .properties ⽂件
resource:引⽤类路径上的 variables.properties ⽂件
scope:
local:默认,会在配置解释时定义,并在结束后清除。

context:上下⽂作⽤域,属性将插⼊到LoggerContext中直到LoggerContext被清除,因此在所有⽇志事件中都可⽤。

system:系统作⽤域,属性将插⼊到JVM系统属性中
<define>:代码动态定义属性,以 PropertyDefiner#getPropertyValue ⽅法返回其值
name
class:PropertyDefiner实现全类名
<conversionRule>:⾃定义转换词
conversionWord:转换词
converterClass:ClassicConverter 实现类全类名
<appender>
*name:声明Appender名称
*class:要使⽤的Appender的完全限定名
<appender>、<layout>⼦标签:
<layout>:0或1个
class:若未声明,表⽰ PatternLayout
<encoder>:0或多个
class:若未声明,表⽰ PatternLayoutEncoder
<filter>:0或多个
<logger>:0或多个,配置 Logger
name(必须)
level:[TRACE | DEBUG | INFO | WARN | ERROR | ALL | OFF],或者 INHERITED / NULL 表⽰从上级继承。

additivity:[true | false]
⼦标签:
<appender-ref> :0或多个,表附加appender
ref:指定先前的名称
<root>:配置根Logger
level:根Logger级别不能设置为 INHERITED / NULL
⼦标签:
<appender-ref>
2.JVM系统属性
logback.configurationFile:指定配置⽂件位置,可以是 URL、类路径资源或外部⽂件系统。

也可以在代码中设置
(System#setProperty),但必须在创建任意Logger实例之前。

⽂件扩展名必须是 .xml 或 .groovy
logback.statusListenerClass:可设置为希望注册的 StatusListener 名称
3. PatternLayout 的格式化消息编写规则
基础规则
转换符 '%' 可后跟规定的word,来获取数据字段,如 logger名称,⽇期,线程名等
转换符可后接格式修饰符(Format modifiers)来指定每个字段最⼩、最⼤宽度以及是否左对齐
⽰例:
写法左对齐最⼩宽度最⼤宽度
%20logger false20none
%.30logger NA none30
%-20.30logger true2030
括号"()" 可将部分内容分组,常配合格式修饰符使⽤
如:
%d{HH:mm:ss.SSS} [%thread]
输出:
13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server
13:09:30 [pool-1-thread-1] INFO ch.qos.logback.demo.LoggingTask - Howdydy-diddly-ho - 0
%-30(%d{HH:mm:ss.SSS} [%thread])
⼀些关键词可使⽤转义符\来输出
常⽤转换词
⽇志事件的消息:m / msg / messages
⽇志级别:p / le / level
Logger 名
语法:
c{length}
lo{length}
logger{length}
含义/⽰例: length表⽰推荐最⼤长度,logback会根据该长度适当缩写Logger名,但始终会保证最右段不会缩写
⽰例Logger原名称打印结果
%logger mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar
%logger{0}mainPackage.sub.sample.Bar Bar
%logger{5}mainPackage.sub.sample.Bar m.s.s.Bar
%logger{16}mainPackage.sub.sample.Bar m.sub.sample.Bar
上下⽂名:contextName
⽇志事件的线程名: t / thread
从"应⽤启动"到"产⽣该⽇志事件"经过的毫秒数:r / relative
⽇期
语法:
d{pattern}
date{pattern}
d{pattern, timezone}
date{pattern, timezone}
含义/⽰例:输出⽇志事件的⽇期,其 pattern 语法与 java.text.SimpleDateFormat 格式兼容
在没有 timezone 的情况下,使⽤ Java 平台默认时区
⽰例结果
%d2006-10-20 14:06:49,812
%date{HH:mm:ss.SSS}14:06:49.812%date{dd MMM yyyy;HH:mm:ss.SSS}20 oct. 2006;14:06:49.812
%date{HH:mm:ss.SSS, Australia/Perth}
⽰例结果
换⾏符:n
异常:
语法:
ex{depth}
exception{depth}
throwable{depth}
ex{depth, evaluator-1, ..., evaluator-n}
exception{depth, evaluator-1, ..., evaluator-n}
throwable{depth, evaluator-1, ..., evaluator-n}
含义/⽰例:输出与⽇志事件关联的异常的stacktrace 信息,默认输出完整的
stacktrace
属性:property{key}
正则替换:replace(p){r,t} 将消息模式p 中的r 替换为t
如:%replace(%logger %msg){'\.', '/'}将所有"."替换为"/"
MDC (Mapped Diagnostic Contex )字段:%X{filedName}
⾃定义转换词:
1. ⾃定义实现 ClassicConverter ,重写 convert(ILoggingEvent) ⽅法
public class MySampleConverter extends ClassicConverter {
long start = System.nanoTime();
@Override
public String convert(ILoggingEvent event) {
long nowInNanos = System.nanoTime();
return Long.toString(nowInNanos-start);
}
}
2. 声明转换词
<configuration>
<conversionRule conversionWord="nanos" converterClass="youts.MySampleConverter" />
<!-- … -->
</configuration>
性能考虑,应避免使⽤的转换词
类名:C{length} / class{length}
⽂件名:F / file
⾏号:L / line
⽅法名:M / method
包含jar 包信息的异常stacktrace :xEx{depth} / xException{depth}…
及root 异常顺序反转的 rEx{depth} / rootException{depth}…
4. 着⾊(Coloring )
基于ANSI 颜⾊代码,Logback 可使⽤颜⾊关键词来为分组设置颜⾊。

内置了:"%highlight","%black", "%red", "%green","%yellow","%blue","%magenta","%cyan", "%white", "%gray", "%boldRed","%boldGreen", "%boldYellow", "%boldBlue", "%boldMagenta""%boldCyan","%boldWhite"
例:
<pattern>%d ${HOSTNAME} [%t] %highlight(%level) %logger{36} - %msg%n %ex{full}</pattern>
踩坑:官⽅说明使⽤ jansi 可以做到兼容不兼容ANSI的终端,但 Windows 下始终报错,即便引⼊了推荐版本仍然报错<dependency>
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>
<version>1.17</version>
</dependency>
5.异步Appender
可通过声明AsyncAppender来执⾏异步⽇志打印,它只进⾏⽇志事件分发,因此必须引⽤另⼀个实际Appender才有意义
六、常见需求
1. 根据环境变量动态附加Appender
参考:
1. 使⽤ logback 官⽅⽀持的语法,但同样需要引⼊ Janino library。

参考:
2. 为,并使⽤环境变量语法动态配置Filter的Level【有些曲线救国,应该仍有性能损耗
3. 使⽤ SpringProfile
例:
application.yaml
spring:
profiles:
active:
- ${ENV:classiclogs}
logback.xml
<configuration>
<!-- appender conf…-->
<springProfile name="jsonlogs">
<root level="info">
<appender-ref ref="stdout-json" />
</root>
</springProfile>
<springProfile name="classiclogs">
<root level="info">
<appender-ref ref="stdout-classic" />
</root>
</springProfile>
</configuration>
七、踩坑
1. 对于嵌套 .xml 配置⽂件,默认域"local"重复声明的话是⽆效的,不会覆盖。

⽐如在我的logback.xml中声明,⽆法覆盖Spring⾃带的配置。

相关文档
最新文档