一提到“日志”,很多新人的反应是“不就是 print 吗”。但如果把 AI 服务比作一家急诊医院,问题就没那么简单了。 想象这样一座“AI 急诊医院”:每天涌进成千上万个请求,每个请求都像一位患者,从挂号、问诊到做检查,一路留下大量记录。如果护士把每位患者的每一声咳嗽、每一滴输液都写进同一本大册子,几天之内册子就会把前台挤爆——想查某位患者的过敏史,得翻到猴年马月。真正的医院怎么干?护士随手写的灰色便签、医生签字的诊断摘要、检查异常的单据、抢救时的红色警报,按重要程度分门别类;近几天的病历放前台随手可查,上了年纪的病历送地下档案室归档。这样既救得快,又存得起。 AI 服务是同一套道理。大模型推理一次请求,可能产生几百条中间状态日志;一万个并发请求,日志量就是天文数字。不分级,关键信息被淹没;不存储分层,账单先把你淹没。这篇文章就用医院的病历体系做地图,把日志分级与冷热存储讲透。读完你会发现,可观测性不是玄学,而是一套扎扎实实的“病历管理”。

岗位关联

对 AI 从业者而言,日志分级与存储是整个可观测性的地基。掌握它,你才能在海量日志里快速定位问题、控制存储成本,系统一挂你能比谁都早发现。

目录
  1. 可视化演示
  2. 日志分级标准
  3. AI 日志特点
  4. 冷热分层存储
  5. 效率与成本
  6. 结构化日志
  7. 最佳实践
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

通过日志分级体系、冷热分层存储与结构化日志管道三模式,展示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 自动被丢弃,保证洪流不淹没主线。这套分级用一句话概括:每条日志该被谁看见、在什么时机看见,由级别决定。

护士把灰色便签当天就扔、蓝色摘要夹进病历、红色警报直接呼叫抢救——分级不是技术洁癖,而是让日志从噪音变成决策工具的关键一步。

