DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Gradle 构建 trace 只剩后一次会话,为每次调用使用独立路径

Gradle 的 trace 文件前缀属于一次会话,后续会话复用它会覆盖旧日志。为可控调用分别指定路径,并检查不受控的附加会话是否仍继承同一前缀。

采集了很久的 Gradle build-operation trace,最后文件却只剩一次短模型查询,先检查是否有第二个会话复用了同一个 trace base 路径。文件存在和任务成功,都不能证明它仍是第一次构建的记录。

Gradle 9.7.1 有过一个精确复现:先执行 :hello,再通过 Tooling API 请求构建模型,两次使用相同 base。第一次的 trace 有任务操作,第二次结束后相同文件只保留模型会话。根因是新会话打开已有 <base>-log.txt 时先删除它,再创建文件;这个参数指定的是一份会话输出的文件前缀,不是自动累积目录。

Gradle 9.8.1 的正式实现仍保留这个旧参数契约。不要把一个新目录参数的已合入补丁当成已发行功能,也不要直接对现有日志使用追加操作:不同会话的结构与辅助文件需要一起对应,简单拼接未必得到工具能正确解释的记录。

能够控制每次调用时,为它们提供不同 base。例如对两次明确的命令:

./gradlew :hello   -Dorg.gradle.internal.operations.trace=/tmp/gradle-task-session

./gradlew <另一次任务>   -Dorg.gradle.internal.operations.trace=/tmp/gradle-second-session

这些名字只是示例,实际采集还应避免与已保存记录撞名。可以先创建一次独立目录,再为该次受控调用指定其中的 base:

trace_dir=$(mktemp -d /tmp/gradle-trace.XXXXXX)
./gradlew <原任务>   "-Dorg.gradle.internal.operations.trace=$trace_dir/task"

不要把这个 base 放进会被全部后续会话继承的公共 JVM 参数,再误以为目录唯一就足够。若同一目录中的 task 被第二个会话继续复用,仍可能覆盖第一份记录。Tooling API 客户端也需要给自己启动的会话设置独立前缀;只修改终端那一次调用,不会自动修改 IDE 后台连接。

原案例没有证明 SonarScanner 就是发起第二次连接的进程,排查时应核对真正的调用来源。无法控制隐藏会话参数时,不能承诺上述命令解决全部覆盖;应采用能隔离采集环境或控制客户端参数的方式,并及时保存已完成输出,保留缺口说明。

验收分别记录每次完成时输出的 resolved trace 路径,查看任务操作、会话时长和辅助 tree 文件是否对应。再执行第二次调用,确认第一份文件内容与哈希没有变化,第二份输出落在另一条路径。不能只看文件修改时间或文件仍存在。

这是 Gradle 内部诊断选项,没有稳定公共 API 保证。正式的常规构建或其他性能采集工具有各自接口;这里的范围是明确使用 operations.trace 时避免会话文件碰撞,不保证恢复已经被覆盖的旧 trace。