当前位置: 首页 > news >正文

Spring Boot项目集成日志系统使用完整指南

Spring Boot项目集成日志系统使用指南

目录

  • Java日志系统简介
  • 日志类型详解
  • Spring Boot日志配置
  • 项目实际配置分析
  • 重难点分析
  • 最佳实践建议

Java日志系统简介

1. 日志系统的作用

日志系统是软件开发中不可或缺的组成部分,主要用于:

  • 问题诊断: 记录程序运行状态和错误信息
  • 性能监控: 记录方法执行时间和资源使用情况
  • 审计追踪: 记录用户操作和系统行为
  • 运维支持: 提供系统运行状态和异常信息

2. Java日志框架发展历程

Java 1.4 (2002) → Logging API (内置)↓
Apache Log4j 1.x (2001-2015)↓
SLF4J + Logback (2006-至今) ← 推荐使用↓
Log4j 2.x (2012-至今) ← 高性能选择

3. 主流日志框架对比

框架优势劣势适用场景
Log4j 1.x成熟稳定,配置灵活已停止维护,性能一般老项目维护
Log4j 2.x性能优秀,功能丰富配置相对复杂高性能要求
Logback性能好,配置简单功能相对简单Spring Boot默认
SLF4J抽象层,统一接口需要配合具体实现框架集成

日志类型详解

1. 日志级别 (Log Levels)

1.1 标准日志级别
// 从低到高的日志级别
TRACE < DEBUG < INFO < WARN < ERROR < FATAL// 实际使用中的日志级别
DEBUG  // 调试信息,开发环境使用
INFO   // 一般信息,记录程序运行状态
WARN   // 警告信息,潜在问题但不影响运行
ERROR  // 错误信息,程序异常但可恢复
1.2 日志级别使用场景
@Log4j2
public class UserService {public User getUserById(Long id) {// DEBUG: 详细的调试信息log.debug("开始查询用户,ID: {}", id);try {User user = userMapper.selectById(id);// INFO: 重要的业务信息log.info("成功查询用户: {}", user.getUsername());return user;} catch (Exception e) {// ERROR: 异常信息log.error("查询用户失败,ID: {}, 错误: {}", id, e.getMessage(), e);throw new RuntimeException("用户查询失败", e);}}
}

2. 日志输出目标 (Appenders)

2.1 控制台输出
<!-- Logback配置 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder>
</appender>
2.2 文件输出
<!-- 滚动文件输出 -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>./logs/application.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>./logs/application.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder>
</appender>
2.3 数据库输出
<!-- 数据库输出 -->
<appender name="db" class="ch.qos.logback.classic.db.DBAppender"><connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource"><driverClass>com.mysql.cj.jdbc.Driver</driverClass><url>jdbc:mysql://localhost:3306/logs</url><user>root</user><password>password</password></connectionSource>
</appender>

3. 日志格式 (Patterns)

3.1 常用格式占位符
<!-- 标准日志格式 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern><!-- 格式说明 -->
%d{yyyy-MM-dd HH:mm:ss.SSS}  <!-- 时间戳 -->
[%thread]                     <!-- 线程名 -->
%-5level                      <!-- 日志级别,左对齐5位 -->
%logger{36}                   <!-- 类名,最大36字符 -->
%msg                          <!-- 日志消息 -->
%n                            <!-- 换行符 -->
3.2 自定义格式示例
<!-- 包含MDC信息的格式 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%X{userId}] %-5level %logger{36} - %msg%n</pattern><!-- 包含调用位置的格式 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}:%line - %msg%n</pattern>

Spring Boot日志配置

1. Spring Boot日志自动配置

1.1 默认配置

Spring Boot默认使用Logback作为日志实现,提供以下自动配置:

# application.yml
logging:level:root: INFOcom.zmy.enrollment: DEBUGorg.springframework.web: WARNpattern:console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"file:name: ./logs/application.logmax-size: 10MBmax-history: 30
1.2 依赖配置
<!-- Spring Boot Starter Web 自动包含日志依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- 显式添加日志依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId>
</dependency>

2. 项目实际配置分析

