模型推理日志结构化与故障根因定位落地

日期:2026-08-26

一、项目背景

我们的模型推理服务跑在好几个容器里,日志各写各的,出了问题全靠 grep 关键词,一次推理变慢了,到底是排队等卡、调度延迟还是模型本身算得慢,谁也说不清。排障经常耗半天,最后发现是某张卡被一个长任务占满,但日志里根本看不出这条线。复盘会也写不清根因,下次同样的问题还来。我们统计过,平均一次跨容器慢推理排障要将近两小时,其中一大半花在定位而不是解决,这效率团队受不了。更尴尬的是,告警天天有,但告警里只有慢没有为什么慢,值班人接到告警还得自己从头查,深更半夜被叫起来却不知道从哪下手,士气掉得厉害。

二、落地场景

我们做了推理链路的结构化埋点。每次请求从进网关、排队、调度到模型计算,每个阶段都打一条带统一字段的日志,阶段名、耗时、卡号、错误码一目了然。后台把这些日志聚合成一条链路视图,慢请求点开就能看到每个阶段花了多久,瓶颈在哪段立刻现形。错误码也做了归一,不同框架抛的异常统一映射成一套码,排障不用再记各家方言。我们还建了根因归因规则,比如排队耗时占比高就标算力不足,调度耗时高就标调度拥塞,告警直接带根因,不用人工猜。故障看板按根因分类统计,哪类问题最多一眼可见。此外,链路数据也接到了容量预测,哪种根因在涨提前扩对应的资源,运维从救火变成看板值守。

三、关键技术挑战与解决思路

埋点统一最费劲。不同推理框架的日志格式五花八门,我们先定义了统一 schema,再用适配层把各框架的输出转成标准字段,新增框架只要加一个适配器。埋点太多会日志爆量,我们第一版把每个子步骤都打了,一天几十 G 日志,存储和查询都崩,后来只保留关键四段:入队、调度、计算、返回,足够定位又不浪费。耗时打点要高精度且低开销,我们用单调时钟打点,开销几乎可忽略。根因规则最容易误判,排队慢可能是真算力不足,也可能是某个调用方突发刷量,我们加了调用方维度交叉验证,单看耗时会误伤,结合来源才准。错误归一踩过坑,初期映射太粗,把可重试的超时和真失败混为一谈,告警全乱,后来细分了可恢复和不可恢复两类,重试策略和升级策略才分清楚。

案例片段(已脱敏): 推理链路埋点与根因规则配置(示意): trace.stages: [enqueue, schedule, compute, return] log.schema: unified_v2 error.code_map: normalized rootcause.rule: stage_duration_ratio error.class: [retryable, fatal] 某服务接入后平均排障时长从约 110 分钟降到 25 分钟,根因命中率约 92%,告警噪声下降约五成,可恢复错误自动重试率约七成。

四、效果数据

我们主要看平均排障时长、根因命中率、错误归因准确率和告警噪声。排障时长从接近两小时压到二十多分钟,团队终于不用为一次慢推理耗掉半天;根因命中率九成以上,告警直接带结论,值班人照着处理就行。错误归因准确率上来之后,可重试的自动重试,真失败的才升级,误报少了。告警噪声降了五成,深夜被叫醒的次数明显少。文中数据为项目复盘口径,已做脱敏。我们把根因分布接到了容量规划,哪类根因涨了提前扩容或限流,从被动救火变成主动防御,稳定性提升比单纯加机器实在。链路视图上线后,新人也能独立排障了,以前这种跨容器慢请求只有老人才看得懂,现在点开看四段耗时就行,团队兜底能力上了一个台阶。

五、可复用经验总结

推理慢了别急着猜,先有分阶段耗时数据再说,我们就是早年靠 grep 瞎找吃了大亏,两小时定位一半是浪费在翻日志上。埋点别贪多,关键四段足够定位,打太细日志爆量反而拖垮查询,这点我们交过存储的学费。错误码必须归一,不然每家框架一套方言,排障的人得是全栈才能看懂,统一映射之后新人也能上手。根因规则要带维度交叉,单看耗时容易误伤调用方,结合来源和时段才准,我们被误伤过一次业务方才加的交叉验证。我现在的判断是,日志结构化真正的价值不是存下来,而是把为什么慢变成一眼能看穿的结论,省下的排障时间比系统本身值钱,告警带根因那一刻,值班人才算真正被解放。

我们把链路数据也喂给了容量预测,哪种根因在涨就提前扩对应的资源,扩卡不再靠拍脑袋。新人的排障门槛也低了,以前这种跨容器慢请求只有老人看得懂,现在点开四段耗时就行。

我们给根因报告也加了时间维度,同一类根因是今天突然涨还是一直都有,一眼能分,突发的才值得紧张。值班人现在接到告警先看是不是新 pattern,老问题按预案走,新问题才升级,误报和误紧张都少了。

告警带根因之后,值班手册也重写了,新人照着根因分类处理,半夜被叫起来也不慌了。