32_生产级Skill可观测性:日志+成本追踪+失败告警
很多团队在 Demo 阶段并不觉得“可观测性”有多重要。因为那时所有事情都发生在眼前: 谁触发了任务、模型回了什么、哪里慢、哪里报错,大家靠聊天记录、几条控制台输出、再加一点直觉,居然也能勉强对上。可一旦 Skill 真正进入生产环境,尤其是多个 Skill 串起来之后,如果没有一套像样的日志、成本追踪和失败告警,团队很快就会陷入一种非常熟悉的混乱: 知道系统不对劲,但不知道是哪一层坏了,不知道坏了多久,也不知道每次坏到底要花多少钱。
更糟的是,很多所谓“优化”其实是在盲修。模型贵了,先换个便宜模型试试;响应慢了,先删一点上下文;成功率掉了,先改几句 Prompt;投诉多了,先把阈值放松。这些动作看上去都像工程优化,实际上很多时候只是靠感觉做外科手术。没有观测,团队不是在调系统,而是在猜系统。
这篇文章要做的,就是把“可观测性”从一个听上去很传统的软件工程概念,翻译成 Skill 系统里必须落地的设计。重点不是喊“要打日志”,而是要讲清楚: 记录什么、怎么统一、成本怎么拆、告警怎么分级、哪些信息该留、哪些绝不能留。因为没有这一层,后面的容错、编排、异步处理,都会失去抓手。
一、先承认一个事实: 没有观测,优化和排障都是瞎猜
很多团队嘴上说自己在做“调优”,实际上做的是一种非常昂贵的迷信活动。响应慢了就换模型,成本高了就截断上下文,准确率低了就再塞几个例子。偶尔这些动作真的有改善,于是大家更相信自己在优化;但大多数时候,他们根本不知道问题的主因在哪。
在 Skill 系统里,性能和质量问题往往不是单点问题。可能是输入缺失导致路由误判,可能是某个工具抖动触发了隐式重试,可能是成本高不是模型贵,而是某个降级分支被频繁触发,导致任务被执行了两遍。没有观测,这些差别全部消失,最后都被压成一句“最近系统不太稳”。
所以可观测性的第一价值,不是事后排障,而是让优化建立在证据上。你应该能回答至少这几个问题: 某类任务最近失败率为什么升高?它坏在输入层、路由层、执行层还是外部依赖?成本上涨是整体上涨,还是某个步骤异常?系统是真的稳定,还是只是靠降级分支勉强活着?如果这些问题答不上来,那系统离生产级还差得很远。
二、Skill 的日志,不是普通接口日志翻版
传统接口日志的核心是请求时间、调用结果、错误码。Skill 系统当然也需要这些,但远远不够。因为 Skill 系统不是简单的输入输出,它有决策、有路由、有模型选择、有工具调用、有回退路径,还有可能存在多轮状态延续。
也就是说,你记录的不只是“发生了什么”,还必须记录“为什么走到这一步”。如果只记最终成功失败,你永远看不出问题是主流程坏了,还是靠 fallback 才成功;看不出输入本来就不完整,还是系统自己判断错了;也看不出某次成本激增,是因为用户问题复杂,还是因为某个隐式重试偷偷跑了三轮。
一个更合理的执行日志结构,至少应该像这样:
name: skill_execution_logger
tracked_fields:
- request_id
- session_id
- skill_name
- skill_version
- trigger_source
- input_completeness
- route_decision
- model_selection
- tool_calls
- retry_count
- fallback_path
- latency_ms
- outcome
constraints:
- 关键分支决策必须记录理由摘要
- 敏感输入不得原文落日志
- outcome 必须区分主流程成功与降级成功
- 日志字段命名必须跨 Skill 统一
注意这里几个特别关键的字段。
input_completeness 让你知道问题是不是从入口就开始了。很多失败其实不是执行层的锅,而是输入资料本来不齐。
route_decision 记录的是为什么走这个 Skill、为什么选这个模型、为什么进入人工升级或降级路径。没有它,所有后续分析都只能从结果倒推。
retry_count 和 fallback_path 用来区分“稳定成功”和“勉强成功”。如果系统表面成功率很高,但大部分成功都靠重试或 fallback 换来的,那它并不健康,只是还没彻底塌。
2.1 日志的目标不是多,而是能拼起来
很多团队打日志有一个非常典型的问题: 每个 Skill 都“有日志”,但每个人记录的字段都不一样。A Skill 用 requestId,B Skill 用 trace_id,C Skill 直接没有链路字段;A 记录 result=success,B 记录 status=ok,C 记录 code=0。看起来都在记录,实际根本拼不起来。
这会直接导致横向分析失效。你没法统一算某类任务的平均耗时,没法比对不同版本 Skill 的失败差异,也没法把一条请求跨越多个 Skill 的执行链路串起来。最后只剩下局部观测,整个系统仍然是黑箱。
所以日志设计一定是平台能力,不是各写各的习惯问题。字段名称、字段语义、埋点时机、状态枚举,都要统一。不统一,后面所有“观测看板”都只是花架子。
三、成本追踪不是财务报表问题,而是架构问题
很多团队一听“成本追踪”,第一反应是财务或者管理层需求。这种理解太浅。对 Skill 系统来说,成本追踪首先是架构治理问题。因为你如果不知道钱花在哪一步,就永远不知道该优化哪里。
总成本当然有意义,但总成本只适合月底汇报,不适合工程优化。真正能指导架构调整的,是步骤级成本拆解。你需要知道某次执行里,模型调用花了多少,工具调用花了多少,重试花了多少,回退路径又花了多少。如果一个看似简单的任务成本飙升,你得知道到底是主模型贵,还是因为工具抖动导致重跑,还是 fallback 触发得太频繁。
一个更像样的成本追踪 Skill,应该至少这样定义:
name: skill_cost_tracker
description: >
汇总单次执行中的模型调用、外部工具调用和失败重试成本。
inputs:
- execution_trace
- pricing_catalog
outputs:
- total_cost
- step_cost_breakdown
- retry_cost
- fallback_cost
- anomaly_flag
constraints:
- 成本异常上涨时必须打标
- 隐式重试不得漏记成本
- fallback 额外成本必须独立统计
- 定价版本变更必须可追溯
这里面最常被忽略的是 retry_cost 和 fallback_cost。很多系统只记主流程花了多少钱,不记补救动作花了多少钱。结果看起来“平均成本还行”,但实际上系统每次遇到某类输入都会暗中自救两三轮。你不把这些隐藏成本翻出来,根本不可能做出正确的架构决策。
3.1 成本异常,往往意味着结构出问题了
成本追踪的价值,不只是记账,更是发现结构性异常。比如某类任务突然成本翻倍,可能是模型上下文膨胀,可能是某个工具调用变慢导致重试,可能是路由判断失准,把本该走轻量流程的任务送进了重分析链路。
所以“成本异常”不应该只是财务预警,它应该和稳定性告警一样被看待。因为对 Agent 系统来说,成本突然异常上涨,本身就说明某个行为模式变了。如果这个变化不是你主动发布的结果,那它就值得被当成故障信号看待。
四、失败告警的关键不是全告,而是分级准确
生产环境里一个很常见的死法叫“全告警”。系统稍微有点风吹草动就群里狂响,结果一周之后大家都学会忽略通知。到了真正关键故障发生的时候,没人再把它当回事。所谓“所有失败都要及时告警”,在真实团队里往往等于“没有告警体系”。
Skill 系统的失败有很强的层次差异。某个外部工具偶发超时,但重试后成功,这种更接近可恢复波动;某类任务连续三十分钟都走入 block,且影响关键业务流,这才应该进入高等级告警;再比如低优先级异步任务延迟增加,可能只需要运营看板提示,不值得凌晨把人叫醒。
所以告警路由必须显式设计,而不是默认任何 error 都推给同一批人。一个清晰的失败告警 Skill 可以这样写:
name: skill_failure_alert_router
description: >
根据失败类型、影响范围和恢复可能性决定告警级别与通知对象。
inputs:
- failure_event
- service_criticality
- recent_incident_history
outputs:
- alert_level
- notify_targets
- retry_or_escalate
- incident_tag
constraints:
- 可自动恢复的瞬时失败不得默认最高级告警
- 影响关键业务流程的持续失败必须升级
- 相同根因告警必须聚合,避免通知风暴
- 告警必须附带排障上下文,不得只发报错文案
alert_level 的设计一定要能映射到真实组织响应。比如信息提示、工作时段处理、当日处理、立即响应。别搞一堆漂亮枚举,结果没有任何明确处置动作。告警体系的价值不在于分类细,而在于每一类都有明确负责人、明确 SLA、明确升级路径。
4.1 告警里最值钱的不是“坏了”,而是“坏在哪”
很多告警做得非常吵,但毫无信息密度。通知里只有“任务执行失败,请关注”,甚至连是哪条链路、哪个版本、哪类输入、是否可以重试都没有。这样的告警只是在把定位成本转嫁给值班的人。
一个真正有用的告警,至少应该带上这些上下文: 失败发生在哪个 Skill、影响哪类任务、最近 15 分钟出现了几次、是否集中在某个版本、是否伴随成本异常、是否可以自动恢复、建议先看哪段 trace。你不是在通知“有事发生了”,你是在缩短排障时间。
五、敏感信息必须在日志层就处理,不要事后补救
可观测性还有一个特别容易被忽略,但一旦出事就很难收场的问题: 日志合规。很多团队上线后才发现,日志里充满用户隐私、业务密文、合同文本、身份证号、医疗信息。然后才想起来“要不要打码”。这已经晚了。
Skill 系统由于天然处理非结构化内容,更容易把敏感信息带进日志。如果你把完整 prompt、完整输入文档、完整模型输出原文都扔进日志系统,确实排障很方便,但也等于给自己埋了一个巨大的合规雷。
正确做法不是彻底不记,而是从一开始把“什么能记、怎么脱敏、哪些字段只能保留摘要或哈希、哪些数据只能短期保留”设计清楚。换句话说,日志不是事后产物,而是正式的数据产品。它同样需要字段分级、访问控制、生命周期管理。
六、评估可观测性,不要只看监控页面长得多漂亮
很多团队做完一套 dashboard,就以为可观测性完成了。真正要问的是: 出问题时它到底帮不帮得上忙。
比起页面截图,更值得盯住的指标通常包括:
- 失败定位平均耗时
- 成本异常发现时延
- 同类故障重复发生率
- 主流程成功率与降级成功率占比
- 关键路径告警命中率
- 日志字段完整率
- 链路 trace 串联成功率
- 告警误报率与漏报率
这些指标的共同点是,它们衡量的是系统是否可诊断、可优化、可运营,而不只是“有没有监控”。真正成熟的观测体系,不是让大家看很多图,而是让团队在故障发生时少猜一点、快一点、准一点。
七、把可观测性当成 Skill 系统的基础设施
如果把前面内容压缩成一句话,那就是: 可观测性不是某个附加模块,而是 Skill 系统的基础设施。日志决定你能不能还原执行路径,成本追踪决定你能不能做结构性优化,失败告警决定你能不能在故障扩散前介入。
一个更完整的生产级观测组合,通常会包含这三层:
observability_stack:
- name: skill_execution_logger
purpose: trace_how_execution_happened
- name: skill_cost_tracker
purpose: trace_where_money_went
- name: skill_failure_alert_router
purpose: decide_when_and_whom_to_notify
global_principles:
- 字段口径跨 Skill 统一
- 成本拆解到步骤级而不是只看总账
- 告警必须有分级、有上下文、有责任人
- 敏感信息治理前置到日志设计阶段
到这一步,你就会发现“看得见”本身就是一种生产能力。没有它,所谓稳定性只是运气,所谓优化只是瞎改,所谓治理只是开会。
八、总结
生产级 Skill 可观测性的价值,不是多打一堆日志,而是让团队知道每一次执行是怎么走的、花了多少钱、哪里开始坏、坏到什么程度该叫谁。只有看得见,后面才谈得上扛得住。
更直白一点说,系统真正可怕的不是失败,而是失败发生了你还看不清。看不清,就无法修;无法修,所谓生产级只是嘴上叫得响。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)