Java 开源日志框架,以继承改善 log4j 为目的而生,是 log4j 创始人 Ceki Gülcü 的开源产品。
它声称有极佳的性能,占用空间更小,且提供其他日志系统缺失但很有用的特性。
其一大特色是,在 logback-classic 中本地(native)实现了 SLF4J API(也表示依赖 slf4j-api)
日志记录器,logback-classic 的部分
每个 Logger 都附加到一个 LoggerContext 上,该 Context 负责构造 Logger 以及将其安排在层级结构中。
命名及层级关系
Logger 名称区分大小写,并遵循层级命名规则。
层级关系用 "." 表示,如:"com.foo" 是 "com.foo.Bar" 的父Logger
且所有 Logger 都可通过LoggerFactory#getlogger(String name)
来获取,且相同名称返回的实例相同
根 Logger
是所有层级结构的顶部Logger,可通过名称检索获取
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
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
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.");
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
A1
not applicable
A1
x
A-x1, A-x2
true
A1, A-x1, A-x2
x.y
none
true
A1, A-x1, A-x2
x.y.z
A-xyz1
true
A1, A-x1, A-x2, A-xyz1
security
A-sec
false
A-sec
security.access
none
true
A-sec
表示日志输出格式,其通过接口ch.qos.logback.core#doLayout(E event): String
将日志事件格式化为String 返回。
Logback 官方提供 PatternLayout,允许以类似c语言printf来指定输出格式。
可通过将 layout 与 appender 关联,来实现自定义输出格式和目的地;但并不是每个 appender 都需要 layout,比如负责序列化的 SocketAppender 自然不需要 doLayout 转字符串
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
Logback 初始化时,根据以下顺序尝试配置:
类路径下尝试寻找 logback-test.xml
若没有,类路径下尝试寻找 logback.groovy
若没有,类路径下尝试寻找 logback.xml
若没有,尝试基于 Java SPI 机制寻找 com.qos.logback.classic.spi.Configurator 接口的实现
若以上都没有,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.
可在值中以 ${KEY:-defaultValue} 的形式引入属性,查找顺序如下:
<property>
)既支持名称(KEY)中的嵌套,也支持值/默认值的嵌套引用
预定义属性:
一些标签涉及到类的标签(如<definer>、<appender>、<encoder>
),其子标签除了规定之外,还可定义与 JavaBean 属性同名,这将调用相应setter注入。
属性:
debug:获知 Logback 内部状态,官方推荐在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
java.lang.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]
示例:
*name:声明Appender名称
*class:要使用的Appender的完全限定名
name(必须)
level:[TRACE | DEBUG | INFO | WARN | ERROR | ALL | OFF],或者 INHERITED / NULL 表示从上级继承。
additivity:[true | false]
子标签:
logback.configurationFile:指定配置文件位置,可以是 URL、类路径资源或外部文件系统。也可以在代码中设置(System#setProperty),但必须在创建任意Logger实例之前。
文件扩展名必须是 .xml 或 .groovy
logback.statusListenerClass:可设置为希望注册的 StatusListener 名称
转换符 '%' 可后跟规定的word,来获取数据字段,如 logger名称,日期,线程名等
转换符可后接格式修饰符(Format modifiers)来指定每个字段最小、最大宽度 以及 是否左对齐
示例:
写法
左对齐
最小宽度
最大宽度
%20logger
false
20
none
%.30logger
NA
none
30
%-20.30logger
true
20
30
括号"()" 可将部分内容分组,常配合格式修饰符使用
如:
%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 平台默认时区
示例
结果
%d
2006-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}
自定义转换词:
类名:C{length} / class{length}
文件名:F / file
行号:L / line
方法名:M / method
包含jar包信息的异常stacktrace:xEx{depth} / xException{depth}…
及root异常顺序反转的 rEx{depth} / rootException{depth}…
基于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>
可通过声明AsyncAppender来执行异步日志打印,它只进行日志事件分发,因此必须引用另一个实际Appender才有意义
根据环境变量动态附加Appender
参考:How to select Logback appender based on property file or environment variable
对于嵌套 .xml 配置文件,默认域"local"重复声明的话是无效的,不会覆盖。
比如在我的logback.xml中声明,无法覆盖Spring自带的配置。
撰文参考:
手机扫一扫
移动阅读更方便
你可能感兴趣的文章