一提到“日志”,很多新人的反应是“不就是 print 吗”。但如果把 AI 服务比作一家急诊医院,问题就没那么简单了。 想象这样一座“AI 急诊医院”:每天涌进成千上万个请求,每个请求都像一位患者,从挂号、问诊到做检查,一路留下大量记录。如果护士把每位患者的每一声咳嗽、每一滴输液都写进同一本大册子,几天之内册子就会把前台挤爆——想查某位患者的过敏史,得翻到猴年马月。真正的医院怎么干?护士随手写的灰色便签、医生签字的诊断摘要、检查异常的单据、抢救时的红色警报,按重要程度分门别类;近几天的病历放前台随手可查,上了年纪的病历送地下档案室归档。这样既救得快,又存得起。 AI 服务是同一套道理。大模型推理一次请求,可能产生几百条中间状态日志;一万个并发请求,日志量就是天文数字。不分级,关键信息被淹没;不存储分层,账单先把你淹没。这篇文章就用医院的病历体系做地图,把日志分级与冷热存储讲透。读完你会发现,可观测性不是玄学,而是一套扎扎实实的“病历管理”。
对 AI 从业者而言,日志分级与存储是整个可观测性的地基。掌握它,你才能在海量日志里快速定位问题、控制存储成本,系统一挂你能比谁都早发现。
可视化演示
通过日志分级体系、冷热分层存储与结构化日志管道三模式,展示AI系统日志管理的核心机制与工程实践。
本节配有交互动效(进入视口后自动加载,约 3KB)。
日志分级体系 六级日志从TRACE到FATAL,严重度递增而量递减,生产环境通常过滤至WARN以上 告警率=Vol(WRN+ERR+FTL)/Vol(ALL) 分级过滤是可观测性第一道防线
日志分级标准
医院护士站的墙上挂着一套四层色卡:灰色便签记随手观察到的小事,蓝色诊疗卡记就诊摘要,黄色异常单记录指标偏离,红色警报只在抢救时拉响。四层从不混用,值班护士一眼就知道该翻哪沓、该先处理哪堆。
AI 日志的级别世界是一模一样的色卡系统。业界通用的四级是 DEBUG、INFO、WARN、ERROR,本质是一根数字标尺,决定这条日志在生产环境是否默认出现。DEBUG 是灰色便签,记录推理中间状态:每步生成的概率、注意力分数、缓存命中与否、第几轮检索的相似度,平时关闭,排障时临时打开。INFO 是蓝色摘要,记录一次请求的“体检单”:时间戳、trace_id、服务名、模型版本、prompt 与输出 token 数、首 token 延迟。WARN 是黄色异常单:低置信度输出、上游超时重试、上下文接近窗口上限。ERROR 是红色警报:推理失败、进程 OOM、网关 5xx。
生产环境通常把阈值设在 INFO,DEBUG 自动被丢弃,保证洪流不淹没主线。这套分级用一句话概括:每条日志该被谁看见、在什么时机看见,由级别决定。
护士把灰色便签当天就扔、蓝色摘要夹进病历、红色警报直接呼叫抢救——分级不是技术洁癖,而是让日志从噪音变成决策工具的关键一步。
- 级别数字映射日志级别不是字符串而是可比较的数字,越严重数值越大
- 阈值比较当前日志级别与配置的保留阈值比较,例如生产设为 INFO 则 20
- 保留决策满足条件记 1 保留,否则记 0 丢弃
AI 日志特点
普通诊所一天看 50 个患者,每个患者 3 条记录,医生都能背下来。AI 医院不一样:一个重症患者推进 ICU,呼吸机每秒钟吐出一条曲线数据,病历不是一页纸,而是一沓曲线图。
AI 服务的日志量正是这种“重症监护”量级。一个普通 Web 请求的日志量与请求是 1:1 关系,而一个 AI 推理请求能产出几十上百条日志。流式生成时,每生成一个 token 就是一次模型前向,想追踪质量就得逐条记录;RAG 检索时,查询改写、embedding、召回、重排,每一步都是独立子过程;工具调用则构成多层嵌套的调用链;再加上长上下文管理、截断策略、token 计费,日志总量瞬间爆炸。
所以单条请求的日志不再是一条,而是一棵有结构的“日志树”,必须靠 trace_id 把散落的叶子和树枝串成完整脉络。这条唯一 ID 就像患者的住院号,从挂号到出院贯穿全程。
ICU 的病历夹里塞满曲线图,但每张图都标着患者住院号。AI 日志体系必须先在量级上认怂,再用 trace_id 把“一沓纸”变成“一条链”,否则后端存储一天就会被冲垮。
- 迭代步日志生成多少 token 就可能有多少条过程日志,是最大项
- 子调用日志检索、工具调用、重试层层叠加
- 上下文与元数据上下文压缩、token 计费、模型版本等数量固定
冷热分层存储
前台病历柜放近三天的病历,医生问诊随取随用;三个月以上的病历送地下档案室,需要时提前调取。档案室不是废弃堆,而是配合“自动转档”的制度,让前台永远清爽、老病历有迹可循。
日志存储同样分“前台”与“档案室”。热存储层承担近 1-7 天的日志,使用 SSD 与高并发索引,常见选型是 Elasticsearch、ClickHouse、云日志服务,查询毫秒到秒级;冷存储层则把历史日志丢进对象存储(S3/GCS/OSS),成本只有热存储的十分之一到二十分之一,查询前必须先“解冻”,分钟级响应。迁移机制通常靠 TTL 生命周期规则:热数据 7 天后自动转冷,或者用定时批处理作业搬运。保留周期建议:DEBUG 24 小时即弃,INFO 热 3-7 天加冷 30 天,WARN/ERROR 热 30 天加冷 180 天以满足合规审计。
前台柜子放得下近期病历,档案室装得下历史包袱,中间的“自动转档”制度让两者各司其职。日志存储不怕量大,怕的是所有日志都堆在前台柜子里。
- 热层成本项热存储的体积乘以热存储单价
- 冷层成本项冷存储的体积乘以冷存储单价
- 总成本两层成本相加,冷层占比越大总成本越低
效率与成本
前台病历柜就那么大,塞满热病历虽然查得快,但柜子一个几万块,扩到一栋楼也不够;档案室虽然便宜,但每次调卷要等十分钟。门诊节奏与档案室容量之间,永远在拔河。
排查线上事故时,最怕日志躺在冷层。事故要分钟级定位,全冷存就是灾难;但全热存账单撑不住。平衡策略是分层路由:ERROR 与 WARN 强制进热层,DEBUG 不进生产;DEBUG 按 1% 采样长期留档用于离线分析;INFO 热 7 天转冷,成本降 80% 以上,而 95% 的查询需求恰好集中在热窗内。索引设计上,主索引用 trace_id 支撑链路检索,辅助索引用 time+level 支撑聚合告警。
好医院不会把所有病历塞前台,也不会把急诊病历扔档案室。把“什么级别进热层、留多久、什么时候转冷”定成规则,拔河就变成了自动化流程。
- 热层命中直接查索引,毫秒到秒级
- 冷层恢复先从对象存储拷贝回可查询介质
- 冷层总耗时恢复加查询
结构化日志
科室多、医生多,如果每个人按自己的风格写病历,会诊时谁也读不懂谁。医院强制统一模板:姓名、主诉、体格检查、医嘱,格子清清楚楚。病历模板统一后,护士和医生的配合效率直线上升。
结构化日志就是“机器能读懂的病历”,常用载体是 JSON Lines:一行一个 JSON 对象,天然适配全文索引、字段聚合与告警规则。AI 服务的标准字段建议:基础字段 ts、level、trace_id(链路入口注入)、service;请求字段 model、model_version、prompt_tokens、completion_tokens、latency_ms;状态字段 status(ok / error / rate_limited / blocked);安全字段 prompt_hash——敏感原文只存哈希,不落原文。
字段一旦不在 schema 里,搜索索引就用不上,告警规则也写不出来。schema 是日志体系的“病历模板”,而 trace_id 就是模板上的住院号栏。
统一病历模板后,会诊不再靠猜。日志 schema 统一后,检索、聚合、告警才谈得上自动化——结构化是这一切的入场券。
- 身份字段时间戳、级别、trace_id,是每条日志的“身份证”
- 服务字段哪个服务、哪个模型,回答“谁打的日志”
- 计量字段输入输出 token 数与延迟,回答“花了多少资源”
- 结果字段请求最终状态,回答“这笔请求成没成”
最佳实践
现代医院的信息科不只管档案,还管采样、脱敏、告警联动。病历体系要靠制度自动运转,而不是靠几个人天天盯。
AI 服务日志的最佳实践可以浓缩成四件事。第一,采样策略:DEBUG 固定 1% 加 ERROR 全量保留,既留足统计分析样本,又保证故障必达。第二,敏感脱敏:prompt 里常有手机号、身份证、商业机密,落地前脱敏或哈希,日志平台配审计权限。第三,告警联动:ERROR 即时通过 Webhook 或 PagerDuty 触达,WARN 按分钟窗口聚合频次再报警,防止抖动刷屏。第四,生命周期自动化:TTL 规则热 7 天转冷、冷 90 天清理,ERROR 类日志单独留 180 天。
制度到位后,病历系统不需要人盯:该归档归档、该告警告警、该脱敏脱敏,医院才不会在深夜里悄悄着火。日志体系做到这一步,可观测性才真正变成基础设施。
- DEBUG 采样率1% 足以发现统计规律,成本骤降 99%
- 关键级别全量INFO 摘要、WARN 预警、ERROR 故障都保留
- 采样后的存储期望原始量乘以采样率就是入库量
AI 应用场景
LLM 网关排障:回答为什么突然变差了
阶段:模型服务与部署
解决的问题:用户反馈机器人回答质量骤降,传统日志只有请求与响应,没有中间状态,无法定位是 prompt 变了、模型版本回滚了,还是上游限制导致低置信度输出。AI 日志分级让 INFO 承载请求摘要(token 数、延迟、模型版本),DEBUG 按需开启中间状态,WARN 记录低置信度输出触发回归回放。
具体案例:某客服机器人接入统一日志平台,INFO 记录每次请求的请求摘要与 latency;运维收到“低置信度比例上升”的 WARN 告警后,通过 trace_id 调出热存储的请求摘要,快速定位到某次模型灰度发布导致概率分布偏移,回滚后恢复。
RAG 问答归因:引用到底来自哪里
阶段:检索增强生成管道
解决的问题:RAG 回答引用了错误来源,需要追溯“查询改写 → recall → rerank → 生成”全链路。AI 日志的调用链上下文与 trace_id 注入,把一次问答拆成一条可回溯的日志树。
具体案例:某知识库问答系统在 INFO 中记录检索命中的 top-k 块 ID,在 DEBUG 中记录相似度分数;线上出现错误引用时,工程师按 trace_id 拉出整棵日志树,发现 rerank 阶段把低分块排到了前面,修正阈值后问题消失。
日志成本审计:账单如何降下来
阶段:平台治理
解决的问题:AI 服务日志量是 Web 服务的几十倍,全量热存存储费每月超标。冷热分层与采样策略用价格差换回预算,同时保住关键链路的排查能力。
具体案例:某模型平台每天产生 100GB 日志,原来全部进 Elasticsearch 热存,月费接近 3 万元。实施“INFO 热 7 天转冷、DEBUG 采样 1%、ERROR 全量保留 180 天”后,月费降到约 9000 元,而线上事故平均定位时间反而因为索引优化缩短了 30%。
Python 演示
import jsonimport timeimport uuidfrom dataclasses import asdict, dataclassfrom pathlib import Path LOG_LEVEL_NUM = {"DEBUG": 10, "INFO": 20, "WARN": 30, "ERROR": 40} @dataclassclass LogEntry: ts: float level: str trace_id: str service: str model: str prompt_tokens: int completion_tokens: int latency_ms: int status: str class AILogger: def __init__(self, dir_path: str = "logs", threshold: str = "INFO"): self.dir_path = Path(dir_path) self.dir_path.mkdir(exist_ok=True) self.threshold = LOG_LEVEL_NUM[threshold] self.hot_path = self.dir_path / "hot.jsonl" self.cold_path = self.dir_path / "cold.jsonl" self.hot_size = 0 def _allowed(self, level: str) -> bool: return LOG_LEVEL_NUM[level] >= self.threshold def emit(self, level: str, **fields) -> None: if not self._allowed(level): return entry = LogEntry( ts=time.time(), level=level, trace_id=fields.get("trace_id", str(uuid.uuid4())[:8]), service=fields.get("service", "llm-server"), model=fields.get("model", "gpt-4o-mini"), prompt_tokens=fields.get("prompt_tokens", 0), completion_tokens=fields.get("completion_tokens", 0), latency_ms=fields.get("latency_ms", 0), status=fields.get("status", "pending"), ) self._write(self.hot_path, entry) self.hot_size += 1 if self.hot_size >= 3: self.migrate() def _write(self, path: Path, entry: LogEntry) -> None: with open(path, "a", encoding="utf-8") as f: f.write(json.dumps(asdict(entry)) + "\n") def migrate(self) -> None: lines = self.hot_path.read_text(encoding="utf-8").splitlines() if not lines: self.hot_size = 0 return with open(self.cold_path, "a", encoding="utf-8") as f: f.write(lines.pop(0) + "\n") self.hot_path.write_text("\n".join(lines) + "\n", encoding="utf-8") self.hot_size = len(lines) if __name__ == "__main__": logger = AILogger(threshold="INFO") tid = "req_abcdef1234" logger.emit("DEBUG", trace_id=tid, prompt_tokens=512, status="thinking") logger.emit("INFO", trace_id=tid, prompt_tokens=512, completion_tokens=128, latency_ms=980, status="ok") logger.emit("WARN", trace_id=tid, status="low_confidence") logger.emit("ERROR", trace_id=tid, prompt_tokens=9999, status="context_window_exceeded") print("hot:", logger.hot_path.read_text(encoding="utf-8").strip() or "(empty)") print("cold:", logger.cold_path.read_text(encoding="utf-8").strip() or "(empty)")
self.threshold = LOG_LEVEL_NUM[threshold]把级别名翻译成数字阈值,与正文的L >= L_阈值一一对应def _allowed(self, level)分级过滤器,低于阈值的日志直接丢弃,DEBUG 在生产环境就是这样被拦下的def emit(self, level, **fields)所有日志的唯一入口,自动补全 ts 与 trace_id,保证字段不缺self.hot_path热存储文件,新日志先写这里,模拟“前台病历柜”if self.hot_size >= 3: self.migrate()热层积压到 3 条就触发迁移,模拟 TTL 生命周期规则def migrate(self)把热存储最旧一条移到冷存储,再重写热文件,模拟“自动转档”logger.emit("DEBUG", ...)DEBUG 被阈值过滤不会落盘,INFO/WARN/ERROR 正常入库
常见误区
误区级别设得越细越专业,TRACE、DEBUG、INFO、NOTICE、WARN、ERROR、FATAL 全都要用上,排查时才能精细控制。
正解级别本质是操作决策标尺,粒度一旦超过团队运维能力,写日志的人无法判断该用哪级,告警规则也无法统一。医院色卡只有四种颜色,因为值班护士只需要四个动作:忽略、摘要、预警、接管。级别与动作一一对应,体系才能运转。
为何常见:新手以为细分等于精确,但分级是组织行为学——级别越多,决策成本越高,最终所有人都随便用。
误区INFO 反正不过滤,把完整 prompt、每个 token 的概率、中间推理结果全塞进 INFO,排查时最省事。
正解AI 请求的 INFO 只放“摘要”:trace_id、模型名、token 数、延迟、状态。完整 prompt 与 token 级概率属于 DEBUG 的灰色便签。否则 INFO 一天几个 TB,而且 prompt 里的敏感信息会在日志平台裸奔。
为何常见:怕丢信息,觉得存得全才安全,却忘了存储成本和隐私风险会反噬。
误区热存储查询快,干脆所有日志都塞 Elasticsearch,反正公司不差钱。
正解热存储单价是冷存储的 10-50 倍。100GB/天的日志全热存 30 天约 3 万元,热 7 天转冷只要约 9000 元。分层存储用 TTL 自动转冷,查询能力几乎不受影响,账单却能降七成。
为何常见:成本是账单到了才刺痛的隐性指标,架构设计时容易把“简单”误当成“便宜”。
误区只要把日志打成 JSON 输出,就算结构化日志,查询平台会自动变好用。
正解结构化 = 统一 schema + 字段类型约束 + 链路 ID 注入。JSON 只是载体,没有 schema 的 JSON 无法建立索引与聚合,检索照样大海捞针。就像病历不是打印得工整就叫结构化,没按模板填格子,医生还是看不懂。
为何常见:看到花括号就以为万事大吉,忽略了 schema 才是结构化的灵魂。
误区只要走到 ERROR 分支就说明系统出事了,必须立刻告警。
正解用户主动取消请求、上下文窗口超限、上游 429 限流,都属于“预期业务分支”。这些打成 ERROR 会让告警规则失聪,把真正故障淹没在噪音里。预期分支应该用 WARN 或自定义 status 字段标记,把 ERROR 留给真正的“病人心脏骤停”。
为何常见:ERROR 这个词自带警示感,让人潜意识觉得“出错了就要报”,却忘了告警的价值在于稀缺。
面试题
Q1. 日志级别从低到高的正确顺序是?
- A.DEBUG < INFO < WARN < ERROR← 正确答案
- B.INFO < DEBUG < ERROR < WARN
- C.ERROR < WARN < INFO < DEBUG
- D.DEBUG < WARN < INFO < ERROR
答案:A。日志级别是单调递增的严重程度标尺,DEBUG 最低、ERROR 最高。就像医院色卡从灰色便签逐步升到红色警报,级别越高越需要人关注。
Q2. 大模型每次生成 token 的概率分布,最适合记在哪一级?
- A.token 级概率分布← 正确答案
- B.请求状态码摘要
- C.用户可见回复
- D.模型版本快照
答案:A。token 级概率属于推理中间状态,是排障时才需要的灰色便签,应放 DEBUG。请求状态码摘要、模型版本快照属于 INFO 的“体检单”内容。
Q3. 关于热存储与冷存储,下列说法正确的是?
- A.热存储贵但查询快← 正确答案
- B.冷存储贵但查询快
- C.热存储便宜查询慢
- D.冷存储便宜查询慢
答案:A。热存储用 SSD 加索引,单价高但毫秒级查询;冷存储用对象存储,单价约 1/10 但需要先解冻、分钟级响应。二者是速度与成本的经典取舍。
Q4. AI 日志从热层迁往冷层,最常见触发机制是?
- A.按 TTL 生命周期规则← 正确答案
- B.人工定期手动挪动
- C.每次请求触发迁移
- D.到达上限即清空日志
答案:A。生产环境靠 TTL 生命周期规则自动转冷,比如“热 7 天后自动归档”。人工迁移不可扩展,每次请求迁移会把系统拖垮,清空日志则丢失排查能力。
Q5. AI 服务日志最佳实践包含哪些?
- A.统一注入 trace_id← 正确答案
- B.对 prompt 敏感脱敏← 正确答案
- C.全量保留所有 DEBUG
- D.为日志建立索引← 正确答案
答案:ABD。trace_id 串起全链路、prompt 脱敏满足隐私合规、索引支撑快速检索都是实践要点。全量保留 DEBUG 会让存储爆炸,正确做法是固定 1% 采样加 ERROR 全量。
Q6. 结构化日志的标准字段中,推荐包含哪些?
- A.时间戳与级别← 正确答案
- B.trace_id 关联← 正确答案
- C.token 与延迟数← 正确答案
- D.完整 prompt 原文
答案:ABC。时间戳、级别、trace_id、token 数、延迟都是标准字段。完整 prompt 原文涉及敏感信息,规范做法是只存 prompt_hash,原文不落日志。
Q7. 结构化日志最常用的存储载体是?
- A.JSON Lines 格式← 正确答案
- B.自由文本段落
- C.二进制图片快照
- D.混合无约束文本
答案:A。JSON Lines 一行一个 JSON 对象,天然适配全文索引和字段聚合。自由文本无法机器解析,图片快照不可检索,混合文本等于没有结构化。
Q8. 适合放入 DEBUG 级别的日志场景是?
- A.注意力分数分布← 正确答案
- B.缓存命中与否← 正确答案
- C.单次请求状态码
- D.token 级生成状态← 正确答案
答案:ABD。注意力分数、缓存命中、token 级生成状态都是推理中间过程,排障才需要,属于 DEBUG。单次请求状态码是“体检单”级别的结论信息,应放 INFO。
Q9. 为控制成本只保留 1% 的 DEBUG 日志,同时全量保留 ERROR,这种策略称为?
- A.固定比率采样← 正确答案
- B.尾部事件采样
- C.关键词过滤采样
- D.全量重复归档
答案:A。固定比率采样按比例抽取普通日志,是全量保留 ERROR 这种“尾部事件”之外的常规做法。二者组合既控成本又保故障必达,是最常见的采样组合。
Q10. 某服务每天产生 100GB 日志,热存储 10 元/GB/月,冷存储 1 元/GB/月。方案 A 全部热存 30 天,方案 B 热存 7 天后自动转冷存 23 天,两者的月存储费差额约为多少?
- A.约 7000 元
- B.约 21000 元← 正确答案
- C.约 35000 元
- D.约 50000 元
答案:B。方案 A 为 100×30×10=30000 元;方案 B 为 100×7×10+100×23×1=9300 元;差额约 20700 元,接近 21000。这正是“热 7 天转冷”能省下七成存储成本的直观证明。