Skip to content

调用追踪、页面留档与文件上传 ​

本文说明服务在自己的工作目录里留下了什么、放在哪、以及客户端-服务器模式下怎么把文件送到服务端。这些产物是排障与事后复盘的唯一凭据,同时也是需要定期清理的磁盘占用。

一、每一次调用都有留档 ​

每一次调用(含批量里的每一步)的请求与响应都会落到 <启动目录>/logs/trace/<自然日>/ 下,例如 logs/trace/20260924/:

文件内容用途
steps.log每次调用一行:时间、序号、任务 ID、方法、成功与否、耗时、一句话结果人看的时间线,一眼看出第几步开始不对
calls.jsonl每次调用一行 JSON:调用摘要 + 从 data 里摘出的关键字段(url / title / seq / screenshot / state_file / changed 等)+ 完整请求体机器读,按 id 或 method 过滤
NNNNNN-<任务ID>-<方法名>.json这一次调用的完整请求与完整响应(含整页 data.text)要看原始报文、要复现某一步时的唯一凭据
uploads.logPOST /playwright/upload 的落盘记录:文件名、大小、摘要只记元数据,不记文件内容

文件名形如 000001-1001-get_browser_state.json,序号与页面留档的序号可以互相印证。

排查顺序建议:先看 steps.log 定位出问题的那一步 → 再看同名序号的 .json 看完整报文 → 最后按里面的 data/<id>/<序号>.txt 与 .png 看当时页面。

写盘失败(磁盘满、目录没权限)只留一条警告,不会让浏览器命令失败 —— 所以不能把日志存在当成命令成功的证据,反过来命令失败也不代表日志写失败。

脱敏 ​

browser.trace.redact.enabled 默认开启,落盘前会把以下内容替换成掩码(默认 ***):

  • 手机号;
  • 18 位身份证号 / 统一社会信用代码;
  • 邮箱;
  • 16~19 位长数字。

browser.trace.redact 可以追加自定义正则(逗号分隔),例如把公司名、商标名也掩掉;browser.trace.redact.mask 改掩码文本。

脱敏是「尽力而为」:按模式匹配,认不出来的个人信息(姓名、门牌号、账号)不会被掩掉。填表类任务里请求体带着姓名、手机号、证件号、详细地址是常态,交付或共享 logs/trace/ 之前请自己过一眼。需要原文时把 browser.trace.redact.enabled 设为 false。

其他开关 ​

上述 trace 脱敏不代表 data/<id>/ 的截图、页面文本或临时参数文件也已经脱敏。六位短信验证码、密钥、签名链接和图片中的个人信息尤其不能依赖普通模式匹配识别;分享前应逐类核验。操作经验见表单与多层弹窗排障。

配置项默认说明
browser.trace.enabledtrue关掉之后完全不落盘
browser.trace.dir<启动目录>/logs/trace换目录
browser.trace.maxRecordChars8000000单次调用完整报文的字符上限,超了截断并打标记。只有 screenshot 不带 path 时的内联大图可能撞到

二、页面留档:data/<id>/ ​

默认保留结构化文本,截图需显式请求。产物落在进程工作目录下的 data/<任务ID>/ 里:

时机产物
「会改变页面」的方法执行成功默认不截图;显式配置 browser.capture.enabled=true 后才生成 PNG
每次 get_browser_state<序号>.txt;显式传 screenshot:true 或 CLI state --screenshot 时另有同序号 PNG
显式调 screenshot / get_element_screenshotdata/<id>/shot-N.png

几点要知道:

  • 序号是每个任务独立的自增序号,从 1 开始;一对 .png / .txt 序号相同,表示是同一时刻的页面。
  • 两个文件都可以直接 GET:GET <服务地址>/data/<id>/<序号>.png 与 .../<序号>.txt。
  • <序号>.txt 的内容是「页签文本块 + 空行 + 可交互结构化文本」,也就是 data.browser_state 加 data.text,方便事后离线复看某一步的页面。
  • 哪些方法算「会改变页面」:导航类、点击与交互类、滚动与鼠标类、页签类、等待类、execute_js 与部分设置类。纯读取类(get_url、get_cookies、is_visible 等)不截图,否则每读一个值就多一张一模一样的图。
  • 显式启用动作自动截图后,批量调用时每一步结果包含对应截图,所以一次批量请求就能拿到整段操作的页面变化历史。
  • 截图前会尽力等页面进入 DOMCONTENTLOADED(有上限,等不到也照常截图),不会因为等待失败丢掉这一张。
  • 截图失败不会让方法失败,原因在 data.screenshot_error。
  • 长时间跑下来 data/ 会涨得很快,browser.capture.enabled 默认 false,仅在明确需要动作自动截图时设置 true;文本留档独立保留(显式调 screenshot 不受影响)。

这些文件不会自动清理,data/ 已经加进版本控制的忽略列表;不需要时直接删目录,或用 cleanup(默认只预演,要真删必须显式传 dryRun:false)。

三、客户端侧的留档 ​

服务端记的是「收到了什么」,客户端记的是「发出去了什么」—— 两者在「服务没起来、请求根本没发出去」这种情况下只有客户端那份能说明问题。

PowerShell 脚本Python 客户端
形态传一个请求文件发一次请求子命令式 CLI,也可作为库导入
留档位置logs/agent/<会话>/同左
文件NNN.req.json / NNN.res.json 成对 + 一份 steps.log同左

请求在发送前就落盘,所以连「没发出去」也能看出来。客户端侧使用与服务端同一套脱敏规则。

四、文件上传:POST /playwright/upload ​

客户端-服务器模式下,upload_file 的 path 必须是服务端能打开的路径。所以客户端要先把文件送到服务端,再把返回的路径回填给 upload_file。

同一个路由支持四种用法:

用法说明
POST /playwright/upload?filename=图样.jpg请求体直接是文件字节
POST /playwright/upload(multipart/form-data)文件字段默认叫 file
POST /playwright/upload(application/json){"filename":"图样.jpg","contentBase64":"..."}
GET /playwright/upload列出暂存目录里的文件
DELETE /playwright/upload?name=图样.jpg删除一个文件

回执里的 path(服务端绝对路径)与 relativePath(相对暂存目录的名字)都可以直接喂给 upload_file。

安全约束:

  • 文件名会被清洗(只留基本名、去掉路径分隔符与控制字符、保留中文),并且只能落在暂存目录里;
  • 单文件上限由 browser.upload.maxBytes 控制(默认 64MB,0 表示不限);
  • 同名文件默认覆盖,browser.upload.overwrite=false 时自动改名(a.jpg → a-1.jpg);
  • 整个接口可以用 browser.upload.enabled=false 关掉 —— 对外暴露的服务建议关掉它。

暂存目录默认是 <启动目录>/upload,同样不会自动清理。

五、execute_js 的脚本目录 ​

execute_js 支持把脚本放在服务端,用 bodyFile 引用:

json
{"id":"1001","method":"execute_js","params":{"bodyFile":"read-table.js","vars":{"sel":".vxe-table--body-wrapper"}}}
  • bodyFile 只能读脚本目录下的文件(默认 <启动目录>/scripts/js,可用 browser.js.dir 改),防止用它去读任意文件;
  • 脚本里可以用 占位,由 vars 注入 —— 中文、引号、换行都不用在客户端拼字符串。

这条路径存在的意义是绕开传输层的坑:多行脚本经命令行或消息队列传递时可能被截断,到服务端只剩第一行,报的还是语法错误(Unexpected end of input),很难联想到是传输问题。服务在检测到「脚本像是被截断了」时会直接给出改用 bodyFile 的提示。