logback 架构 Logback 架构 logback的核心依赖有:logback-core,logback-classic 和 logback-access
core: 核心实现,是其他两个包的基础 classic: logback-classic 模块可以被同化为 log4j 1.x 的显着改进版本。此外,logback-classic 本机实现了 SLF4J API
access: 与 Servlet 容器(例如 Tomcat 和 Jetty)集成,以提供 HTTP 访问日志功能
配置 Logback.xml配置的两个重要标签:Logger
,Appender
logger: 指定日志记录根(全限定类名)和appender的关联 appender: 日志的具体输出实现,例如: 控制台输出、文件输出等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 示例配置 <configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="console" value="==\n[%-5level] %red(%d{HH:mm}) Thread:[%thread] Method:%green(%M) %cyan(%X{traceId}) classpath:%c \n%highlight(return):%m%n"></property> <property name="log_dir" value="./data/log"></property> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${console}</pattern> <charset>utf8</charset> </encoder> </appender> <!--html格式日志文件输出appender--> <appender name="SERVICE_APPENDER" class="ch.qos.logback.core.FileAppender"> <!--日志文件保存路径--> <file>${log_dir}/logback.html</file> <!--html 消息格式配置--> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="ch.qos.logback.classic.html.HTMLLayout"> </layout> </encoder> </appender> <appender name="All_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log_dir}/All/demo.log</file> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log_dir}/All/demo.%d{yyyy-MM-dd}.log</fileNamePattern> </rollingPolicy> </appender> <!-- </appender>--> <root level="DEBUG"> <appender-ref ref="STDOUT"/> <appender-ref ref="All_APPENDER"></appender-ref> <appender-ref ref="SERVICE_APPENDER"/> </root> <logger name="org/example" level="ERROR" additivity="true"> <appender-ref ref="SERVICE_APPENDER"/> </logger> </configuration>
官网文档阅读 文档首页
依赖导入说明
ps: 以下阅读并非纯粹的搬运、翻译,而是强调某些值得注意的地方。
Chapter 1: Introduction 1,logback内部状态打印 1 2 3 4 5 6 7 import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.core.util.StatusPrinter2; LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); new StatusPrinter2().print(lc);
注意,上面使用的输出类为StatusPrinter2()
,将打印logback上下文运状态,例如对配置文件的使用等,用于诊断logback的相关问题,且注意,
Chapter 2: Architecture 1,依赖架构
[!NOTE] 官网描述 _核心_模块为其他两个模块奠定了基础。 经典_模块扩展_了 core 。classic 模块对应于 log4j 的显著改进版本。Logback-classic 原生实现了 SLF4J API ,以便您可以轻松地在 logback 和其他日志记录系统之间来回切换,例如 JDK 1.4 中引入的 log4j 或 java.util.logging (JUL)。第三个模块称为 access ,它与 Servlet 容器集成以提供 HTTP 访问日志功能。一个单独的文档涵盖了 Access Module 文档 。
(1)Logback-classic 原生实现了 SLF4J API 这句话在api层面的表现为
1 2 3 4 import ch.qos.logback.classic.Logger; import org.slf4j.LoggerFactory; Logger logger =(Logger) LoggerFactory.getLogger("chapters.introduction.HelloWorld1"); logger.debug("Hello world.");
在ch.qos.logback.classic.Logger
实现看到实现了org.slf4j.Logger
这个接口,这就是代表他在扩展功能的同时,仍然支持原有的日志门面的功能,也就是在 logback 和其他日志记录系统之间来回切换 。
2,appender和layout 布局负责根据用户的意愿格式化日志记录请求,而 appender 负责将格式化的输出发送到其目的地。
默认配置:
3,关于参数构造成本的优化 目前好像无论是slf4j,还是logback-classic的logger都支持参数传递
1 2 3 logger.debug("The new entry is "+entry+"."); logger.debug("The new entry is {}.", entry);
第一种写法会先构造message造成额外浪费,而第二种会在真正需要打印debug日志时,才会拼接。
4,info调用的关键节点
1, 获取过滤器链决策
2,应用基本选择规则
3, 创建 LoggingEvent
对象: 该对象包含要打印的各种数据,
4,从logger context中获取 appender,并执行(并非执行完成,而是进入下一步)
5, 格式化输出:部分需要将LoggingEvent
委托给布局进行输出,部分不需要。
该步骤貌似是格式化一个完整的日志事件,包含输出的目的地等
6,发送 LoggingEvent
ps: 如何找到或者定义每个阶段?
Chapter 3: Logback configuration 1,Configurator 全限定类名为:import ch.qos.logback.classic.spi.Configurator;
默认实现有三个:
BasicConfigurator: 最基本的默认实现,将输出指向控制台
DefaultJoranConfigurator: 依次寻找logback-test.xml
、logback.xml
。
SerializedModelConfigurator: 将于 2025 年 7 月 1 日从初始化序列中删除。
自定义实现:
实现import ch.qos.logback.classic.spi.Configurator;
文件资源位于 META-INF/services/ch.qos.logback.classic.spi.Configurator
,内容是自定义类的全限定类名
加载顺序: 只要找到一个实现就不会继续向下执行
1,自定义
2,SerializedModelConfigurator
3,DefaultJoranConfigurator
4,BasicConfigurator
自定义 1,一个自定义的加载器应当具有以下格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class MyConfigurator extends ContextAwareBase implements Configurator { @Override public ExecutionStatus configure(LoggerContext context) { 1,加载配置文件 ClassLoader myClassLoader= Loader.getClassLoaderOfObject(this); URL resource = getResource(configFile, myClassLoader); 2,处理加载文件,并判断是否该加载器是否运行成功 if(resource==null){ return ExecutionStatus.INVOKE_NEXT_IF_ANY; //寻找其他 } try { configureByResource(resource); } catch (JoranException e) { throw new RuntimeException(e); } addInfo("自定义配置: logback-spring.xml 加载成功,"); return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY; //停止寻找其他 }
在以上自定义的过程中需要注意两点 1,适当的为上下文状态插入日志,也就是ContextAwareBase
接口下实现的方法 2,ExecutionStatus菜单类的返回值,该返回值帮助调用者判断下一步该如何执行。
2,上下文状态监听器
编码控制,动态添加: 由于无法获取添加之前的上下文状态,不去考虑
在配置文件使用使用标签<statusListener>
指定ch.qos.logback.core.status.StatusListener
的实现类
可以自定义实现也可以使用官方的实现,且注意,该监听器并不能融入自定义的logger机制,他们只是对于上下文状态的日志监听!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 logback.xml <configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="console" value="==\n[%-5level] %red(%d{HH:mm}) Thread:[%thread] Method:%green(%M) %cyan(%X{traceId}) classpath:%c \n%highlight(return):%m%n"></property> <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" /> <statusListener class="ch.qos.logback.core.status.OnFileStatusListener" /> <root level="DEBUG"> <appender-ref ref="STDOUT"></appender-ref> </root> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${console}</pattern> <charset>utf8</charset> </encoder> </appender></configuration>
3,停止classic
[!NOTE] Title 自1.1.10版本起,Logback-classic将自动请求Web服务器安装一个实现ServletContainerInitializer接口的LogbackServletContainerInitializer(在servlet-api 3.x及以后版本中可用)。这个初始化器反过来会安装一个LogbackServletContextListener的实例。当Web应用程序停止或重新加载时,这个监听器将停止当前的logback-classic上下文。
具体实现上,则是通过shutdown
钩子实现的,且在1.5.18版本上,只有一个钩子ch.qos.logback.core.hook.
这种关闭方式在底层的逻辑中关键语句为: loggerContext.stop(); ,即关闭整个logback,那么同样也就是关闭了classic。
混淆点:
logbackContext并不是核心包的内容,或者说在真正使用中,单独的核心包并不能完成日志功能。 ch.qos.logback.classic.LoggerContext
仔细排查之后发现,加载外部xml配置的Configurator都是classic的内容。
xml配置语法 ![[Pasted image 20250514154750.png]]
ps: 有点长,等待阅读,给出一个我个人的控制台输出配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <property name="console" value="==\n[%-5level] %red(%d{HH:mm}) Thread:[%thread] Method:%green(%M) %cyan(%X{traceId}) classpath:%c \n%highlight(return):%m%n"></property> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${console}</pattern> <charset>utf8</charset> </encoder></appender> <root level="DEBUG"> <appender-ref ref="STDOUT"></appender-ref> </root> <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" /> <statusListener class="ch.qos.logback.core.status.OnFileStatusListener" />