官方文档: http://logback.qos.ch/manual/index.html
updated 22/1/13:加入用例,更了下文章 符合标题"快速入门"
一、简介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 访问日志功能
每个 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 nameAssigned levelEffective levelrootDEBUGDEBUGXINFOINFOX.YnoneINFOX.Y.ZERRORERROR - Level 与 log 规则(basic selection rule)
Logger 只会启用等级 ≥ Logger等级的日志请求
等级排序(严重程度,而非优先级):TRACE < DEBUG < INFO < WARN < ERROR
如:
Logger logger = LoggerFactory.getLogger("com.foo");logger.setLevel(Level. INFO);// 启用,因为 WARN >= INFOlogger.warn("Low fuel level.");// 禁用, 因为 DEBUG < INFO. logger.debug("Starting search for nearest gas station.");
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 NameAttached AppendersAdditivity FlagOutput TargetsrootA1not applicableA1xA-x1, A-x2trueA1, A-x1, A-x2x.ynonetrueA1, A-x1, A-x2x.y.zA-xyz1trueA1, A-x1, A-x2, A-xyz1securityA-secfalseA-secsecurity.accessnonetrueA-sec· Layout表示日志输出格式,其通过接口
ch.qos.logback.core#doLayout(E event): String将日志事件格式化为String 返回 。Logback 官方提供 PatternLayout,允许以类似c语言printf来指定输出格式 。
可通过将 layout 与 appender 关联,来实现自定义输出格式和目的地;但并不是每个 appender 都需要 layout,比如负责序列化的 SocketAppender 自然不需要 doLayout 转字符串
· EncoderEncoder的概念在 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) 使用示例
- 引入依赖(
logback-classic背后会自动引入 logback-core、slf4j 等依赖包
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.10</version></dependency>- 基于slf4j用法,获取并使用Logger
public class Sample {private static final Logger LOGGER = LoggerFactory.getLogger(Sample.class);public static void main(String[] args){LOGGER.info("A Message From LOGGER:{}", "Hello World");}}输出:16:55:54.091 [main] INFO logbacktest.Sample - A Message From LOGBACK:Hello World2) logback 配置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 typech.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 整体流程- 获取 filter 链决策
- 应用 basic selection rule
- 创建 LoggingEvent 对象
- 调用 appenders
- 调 Layout 格式化
- 输出到目的地
- 可在值中以 ${KEY:-defaultValue} 的形式引入属性,查找顺序如下:
- 首先在本地作用域查找(详见
<property>) - 若没有,在上下文作用域查找
- 若没有,在JVM系统属性查找
- 最后,在系统环境变量中查找
- 首先在本地作用域查找(详见
- 预定义属性:
- HOSTNAME:系统hostname,是配置时在 context 域中被定义被定义
- CONTEXT_NAME:上下文名
- 一些标签涉及到类的标签(如
<definer>、<appender>、<encoder>),其子标签除了规定之外,还可定义与 JavaBean 属性同名,这将调用相应setter注入 。
属性:
- 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="https://tazarkount.com/read/true">
输出示例:14:28:48.835 [btpool0-7] INFOc.q.l.demo.prime.PrimeAction - 99 is not a valid valuejava.lang.Exception: 99 is invalidat 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]
- <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或多个
- <layout>:0或1个
- <logger>:0或多个,配置 Logger
- name(必须)
- level:[TRACE | DEBUG | INFO | WARN | ERROR | ALL | OFF],或者 INHERITED / NULL 表示从上级继承 。
- additivity:[true | false]
- 子标签:
- <appender-ref> :0或多个,表附加appender
- ref:指定先前的名称
- <appender-ref> :0或多个,表附加appender
- <root>:配置根Logger
- level:根Logger级别不能设置为 INHERITED / NULL
- 子标签:
- <appender-ref>
- logback.configurationFile:指定配置文件位置,可以是 URL、类路径资源或外部文件系统 。也可以在代码中设置(System#setProperty),但必须在创建任意Logger实例之前 。
文件扩展名必须是 .xml 或 .groovy - logback.statusListenerClass:可设置为希望注册的 StatusListener 名称
- 转换符 '%' 可后跟规定的word,来获取数据字段,如 logger名称,日期,线程名等
- 转换符可后接格式修饰符(Format modifiers)来指定每个字段最小、最大宽度 以及 是否左对齐
示例:
写法左对齐最小宽度最大宽度%20loggerfalse20none%.30loggerNAnone30%-20.30loggertrue2030 - 括号"()" 可将部分内容分组,常配合格式修饰符使用
如:%d{HH:mm:ss.SSS} [%thread]
输出:13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server13:09:30 [pool-1-thread-1] INFOch.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原名称打印结果%loggermainPackage.sub.sample.BarmainPackage.sub.sample.Bar%logger{0}mainPackage.sub.sample.BarBar%logger{5}mainPackage.sub.sample.Barm.s.s.Bar%logger{16}mainPackage.sub.sample.Barm.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}
- 自定义转换词:
- 自定义实现 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); }} - 声明转换词
<configuration> <conversionRule conversionWord="nanos" converterClass="chapters.layouts.MySampleConverter" /> <!-- … --></configuration>
- 自定义实现 ClassicConverter,重写 convert(ILoggingEvent) 方法
- 类名:C{length} / class{length}
- 文件名:F / file
- 行号:L / line
- 方法名:M / method
- 包含jar包信息的异常stacktrace:xEx{depth} / xException{depth}…
及root异常顺序反转的 rEx{depth} / rootException{depth}…
例:
<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才有意义六、常见需求
- 根据环境变量动态附加Appender
参考:How to select Logback appender based on property file or environment variable- 使用 logback 官方支持的
语法,但同样需要引入 Janino library 。参考:configuration - 为 Appender 设置 <filter>,并使用环境变量语法动态配置Filter的Level【有些曲线救国,应该仍有性能损耗
- 使用 SpringProfile
例:application.yamlspring: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>
- 使用 logback 官方支持的
- 对于嵌套 .xml 配置文件,默认域"local"重复声明的话是无效的,不会覆盖 。
比如在我的logback.xml中声明,无法覆盖Spring自带的配置 。
http://logback.qos.ch/manual/index.html
如有帮助,不妨点下“推荐”;若有问题,欢迎指正讨论 。
作者:SimpleIto
地址:https://www.cnblogs.com/simpleito/p/15133654.html
【Logback 快速入门使用详解】版权:本作品采用 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可 。
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
