主页 > 创业  > 

Java日志

Java日志

“凌晨三点的调试现场,曾续缘的技术锦囊准时上线!这是你今晚第N次搜索解决方案?点击关注,下次遇到难题直接来主页搜答案💡”

Java日志发展历程

Java日志系统的实现是Java生态系统中的一个重要组成部分,其发展历程反映了Java社区对日志记录需求的不断演进和改进。

早期Java日志(Java 1.0 - 1.3)

在Java的早期版本中,日志功能相对较弱,开发人员通常使用System.out.println或System.err.println来打印信息,这种方法简单但缺乏灵活性,无法满足生产环境中对日志管理的需求。

Java Logging API(Java 1.4)

2002年,Java 1.4发布,引入了java.util.logging(JUL)作为Java标准库的一部分,这是Java官方提供的日志框架。JUL提供基本的日志功能,包括日志级别控制、日志处理器的配置等,但它在企业级应用中的表现并不十分突出,因为它的功能相对有限,且扩展性不如其他框架。

Log4j

在Java官方日志API出现之前,Log4j就已经成为Java社区广泛使用的日志框架。Log4j由Ceki Gülcü创建,提供了丰富的功能,如灵活的配置、多种日志输出目的地、以及强大的日志级别和过滤器设置。Log4j很快成为了Java日志的事实标准。

Commons Logging

为了解决不同日志框架之间的兼容性问题,Apache推出了Commons Logging(JCL)。它提供了一个日志抽象层,允许开发者使用统一的接口,底层可以切换不同的日志实现,如Log4j或JUL。

SLF4J 和 Logback

Ceki Gülcü创建了另一个日志抽象层——SLF4J(Simple Logging Facade for Java),以及一个新的实现——Logback。SLF4J与Commons Logging类似,但它提供了更好的类型安全,并且能够更简单地与实际的日志框架绑定。Logback作为Log4j的替代品,提供了更好的性能和更丰富的功能。

Log4j2

随着时间的推移,Log4j被升级为Log4j2,它提供了更快的性能、更好的API设计、以及强大的插件和配置系统。Log4j2在许多方面都是对Logback的直接改进,包括在锁的开销、垃圾收集的压力等方面。

现代日志框架的发展

随着微服务、容器化和云原生应用的发展,日志系统也不断进化。例如,日志系统开始支持结构化日志输出,便于与日志分析工具集成,支持日志的集中管理和分析。

日志抽象

Spring Boot的日志抽象由spring-boot-starter-logging模块提供,它依赖于Logback和SLF4J。SLF4J是日志框架的抽象层,它允许我们在部署时切换具体的日志实现。而Logback是SLF4J的实现,也是Spring Boot的默认日志框架。

spring-boot-starter-logging 是 Spring Boot 的一个起步依赖(starter),它为 Spring Boot 应用程序提供了一套完整的日志解决方案。这个模块包含了日志框架的抽象层 SLF4J 和 Logback,它们共同构成了 Spring Boot 默认的日志框架。

SLF4J(Simple Logging Facade for Java)

SLF4J 是一个抽象层,它提供了统一的日志接口,允许开发者使用统一的编程接口,而无需关心底层的日志实现。这样做的目的是为了在部署时能够灵活地切换不同的日志框架,例如 Logback、Log4j 或 java.util.logging,而不需要修改代码。

SLF4J 的主要组件包括:

SLF4J API:提供日志记录的接口和抽象类。SLF4J binding:将 SLF4J API 绑定到具体的日志实现框架上,如 logback-classic 或 log4j-over-slf4j。SLF4J bridges:允许将现有的日志框架(如 java.util.logging、Log4j)转换为 SLF4J,从而可以在不修改代码的情况下迁移到 SLF4J。 Logback

Logback 是 SLF4J 的原生实现,由 Log4j 的原作者 Ceki Gülcü 开发。Logback 提供了丰富的特性,包括自动重新加载配置文件、高级过滤器和格式化器等。Logback 的性能优于 Log4j,特别是在垃圾收集和同步开销方面。

Logback 的主要组件包括:

logback-classic:实现了 SLF4J API,是 Logback 的核心模块。logback-core:提供了 Logback 的核心功能,如日志管理、过滤器、日志滚动等。logback-access:与 Servlet 容器集成,提供了 HTTP 访问日志的功能。 Spring Boot 中的日志抽象

