banner
NEWS LETTER

logback官方文档阅读(一)

Scroll down

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配置的两个重要标签:LoggerAppender

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 负责将格式化的输出发送到其目的地。

默认配置:

1

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.xmllogback.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" />
其他文章