← 返回文章列表

Dify 韧性验证实验(06):全链路追踪——一次请求如何在 Dify 中被完整追踪?

1. 业务场景

先讲一个我们实际遇到的场景。

一家做客服工单 SaaS 的公司,应用是跨应用链路:门户对话 → 工单应用 → 通知。用户打电话来说「刚才建单失败了」——运维要回答三个问题:卡在哪个节点、哪一圈、什么原因?没有 trace,只能全链路猜:翻日志、试复现、问开发。更麻烦的是指标造假:看板显示「全部成功」,实际通知已经失败——用户都投诉了,指标还全绿。

我们第一次接这类需求时,第一反应是「Dify 不是自带 node-executions 吗,还要我们自己建可观测性?」。真正动手才发现——平台的执行记录是「有」,能不能回答客户的问题、指标真不真,是另一回事。我们把 trace、日志、指标拆成三层面逐项建,建完再拿「用户说刚才卡住了」的真实场景演练一遍,能定位才算数。

这不是个例。任何「多应用协作、要上线要接客户」的系统都是这个模式:可观测性不是锦上添花——「客户说刚才卡住了」时,你能不能只用日志回答「卡在哪、为什么、影响多大」?

2. 场景痛点

这套链路的痛点,在跨应用协作时体现得最直接:

本质上,没有 trace 的结论是猜测,有 trace 的结论是证据——可观测性是验收体系的元模块,没有它其它五个模块的验收都跑不起来

3. 方案:为什么是可观测性建设

Dify 工作流里建设可观测性最系统的方法,就是三层面建设:trace 完整、日志结构化、指标真实。

选它的理由:

这篇文章我们就用它搭「门户对话 + 工单流程 + 数据看板」三个应用,把 trace/日志/指标三层可观测性建起来。

4. 整体架构

graph TD start["开始:用户操作"] portal["门户对话(trace_id 贯穿)"] wf_tool["Workflow as Tool 调用工单应用"] flow["工单流程(trace_id 贯穿 + 日志埋点 success/degraded)"] notify["通知(可失败,降级留痕)"] log["统一日志(KV dify105_06_logs)"] board["数据看板(定时 workflow:读统一日志 → 指标统计)"] start --> portal --> wf_tool --> flow --> notify --> log --> board %% 每圈四元组:圈数 / 思考摘要 / 工具调用 / 结果

链路很清晰:门户对话 →(Workflow as Tool)工单应用 → 通知 → 统一日志 → 数据看板。关键设计是 trace_id 贯穿全链路、每圈记录四元组(圈数/思考摘要/工具调用/结果),降级分支必须留痕——出了事能顺着日志一路查到根因。

5. 模块设计

5.1 可观测性建设三层面(本实验核心)

  1. Trace 完整:每个关键节点输出可查——多出口 end 有明确输出变量名;node-executions 全链路可追
  2. 日志结构化:关键事件(任务开始/结束/工具调用/降级/错误)有记录;降级分支输出明确降级信息(不静默)
  3. 指标真实:成功/失败计数与真实行为一致(不造假)

5.2 降级留痕(不静默)

降级分支输出「已降级 + 原因」——D102-P1-01 教训:

def main(reason: str, trace_id: str) -> dict:

    return {"status": "degraded",

            "reason": reason,          # 如实记录,如 notify_failed

            "trace_id": trace_id,

            "message": "(已降级)通知通道异常,工单已站内记录"}

5.3 日志写入(KV 结构化)

def main(trace_id: str, query: str, status: str, app: str) -> dict:

    # 写 KV dify105_06_logs:{trace_id, query, status, app, ts}

    log_entry = {"trace_id": trace_id, "query": query,

                 "status": status, "app": app}

    return {"log_ok": True, "entry": log_entry}

5.4 run_id 取证

workflow blocking 用 data.id(succeeded/partial 一致,实测统一);chatflow 取证路径不同(chat-messages 无 run_id,需 console 触发——先确认 mode)。

5.5 数据看板(指标真实不造假)

定时读统一日志 → 指标统计(总数/成功/降级/按应用分布),指标与 KV 实际记录一致

def main(logs: str) -> dict:

    # 解析 KV 日志 → 统计

    return {"total": n, "success": s, "degraded": d,

            "success_rate": f"{s / n * 100:.0f}%",

            "by_app": {"portal": p, "ticket": t}}

6. 运行验证

用例 输入要点 预期 结果
门户 trace + 日志 跑门户对话 KV dify105_06_logs 记录 portal 2 条(trace_id/query/status=success) 通过(实测)
工单 trace + 日志 触发工单(含一次通知失败) ticket 2 条(1 success + 1 degraded with reason=notify_failed)——降级如实留痕 通过(实测)
指标真实 看板统计 输出「近 4 条日志,成功 3(75%),降级 1,portal=2; ticket=2」——与 KV 实际记录完全一致,无造假 通过(实测)
看板触发 trigger-schedule 定时(演示 weekly) console draft run 手动触发验证通过 通过(实测)
排障演练 「刚才卡住了」场景 仅凭可观测性定位根因(卡在哪节点/什么原因/影响范围) 通过(实测)

7. 实战坑

现象 修复
run_id 取值 data.id vs workflow_run_id 两态不一致取值错 blocking 统一用 data.id(succeeded/partial 一致,实测)
chatflow 取证限制 chat-messages 无 run_id 用 console 触发取证(实测,104/103)
指标造假 显示成功实际失败 = P1 指标与 KV 实际记录核对,10 次任务注入 2 次失败应如实反映(实验文档设计约束)
节点 title 英文 排查时用户按中文 UI 定位 节点 title 用中文(用户要求,102)

8. 实验文档及源码获取

文章聚焦核心配置与采坑点;实验的完整分步操作(节点搭建/参数表/调试指引)见实验文档原文。

联系我

15088711270

手机端点击号码可直接拨打 · 桌面端可复制

微信二维码

扫码加微信 · 备注「门户」更快通过