在 Spring Boot 中,spring-boot-starter-logging 负责自动配置日志系统。当我们添加了这个起步依赖到我们的项目中时,Spring Boot 会自动配置 Logback 作为日志框架。Spring Boot 的自动配置会根据应用程序的属性和类路径上的库来配置日志系统。

Spring Boot 还提供了一个名为 LoggerFactory 的工厂类,它用于创建 Logger 实例。在运行时,LoggerFactory 会绑定到具体的日志实现上,例如 Logback。

使用 Spring Boot 日志抽象

在 Spring Boot 应用程序中,可以通过以下方式来使用日志:

import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MySpringBootApplication { private static final Logger logger = LoggerFactory.getLogger(MySpringBootApplication.class); public static void main(String[] args) { logger.info("Hello, World!"); } }

在这个例子中,我们通过 LoggerFactory 获取了一个 Logger 实例,然后使用它来记录一条信息级别的日志消息。由于 Spring Boot 默认使用 Logback,这个 Logger 实例实际上是 Logback 的实例。

通过这种方式,应用程序代码只需要与 SLF4J API 交互,而无需关心底层的日志实现。这使得应用程序更加灵活,可以在不修改代码的情况下切换到不同的日志框架。

日志配置

Spring Boot允许通过外部配置文件来配置日志,这些配置文件可以是application.properties或application.yml。我们可以在配置文件中设置日志级别、日志输出格式、日志文件路径等。

日志级别配置

在 Spring Boot 中,我们可以为不同的日志记录器(loggers)设置日志级别。日志级别决定了哪些日志消息会被记录下来。常见的日志级别包括:

TRACE: 最详细的日志级别,用于诊断问题。DEBUG: 用于调试和诊断问题。INFO: 用于常规信息,默认级别。WARN: 用于警告信息,表示潜在的问题。ERROR: 用于错误信息,表示已经发生的问题。OFF: 禁用所有日志输出。

在 application.properties 或 application.yml 文件中,我们可以这样设置日志级别:

application.properties 示例:

# 设置所有日志记录器的日志级别为 INFO logging.level.root=INFO # 设置 org.springframework.web 包的日志级别为 DEBUG logging.level.org.springframework.web=DEBUG # 设置 org.hibernate 包的日志级别为 ERROR logging.level.org.hibernate=ERROR

application.yml 示例:

logging: level: root: INFO org.springframework.web: DEBUG org.hibernate: ERROR 日志输出格式配置

Spring Boot 允许开发者自定义日志输出格式。默认的日志输出格式通常包括以下信息:

时间戳:日志消息发生的时间。日志级别:消息的级别,如 INFO、WARN 等。进程 ID:正在运行的应用程序的进程 ID。线程名:生成日志消息的线程名。日志消息:实际的日志信息。

日志输出格式决定了日志消息在控制台或日志文件中的显示方式。Spring Boot 允许我们自定义日志输出格式。例如,在 application.properties 中:

# 设置日志输出格式 logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

在 application.yml 中:

logging: pattern: console: '%d{yyyy-MM-dd HH:mm:ss} - %msg%n' file: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n'

在这里,%d 表示日期和时间,%msg 表示日志消息,%n 表示换行符,%thread 表示线程名,%-5level 表示日志级别,%logger{36} 表示日志记录器名。

日志文件配置

Spring Boot 还允许我们配置日志文件的位置和名称。例如:

# 设置日志文件名(如果不设置,默认为 spring.log) logging.file.name=myapp.log # 设置日志文件路径(如果同时设置了 logging.file.name,则此设置无效) logging.file.path=/var/log

在 application.yml 中:

logging: file: name: myapp.log path: /var/log 日志分组配置

日志分组功能允许我们将多个相关的日志记录器归为一个组,并为这个组设置统一的日志级别。例如:

# 定义一个名为 "Tomcat" 的日志组,包含两个日志记录器 logging.group.tomcat=org.apache.catalina,org.apache.coyote # 设置 "Tomcat" 组的日志级别为 WARN logging.level.tomcat=WARN

在 application.yml 中:

logging: group: tomcat: - org.apache.catalina - org.apache.coyote level: tomcat: WARN 自定义日志配置

