Midscene 分布式追踪指南:一次执行故障的全链路回溯
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
Midscene 是一款用自然语言驱动浏览器、手机和桌面应用的开源 GUI Agent。它的分布式追踪能力解决的是另一类问题:一次自动化执行失败了,到底败在哪一步、哪一次模型调用、哪个请求上?通过给每次执行发放全局唯一的executionId,Midscene 把报告回放、任务步骤、模型请求与重试串成同一条可回溯的链路,让你不用翻日志就能定位故障根源。
🧩 场景:线上一次执行失败,从哪里查起?
假设你的回归任务在「点击结算按钮」这一步超时。报告文件能告诉你这一步失败了,却回答不了三个更细的问题:那一步里模型到底被调了几次?最后一次请求的响应是什么?失败前模型是不是先定位到了错误的元素?
Midscene 的追踪机制就是为这种「从结果倒推过程」的场景设计的。它没有引入额外的中间件,而是靠一个贯穿始终的执行编号,把三层信息缝在一起:
- 报告层:
midscene_run/下生成的回放报告,记录每一步的截图与结果 - 任务层:任务执行器(TaskRunner)的每一步动作与规划
- 请求层:发给模型服务的每一次 HTTP 请求、流式响应与错误
三层各有一份数据,executionId是唯一的关联键。下面从最底层往上讲。
🎟️ 执行编号从哪来:executionId 的发放时机
每次执行启动时,Midscene 的 TaskRunner 生成一个 id,并在初始化模型运行时把它注入进去(实现见 packages/core/src/agent/tasks.ts)。此后同一次执行里,无论模型被规划器、定位器还是洞察模块调用了多少次,拿到的都是这同一个 id。
这一步是刻意设计的:一次aiAct内部可能触发多次模型调用,甚至带重试。如果每次调用各自编号,你就无法回答「这一次动作到底花了多少轮请求」。按执行粒度发放编号,重试、并行、分阶段规划都天然归在同一张「单子」下——executionId的作用就像快递单号,包裹(请求)可以拆很多段,但单号只有一个。
有一个例外值得记住:不属于报告内执行的调用(例如启动时的连接检查)会使用带unscoped-前缀的生成 id,不会污染正式执行的数据。
📡 编号如何跨出进程边界:请求头传播
单进程内共享变量就够了,但 Midscene 要追踪的是「发出的请求本身」。为此它给每个 OpenAI 兼容协议的 HTTP 模型请求自动附加两个请求头(实现见 packages/core/src/ai-model/service-caller/openai-client.ts):
| 请求头 | 值 | 用途 |
|---|---|---|
x-midscene-version | @midscene/core当前版本 | 标识发起请求的客户端版本 |
x-midscene-execution-id | 当前执行编号 | 服务端日志可反查到对应执行 |
这两头默认发送;如果你在MIDSCENE_*_INIT_CONFIG_JSON里自定义过同名头,Midscene 会覆盖它。
实际效果是双向的:你的自建网关或代理按x-midscene-execution-id给请求打标签,网关侧的慢请求日志就能和执行侧的失败步骤对上号——这是跨「自动化端 ↔ 模型服务端」的上下文传播。
📼 结果落在哪:模型调用日志与报告文件
追踪数据最终要能看。Midscene 提供两个默认关闭、按需开启的落盘开关:
# 写入 .env 或 shell export MIDSCENE_RECORD_MODEL_CALL=true开启后,每次模型请求、流式 Chunk、响应与错误会以 JSONL 形式写入midscene_run/model-requests/<启动时间>-<pid>.jsonl,每行一个事件,事件的type取值为request、chunk、response或error,并都携带executionId(说明见 模型调试与可观测性)。
拿到这个文件后,排查路径变成纯文本操作:先按失败步骤在报告里找到对应时间窗,再在 JSONL 里grep该步骤所属执行的executionId,即可看到该执行内所有请求的原始请求体与响应。注意文件包含请求 Body 与 Base64 截图,体积大且可能敏感,只在排障时开启。
🛰️ 接第三方平台:OpenTelemetry 路线
如果你已经用 Langfuse 或 LangSmith 管理 LLM 应用,Midscene 可以零代码接入:它自动包装 OpenAI 客户端,把模型调用上报为平台 Trace。
以 Langfuse 为例,先在应用入口初始化 OTel SDK,再设两个开关:
import { NodeSDK } from "@opentelemetry/sdk-node"; import { LangfuseSpanProcessor } from "@langfuse/otel"; new NodeSDK({ spanProcessors: [new LangfuseSpanProcessor()], }).start();然后设置MIDSCENE_LANGFUSE_DEBUG=1与LANGFUSE_PUBLIC_KEY、LANGFUSE_SECRET_KEY、LANGFUSE_BASE_URL三个环境变量,启动时看到langfuse wrapper enabled日志即接入成功。LangSmith 同理:装好依赖后设MIDSCENE_LANGSMITH_DEBUG=1和LANGCHAIN_API_KEY即可。
三条边界条件:两种集成可以同时开启;仅支持 Node.js 环境,浏览器中会抛错;若你通过createOpenAIClient自定义了客户端,会覆盖环境变量触发的自动集成。日常只想看延迟和 Token 用量,甚至不需要平台,一条DEBUG=midscene:ai:profile:stats就能在控制台打印每次模型调用的耗时与用量。
🧭 下一步:今晚就能做的一件事
选一个最近失败的执行,把MIDSCENE_RECORD_MODEL_CALL=true加进.env重跑一遍,然后用报告里的执行编号去model-requests/目录里 grep 一次——你会第一次看清「失败的点击之前,模型到底被问了几次、每次答了什么」。把这个「报告编号 → JSONL 反查」的动作固化为排障习惯后,再把x-midscene-execution-id加进你模型网关的日志字段,前后端两侧的数据就真正合流了。
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考