11 KiB
日志规范
本文件是 skill 日志规范的权威入口,面向技术人员与 AI 编程代理。涉及长任务、RPA、外部系统对接的技能,必须在实现前通读本文,并在 code review 时对照「必打日志节点清单」人工检查。
1. 为什么日志是必需的
OpenClaw 技能常在客户电脑上异步执行,且大量依赖 RPA、浏览器、ERP、微信等外部系统。这类任务具备以下特征:
- 耗时长:单次 run 可能数分钟甚至更久,stdout 长时间无输出不代表卡死。
- 失败点多:网络抖动、页面改版、登录态失效、验证码、U 盾等都会导致中途失败。
- 环境差异大:客户 OS、浏览器版本、代理、杀毒软件、屏幕分辨率各不相同,无法复现开发机行为。
- 必须离线排查:技术支持往往无法远程登录客户电脑,只能依赖本地落盘的日志与 artifacts。
日志用于定位:
| 维度 | 说明 |
|---|---|
| 失败阶段 | 任务停在鉴权、取号、打开页面、提交还是等待结果 |
| 输入范围 | task_type、target_id、input_id、batch_id |
| 外部系统状态 | HTTP 状态、RPA 步骤、兄弟技能返回码 |
| 耗时 | elapsed_ms、批量 current/total |
| 重试与人工介入 | 第几次重试、是否等待验证码 / U 盾 |
| 存证路径 | 截图、录屏、video_log、失败 artifacts |
没有关键节点日志 = 客户现场不可排障。 不要把 print 当作日志;stdout 面向用户与 Agent,文件日志与 Run Journal 面向运维。
2. 日志分层
技能日志分四层,职责互不替代:
2.1 统一文件日志(开发 / 运维排查)
来源:jiangchang_skill_core.unified_logging(技能内通过 util.logging_config 薄封装 import)。
| API | 用途 |
|---|---|
setup_skill_logging |
CLI 入口启动时初始化(cli/app.py 的 main()) |
get_skill_logger |
获取带 skill_slug 的 logger |
subprocess_env_with_trace |
子进程 / 兄弟技能调用时传递 trace_id |
路径:
{JIANGCHANG_DATA_ROOT}/{JIANGCHANG_USER_ID}/logs/jiangchang.log
特征:每行带 trace_id、skill_slug;适合 grep、离线打包发给技术支持。
2.2 Activity / Run Journal(宿主 UI 与用户可见进度)
来源:jiangchang_skill_core.activity
| API | 用途 |
|---|---|
emit |
推送用户可读进度(不写 stdout) |
step |
结构化步骤 |
finish |
任务结束;唯一写单行 result JSON 到 stdout 的场景 |
rpa_step |
RPA 专用步骤文案 |
路径:
{JIANGCHANG_DATA_ROOT}/.jiangchang/runs/{job_id}.jsonl
约定:
emit不写 stdout;长任务应持续 emit,避免用户以为卡死。finish才输出单行 result JSON 供宿主解析。- RPA 类技能:
RpaVideoSession.add_step会自动同步 activity(无需重复手写每步 emit)。
2.3 task_logs(任务结果审计)
来源:db/task_logs_repository.save_task_log
- 适合
python scripts/main.py logs/log-get <id>查询。 - 记录任务最终状态、
result_summary(可含video_path、video_log等)。 - 面向「这次任务成功还是失败、摘要是什么」,不是逐步 trace。
- 鉴权失败与未捕获异常也必须写入
task_logs,保证logs/log-get排查链不断(见模板cmd_run示范)。
表结构与字段见 references/SCHEMA.md。
2.4 RPA video step / artifacts(用户可见动作与存证)
来源:RpaVideoSession、rpa-artifacts/ 目录
- 用户可见的中文步骤(「打开登录页」「点击提交」)。
- 录屏 MP4、
video_log(ffmpeg 诊断)。 - 失败截图:
{数据目录}/rpa-artifacts/{batch_id}/...
详见 RPA.md §失败存证与录屏标准。
3. 必打日志节点清单
以下节点应在生产代码中有对应 log.info / log.warning / log.exception(或 Activity / RPA step)。复制模板后按业务增删,但不可整体省略。
| 阶段 | 建议日志 / emit |
|---|---|
| CLI 入口启动 | cli_start(cli/app.py,已由模板提供) |
| 参数解析完成 | run_args target_id=... input_id=... |
| 鉴权开始 | entitlement_check_start |
| 鉴权成功 | entitlement_ok |
| 鉴权失败 | entitlement_failed(warning) |
| 任务开始 | task_start task_type=... target_id=... input_id=... batch_id=... + emit("开始处理任务") |
| adapter / test target 选择 | adapter_selected adapter=... system=... |
| 账号 / profile / lease 获取 | account_acquired account_id=... |
| 账号 / lease 释放 | account_released account_id=... |
| 外部 API 开始 | external_call_start system=... operation=... |
| 外部 API 结束 | external_call_done system=... operation=... elapsed_ms=... status=... |
| 兄弟技能调用开始 / 结束 | 同上,或 sibling_call_start/done skill_slug=... |
| RPA 操作开始 / 结束 | rpa_start / rpa_done + video.add_step 中文步骤 |
| 打开页面 | step:「打开 xxx 页面」 |
| 检查登录 | step + log |
| 定位输入框 / 点击提交 | step + log |
| 等待结果 | step + log(含 timeout 预期) |
| 批量循环 | batch_progress current=... total=... |
| 重试 | retry_attempt n=... reason=...(warning) |
| 跳过 / 部分失败 | skipped / partial_failure(warning) |
| 人工介入 | `human_intervention type=captcha |
| 失败截图 / 视频 | artifact_saved artifact_path=... / video_path=... |
| 任务成功 | task_success ... + task_log_saved status=success |
| 任务失败 | task_failed ...(exception 保留 traceback)+ task_log_saved status=failed |
4. 字段规范
推荐在 log.info 等消息中使用 key=value 结构化字段,便于 grep:
| 字段 | 含义 |
|---|---|
task_type |
任务类型(与 task_logs.task_type 对齐) |
target_id |
目标标识(平台、店铺、报表类型等) |
input_id |
输入记录 ID |
batch_id |
批次 / 录屏批次 |
stage |
阶段:auth / run / cleanup |
system |
外部系统名:erp / wechat / 1688 |
operation |
操作名:submit_order / fetch_report |
adapter |
adapter 档位:mock / simulator_api / real_api |
elapsed_ms |
耗时毫秒 |
status |
ok / failed / timeout / skipped |
error_code |
业务错误码(非 Python 异常名) |
artifact_path |
截图 / 附件路径 |
video_path |
录屏成品路径 |
示例:
external_call_done system=erp operation=download_report elapsed_ms=4523 status=ok
batch_progress current=7 total=20 target_id=store-001
5. 日志级别规范
| 级别 | 使用场景 |
|---|---|
| info | 关键阶段、成功路径、外部调用开始/结束、批量进度、task_log_saved |
| warning | 可恢复问题、重试、跳过、人工介入、部分失败、鉴权失败(业务可预期) |
| exception | 异常路径;必须用 log.exception(...) 保留 traceback |
| debug | 低频诊断;默认不依赖 debug 才能排查问题 |
原则:生产排障应主要靠 info + warning + exception,不要把 debug 当作唯一线索。
6. 敏感信息红线
禁止记录原始值
以下字段不得以明文出现在日志、Activity、task_logs 的 error_msg / result_summary、stdout:
password、token、cookie、secret、api_key、authorization- 验证码、动态口令全文
- 身份证、银行卡、手机号完整值
建议记录的安全替代
| 替代字段 | 示例 |
|---|---|
credential_ref |
vault / account-manager 引用 ID |
account_id |
账号表主键 |
masked_user |
138****8000 |
domain |
erp.example.com |
last4 |
卡号后四位 |
hash / short_id |
内容摘要 |
变量名可以叫 token,但日志里不能出现 token=eyJhbG... 或 f-string 拼接明文。
7. 推荐代码示例(service 层)
from util.logging_config import get_skill_logger
from jiangchang_skill_core.activity import emit
from util.constants import SKILL_SLUG
log = get_skill_logger()
def cmd_run(target=None, input_id=None):
task_type = "your_task"
log.info(
"task_start task_type=%s target_id=%s input_id=%s",
task_type, target, input_id,
)
emit("开始处理任务", skill=SKILL_SLUG, stage="run")
try:
ok, reason = check_entitlement(SKILL_SLUG)
if not ok:
log.warning("entitlement_failed task_type=%s reason=%s", task_type, reason)
return 1
t0 = time.monotonic()
# ... 外部调用 ...
elapsed_ms = int((time.monotonic() - t0) * 1000)
log.info(
"external_call_done system=%s operation=%s elapsed_ms=%d status=%s",
"erp", "submit", elapsed_ms, "ok",
)
tlr.save_task_log(..., status="success", ...)
log.info("task_log_saved task_type=%s status=success", task_type)
emit("任务完成", skill=SKILL_SLUG, stage="run")
return 0
except Exception:
log.exception(
"task_failed task_type=%s target_id=%s input_id=%s",
task_type, target, input_id,
)
emit("任务失败,已记录诊断信息", type="warn", skill=SKILL_SLUG, stage="run")
tlr.save_task_log(..., status="failed", error_msg="...", ...)
return 1
模板示范见 scripts/service/task_service.py 的 cmd_run。
8. 错误排查顺序
客户现场或测试机排障,建议按以下顺序(由快到慢、由用户可见到运维细节):
- CLI stdout — 是否有
ERROR:<CODE>:、HINT:、模板提示文案。 python scripts/main.py logs— 最近任务是否写入task_logs、status 与error_msg。python scripts/main.py log-get <id>— 单条 JSON,含result_summary(video 路径等)。- 统一日志文件 —
{JIANGCHANG_DATA_ROOT}/{JIANGCHANG_USER_ID}/logs/jiangchang.log(greptrace_id、task_failed)。 - Run Journal —
{JIANGCHANG_DATA_ROOT}/.jiangchang/runs/{job_id}.jsonl(宿主 UI 进度来源)。 - RPA artifacts —
rpa-artifacts/截图、录屏 MP4、video_log。
长时间无 stdout 不代表卡死;先看 Run Journal / Activity,再看统一日志。
9. 与现有文档关系
| 文档 | 关系 |
|---|---|
RUNTIME.md |
统一日志能力来源、util.logging_config 薄封装、数据根约定 |
TESTING.md |
日志相关 hard policy 测试(test_development_policy_guard.py) |
RPA.md |
RPA step、RpaVideoSession、video / artifacts 标准 |
SCHEMA.md |
task_logs 表结构与查询命令 |
CLI.md |
logs / log-get 命令与手工排查入口 |
CONFIG.md |
敏感配置不进日志;.env 边界 |
DEVELOPMENT.md |
service/ 层日志职责与发布前检查清单 |
POLICY_MATRIX.md |
可自动检测的 logging hard policy 索引 |