如果需要更高级的日志配置,Spring Boot 支持自定义 Logback、Log4j2 或 Java Util Logging 的配置文件。

只需要在类路径下提供相应的配置文件,Spring Boot 就会自动加载它。

对于 Logback,我们可以提供 logback-spring.xml 或 logback.xml 文件。对于 Log4j2,我们可以提供 log4j2-spring.xml 或 log4j2.xml 文件。对于 Java Util Logging,我们可以提供 logging.properties 文件。

这些自定义配置文件允许我们进行更详细的配置,例如设置日志滚动策略、定义复杂的日志过滤规则等。

日志切分配置

日志切分是一种管理日志文件的技术,它允许我们根据时间或文件大小来分割日志文件。这样做的好处包括:

避免单个日志文件过大:大型的日志文件难以管理和分析。便于日志归档:可以按时间顺序存储和检索日志文件。方便日志轮换:可以定期清理旧的日志文件,以节省磁盘空间。

要在 Spring Boot 中配置日志切分,我们需要在 Logback 的配置文件中定义一个 RollingFileAppender,并设置 SizeAndTimeBasedRollingPolicy。

logback-spring.xml 示例:

<configuration> <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>myapp.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!-- 日志文件的名字会根据时间和大小来命名 --> <fileNamePattern>myapp-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 每个日志文件的最大大小 --> <maxFileSize>100MB</maxFileSize> <!-- 日志文件保留的最长时间,这里设置为30天 --> <maxHistory>30</maxHistory> <!-- 总的日志文件大小限制,这里设置为3GB --> <totalSizeCap>3GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="ROLLING" /> </root> </configuration>

在这个配置中:

fileNamePattern 定义了日志文件的命名模式,包括日期和索引 %i。maxFileSize 设置了单个日志文件的最大大小,超过这个大小就会触发切分。maxHistory 设置了日志文件保留的最长时间,超过这个时间范围的日志文件将被删除。totalSizeCap 设置了所有日志文件的总大小限制,超过这个限制的日志文件将被删除。 日志切分的触发条件

日志切分会基于以下条件触发:

日志文件大小:当当前日志文件的大小超过 maxFileSize 指定的值时,日志文件会被切分。时间:每天一个新的日志文件会被创建,这是通过 fileNamePattern 中的日期格式 %d{yyyy-MM-dd} 实现的。 日志文件的命名和索引

在日志切分时,Logback 会在文件名中添加一个索引 %i,以区分不同的日志文件。例如,如果我们的日志文件名为 myapp.log,切分后的文件名可能为 myapp-2023-04-01.0.log、myapp-2023-04-01.1.log 等。每个索引代表一个切分后的文件。

日志文件的清理

Logback 会根据 maxHistory 和 totalSizeCap 的设置来清理旧的日志文件。maxHistory 控制日志文件的保留时间,而 totalSizeCap 控制所有日志文件的总大小。

日志文件配置选项 配置元素类别配置元素描述根配置元素<configuration>配置文件的根元素。配置文件属性<property>定义属性,可以在配置文件中复用。配置文件变量<variable>定义变量,可以在配置文件中复用。Appender<appender>定义日志的输出目的地。<ConsoleAppender>控制台输出。<FileAppender>文件输出。<RollingFileAppender>滚动文件输出。<SocketAppender>远程日志输出。<SMTPAppender>通过 SMTP 发送日志邮件。Encoder<encoder>定义日志的格式。<PatternLayout>定义日志输出的格式模式。RollingPolicy<rollingPolicy>定义日志文件滚动策略。<TimeBasedRollingPolicy>基于时间的滚动策略。<SizeAndTimeBasedRollingPolicy>基于大小和时间的滚动策略。TriggeringPolicy<triggeringPolicy>定义日志文件触发的策略。<SizeBasedTriggeringPolicy>基于文件大小的触发策略。Logger<logger>定义特定包或类的日志级别。<root>定义根日志级别。Filter<filter>定义日志过滤器。<ThresholdFilter>基于日志级别的过滤器。<RegexFilter>基于正则表达式的过滤器。<LevelFilter>基于日志级别的过滤器。转换器<conversionRule>定义自定义的转换规则。

以下是一个包含多个配置选项的 logback-spring.xml 示例:

