日志基础与重要性

日志这东西,说白了就是系统的「黑匣子」。我做了十几年运维,见过太多系统出问题后两眼一抹黑的场景。那时候大家围着服务器转,谁也不知道刚才发生了什么。嗯,日志就是用来回答这个问题的。

日志的作用

日志到底能干嘛?我个人习惯把它分成三个层次:

  • 故障排查:系统崩了,第一反应就是翻日志。我记得有一次线上服务半夜挂了,靠的就是一条「OutOfMemoryError」日志定位到内存泄漏。
  • 安全审计:谁在什么时候干了什么,日志里一清二楚。我曾经帮客户追查过数据泄露事件,就是靠登录日志和操作日志还原了整个攻击路径。
  • 性能分析:接口响应慢、数据库查询超时,这些都能从日志里找到蛛丝马迹。你想想看,没有日志,你连系统在干什么都不知道。

核心观点:日志不是写给机器看的,是写给人看的。尤其是出问题时的你。

日志级别

日志级别这东西,很多团队一开始都不重视。我见过一个项目,所有日志全用 INFO 级别,结果生产环境一天刷几个 GB,真正有用的信息全被淹没了。

常见的日志级别,我一般这么用:

级别 含义 我的使用习惯
TRACE 跟踪 开发调试用,生产环境基本不开
DEBUG 调试 排查问题时临时开启,平时关掉
INFO 信息 记录关键业务流程,比如用户登录、订单创建
WARN 警告 不影响运行但值得关注的情况,比如配置缺失
ERROR 错误 需要人工介入的问题,比如数据库连接失败
FATAL 致命 系统无法继续运行,比如内存溢出

避坑指南:我曾经见过一个团队把 ERROR 当 INFO 用,结果报警系统天天响,最后大家直接无视了所有报警。日志级别不是摆设,选对了能救命。

日志格式规范

日志格式这件事,我踩过不少坑。早期做项目时,日志格式五花八门,有的用逗号分隔,有的用竖线,有的干脆就是一段话。等到要写脚本分析日志时,那叫一个痛苦。

我个人推荐的标准格式:

[时间戳] [日志级别] [线程名] [类名:行号] - 日志内容

举个例子:

[2024-01-15 14:30:22.123] [ERROR] [http-nio-8080-exec-3] [OrderService.java:45] - 订单创建失败,订单号:ORD20240115001,原因:库存不足

为什么要这么写?

  • 时间戳:精确到毫秒,方便定位问题发生的时间点
  • 日志级别:一眼就能看出问题的严重程度
  • 线程名:多线程环境下,知道是哪个线程出的问题
  • 类名和行号:直接定位到代码位置,省去翻代码的时间
  • 日志内容:包含关键业务信息,比如订单号、用户ID

注意:日志里不要记录敏感信息,比如密码、身份证号、银行卡号。我曾经见过一个项目,日志里明文记录了用户的支付密码,这要是泄露出去,后果不堪设想。

日志生命周期管理

日志不是存得越久越好。你想想看,一个日活百万的系统,一天能产生几十 GB 的日志。如果不加管理,硬盘很快就满了。

我一般把日志生命周期分成三个阶段:

  1. 热数据(最近 7 天):保存在本地磁盘,方便实时排查问题
  2. 温数据(7-30 天):压缩后存储,或者发送到集中式日志平台
  3. 冷数据(30 天以上):归档到对象存储或者磁带库,保留以备审计

具体的保留策略,我建议这样:

日志类型 保留时间 存储方式
应用日志 30 天 本地 + 远程
访问日志 90 天 远程存储
审计日志 1 年 归档存储
调试日志 7 天 本地

我的经验:日志轮转一定要配置好。我曾经接手过一个项目,日志文件没有做轮转,结果一个文件写了 50 GB,用文本编辑器打开直接卡死。用 logrotate 或者框架自带的轮转功能,按大小或时间切分,这是基本功。

嗯,日志基础这部分就这些。说白了,日志就是系统的「眼睛」和「耳朵」。没有日志,你就像在黑暗中摸索。有了日志,你才能知道系统到底在干什么,出了问题时才能快速定位。下一章我们聊聊日志收集的实战技巧。