每天5分钟,掌握一个SpringBoot核心知识点。大家好,我是SpringBoot指南的小坏。前两天我们讲了限流保护系统,今天聊点更基础的——日志。别小看日志,线上问题排查80%靠它!
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java 回复"Swagger源码",获取本文所有示例代码、配置模板及导出工具。
一、先看个真实事故
上周朋友公司出了个事故,过程是这样的:
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java 回复"Swagger源码",获取本文所有示例代码、配置模板及导出工具。
- 用户反馈:“我的订单一直显示处理中…”
- 客服回复:“可能是网络问题,重启试试”
- 三天后,同样问题用户达到5000人
- 开发查日志,发现只有一句:“订单处理失败”
- 关键信息全没记录!为什么失败?数据库异常?网络超时?第三方接口挂了?
- 最后发现是支付网关证书过期,但日志没打出来
- 损失:3天无法下单,退款2000多单
你看,不会打日志 = 埋地雷,随时可能爆炸!
二、日志配置:从混乱到清晰
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java 回复"Swagger源码",获取本文所有示例代码、配置模板及导出工具。
2.1 别再只用System.out.println()
很多新手喜欢这么写:
System.out.println("用户登录成功,ID:"+userId);问题:
- 没时间戳,不知道什么时候发生的
- 没日志级别,分不清是错误还是普通信息
- 没法分文件,所有日志混在一起
- 没法控制输出到哪里(控制台还是文件)
2.2 正确姿势:5分钟搞定基础配置
在application.yml里加这些配置:
logging:# 1. 设置不同包的日志级别level:root:INFO# 全局默认级别com.example.user:DEBUG# 用户模块详细日志com.example.order:WARN# 订单模块只警告以上org.springframework:ERROR# 框架日志只记录错误# 2. 输出到文件file:name:logs/app.log# 日志文件位置max-size:10MB# 每个文件最大10Mmax-history:30# 保留30天的日志# 3. 控制台美化(开发环境用)pattern:console:"%d{yyyy-MM-dd HH:mm:ss} - %highlight(%-5level) - %cyan(%logger{15}) - %msg%n"这样配置后,你的日志就会:
- ✅ 自动按天分割文件
- ✅ 不同模块不同详细程度
- ✅ 自动清理30天前的旧日志
- ✅ 开发环境有颜色,看得清楚
三、日志级别:什么时候打什么日志?
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java 回复"Swagger源码",获取本文所有示例代码、配置模板及导出工具。
简单理解成4个等级:
1. DEBUG(调试)
场景:开发时用,生产环境一般不打开
// 比如:记录详细的SQL语句log.debug("执行SQL:{},参数:{}",sql,params);2. INFO(信息)
场景:正常业务流程
// 比如:用户注册成功log.info("用户注册成功,手机号:{},注册来源:{}",phone,source);3. WARN(警告)
场景:有点问题,但不影响主流程
// 比如:接口响应慢log.warn("获取用户信息超时,耗时:{}ms,用户ID:{}",costTime,userId);4. ERROR(错误)
场景:真的出错了,需要立即关注
// 比如:数据库连接失败try{// 业务代码}catch(Exceptione){log.error("创建订单失败,用户ID:{},商品ID:{}",userId,productId,e);// 关键:要把异常e也打印出来!}黄金法则:
- 能用INFO就不用DEBUG
- 该用ERROR时别用WARN
- 打印异常一定要带上异常对象
- 关键业务参数一定要记录
四、高级技巧:让日志更聪明
4.1 给日志添加"身份证"
线上有几十台服务器,怎么知道这条日志是哪个服务、哪个实例打的?
logging:pattern:# 添加应用名和实例IDfile:"%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg [app=${spring.application.name}, instance=${HOSTNAME}]%n"4.2 不同环境不同配置
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java 回复"Swagger源码",获取本文所有示例代码、配置模板及导出工具。
开发环境想看得详细,生产环境想性能好,怎么办?
# application-dev.yml(开发环境)logging:level:root:DEBUG# 开发环境看详细日志file:enabled:false# 开发环境不写文件,只控制台# application-prod.yml(生产环境)logging:level:root:INFO# 生产环境只记录重要信息file:name:/data/logs/${spring.application.name}.logmax-size:100MB4.3 敏感信息脱敏
千万别把密码、手机号、身份证号明文打印!
// ❌ 错误写法log.info("用户登录,手机号:13800138000,密码:123456");// ✅ 正确写法publicStringmaskPhone(Stringphone){if(phone==null||phone.length()<7)returnphone;returnphone.substring(0,3)+"****"+phone.substring(7);}log.info("用户登录,手机号:{}",maskPhone("13800138000"));// 输出:用户登录,手机号:138****8000五、ELK三件套:日志的"搜索引擎"
如果你觉得看日志文件太费劲,可以试试ELK:
5.1 ELK是什么?
- E:Elasticsearch(存储和搜索)
- L:Logstash(收集和过滤)
- K:Kibana(可视化展示)
简单理解:
- 以前:在几十个文件里
grep关键字 - 现在:在网页上搜索,像用百度一样方便
5.2 快速集成(Docker版)
# 一键启动ELK(需要先安装Docker)docker-composeup -d# 配置SpringBoot输出到Logstashlogging: logstash: enabled:truehost: localhost port:5000启动后访问 http://localhost:5601,你就能:
- ✅ 实时查看日志
- ✅ 按关键字搜索
- ✅ 统计错误次数
- ✅ 设置告警(比如:5分钟出现10次ERROR就发邮件)
六、避坑指南:这些错你别犯
坑1:日志打太多,磁盘满了
// ❌ 错误:循环里打日志for(Useruser:userList){log.info("处理用户:{}",user.getId());// 如果有10万用户...}// ✅ 正确:批量处理才打日志log.info("开始批量处理用户,总数:{}",userList.size());// 处理逻辑...log.info("批量处理完成,成功:{},失败:{}",successCount,failCount);坑2:拼接字符串性能差
// ❌ 错误:直接拼接log.info("用户"+userId+"购买商品"+productId);// ✅ 正确:用占位符log.info("用户{}购买商品{}",userId,productId);// 好处:只有INFO级别开启时才会拼接字符串坑3:异常信息丢失
// ❌ 错误:只打印异常信息catch(Exceptione){log.error("出错了:"+e.getMessage());// 如果e.getMessage()是null,就什么信息都没有}// ✅ 正确:打印整个异常catch(Exceptione){log.error("创建订单失败,参数:{}",request,e);// 会把完整的堆栈信息都打印出来}坑4:日志格式不统一
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java 回复"Swagger源码",获取本文所有示例代码、配置模板及导出工具。
// ❌ 错误:不同人写法不同log.info("用户注册:手机号="+phone);log.info("用户注册,手机号:{}",phone);log.info("[注册]手机号:"+phone);// ✅ 正确:团队统一格式// 建议模板:时间 + 操作 + 关键参数 + 结果// 例如:用户注册 - 手机号:13800138000 - 成功七、最佳实践总结
7.1 打日志的"3要3不要"
三要:
- 要打关键业务参数(谁、干了什么、结果)
- 要包含上下文信息(请求ID、用户ID)
- 异常要打印完整堆栈
三不要:
- 不要打印敏感信息(密码、token)
- 不要在循环里打大量日志
- 不要用System.out.println()
7.2 根据团队规模选择方案
个人/小团队:
- 用SpringBoot默认配置
- 日志写到文件,按天分割
- 用
grep命令简单搜索
中小团队:
- 配置Logback,按模块分文件
- 集成Sentry或Loggly(云服务)
- 设置关键错误告警
大团队:
- 搭建ELK或商业日志平台
- 制定日志规范,Code Review检查
- 日志接入监控告警系统
7.3 一个完整的配置示例
logging:# 基础配置level:root:INFOcom.example:DEBUG# 文件配置file:name:logs/myapp.logmax-size:50MBmax-history:60# 按模块分文件logback:rollingpolicy:# 错误日志单独文件error-file:logs/error.logerror-max-size:100MB# 格式配置pattern:console:"%d{HH:mm:ss} %-5level %logger{15} - %msg%n"file:"%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{40} - %msg%n"下期预告:《应用监控与健康检查:你的系统"活"得好吗?》
日志工具包:关注公众号回复"日志配置",获取完整的Logback配置模板和ELK搭建脚本。
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目
资源获取:关注公众号: 小坏说Java 回复"Swagger源码",获取本文所有示例代码、配置模板及导出工具。
坏哥运营小贴士:
📅发布时间:今晚8:30,打工人下班后学习时间
🏷️今日标签:#SpringBoot日志 #线上排查 #Java开发
💡互动设计:
- 评论区征集:你见过最"坑"的日志是什么?
- 投票:你们团队用ELK还是自己搭日志系统?
- 经验分享:点赞最高的3位分享者送技术书籍
🔄转发话术:
- 技术版:SpringBoot日志配置,看这一篇就够了
- 吐槽版:因为日志没打好,我们损失了2000单…
- 实用版:别再乱打日志了!这是正确姿势
🎁粉丝福利:
- 资源获取:关注公众号: 小坏说Java ,获取《Java日志开发规范.pdf》
- 转发到技术群,截图领《线上问题排查手册》
👥社群引导:
文末加一句:“遇到日志问题?扫码加入SpringBoot交流群,3000+开发者等你!”
零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目