<configuration> <!-- 定义属性 --> <property name="LOG_PATH" value="/home/generator"/> <property name="LOG_NAME" value="generator.log"/> <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} - %msg%n"/> <!-- 控制台输出 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${LOG_PATTERN}</pattern> </encoder> </appender> <!-- 文件输出 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_PATH}/${LOG_NAME}</file> <encoder> <pattern>${LOG_PATTERN}</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!-- 日志文件的名字会根据时间和大小来命名 --> <fileNamePattern>${LOG_PATH}/log-archives/generator-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 每个日志文件的最大大小 --> <maxFileSize>100MB</maxFileSize> <!-- 日志文件保留的最长时间,这里设置为30天 --> <maxHistory>30</maxHistory> <!-- 总的日志文件大小限制,这里设置为3GB --> <totalSizeCap>3GB</totalSizeCap> </rollingPolicy> </appender> <!-- 根日志级别 --> <root level="INFO"> <appender-ref ref="FILE"/> </root> <!-- 特定包的日志级别 --> <logger name="org.springframework.web" level="DEBUG"/> <logger name="com.example" level="DEBUG"/> <!-- 过滤器示例 --> <appender name="FILTERED_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/filtered.log</file> <encoder> <pattern>${LOG_PATTERN}</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logs/filtered-%d{yyyy-MM-dd}.log</fileNamePattern> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> </configuration>

主要解释:

<pattern>配置:这个配置使得日志输出时,每条日志消息都会以 日期时间 - 日志消息 的格式显示,并且每条消息之间会换行。<file> 配置:应用程序启动时会创建一个名为 generator.log 的文件,位于 /home/generator/ 目录下。<fileNamePattern> 配置:这个配置表示日志文件会根据日期和索引进行滚动。例如,如果当前活动日志文件达到 100MB,它会被重命名为 generator-2023-10-01.0.log,然后创建一个新的 generator.log 文件继续记录日志。 日志系统切换

虽然Spring Boot默认使用Logback,但我们也可以切换到其他日志系统,如Log4j2。要做到这一点,我们需要从spring-boot-starter-logging中排除Logback,并添加我们选择的日志系统的依赖。

在 Spring Boot 中,虽然 Logback 是默认的日志框架,但我们可以根据项目需求切换到其他日志系统,如 Log4j2。这种切换通常涉及到改变项目的依赖配置,以便排除默认的 Logback 依赖,并添加所选日志系统的依赖。

排除 Logback 依赖

首先,我们需要从 spring-boot-starter-logging 中排除 Logback 的依赖。这可以通过在项目的构建配置文件中(如 Maven 的 pom.xml 或 Gradle 的 build.gradle)显式地排除 Logback 相关的依赖来实现。

Maven pom.xml 示例:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> <exclusions> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusion> </exclusion> </exclusions> </dependency>

Gradle build.gradle 示例:

dependencies { implementation('org.springframework.boot:spring-boot-starter-logging') { exclude group: 'ch.qos.logback', module: 'logback-classic' } } 添加 Log4j2 依赖

在排除 Logback 之后,我们需要添加 Log4j2 的依赖。Spring Boot 提供了一个名为 spring-boot-starter-log4j2 的起步依赖,它包含了 Log4j2 和必要的配置。

Maven pom.xml 示例:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>

Gradle build.gradle 示例:

dependencies { implementation 'org.springframework.boot:spring-boot-starter-log4j2' } 配置 Log4j2

一旦添加了 Log4j2 的依赖,Spring Boot 会自动配置 Log4j2 作为日志系统。我们可以通过在 application.properties 或 application.yml 文件中设置相应的属性来配置 Log4j2。

application.properties 示例:

logging.level.root=INFO logging.level.org.springframework.web=DEBUG logging.level.org.hibernate=ERROR 注意事项 当我们切换到 Log4j2 时,确保移除了所有 Logback 的配置文件,如 logback.xml 或 logback-spring.xml。如果我们使用的是 Log4j2 的 XML 或 YAML 配置文件,确保它们在类路径的根目录下。在某些情况下,可能需要手动配置 Log4j2,例如在 log4j2.xml 文件中定义日志 appenders 和 loggers。

参考链接:

developer.aliyun /article/1090032

参考链接: cengxuyuan

标签:

Java日志由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Java日志