2.1 主配置文件 (application.yml)
# Logger Config
logging:level:com:baomidou:mybatisplus: ERROR      # MyBatis Plus日志级别zmy:enrollment: DEBUG       # 项目业务日志级别org:springframework:web:client: ERROR         # Spring Web客户端日志级别springfox:documentation: ERROR      # Swagger文档日志级别
2.2 Logback配置文件 (logback-spring.xml)
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false"><contextName>logback</contextName><!-- 控制台输出 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] [%X{traceId}] [%X{userId}-%X{loginName}-%X{username}] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 应用日志文件 --><appender name="file" class="ch.qos.logback.classic.sift.SiftingAppender"><discriminator><Key>systemFlag</Key><DefaultValue>zmbm</DefaultValue></discriminator><sift><appender name="EXTRACTOR_LOG_${systemFlag}" class="ch.qos.logback.core.rolling.RollingFileAppender"><File>./logs/${systemFlag}/application.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>./logs/${systemFlag}/%d{yyyy-MM-dd}/%d{yyyy-MM-dd}-%i.log.gz</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>512MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n</pattern></encoder></appender></sift></appender><!-- 根日志配置 --><root level="info"><appender-ref ref="console" /><appender-ref ref="file" /></root><!-- 特定包日志配置 --><logger name="org.springframework.scheduling" level="info" /><logger name="com.zmy.enrollment.web.base.filter" level="info" /><logger name="com.zmy.enrollment.web.zmbm.task" level="info" />
</configuration>

3. 代码中的日志使用

