Logback 日志体系:日志分级、归档、持久化 Logback 日志体系日志分级、归档、持久化线上出了问题日志就是你唯一的时间回溯器。日志写得好故障三分钟定位写得差加班到天亮也找不到 bug。一、日志体系总览SLF4J LogbackSpringBoot 默认的日志体系是SLF4J门面 Logback实现。这个组合非常重要理解门面模式对后续日志选型大有帮助。你的代码 → SLF4J API门面 → Logback具体实现打个比方SLF4J 是插座面板Logback 是墙里的电线。你只需要怼着面板插调 SLF4J 接口至于墙里走的是铜线还是铝线底层实现是 Logback 还是 Log4j2插件一换就行代码不用动。这就是门面模式的精髓。为什么不直接调 Logback API万一哪天要切成 Log4j2所有 import 都得改。用了 SLF4J只换依赖和配置文件即可。二、五大日志级别级别数值用途TRACE最低跟踪级别打印每条 SQL、每个方法参数DEBUG调试开发排查用参数值、中间结果INFO信息默认业务流程节点用户登录、订单创建WARN警告可恢复的异常网络超时重试、降级处理ERROR错误需人工介入数据库连不上、支付失败日志级别控制规则设置某个级别后只会输出该级别及以上的日志。比如设为 WARN只输出 WARN 和 ERROR。三、logback-spring.xml 三要素root、logger、appenderlogback-spring.xml 放在src/main/resources下SpringBoot 自动加载。整个配置由三类组件构成appender日志输出到哪里控制台 / 文件 / 邮件 / 数据库logger哪个包/类的日志怎么处理root所有 logger 的爹兜底的全局配置三者关系日志事件 → 匹配 logger → 匹配其 appender → 如果 logger 的 additivitytrue默认继续向上传递给 root 的 appender。四、完整 logback-spring.xml 配置示例?xml version1.0 encodingUTF-8?configuration!-- 日志文件路径 --propertynameLOG_PATHvalue./logs/propertynameLOG_FILEvalueapp/!-- 控制台输出 --appendernameCONSOLEclassch.qos.logback.core.ConsoleAppenderencoderpattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/patterncharsetUTF-8/charset/encoder/appender!-- 按天滚动文件输出 --appendernameFILEclassch.qos.logback.core.rolling.RollingFileAppenderfile${LOG_PATH}/${LOG_FILE}.log/fileencoderpattern%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n/patterncharsetUTF-8/charset/encoderrollingPolicyclassch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy!-- 每天滚动文件名格式app.2024-01-01.0.log --fileNamePattern${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.%i.log/fileNamePatternmaxFileSize100MB/maxFileSize!-- 单文件超过100MB就切分 --maxHistory30/maxHistory!-- 只保留最近30天 --totalSizeCap5GB/totalSizeCap!-- 总大小超过5GB时清理最旧的 --/rollingPolicy/appender!-- 环境区分 --springProfilenamedevrootlevelINFOappender-refrefCONSOLE//root/springProfilespringProfilenameprodrootlevelWARNappender-refrefCONSOLE/appender-refrefFILE//root/springProfile/configuration4.1 Pattern 格式说明%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n%d日期时间按 pattern 格式化[%thread]线程名%-5level日志级别左对齐占 5 字符%logger{36}Logger 类名最多 36 字符%msg日志内容%n换行4.2 滚动策略SizeAndTimeBasedRollingPolicy是官方推荐的组合策略按时间切每天零点生成新文件由%d{yyyy-MM-dd}控制按大小切单文件超过maxFileSize自动创建新序号文件%i按数量清理maxHistory30只保留 30 天totalSizeCap5GB总大小不超限五、代码中使用日志Lombok 的Slf4j一行搞定省去手写LoggerFactory.getLogger()Slf4jRestControllerRequestMapping(/order)publicclassOrderController{PostMappingpublicResultcreate(RequestBodyOrderDTOdto){log.info(创建订单请求userId{}, amount{},dto.getUserId(),dto.getAmount());if(dto.getAmount()0){log.warn(订单金额非法amount{},dto.getAmount());returnResult.fail(金额不能小于等于0);}try{OrderorderorderService.create(dto);log.info(订单创建成功orderId{},order.getId());returnResult.ok(order);}catch(Exceptione){log.error(订单创建失败dto{},dto,e);// 把异常对象传进去打堆栈returnResult.fail(系统繁忙);}}}两个关键习惯日志用占位符{}不要用字符串拼接id id避免浪费字符串拼接性能log.error()一定要把异常对象传进去不然堆栈打不出来六、多环境日志配置springProfile标签按 profile 区分环境dev 环境打印类 SQL 和业务日志prod 环境只打 WARN 以上。loggernamecom.examplelevelDEBUGadditivityfalseappender-refrefCONSOLE//loggerloggernameorg.springframeworklevelWARN/loggernamecom.zaxxer.hikarilevelINFO/此处additivityfalse表示不向上级传递避免日志重复打印两条。七、日志最佳实践清单实践说明别在循环里打日志1000 条数据 for 循环打 1000 条日志IO 直接拖垮异常日志带上下文log.error(扣款失败userId{}, amount{}, uid, amt, e)敏感信息脱敏手机号中间 4 位打星号、密码绝不打日志日志文件权限Linux 下chmod 640防止其他用户抓取周期性压测验证日志写入不成为性能瓶颈totalSizeCap一定要配置曾经某项目日志跑了一年没清理磁盘塞满导致服务宕机血的教训。日志归档自动化别等运维找上门才想起。日志是开发者的产线监控写好了省命写差了要命。