r(L)={1,L≥L阈值0,L<L阈值\displaystyle r(L)=\begin{cases}1, & L\ge L_{\text{阈值}}\\ 0, & L < L_{\text{阈值}}\end{cases}
这个指示函数就是分级过滤的心脏:级别达到阈值的日志留下,达不到的直接扔进回收站。
  1. 级别数字映射日志级别不是字符串而是可比较的数字,越严重数值越大
    DEBUG=10, INFO=20, WARN=30, ERROR=40\displaystyle \text{DEBUG}=10,\ \text{INFO}=20,\ \text{WARN}=30,\ \text{ERROR}=40
  2. 阈值比较当前日志级别与配置的保留阈值比较,例如生产设为 INFO 则 20
    L≥L阈值\displaystyle L \ge L_{\text{阈值}}
  3. 保留决策满足条件记 1 保留,否则记 0 丢弃
    r(L)∈{1,0}\displaystyle r(L)\in\{1,0\}

AI 日志特点

普通诊所一天看 50 个患者,每个患者 3 条记录,医生都能背下来。AI 医院不一样:一个重症患者推进 ICU,呼吸机每秒钟吐出一条曲线数据,病历不是一页纸,而是一沓曲线图。

AI 服务的日志量正是这种“重症监护”量级。一个普通 Web 请求的日志量与请求是 1:1 关系,而一个 AI 推理请求能产出几十上百条日志。流式生成时,每生成一个 token 就是一次模型前向,想追踪质量就得逐条记录;RAG 检索时,查询改写、embedding、召回、重排,每一步都是独立子过程;工具调用则构成多层嵌套的调用链;再加上长上下文管理、截断策略、token 计费,日志总量瞬间爆炸。

所以单条请求的日志不再是一条,而是一棵有结构的“日志树”,必须靠 trace_id 把散落的叶子和树枝串成完整脉络。这条唯一 ID 就像患者的住院号,从挂号到出院贯穿全程。

ICU 的病历夹里塞满曲线图,但每张图都标着患者住院号。AI 日志体系必须先在量级上认怂,再用 trace_id 把“一沓纸”变成“一条链”,否则后端存储一天就会被冲垮。

Nreq=n迭代+n调用+n上下文+n元数据\displaystyle N_{\text{req}} = n_{\text{迭代}} + n_{\text{调用}} + n_{\text{上下文}} + n_{\text{元数据}}
单请求日志量由四部分组成,理解这个公式就理解了为什么 AI 日志不能照搬 Web 日志方案。
  1. 迭代步日志生成多少 token 就可能有多少条过程日志,是最大项
    n迭代=O(输出 token 数)\displaystyle n_{\text{迭代}} = O(\text{输出 token 数})
  2. 子调用日志检索、工具调用、重试层层叠加
    n调用=∑k第 k 次子调用产生的条数\displaystyle n_{\text{调用}} = \sum_{k} \text{第 } k \text{ 次子调用产生的条数}
  3. 上下文与元数据上下文压缩、token 计费、模型版本等数量固定
    n上下文+n元数据≈常数\displaystyle n_{\text{上下文}} + n_{\text{元数据}} \approx \text{常数}

冷热分层存储

前台病历柜放近三天的病历,医生问诊随取随用;三个月以上的病历送地下档案室,需要时提前调取。档案室不是废弃堆,而是配合“自动转档”的制度,让前台永远清爽、老病历有迹可循。

日志存储同样分“前台”与“档案室”。热存储层承担近 1-7 天的日志,使用 SSD 与高并发索引,常见选型是 Elasticsearch、ClickHouse、云日志服务,查询毫秒到秒级;冷存储层则把历史日志丢进对象存储(S3/GCS/OSS),成本只有热存储的十分之一到二十分之一,查询前必须先“解冻”,分钟级响应。迁移机制通常靠 TTL 生命周期规则:热数据 7 天后自动转冷,或者用定时批处理作业搬运。保留周期建议:DEBUG 24 小时即弃,INFO 热 3-7 天加冷 30 天,WARN/ERROR 热 30 天加冷 180 天以满足合规审计。

前台柜子放得下近期病历,档案室装得下历史包袱,中间的“自动转档”制度让两者各司其职。日志存储不怕量大,怕的是所有日志都堆在前台柜子里。

C总=V热×P热+V冷×P冷\displaystyle C_{\text{总}} = V_{\text{热}} \times P_{\text{热}} + V_{\text{冷}} \times P_{\text{冷}}
冷热分层不是额外复杂度,而是用价格差换排查能力的算术题。
  1. 热层成本项热存储的体积乘以热存储单价
    C热=V热×P热\displaystyle C_{\text{热}} = V_{\text{热}} \times P_{\text{热}}
  2. 冷层成本项冷存储的体积乘以冷存储单价
    C冷=V冷×P冷\displaystyle C_{\text{冷}} = V_{\text{冷}} \times P_{\text{冷}}
  3. 总成本两层成本相加,冷层占比越大总成本越低
    C总=C热+C冷\displaystyle C_{\text{总}} = C_{\text{热}} + C_{\text{冷}}

效率与成本

前台病历柜就那么大,塞满热病历虽然查得快,但柜子一个几万块,扩到一栋楼也不够;档案室虽然便宜,但每次调卷要等十分钟。门诊节奏与档案室容量之间,永远在拔河。

排查线上事故时,最怕日志躺在冷层。事故要分钟级定位,全冷存就是灾难;但全热存账单撑不住。平衡策略是分层路由:ERROR 与 WARN 强制进热层,DEBUG 不进生产;DEBUG 按 1% 采样长期留档用于离线分析;INFO 热 7 天转冷,成本降 80% 以上,而 95% 的查询需求恰好集中在热窗内。索引设计上,主索引用 trace_id 支撑链路检索,辅助索引用 time+level 支撑聚合告警。

好医院不会把所有病历塞前台,也不会把急诊病历扔档案室。把“什么级别进热层、留多久、什么时候转冷”定成规则,拔河就变成了自动化流程。

T查={τ热,日志在热层τ热+τ恢复,日志在冷层,τ热≪τ恢复\displaystyle T_{\text{查}} = \begin{cases}\tau_{\text{热}}, & \text{日志在热层} \\ \tau_{\text{热}} + \tau_{\text{恢复}}, & \text{日志在冷层}\end{cases},\quad \tau_{\text{热}} \ll \tau_{\text{恢复}}
查询时延取决于日志所在的存储层,热层毫秒级,冷层分钟级,差距可达三个数量级。
  1. 热层命中直接查索引,毫秒到秒级
    τ热≈10−3∼100 秒\displaystyle \tau_{\text{热}} \approx 10^{-3} \sim 10^{0}\ \text{秒}
  2. 冷层恢复先从对象存储拷贝回可查询介质
    τ恢复≈101∼102 秒\displaystyle \tau_{\text{恢复}} \approx 10^{1} \sim 10^{2}\ \text{秒}
  3. 冷层总耗时恢复加查询
    T冷=τ热+τ恢复\displaystyle T_{\text{冷}} = \tau_{\text{热}} + \tau_{\text{恢复}}

结构化日志

科室多、医生多,如果每个人按自己的风格写病历,会诊时谁也读不懂谁。医院强制统一模板:姓名、主诉、体格检查、医嘱,格子清清楚楚。病历模板统一后,护士和医生的配合效率直线上升。

结构化日志就是“机器能读懂的病历”,常用载体是 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 统一后,检索、聚合、告警才谈得上自动化——结构化是这一切的入场券。

LogEntry=⟨ts, level, trace_id, service, model, tokensin, tokensout, latencyms, status⟩\displaystyle \text{LogEntry} = \langle \text{ts},\ \text{level},\ \text{trace\_id},\ \text{service},\ \text{model},\ \text{tokens}_{\text{in}},\ \text{tokens}_{\text{out}},\ \text{latency}_{\text{ms}},\ \text{status} \rangle
一条结构化日志就是一个有固定列的“病历表”,九个字段各有各的查询与告警用途。
  1. 身份字段时间戳、级别、trace_id,是每条日志的“身份证”
    ⟨ts, level, trace_id⟩\displaystyle \langle \text{ts},\ \text{level},\ \text{trace\_id} \rangle
  2. 服务字段哪个服务、哪个模型,回答“谁打的日志”
    ⟨service, model⟩\displaystyle \langle \text{service},\ \text{model} \rangle
  3. 计量字段输入输出 token 数与延迟,回答“花了多少资源”
    ⟨tokensin, tokensout, latencyms⟩\displaystyle \langle \text{tokens}_{\text{in}},\ \text{tokens}_{\text{out}},\ \text{latency}_{\text{ms}} \rangle
  4. 结果字段请求最终状态,回答“这笔请求成没成”
    ⟨status⟩\displaystyle \langle \text{status} \rangle

最佳实践

现代医院的信息科不只管档案,还管采样、脱敏、告警联动。病历体系要靠制度自动运转,而不是靠几个人天天盯。

AI 服务日志的最佳实践可以浓缩成四件事。第一,采样策略:DEBUG 固定 1% 加 ERROR 全量保留,既留足统计分析样本,又保证故障必达。第二,敏感脱敏:prompt 里常有手机号、身份证、商业机密,落地前脱敏或哈希,日志平台配审计权限。第三,告警联动:ERROR 即时通过 Webhook 或 PagerDuty 触达,WARN 按分钟窗口聚合频次再报警,防止抖动刷屏。第四,生命周期自动化:TTL 规则热 7 天转冷、冷 90 天清理,ERROR 类日志单独留 180 天。

制度到位后,病历系统不需要人盯:该归档归档、该告警告警、该脱敏脱敏,医院才不会在深夜里悄悄着火。日志体系做到这一步,可观测性才真正变成基础设施。

p(L)={0.01,L=DEBUG1,L∈{INFO,WARN,ERROR}\displaystyle p(L)=\begin{cases}0.01, & L=\text{DEBUG} \\ 1, & L \in \{\text{INFO},\text{WARN},\text{ERROR}\}\end{cases}
采样不是“丢日志”,而是有策略地决定哪些值得留、哪些可以算着留。
  1. DEBUG 采样率1% 足以发现统计规律,成本骤降 99%
    p(DEBUG)=0.01\displaystyle p(\text{DEBUG}) = 0.01
  2. 关键级别全量INFO 摘要、WARN 预警、ERROR 故障都保留
    p(INFO)=p(WARN)=p(ERROR)=1\displaystyle p(\text{INFO})=p(\text{WARN})=p(\text{ERROR})=1
  3. 采样后的存储期望原始量乘以采样率就是入库量
    V期望=V原始×p\displaystyle V_{\text{期望}} = V_{\text{原始}} \times p

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 演示

python79 行
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)")
目的:用 20 行核心逻辑演示 AI 日志的“分级过滤 + 热存储 + 自动迁移冷归档”完整链路。
  1. self.threshold = LOG_LEVEL_NUM[threshold]把级别名翻译成数字阈值,与正文的 L >= L_阈值 一一对应
  2. def _allowed(self, level)分级过滤器,低于阈值的日志直接丢弃,DEBUG 在生产环境就是这样被拦下的
  3. def emit(self, level, **fields)所有日志的唯一入口,自动补全 ts 与 trace_id,保证字段不缺
  4. self.hot_path热存储文件,新日志先写这里,模拟“前台病历柜”
  5. if self.hot_size >= 3: self.migrate()热层积压到 3 条就触发迁移,模拟 TTL 生命周期规则
  6. def migrate(self)把热存储最旧一条移到冷存储,再重写热文件,模拟“自动转档”
  7. 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. 日志级别从低到高的正确顺序是?

单选题 · easy

  • 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 的概率分布,最适合记在哪一级?

单选题 · easy

  • A.token 级概率分布← 正确答案
  • B.请求状态码摘要
  • C.用户可见回复
  • D.模型版本快照

答案:A。token 级概率属于推理中间状态,是排障时才需要的灰色便签,应放 DEBUG。请求状态码摘要、模型版本快照属于 INFO 的“体检单”内容。

Q3. 关于热存储与冷存储,下列说法正确的是?

单选题 · mid

  • A.热存储贵但查询快← 正确答案
  • B.冷存储贵但查询快
  • C.热存储便宜查询慢
  • D.冷存储便宜查询慢

答案:A。热存储用 SSD 加索引,单价高但毫秒级查询;冷存储用对象存储,单价约 1/10 但需要先解冻、分钟级响应。二者是速度与成本的经典取舍。

Q4. AI 日志从热层迁往冷层,最常见触发机制是?

单选题 · mid

  • A.按 TTL 生命周期规则← 正确答案
  • B.人工定期手动挪动
  • C.每次请求触发迁移
  • D.到达上限即清空日志

答案:A。生产环境靠 TTL 生命周期规则自动转冷,比如“热 7 天后自动归档”。人工迁移不可扩展,每次请求迁移会把系统拖垮,清空日志则丢失排查能力。

Q5. AI 服务日志最佳实践包含哪些?

多选题 · mid

  • A.统一注入 trace_id← 正确答案
  • B.对 prompt 敏感脱敏← 正确答案
  • C.全量保留所有 DEBUG
  • D.为日志建立索引← 正确答案

答案:ABD。trace_id 串起全链路、prompt 脱敏满足隐私合规、索引支撑快速检索都是实践要点。全量保留 DEBUG 会让存储爆炸,正确做法是固定 1% 采样加 ERROR 全量。

Q6. 结构化日志的标准字段中,推荐包含哪些?

多选题 · mid

  • A.时间戳与级别← 正确答案
  • B.trace_id 关联← 正确答案
  • C.token 与延迟数← 正确答案
  • D.完整 prompt 原文

答案:ABC。时间戳、级别、trace_id、token 数、延迟都是标准字段。完整 prompt 原文涉及敏感信息,规范做法是只存 prompt_hash,原文不落日志。

Q7. 结构化日志最常用的存储载体是?

单选题 · easy

  • A.JSON Lines 格式← 正确答案
  • B.自由文本段落
  • C.二进制图片快照
  • D.混合无约束文本

答案:A。JSON Lines 一行一个 JSON 对象,天然适配全文索引和字段聚合。自由文本无法机器解析,图片快照不可检索,混合文本等于没有结构化。

Q8. 适合放入 DEBUG 级别的日志场景是?

多选题 · mid

  • A.注意力分数分布← 正确答案
  • B.缓存命中与否← 正确答案
  • C.单次请求状态码
  • D.token 级生成状态← 正确答案

答案:ABD。注意力分数、缓存命中、token 级生成状态都是推理中间过程,排障才需要,属于 DEBUG。单次请求状态码是“体检单”级别的结论信息,应放 INFO。

Q9. 为控制成本只保留 1% 的 DEBUG 日志,同时全量保留 ERROR,这种策略称为?

单选题 · hard

  • A.固定比率采样← 正确答案
  • B.尾部事件采样
  • C.关键词过滤采样
  • D.全量重复归档

答案:A。固定比率采样按比例抽取普通日志,是全量保留 ERROR 这种“尾部事件”之外的常规做法。二者组合既控成本又保故障必达,是最常见的采样组合。

Q10. 某服务每天产生 100GB 日志,热存储 10 元/GB/月,冷存储 1 元/GB/月。方案 A 全部热存 30 天,方案 B 热存 7 天后自动转冷存 23 天,两者的月存储费差额约为多少?

单选题 · extreme

  • 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 天转冷”能省下七成存储成本的直观证明。