3.1 Lombok注解使用
// 使用@Log4j2注解
@Log4j2
@RestController
@RequestMapping("/api/user")
public class UserController {@GetMapping("/{id}")public ResponseEntity<User> getUser(@PathVariable Long id) {log.info("查询用户信息,ID: {}", id);try {User user = userService.getUserById(id);log.debug("用户查询成功: {}", user);return ResponseEntity.ok(user);} catch (Exception e) {log.error("查询用户失败,ID: {}, 错误: {}", id, e.getMessage(), e);return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();}}
}// 使用@Slf4j注解
@Slf4j
@Service
public class UserService {public void processUser(User user) {log.info("开始处理用户: {}", user.getUsername());if (log.isDebugEnabled()) {log.debug("用户详细信息: {}", user);}// 业务逻辑处理log.info("用户处理完成: {}", user.getUsername());}
}
3.2 手动创建Logger
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class CustomService {private static final Logger logger = LoggerFactory.getLogger(CustomService.class);public void doSomething() {logger.info("开始执行任务");try {// 业务逻辑logger.debug("任务执行中...");} catch (Exception e) {logger.error("任务执行失败", e);}}
}

项目实际配置分析

1. 多环境日志配置

1.1 开发环境配置
<!-- logback-spring.xml -->
<springProfile name="dev"><root level="debug"><appender-ref ref="console" /><appender-ref ref="file" /></root>
</springProfile>
1.2 生产环境配置
<!-- logback-spring.xml -->
<springProfile name="prod"><root level="warn"><appender-ref ref="file" /><appender-ref ref="traceFile" /></root>
</springProfile>

2. 特殊日志配置

2.1 追踪日志 (Trace Log)
<!-- 追踪日志,用于性能监控 -->
<appender name="traceFile" class="ch.qos.logback.classic.sift.SiftingAppender"><discriminator><Key>systemFlag</Key><DefaultValue>zmbm</DefaultValue></discriminator><sift><appender name="EXTRACTOR_LOG_${systemFlag}" class="ch.qos.logback.core.rolling.RollingFileAppender"><File>/data/logstash/${systemFlag}/trace.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>/data/logstash/${systemFlag}/%d{yyyy-MM-dd}/trace-%d{yyyy-MM-dd}-%i.log.gz</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>512MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><maxHistory>60</maxHistory></rollingPolicy><!-- JSON格式输出,便于ELK分析 --><encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"><providers><pattern><pattern>{"timestamp": "%d{yyyy-MM-dd HH:mm:ss.SSS}","traceId": "%X{traceId}","userId": "%X{userId}","level": "%level","message": "%message"}</pattern></pattern></providers></encoder></appender></sift>
</appender>
2.2 第三方接口日志
<!-- 第三方接口调用日志 -->
<appender name="thirdFile" class="ch.qos.logback.classic.sift.SiftingAppender"><discriminator><Key>systemFlag</Key><DefaultValue>zmbm</DefaultValue></discriminator><sift><appender name="EXTRACTOR_LOG_${systemFlag}" class="ch.qos.logback.core.rolling.RollingFileAppender"><File>./logs/${systemFlag}/thrid.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>./logs/${systemFlag}/%d{yyyy-MM-dd}/thrid-%d{yyyy-MM-dd}-%i.log.gz</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>512MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n</pattern></encoder></appender></sift>
</appender>

3. 日志分类管理

3.1 按业务模块分类
<!-- 不同业务模块使用不同的日志文件 -->
<logger name="com.zmy.enrollment.web.zmbm.activity" level="info" additivity="false"><appender-ref ref="activityFile" />
</logger><logger name="com.zmy.enrollment.web.zmbm.registration" level="info" additivity="false"><appender-ref ref="registrationFile" />
</logger><logger name="com.zmy.enrollment.web.zmbm.lottery" level="info" additivity="false"><appender-ref ref="lotteryFile" />
</logger>
3.2 按日志级别分类
<!-- 错误日志单独输出 -->
<appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>./logs/error.log</file><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>./logs/error.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>90</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder>
</appender>

重难点分析

1. 日志性能优化

难点描述
  • 日志输出对应用性能的影响
  • 大量日志导致的磁盘I/O问题
  • 日志级别判断的性能开销
解决方案
// 使用条件日志,避免不必要的字符串拼接
@Log4j2
public class PerformanceService {public void processData(List<Data> dataList) {// 避免在非DEBUG级别时执行复杂操作if (log.isDebugEnabled()) {log.debug("处理数据列表,数量: {}, 详情: {}", dataList.size(), dataList);}// 使用占位符,避免字符串拼接log.info("开始处理数据,数量: {}", dataList.size());// 异步日志处理log.info("数据处理完成,耗时: {}ms", System.currentTimeMillis() - startTime);}
}
<!-- 异步日志配置 -->
<appender name="asyncFile" class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="file" /><queueSize>512</queueSize><discardingThreshold>0</discardingThreshold>
</appender>

2. 日志文件管理

难点描述
  • 日志文件大小控制
  • 日志文件轮转策略
  • 日志文件清理策略
解决方案
<!-- 时间和大小双重控制的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 按日期滚动 --><fileNamePattern>./logs/application.%d{yyyy-MM-dd}.%i.log</fileNamePattern><!-- 单个文件最大大小 --><maxFileSize>100MB</maxFileSize><!-- 保留天数 --><maxHistory>30</maxHistory><!-- 总大小限制 --><totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>

3. 分布式日志追踪

难点描述
  • 分布式系统中的请求追踪
  • 日志关联和聚合
  • 跨服务调用链追踪
解决方案
// 使用MDC存储追踪信息
@Component
public class LogTraceFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {try {// 生成追踪IDString traceId = UUID.randomUUID().toString();MDC.put("traceId", traceId);// 设置用户信息String userId = getUserId(request);MDC.put("userId", userId);chain.doFilter(request, response);} finally {// 清理MDCMDC.clear();}}
}
<!-- 日志格式包含MDC信息 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%X{userId}] %-5level %logger{36} - %msg%n</pattern>

4. 日志安全控制

难点描述
  • 敏感信息泄露
  • 日志文件权限控制
  • 日志内容脱敏处理
解决方案
// 敏感信息脱敏工具类
@Component
public class LogMaskUtil {public static String maskPhone(String phone) {if (StringUtils.isEmpty(phone) || phone.length() < 7) {return phone;}return phone.substring(0, 3) + "****" + phone.substring(phone.length() - 4);}public static String maskIdCard(String idCard) {if (StringUtils.isEmpty(idCard) || idCard.length() < 10) {return idCard;}return idCard.substring(0, 6) + "********" + idCard.substring(idCard.length() - 4);}
}// 使用脱敏工具
@Log4j2
public class UserService {public void createUser(User user) {// 脱敏后记录日志log.info("创建用户: 姓名={}, 手机={}, 身份证={}", user.getName(), LogMaskUtil.maskPhone(user.getPhone()),LogMaskUtil.maskIdCard(user.getIdCard()));}
}

最佳实践建议

1. 日志级别使用规范

// 推荐的日志级别使用
@Log4j2
public class BestPracticeService {public void processBusinessLogic() {// TRACE: 详细的执行步骤log.trace("进入方法 processBusinessLogic");// DEBUG: 调试信息,开发环境使用log.debug("处理业务逻辑,参数: {}", businessParam);// INFO: 重要的业务节点log.info("开始处理业务,业务ID: {}", businessId);try {// 业务逻辑处理if (log.isDebugEnabled()) {log.debug("业务处理中,当前状态: {}", currentStatus);}// 业务完成log.info("业务处理完成,结果: {}", result);} catch (BusinessException e) {// WARN: 业务异常,可恢复log.warn("业务处理警告,业务ID: {}, 原因: {}", businessId, e.getMessage());throw e;} catch (Exception e) {// ERROR: 系统异常,需要关注log.error("业务处理异常,业务ID: {}, 错误: {}", businessId, e.getMessage(), e);throw new RuntimeException("系统异常", e);}}
}

2. 日志配置优化

<!-- 生产环境推荐配置 -->
<configuration><!-- 异步日志处理 --><appender name="asyncFile" class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="file" /><queueSize>512</queueSize><discardingThreshold>0</discardingThreshold><includeCallerData>false</includeCallerData></appender><!-- 错误日志单独处理 --><appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>./logs/error.log</file><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>./logs/error.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>90</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 根日志配置 --><root level="info"><appender-ref ref="asyncFile" /><appender-ref ref="errorFile" /></root>
</configuration>

3. 日志监控和告警

# 日志监控配置
management:endpoints:web:exposure:include: health,info,metrics,loggersendpoint:loggers:enabled: truehealth:show-details: always# 日志级别动态调整
logging:level:root: INFOcom.zmy.enrollment: INFO# 可以通过Actuator动态调整# POST /actuator/loggers/com.zmy.enrollment# {"configuredLevel": "DEBUG"}

4. 日志分析工具集成

<!-- ELK集成配置 -->
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender"><destination>localhost:5000</destination><encoder class="net.logstash.logback.encoder.LogstashEncoder"><customFields>{"app_name":"enrollment-web","env":"prod"}</customFields></encoder>
</appender><!-- 结构化日志输出 -->
<appender name="jsonFile" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>./logs/application.json</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>./logs/application.%d{yyyy-MM-dd}.json</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"><providers><timestamp/><logLevel/><loggerName/><message/><mdc/><stackTrace/></providers></encoder>
</appender>

总结

本项目采用了完善的日志系统配置,具有以下特点:

1. 多层次日志配置

  • 控制台输出:开发调试使用
  • 文件输出:生产环境持久化
  • 追踪日志:性能监控和问题排查
  • 第三方日志:接口调用记录

2. 灵活的日志管理

  • 按业务模块分类
  • 按日志级别分类
  • 支持动态配置调整
  • 自动文件轮转和清理

3. 性能优化考虑

  • 异步日志处理
  • 条件日志输出
  • 合理的文件大小控制
  • 日志级别过滤

4. 运维友好设计

  • JSON格式输出,便于ELK分析
  • 包含追踪ID,支持分布式追踪
  • 结构化日志,便于监控告警
  • 多环境配置支持

这种日志配置方案既满足了开发调试的需求,又为生产环境的运维监控提供了强有力的支持,是一个值得参考的企业级日志配置实践。

http://www.xdnf.cn/news/1374751.html

相关文章:

  • 欧洲数字化养殖平台 Herdwatch 借力 Iceberg + StarRocks 提升分析能力
  • 嵌入式开发学习 C++:day01
  • 动态规划:硬币兑换(有趣)
  • LeetCode - 739. 每日温度
  • 线性回归原理推导与应用(十一):多重共线性
  • 获取服务器指标的信息
  • bin log 和 redo log有什么区别
  • Mybatis总结
  • 【如何解决Java中的ClassCastException类转换异常问题】
  • 基于Matlab结合肤色检测与卷积神经网络的人脸识别方法研究
  • 基于MATLAB/Simulink的单机带负荷仿真系统搭建
  • 分布式2PC理论
  • 使用 html2canvas + jspdf 实现页面元素下载为pdf文件
  • UE5 查找组件
  • 云原生安全架构设计与零信任实践
  • 预测模型及超参数:1.传统机器学习:SVR与KNN
  • 工业网络安全:保护制造系统和数据
  • HIVE的Window functions窗口函数【二】
  • 【Hadoop】Zookeeper、HBase、Sqoop
  • 全球位置智能软件CR10为73%,市场集中度高
  • Java中高效获取IP地域信息方案全解析:从入门到生产实践
  • jQuery版EasyUI的ComboBox(下拉列表框)问题
  • JS(面试)
  • Proxmox VE 中启用 CentOS 虚拟机的串口终端(xterm.js 控制台)
  • 深度剖析HTTP和HTTPS
  • .NetCore 接入 Nacos,实现配置中心和服务注册
  • 本地windows电脑部署html网页到互联网:html+node.js+ngrok/natapp
  • oracle 表空间扩容(增加新的数据文件)
  • 使用appium对安卓(使用夜神模拟器)运行自动化测试
  • STM32八大模式