湘潭建设企业网站,优化防疫政策,上海多家商场调整营业时间,合肥市建设通网站一、简介
Java 开源日志框架#xff0c;以继承改善 log4j 为目的而生#xff0c;是 log4j 创始人 Ceki Glc 的开源产品。 它声称有极佳的性能#xff0c;占用空间更小#xff0c;且提供其他日志系统缺失但很有用的特性。 其一大特色是#xff0c;在 logback-classic 中本…一、简介
Java 开源日志框架以继承改善 log4j 为目的而生是 log4j 创始人 Ceki Gülcü 的开源产品。 它声称有极佳的性能占用空间更小且提供其他日志系统缺失但很有用的特性。 其一大特色是在 logback-classic 中本地(native)实现了 SLF4J API也表示依赖 slf4j-api
二、架构 / Logback知识
1. 项目分为三个模块
logback-core其他俩模块基础模块作为通用模块 其中没有 logger 的概念logback-classic日志模块完整实现了 SLF4J APIlogback-access配合Servlet容器提供 http 访问日志功能
2. 在 logback 中主要概念Logger、Appender、Layout、Encoder
· Logger
日志记录器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 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 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方法可被附加多个 appenderappender 同样适用于继承结构且是以追加的方式而非覆盖 但继承行为可被 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 转字符串
· 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) 使用示例
引入依赖 logback-classic 背后会自动引入 logback-core、slf4j 等依赖包
dependencygroupIdch.qos.logback/groupIdartifactIdlogback-classic/artifactIdversion1.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 LOGBACKHello 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 nameSTDOUT classch.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
/appenderroot leveldebug
appender-ref refSTDOUT /
/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.BasicConfigurator5f16132a - Setting up default configuration.四、log 整体流程
获取 filter 链决策应用 basic selection rule创建 LoggingEvent 对象调用 appenders调 Layout 格式化输出到目的地
五、配置详解
1.配置文件
一些写法/背景知识 可在值中以 ${KEY:-defaultValue} 的形式引入属性查找顺序如下 首先在本地作用域查找详见property若没有在上下文作用域查找若没有在JVM系统属性查找最后在系统环境变量中查找 既支持名称(KEY)中的嵌套也支持值/默认值的嵌套引用 预定义属性 HOSTNAME系统hostname是配置时在 context 域中被定义被定义CONTEXT_NAME上下文名 一些标签涉及到类的标签如definer、appender、encoder其子标签除了规定之外还可定义与 JavaBean 属性同名这将调用相应setter注入。
顶级标签 属性 debug获知 Logback 内部状态官方推荐在上设置 debug属性而非在代码中调用 StatusPrinter。例 configuration debugtrue这也等同于设置状态监听器 OnConsoleStatusListener 例 configurationstatusListener classch.qos.logback.core.status.OnConsoleStatusListener / !-- … --
/configurationscan / scanPeriod可定期扫描配置文件的更改并在更改时自动应用。默认每分钟一次 例configuration scantrue scanPeriod30 seconds packagingData可令每一行StackTrace输出其对应jar包。需注意其计算成本高昂 例 configuration packagingDatatrue输出示例 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]子标签
从另外的文件引入配置目标文件必须将其标签放入下。SpringBoot基础配置便是如此可参考spring-boot:2.4.0包中base.xml fileresourceurloptional[true | false]默认若找不到目标文件将输出警告可设置为可选避免该行为 设置上下文名称可作为区分不同多个应用程序到同一target的区分默认为default 示例
contextNamemyAppName/contextName
appender nameSTDOUT classch.qos.logback.core.ConsoleAppenderencoderpattern%d %contextName [%t] %level %logger{36} - %msg%n/pattern
/encoder
/appender配置或引入外部属性别名 namevaluefile引用文件系统的 .properties 文件resource引用类路径上的 variables.properties 文件scope local默认会在配置解释时定义并在结束后清除。context上下文作用域属性将插入到LoggerContext中直到LoggerContext被清除因此在所有日志事件中都可用。system系统作用域属性将插入到JVM系统属性中 代码动态定义属性以 PropertyDefiner#getPropertyValue 方法返回其值 nameclassPropertyDefiner实现全类名 自定义转换词 conversionWord转换词converterClassClassicConverter 实现类全类名 - *name声明Appender名称 - *class要使用的Appender的完全限定名 - 、子标签 - 0或1个 - class若未声明表示 PatternLayout - 0或多个 - class若未声明表示 PatternLayoutEncoder - 0或多个 0或多个配置 Logger name必须level[TRACE | DEBUG | INFO | WARN | ERROR | ALL | OFF]或者 INHERITED / NULL 表示从上级继承。additivity[true | false]子标签 0或多个表附加appender ref指定先前的名称 配置根Logger level根Logger级别不能设置为 INHERITED / NULL子标签
2.JVM系统属性
logback.configurationFile指定配置文件位置可以是 URL、类路径资源或外部文件系统。也可以在代码中设置System#setProperty但必须在创建任意Logger实例之前。 文件扩展名必须是 .xml 或 .groovylogback.statusListenerClass可设置为希望注册的 StatusListener 名称
3. PatternLayout 的格式化消息编写规则
基础规则 转换符 ‘%’ 可后跟规定的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 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原名称打印结果%loggermainPackage.sub.sample.BarmainPackage.sub.sample.Bar%loggermainPackage.sub.sample.BarBar%loggermainPackage.sub.sample.Barm.s.s.Bar%loggermainPackage.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%date14:06:49.812%date20 oct. 2006;14:06:49.812%date 换行符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 正则替换replace§{r,t} 将消息模式p中的r替换为t 如%replace(%logger %msg){\., /}将所有.“替换为”/ MDCMapped Diagnostic Contex字段%X{filedName} 自定义转换词 自定义实现 ClassicConverter重写 convert(ILoggingEvent) 方法 public class MySampleConverter extends ClassicConverter {long start System.nanoTime();Overridepublic String convert(ILoggingEvent event) {long nowInNanos System.nanoTime();return Long.toString(nowInNanos-start);}
}声明转换词 configurationconversionRule conversionWordnanos converterClasschapters.layouts.MySampleConverter /!-- … --
/configuration性能考虑应避免使用的转换词
类名C{length} / class文件名F / file行号L / line方法名M / method包含jar包信息的异常stacktracexEx{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 下始终报错即便引入了推荐版本 仍然报错
dependencygroupIdorg.fusesource.jansi/groupIdartifactIdjansi/artifactIdversion1.17/version
/dependency5.异步Appender
可通过声明AsyncAppender来执行异步日志打印它只进行日志事件分发因此必须引用另一个实际Appender才有意义
六、常见需求 根据环境变量动态附加Appender 参考 How to select Logback appender based on property file or environment variable 使用 logback 官方支持的 语法但同样需要引入 Janino library。参考configuration 为 Appender 设置 并使用环境变量语法动态配置Filter的Level【有些曲线救国应该仍有性能损耗 使用 SpringProfile 例 application.yaml
spring:profiles:active:- ${ENV:classiclogs}logback.xml
configuration!-- appender conf…--springProfile namejsonlogsroot levelinfoappender-ref refstdout-json //root/springProfilespringProfile nameclassiclogsroot levelinfoappender-ref refstdout-classic //root/springProfile
/configuration七、踩坑
对于嵌套 .xml 配置文件默认域local重复声明的话是无效的不会覆盖。 比如在我的logback.xml中声明无法覆盖Spring自带的配置。 撰文参考 http://logback.qos.ch/manual/index.html