日志
OpenClaw 有两个主要日志界面:
- 文件日志(JSON 行)由 Gateway 写入。
- 控制台输出在运行 Gateway 的终端中。
Control UI 的 Logs 选项卡会跟踪 Gateway 文件日志。本页说明日志存放位置、如何读取日志,以及如何配置日志级别和格式。
日志存放位置¶
默认情况下,Gateway 每天写入一个滚动日志文件。默认配置保留历史路径:
/tmp/openclaw/openclaw-YYYY-MM-DD.log
命名配置使用同一目录中带配置限定的文件名:
/tmp/openclaw/openclaw-<profile>-YYYY-MM-DD.log
文件名中的配置段为小写,且仅限字母、数字和连字符。简单的小写名称保持可读,因此 --dev 简写会写入
openclaw-dev-YYYY-MM-DD.log。大小写、下划线和字面连字符会使用可逆的连字符转义,以确保不同的配置名称不会共享同一个日志文件。
通过环境变量直接设置的超大值会使用有界的哈希后缀,以保持在文件系统文件名限制内。显式的 logging.file 会覆盖这些默认值。
日期使用 Gateway 主机的本地时区。当 /tmp/openclaw 不安全或不可用(在 Windows 上始终如此)时,OpenClaw 会改用操作系统临时目录下的用户级
openclaw-<uid> 目录。带日期的日志文件会在 24 小时后被清理。
当下一次写入将超过 logging.maxFileBytes(默认:100 MB)时,每个文件都会轮转。OpenClaw 会在活动文件旁边保留最多五个带编号的归档文件,例如
openclaw-YYYY-MM-DD.1.log 或
openclaw-dev-YYYY-MM-DD.1.log,并继续写入新的活动日志,而不是抑制诊断信息。
你可以在 ~/.openclaw/openclaw.json 中覆盖路径:
如何读取日志¶
CLI:实时跟踪(推荐)¶
通过 RPC 跟踪 Gateway 日志文件:
根配置选择器会解析 Gateway 使用的同一配置特定文件,包括在本地 RPC 不可用时 CLI 的回退读取。
选项:
| 标志 | 默认值 | 行为 |
|---|---|---|
--follow |
关闭 | 持续跟踪;断开时带退避重连 |
--limit <n> |
200 |
每次获取的最大行数 |
--max-bytes <n> |
250000 |
每次读取的最大字节数 |
--interval <ms> |
1000 |
跟踪时的轮询间隔 |
--json |
关闭 | 按行分隔的 JSON(每行一个事件) |
--plain |
关闭 | 在 TTY 会话中强制纯文本 |
--no-color |
— | 禁用 ANSI 颜色 |
--utc |
关闭 | 以 UTC 渲染时间戳(默认为本地时间) |
--local-time |
关闭 | 接受作为本地时间默认值的兼容拼写;除此之外无其他效果 |
--url / --token |
— | 标准 Gateway RPC 标志 |
--timeout <ms> |
30000 |
Gateway RPC 超时 |
--expect-final |
关闭 | 由 Agent 支持的 RPC 最终响应等待标志(此处通过共享客户端层接受) |
输出模式:
- TTY 会话:美观、带颜色的结构化日志行。
- 非 TTY 会话:纯文本。
当传入显式 --url 时,CLI 不会自动应用配置或环境凭据;请自行包含 --token,否则调用会失败并提示
gateway url override requires explicit credentials。
在 JSON 模式下,CLI 会输出带 type 标签的对象:
meta:流元数据(file、source、sourceKind、service、cursor、size)log:已解析的日志条目notice:截断/轮转提示raw:未解析的日志行error:Gateway 连接失败(写入 stderr)
如果隐式的本地回环 Gateway 要求配对、在连接期间关闭,或在 logs.tail 响应前超时,openclaw logs 会自动回退到已配置的 Gateway 文件日志。显式 --url 目标不使用此回退。openclaw logs --follow 更严格:在 Linux 上,如果可用,它会按 PID 使用活动的用户 systemd Gateway 日志;否则,它会带退避重试实时 Gateway,而不是跟踪可能过时的并排文件。
如果 Gateway 不可达,CLI 会打印一条简短提示,建议运行:
Control UI(Web)¶
Control UI 的 Logs 选项卡使用 logs.tail 跟踪同一文件。
有关打开方式,请参阅 Control UI。
仅通道日志¶
要过滤通道活动(WhatsApp/Telegram 等),请使用:
--channel 默认为 all;还可使用 --lines <n>(默认 200)和 --json。
日志格式¶
文件日志(JSONL)¶
日志文件中的每一行都是一个 JSON 对象。CLI 和 Control UI 会解析这些条目以渲染结构化输出(时间、级别、子系统、消息)。
文件日志 JSONL 记录在可用时还会包含可机器过滤的顶层字段:
hostname:Gateway 主机名。message:用于全文搜索的扁平化日志消息文本。agent_id:当日志调用携带 Agent 上下文时,活动的 Agent ID。session_id:当日志调用携带会话上下文时,活动的会话 ID/密钥。channel:当日志调用携带通道上下文时,活动的通道。
OpenClaw 会保留原始结构化日志参数,并与这些字段并存,以便读取带编号 tslog 参数键的现有解析器继续正常工作。
Talk、实时语音和托管房间活动通过同一文件日志管道发出有界生命周期日志记录。这些记录在可用时包括事件类型、模式、传输、提供商以及大小/计时测量,但省略转录文本、音频负载、轮次 ID、通话 ID 和提供商项 ID。
控制台输出¶
控制台日志支持 TTY,并按可读性格式化:
- 子系统前缀(例如
gateway/channels/whatsapp) - 级别着色(info/warn/error)
- 可选紧凑或 JSON 模式
warn、error和fatal记录上的结构化字段,会作为一条紧凑的key=value ...尾部追加(嵌套值以 JSON 表示,上限为 2 KiB),以便 journald 等纯文本接收端保留诊断信息;info及更低级别的控制台行仅保留消息,而文件日志始终携带完整记录。 这些字段在展平前会经过与json控制台样式相同的脱敏处理,因此像apiToken这样的敏感键会按名称掩码,长度上限只能截断已经掩码的文本。
控制台格式由 logging.consoleStyle 控制。
SQLite 工作进程诊断使用 stderr。最终后端正常关闭后,工作进程会给予待处理控制台输出最多五秒的排空时间,然后再确认关闭。这是尽力而为;强制终止工作进程仍可能丢弃待处理诊断。
Gateway WebSocket 日志¶
openclaw gateway 还具有用于 RPC 流量的 WebSocket 协议日志:
- 普通模式:仅记录值得注意的结果(错误、解析错误、慢调用)
--verbose:所有请求/响应流量--ws-log auto|compact|full:选择详细渲染样式--compact:--ws-log compact的别名
示例:
openclaw gateway
openclaw gateway --verbose --ws-log compact
openclaw gateway --verbose --ws-log full
转向与输入取消¶
当保留的回复投递状态阻止转向时,Gateway 会记录 chat steering rejected; falling back to follow-up dispatch。其结构化字段会区分传入输入的 runId 与 activeRunId,并记录会话、活动源轮次、恢复声明以及确切的 reason:
terminal-pending或delivered-terminal:存在最终回复回执。unresolved-terminal-tool或delivery-ambiguous:最终回复投递未解决。already-delivered:活动源轮次被记录为已完成。unknown-source-with-terminal-history:活动源未知,且保留了已完成的源轮次。stale-claim:恢复声明未授权活动源轮次。session-entry-unavailable:Gateway 无法读取当前会话状态。
这些检查也会在普通对话期间运行;该警告并不意味着 Gateway 重启正在进行。拒绝会回退到后续分发;它本身不会取消输入。
chat pending input aborted 记录在消费前被中止的已接受输入,包括等待在后续队列中的输入。消息包含原因以及已保存输入变为 cancelled 还是 interrupted。结构化字段包括其运行、会话和代理 ID。原因区分 rpc、stop、timeout、restart、archive、delete、authority-revoked 和 superseded;未分类的中止使用 aborted。这些记录省略消息文本和附件。
配置日志¶
所有日志配置都位于 ~/.openclaw/openclaw.json 中的 logging 下。
{
"logging": {
"level": "info",
"file": "/path/to/openclaw.log",
"consoleLevel": "info",
"consoleStyle": "pretty",
"redactPatterns": ["sk-.*"]
}
}
日志级别¶
级别:silent、fatal、error、warn、info、debug、trace。
logging.level:文件日志(JSONL)级别(默认:info)。logging.consoleLevel:控制台详细级别。
你可以通过 OPENCLAW_LOG_LEVEL 环境变量覆盖两者(例如 OPENCLAW_LOG_LEVEL=debug)。环境变量优先于配置文件,因此你可以在不编辑 openclaw.json 的情况下为单次运行提高详细程度。你还可以传入全局 CLI 选项 --log-level <level>(例如 openclaw --log-level debug gateway run),它会针对该命令覆盖环境变量。
--verbose 仅影响控制台输出和 WS 日志详细程度;它不会更改文件日志级别。
提供商请求失败¶
Anthropic 兼容的 HTTP 失败会将 HTTP 状态与有界、已脱敏的响应体分开保留。JSON 错误体会在诊断脱敏和预览截断之前解析,因此较长的代理错误不会仅仅因为控制台预览较短而丢失其状态或上游拒绝原因。超大或格式错误的响应体仍可能被诊断脱敏器省略。
聊天会显示已识别的请求限制事实,包括允许和实际的 cache_control 块数量,既适用于实时失败,也适用于保存的历史记录。原始代理元数据保留在已脱敏的诊断信息中,而不是聊天消息中。
保存的失败回复还会区分速率限制、身份验证失败、提供商 HTTP 错误和网络中断。工作进程推理会保留有界、已脱敏的错误详情用于分类,包括当大型部分响应无法放入转录时。未识别的错误仍使用通用聊天文案;请检查 Gateway 日志和存储的错误以进行诊断。
Responses 输出身份冲突会记录事件类型、输出位置、预期和观察到的项类型,以及工具调用是否完成,而不记录项 ID 或响应内容。OpenClaw 在失败响应未产生可见文本或已完成工具调用,且其请求仅启用客户端执行函数工具时,使用现有的有界会话重试策略。继续会保留较早的工具结果,因此这些已完成操作不会被重放。输出之后的冲突或涉及提供商托管工具的冲突仍为终止状态;继续之前请检查较早的结果。先前已输出的文本即使后续快照将其清除也仍为终止状态。自动恢复需要一个成功完成且无拒绝的响应;该终止之前的冲突无法重试,因为最终结果未知。失败或不完整的终止响应(包括内容过滤)不能被身份恢复覆盖。身份检查在每次尝试中都会强制执行。
worker 消息大小失败与模型上下文窗口限制是相互独立的问题。 请使用更小的响应重试,或继续在 Gateway 上继续。如果 worker 无法保留 模型的继续数据,请在 Gateway 上重试之前停止或回收它。较早的工具操作 可能已经完成,因此在重复执行之前请检查其结果。
定向模型传输诊断¶
调试提供商调用时,请使用有针对性的环境变量标志,而不是将所有日志级别
提高到 debug:
OPENCLAW_DEBUG_MODEL_TRANSPORT=1 openclaw gateway
OPENCLAW_DEBUG_MODEL_PAYLOAD=tools OPENCLAW_DEBUG_SSE=events openclaw gateway
可用标志:
OPENCLAW_DEBUG_MODEL_TRANSPORT=1:在info级别输出请求开始、获取响应、SDK 请求头、首个流式事件、流完成以及传输错误。OPENCLAW_DEBUG_MODEL_PAYLOAD=summary:在模型请求日志中包含有界请求负载 摘要。OPENCLAW_DEBUG_MODEL_PAYLOAD=tools:在负载摘要中包含所有面向模型的工具名称。OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted:包含一个经过脱敏且截断的 JSON 负载快照。仅在调试时使用;密钥会被脱敏,但提示词和消息文本可能仍然存在。OPENCLAW_DEBUG_SSE=events:输出首个事件和流完成的时间信息。OPENCLAW_DEBUG_SSE=peek:同时输出前五个经过脱敏的 SSE 事件负载,每个事件均有截断上限。OPENCLAW_DEBUG_CODE_MODE=1:输出代码模式模型界面诊断信息,包括有界的激活事实、 最终可见界面,以及因代码模式拥有工具界面而被过滤的提供商原生工具名称。
这些标志通过常规 OpenClaw 日志记录,因此 openclaw logs --follow
和控制 UI 的日志选项卡会显示它们。出于向后兼容,
OPENCLAW_DEBUG_CODE_MODE 还会将通用模型传输诊断提升到
info;专用代码模式诊断仅在该标志启用时输出。
[model-fetch] 的开始和响应元数据(提供商、API、模型、状态、
延迟,以及诸如方法、URL、超时、代理和策略等请求字段)
默认使用 debug。状态非 2xx 或耗时至少一秒的响应仍保持 info,传输失败仍保持警告。
耗时包括本地服务准备和等待响应头,但不包括流式传输响应体。故障排查时,上述有针对性的调试标志会将
开始和快速成功响应的元数据提升到 info。
[anthropic] replayed thinking dropped: N block(s) 是警告,当 Anthropic
报告在重放中丢弃了失效的思考内容时出现。它包含不匹配
原因和最多五个受影响的消息路径,不包含思考内容。无需
调试标志。
[anthropic] server-side context edit: cleared N tool results (M input tokens)
是信息级别日志,当 Anthropic 报告应用了服务端工具结果清除时出现。它仅包含计数,不包含工具参数或结果内容,且
无需调试标志。有关启用清除的路由和阈值,请参阅 会话修剪。
跟踪关联¶
文件日志为 JSONL。当日志调用携带有效的诊断跟踪上下文时,
OpenClaw 会将跟踪字段写入为顶层 JSON 键(traceId、spanId、
parentSpanId、traceFlags),以便外部日志处理器将该行与 OTEL span 以及提供商的 traceparent 传播进行关联。
Gateway HTTP 请求和 Gateway WebSocket 帧会建立内部请求跟踪作用域。在该异步作用域内输出的日志和诊断事件,如果未传递显式跟踪上下文,则会继承请求跟踪。代理运行和模型调用跟踪会成为活动请求跟踪的子项,因此本地日志、诊断快照、OTEL span 以及受信任提供商的 traceparent 头可以通过 traceId 关联,而无需记录原始请求或模型内容。
Talk 生命周期日志记录在启用 OpenTelemetry 日志导出时也会流向 diagnostics-otel 日志导出,使用与文件日志相同的有界属性。配置 diagnostics.otel.logsExporter 可选择 OTLP、stdout JSONL 或两者作为输出目标。
嵌入式尝试准备¶
嵌入式 prep stages 摘要区分了两个工具准备区间:
bundle-tools:等待的 MCP/LSP 准备、工具规范化以及策略投影,在准备准入后测量。tool-catalog:同步目录构建,包括启用时的 Code Mode 或工具搜索、模式投影和工具诊断。
tool-preparation 是从前一个 bootstrap 检查点开始的包含性检查点。它包括上述两个区间、准备准入等待以及剩余的 bootstrap 工作。这些条目存在重叠:不要将它们相加,也不要将其解释为 CPU 时间。后续权限刷新不会追加初始准备条目。条件性的 Code Mode 和工具搜索目录消息仍会报告其原始激活/压缩事件。
旧版摘要将 bundle 等待计入 code-mode 或 tool-search,并使用 bundle-tools 作为后续记账检查点。这些名称无法提供与修正后的 span 相同的计时边界。
该摘要保留其现有标识字段和警告阈值:总计十秒或任何已记录阶段五秒;更快的摘要使用跟踪日志。缺少摘要并不能证明准备已完成且无延迟。
会话目录提供商等待¶
启用进程诊断后,gateway/session-catalog 日志记录器会为至少一秒后才结算的尝试记录 slow session catalog provider list。
admissionWaitMs 记录初始提供商准入等待。providerElapsedMs
涵盖从首次提供商调用到最终逻辑结算,包括分步填充中各步骤之间的等待。completionDelayMs 从最终结算和队列释放之后开始。Gateway 更早的 operator-start 队列是独立的。
stepCount 统计已准入的回调。admittedStepMs 汇总其经过实际结算的耗时,包括权限检查、工厂工作和 I/O 等待。continuationWaitMs 测量不完整步骤之后直到恢复或取消的队列等待;它不包括初始准入。这些字段并非精确的不相交划分,也不测量 CPU 时间。
admitted 和 providerInvoked 区分从未进入队列活动槽位的尝试与调用了提供方的尝试。未到达的区间会被省略。outcome 报告尝试的完成或拒绝;signalAborted 独立报告信号,并不标识错误原因,也不证明原生工作已停止。活动提供方调用或 next() 步骤会保留其槽位,直到其实际 Promise 完成,包括取消之后。惰性延续会在步骤之间与其他调用者一起排队。
providerIdHash 对最多 256 个 UTF-16 单元的提供方 ID 进行哈希;更长的 ID 会省略该字段。它支持关联,而不是匿名化或授权。主机摘要仅统计返回的 gateway/node 类型、连接标志和错误存在情况,最多检查 512 个主机。returnedHostCount 报告完整数组长度,hostCountsComplete=false 表示部分计数。不包含会话行、主机 ID、提供方标签、搜索文本或错误消息。
每个摘要描述一个底层提供方尝试。缓存中和进行中的跟随者可能从该一次尝试中收到多个 RPC 响应。后续的 waitUntil 主机发布具有独立的生存期,不计入提供方持续时间或返回主机计数。日志不能证明客户端已接收、识别哪个原生操作较慢,或涵盖从未完成的尝试。缺失记录不能证明没有发生停滞。
Codex 目录阶段¶
相同的 gateway/session-catalog 日志记录器在启用进程诊断和警告级别日志时记录三个 Codex 摘要。每个摘要仅在其观察到的操作完成且耗时至少一秒后发出:
slow Codex catalog list phases覆盖插件的列表操作。managedSnapshotMs、controlWaitSumMs、exclusionMarkSumMs、adoptionSumMs和mappingMs标识已到达的工作。计数包括localHostCount、controlPageCalls、exclusionMarkCalls和adoptionCalls。 当可选快照方法或存储不可用时,managedSnapshotMs会缺失。nodeRegistryCalls和nodeRegistryMs测量现有节点注册表调用;pairedNodeCalls、pairedNodeSettled和nodeWaitSumMs描述列表到达的配对节点 Promise。缓存计数器coldStarts、refreshStarts、freshHits、staleHits和pendingJoins区分新生产者、后台刷新、即时缓存交付以及等待现有冷页面的调用者。slow Codex catalog page producer测量一次控制页计算。listOperationId在观察到时标识其来源列表。origin为cold、refresh或uncached。controlRequestCalls统计 已进入的控制请求;inclusiveControlRequestWaitMs汇总它们的已耗时 等待,inclusiveControlRequestWaitMaxMs报告最长的一项。postResponseMs覆盖后续来源检查和页面投影。provenanceChecks、provenanceCacheHits、provenanceReadCalls和provenanceMs描述现有来源路径。provenanceReadCalls统计对元数据读取器的调用,而不是文件系统读取系统调用或数据块。stopReason在到达时为exhausted、limit或page-bound。slow Codex catalog cache wait测量调用者等待一个待处理的冷页面。producerOperationId将其链接到已观察到的生产者;listOperationId在可用时链接周围的列表。producerObserved=false表示生产者的诊断标识不可用,而不是不存在生产者。
页面生产者摘要还会在现有控制阶段转换处累积已耗时。重复阶段(包括选择重试)以及多次控制调用都会计入同一页面总计。每个总计仅在摘要发出时舍入。未到达的阶段会缺失;已到达的阶段可能报告零毫秒。
被拒绝的控制调用可以添加 controlFailurePhase 和
controlFailureCategory。失败阶段使用相同的逻辑边界:
| 控制阶段 | 耗时字段 | 边界 |
|---|---|---|
load-control |
controlLoadMs |
在请求所有者报告其第一个阶段之前,加载并进入控制模块。 |
prepare |
controlPrepareMs |
在获取或客户端 API 入口之前,进行选项、守卫、导入或参数/预算评估。 |
acquire-client |
controlAcquireClientMs |
共享客户端选择、进程注册准备、可能的启动、身份验证、初始化和就绪状态。 |
client-request |
controlClientRequestMs |
已调用客户端 API;就绪状态、共享原生请求等待、重试和调用者延续仍可能发生在其中。 |
release-client |
controlReleaseClientMs |
逻辑租约释放或清理,包括清理后的更晚截止期限决定。这不是物理进程退出的证明。 |
这些是调用者观察到的区间,在该控制调用报告失败或关闭时冻结。它们排除在外部超时后继续的底层工作。对已固定连接的调用可能省略获取和释放,因为周围的固定拥有这些操作。设置/结算间隙和舍入意味着阶段总计不必恰好等于包含式等待。
类别为 deadline-observed、scoped-rejection、
rpc-method-unavailable(类型化 RPC 错误代码 -32601)、rpc-error 或 other。
它们使用现有所有者决定和类型化错误,不复制异常
消息、堆栈、响应数据或任意错误代码。普通启动、
传输和其他未分类错误仍为 other;该类别不会
标识其原因。公开的不可用主机消息仍保持脱敏。
成功的清理会保留较早错误的阶段,除非外部请求所有者观察到其截止时间。对于 deadline-observed,阶段是稍后决策时的活动阶段,即使清理刚刚完成。例如,release-client/deadline-observed 可能出现在客户端 API 从未被调用之前的预算耗尽之后;它不能证明清理导致了截止时间。替换请求错误的清理错误会报告 release-client。内部处理的重试和成功请求不会发布失败字段,延迟回调也不能覆盖已确定的观察。
这些字段不能证明原生请求已写入、原生进程失败,或响应已到达客户端。在控制调用拒绝后,包含列表可以解析为不可用主机。
operationId 局限于 diagnosticEpoch、PID 和线程。它不是会话、原生请求或审计执行身份。一个生产者可以服务多个等待者,并且过期刷新可以在列表返回后继续。outcome=resolved 表示被观察的操作已返回;已解析列表可以包含已断开或携带错误的主机。
所有计时均为经过时间,包括异步等待。包含控制请求的区间及其逻辑阶段总和不能隔离物理请求写入、线路延迟或原生 CPU,也不能证明原生进程已停止。多个调用者可能正在等待同一底层工作。来源时间包含在响应后时间中,并且主机工作可能重叠,因此总和无需划分列表的经过时间。nodeWaitSumMs 对现有配对节点承诺等待求和;它不是不相交的节点阶段,也不是原生完成的证明。如果列表关闭时某个子承诺尚未确定,pairedNodeCalls 可能超过 pairedNodeSettled,并且总和是部分的。后续主机发布保留其独立生命周期。未到达的计时被省略,而已到达的阶段可能报告零毫秒。
跟踪器每个 JavaScript 运行时隔离区最多允许 64 个活动诊断观察,并且在这三个摘要之间共享每个固定 60 秒窗口 60 条记录的预算。这些限制会抑制观察,而不是目录工作。每条记录的元数据上限为 28 个标量字段和 2 KiB,不包括日志记录器信封。omittedObservations 在稍后发出的记录上报告累积的容量、速率或元数据限制抑制。窗口边界突发仍然可能发生。禁用的诊断、日志级别、短操作、未确定或日志失败也可能不留下记录。
记录包含固定标签、计数、计时和诊断操作身份。它们省略连接指纹、查询、游标、主目录、路径、会话/线程标识符、标题、凭据和原始错误。现有跟踪上下文可能伴随日志;不会创建跟踪或审计身份。这些是普通性能日志,不会更改审计收集、授权、缓存行为或截止时间。其脱敏属性可能通过已启用的OpenTelemetry 日志导出器流动,即使内容捕获已关闭。缺失日志不能证明不存在停顿。
生命周期队列等待¶
当进程诊断启用时,sessions/lifecycle 日志记录器会在队列获取在一秒后仍待处理时,一次性发出 session lifecycle queue waiting。它标识 mutation 或 lifecycle 队列,并在该瞬间采样其当前持有者。持有者可能自等待者进入队列以来已经改变。在获取之后运行的延迟计时器不会发出持有者样本。
operationId 和 holderOperationId 在 diagnosticEpoch、PID 和线程内标识诊断操作实例。操作使用固定边界标签 lifecycle、mutation 和 compaction;它们不命名任意调用者。现有请求跟踪在存在时出现在 operationTraceId/operationSpanId 和单独的 holderTraceId/holderSpanId 字段中。缺失的跟踪字段保持未知;不会创建新的跟踪或审计执行身份。
identityHash 是已规范化存储/会话身份的加盐摘要。它仅在同一 JavaScript 运行时隔离区和诊断纪元内关联。原始会话键和路径被省略。该摘要用于操作关联,不是匿名化或授权证据。
slow session lifecycle operation 记录至少持续一秒的操作,直至其实际排队工作确定。它区分 mutationQueueWaitMs、lifecycleQueueWaitMs、completionDelayMs 以及 phaseDurationsMs.prepare、.run 和 .finalize。持有者当前的 holderPhase 也可以标识激活、准入或释放工作。lifecycle 操作描述其在现有活动变更空闲等待之后的队列尝试;该先前空闲等待不在此处测量。没有规范化身份的调用没有队列,并且不发出队列操作摘要。调用者可以在其所有排队工作展开之前取消;signalAborted 报告信号,但不声称持有者已释放。
跟踪器跨重入工作保留外部所有权,并且仅在其实际队列回调退出时退役持有者。其状态弱跟随现有队列对象;它不创建另一个执行队列。每个运行时隔离区,它最多保留 128 个持有者描述符和 32 个一次性等待计时器,并且每分钟最多发出 60 条记录。队列计时所有者显式区分重入,因此未观察的外部持有者在容量达到或启用后保持未知。稍后记录上的 omittedObservations 报告被抑制的观察;缺失记录永远不能证明没有等待。
经过区间可以包括异步等待和嵌套工作,因此阶段和队列总和无需形成不相交划分。持有者样本标识采样瞬间谁拥有该队列,而不是负责整个等待的每个前驱,或哪项工作消耗了 CPU。这些是普通性能日志。它们不使用或更改审计身份、决策、保留、主体归属或准入权限。
工作池容量¶
Gateway status 响应包含 workerPools.transcriptReconciliation 和
workerPools.modelCatalog。每个池报告来自池所有者的 maxWorkers、workers、workersCreated、
activeTasks 和 pendingTasks。两个 Gateway 池每次只接纳一个
worker。待处理任务包括排队中和执行中的工作;创建计数
属于当前池生命周期。启动跟踪中的 memory.ready 记录也
包含这些池计数。
这些数字描述 worker 和任务数量。进程 RSS 包含每个 isolate 和原生分配;Node 的进程堆标志可以覆盖某个 worker 请求的 堆限制。在将内存增长归因于特定 worker 时,请使用构造函数或按 isolate 的测量。
慢速 worktree 清理¶
启用进程诊断和 info 级别日志后,两个子系统会在操作返回或抛出后记录持续至少一秒的操作:
agents/worktrees:slow managed worktree removal测量移除直至分配租约结算。admissionMs覆盖移除回调开始前的获取尝试、 退避、设置和调度。bodyMs覆盖该回调;finalizeMs覆盖排空、最终权限检查、 租约释放和完成投递。创建和恢复操作不会 发出此记录。git/ref-mutation:slow Git ref mutation测量共享 Git 引用队列 操作。resolveMs覆盖公共目录解析;queueWaitMs覆盖从入队到回调进入的时间;queuedOperationMs覆盖 回调及其结算的投递。它可以包含多个 Git 命令, 并且不会识别队列持有者或每个前序操作。
移除还会记录在 bodyMs 内到达的阶段:
preparationMs:权限和移除声明检查、仓库重绑定,以及 worktree 锁检查或解锁。snapshotMs:快照准备和发布,包括预置文件 捕获和快照失败清理。checkoutRemovalMs:删除准入检查,以及物理 Git worktree 移除直至结果验证。bodyFinalizeMs:分支删除、修剪、空父级清理、注册表 最终化,或失败后的移除声明清理。这与finalizeMs不同,后者测量分配租约包装器的最终结算。
未到达的阶段不存在;已到达的阶段可以报告零毫秒。
异常会关闭活动阶段,并将声明清理计入 bodyFinalizeMs。
这些字段细分的是已准入的主体,而不是单个 Git 命令或 CPU
工作。它们使用相同的完成记录和速率预算。
两条记录都包含以整数毫秒为单位的 durationMs、callbackEntered 和
outcome(returned 或 threw)。从未进入其回调的移除会将
所有经过时间报告为 admissionMs,并省略 bodyMs 和 finalizeMs。Git 目录
解析失败会报告 resolveMs,并省略未到达的队列和操作
时长。阶段时长在舍入前划分每条记录的区间。
这些区间包含异步等待:准入不是纯锁等待,
排队操作时间也不是子进程 CPU 时间。它们嵌套在
更广泛的操作中,例如会话补丁 worktreeCleanup;不要将嵌套
时长加到外层总时长中。
每个子系统都有独立的固定预算:每个 JavaScript 运行时 isolate 每 60 秒窗口
60 条记录。跨窗口边界的突发仍可能发生。
omittedObservations 会在下一条发出的记录中报告被抑制的记录,
然后重置。待处理操作在结算前不会发出任何内容;禁用的
诊断、日志级别、阈值和预算也可能不留下记录。
缺失记录永远不能证明没有延迟。
新增字段是固定的标量计时、结果、计数、pid、threadId
和 isMainThread。它们省略仓库路径、引用、参数、原始错误和
命令输出。记录在可用时保留现有有效诊断跟踪;它们不创建跟踪、操作标识或私有标识哈希。
使用跟踪来关联嵌套记录,但不要将经过时间视为 CPU
归因。这些诊断测量清理过程,但不改变其顺序或
完成行为。
慢速代理数据库打开¶
当持久数据库打开至少需要一秒时,slow OpenClaw agent database open 警告会包含 phaseDurationsMs:
| 阶段 | 包含的工作 |
|---|---|
open |
权限、句柄驱逐以及打开连接。 |
validation |
完整性、版本和所有者检查,包括异步准入期间等待 Worker 和重新验证。 |
configuration |
连接和 WAL 设置。 |
schema |
需要时的模式初始化或收敛。 |
registration |
验证后的驱逐和权限、清理设置以及共享状态注册。 |
以整数毫秒为单位的时长划分 elapsedMs,该值在获取租约后使用单调时钟测量。实时缓存命中保持静默。这些
是经过时长,包括异步等待,而不是 CPU 时间,也不是主事件循环在整个区间内都被阻塞的证明。
结构化警告还包含发出它的打开者的 pid、Node 的 threadId 和 isMainThread。检查每个 openclaw logs --json 事件的原始
raw 记录;warn 级别的控制台文本也会以 key=value 对携带这些字段。
主线程上的打开者可能已等待完整性 Worker,因此这些
字段不能识别执行每个阶段的线程。admissionMode 记录
实际的 sync 或 async 打开驱动。异步准入会卸载其初始
完整性检查;恢复的验证和修复仍可能在打开者上运行。
将进程 ID 与日志时间戳和当前进程进行关联;PID 在退出后可能被重用。
integrityGateMs 覆盖从初始完整性检查到准入重新验证和恢复的整个过程。当驱动程序测量其同步完整性和外键回调时,integrityCheckSyncMs 报告该回调的耗时,integrityOutsideCheckMs 报告剩余的闸门时间。这两个整数字段划分 integrityGateMs;剩余部分包括准入、IPC、调度和重新验证,而不仅仅是父队列等待。这些是墙钟时长,而不是 CPU 时间。回收 Worker 可以在其 admissionMode 为 async 时报告此同步检查。异步子进程检查会使这两个字段缺失,因为其父进程无法测量该回调本身。
SQLite 回收 Worker 还会在其参与的操作耗时至少一秒时,以 warn 级别发出 slow SQLite reclamation Worker operation。该记录在 Worker 结果已确定或原生退出以及父进程准入结算之后发出。它包括父进程的 pid、threadId 和 isMainThread、实际的 Node workerThreadId、reclamationKind、elapsedMs、最终 outcome(resolved 或 rejected)以及 exitCode。计时从准入到归档 Worker 队列之后开始,包括启动、验证、准入等待、工作和清理。它不测量 CPU 时间,不单独隔离验证阶段,也不证明发出该记录的父线程发生了阻塞。因此,较短的写入器区段可能保持安静,而此整个操作警告会暴露它们之间缓慢的准备过程。当存在可用的父级跟踪时,该记录会继承现有父级跟踪。失败的保留回收操作还包括 sessionIdHash(当针对单个会话时)、error(脱敏后的消息和原因)以及 errorFrame(第一个堆栈帧)。这些失败即使低于一秒也会发出一个名为 SQLite reclamation Worker failed 的警告;更慢的失败使用现有的慢操作警告。如果较新的会话写入在提交前取代了自动维护,则这不属于 Worker 失败:维护会在写入静默窗口之后重试,而快速被取代的 Worker 会以 debug 级别记录 SQLite reclamation Worker superseded by newer inputs。会话标识符使用与其他会话 SQLite 诊断相同的哈希;失败字段经过脱敏,并且每个字段限制为 2,048 个字符。冷存储操作使用相同的警告,reclamationKind 设置为 cold-batch(归档或外部化)、cold-maintain(回收空闲页)或 cold-restore(恢复转录)。它们的写入器警告携带相同的 Worker 标识和编号准入字段。
SQLite 事务计时¶
sqlite/transaction 警告 slow SQLite transaction hold、slow SQLite transaction step 和 SQLite transaction lock wait failed 包括执行事务的线程的 database、operation、pid、Node 的 threadId 以及 isMainThread。显式标签优先;否则诊断使用原生数据库路径和当前 Worker 操作。内存数据库为 :memory:,已退役句柄为 unavailable,没有操作上下文的调用方为 unlabeled。持有警告还包括 mode(deferred 或 immediate)。检查 openclaw logs --json 中的原始 raw 记录,以区分主线程和共享同一进程的 Worker。async: false 描述同步事务辅助函数;它不用于识别线程。
持有时间从 BEGIN 成功之后开始,包括同步回调、结果检查以及提交或回滚。它不包括数据库打开和 begin 步骤。事务内部的宿主准入等待计入其持有时间;重叠的延迟读持有并不能证明多个写入器持有锁。成功的 begin 和 commit 步骤计时包括原生执行、存储工作和调度延迟;它们不证明存在锁争用。单独的 SQLite transaction lock wait failed 警告标识捕获到的 SQLite 锁错误。这些耗时不测量 SQL CPU 时间,也不建立与附近请求的因果联系。
旧版本构建会为父端在授权回收或冷存储提交后执行的同步 SQLite 探测报告 session.reclamation.commit-settlement。父进程现在在检查实时权限后原子地接受提交,并异步等待结算,不再进行该探测或其锁等待。
热转录读取在 operation 中识别其目的:session transcript <purpose> read,其中 <purpose> 为 identity、header、tail、incremental、checkpoint、events、raw rows 或 match。这些固定标签用于区分读取器,而无需保留会话 ID 或转录内容。嵌套读取仍然是外层事务计时的一部分;旧警告使用通用的 session transcript hot read 标签。
session branch summaries read 覆盖快照读取和分支摘要计算。存储会话在后台 Worker 中执行此工作;隐身会话使用其进程持有的数据库。缓存命中不会执行此扫描。
立即 BEGIN 警告还包括 beginAdmission:nativeAttempts 统计实际的原生 BEGIN IMMEDIATE 调用,nativeMs 测量这些调用;serviceCalls 统计同步准入服务回调,serviceMs 测量它们。服务回调可能没有发现工作,因此其计数并不意味着回收已获授权。失败的尝试和抛出异常的回调会保留其部分测量值。延迟 BEGIN 和 COMMIT 没有细分。
这些字段使用与未更改的 elapsedMs 总计相同的墙钟。原生时间不包括 busy-timeout 配置和恢复;其他簿记可能留下余量。服务可以同步加入另一个事务,其时间已包含在外层 serviceMs 中;不要将嵌套警告相加。该细分不识别 CPU 时间或物理锁持有者。
SQLite 会话写入¶
session-sqlite 子系统在总耗时达到 1000 ms 时发出 slow SQLite session write,在写入失败时发出 SQLite session write failed。两个警告都包括 operation,它是来自一组固定语义操作名称的标签,用于标识拥有 SQLite 写入器通道的回调。
计时字段将经过时间区间拆分为:
queueWaitMs:等待进入写入通道的时间。writerExecutionMs:所属回调的持续时间,包括异步等待。completionDelayMs:回调完成与调用方恢复之间的时间。
这些字段在排队回调开始和结束时可用;
elapsedMs 记录总持续时间。警告的控制台行以 key=value 对形式携带相同字段;openclaw logs --json 显示原始 raw 记录。
使用 operation 定位所属代码路径。它不会识别特定 SQL 语句,不会测量 CPU 时间或锁争用,也不会证明附近的 RPC 导致了延迟。旧记录可能缺少 operation;不要根据相邻日志消息推断它。
session.reclamation.worker-commit 标记每个带编号的 Worker 写入准入,而不仅仅是其最终提交。reclamationAdmissionId 是实际请求 ID,作用域限定于该 Worker 和进程。reclamationAdmissionReleaseCause 记录观察到的 worker-release 消息或 worker-exit 事件。它不会推断初始/最终阶段,也不会证明提交或清理成功。早期失败可能导致释放原因缺失,因为尚未观察到任一事件。
对于 session.lifecycle.artifacts-prepare,同一警告包含一个有界的 artifactPreparation 对象。admissionMode 区分已存在的缓存句柄与异步获取;admissionMs 在规划器收到该句柄时停止。异步获取可能包含共享准入和完整性检查等待,因此不是 CPU 测量。
其余毫秒字段分别区分节点清单和选择(nodeInventoryMs)、引用和条目删除计划(referencePlanningMs)、孤儿选择和计划(orphanPlanningMs),以及转录标记迭代(markerScanMs)。孤儿规划不包含标记时间。计数报告在 agent 或前缀过滤之前已存在的节点/窗口行、被引用 ID、选中的条目、进入的标记查询、消耗的标记行以及删除计划。它们是观察到的结果计数,而不是 SQLite 内部行访问。不会添加标识符、标记文本、转录内容或字节计数。completed: false 标记准备失败时的部分观察;缺失字段表示未完成。这些字段不会更改警告阈值,也不会证明附近的请求导致了该工作。舍入以及测量子阶段之外的工作可能导致与 writerExecutionMs 存在差异;不要将该余量归因于特定阶段。
对于 session.history.archive-prune,同一慢速或失败警告可以包含一个有界的 archivePruning 对象。其 trigger 在调用点记录:initial、after-eviction 或 final。它区分维护流程中的修剪遍次;它不会识别导致维护的请求。
该对象汇总整个修剪遍次中的观察:
admissionMs、cachedAdmissions和asyncAdmissions测量数据库获取并统计其观察到的模式。准入时间在回调入口或获取失败时结束,可能包含共享准入和完整性检查等待。在模式选择之前的拒绝会增加准入时间,但不会增加任一模式计数。checkpointMs、checkpointMaxMs和checkpointCalls报告总时间、最长调用和已进入的调用次数。checkpointIncomplete统计返回 false 的调用,这可能表示繁忙的检查点或错误;它不会识别锁持有者,也不会区分这些结果。抛出的检查点会计入调用次数和时间,但不会增加checkpointIncomplete。vacuumMs、vacuumPasses和vacuumPagesRequested测量增量 vacuum 调用及其请求页数。请求页数不是已确认回收的页数。queryMs覆盖现有存档存在性、候选、未发布名称和 freelist 读取。rowDeletionMs覆盖规范存档行删除事务。fileRemovalMs、removedFiles、missingFiles和failedRemovals报告现有文件移除结果。removedFiles统计成功的规范和旧版移除。missingFiles统计返回ENOENT的规范移除尝试。其他规范失败以及所有不成功的旧版移除都计入failedRemovals;旧版计数包括缺失路径、非文件以及 stat 或移除失败。measurementMs和measurements覆盖等待的磁盘使用量测量尝试,包括失败以及为测量 Worker 排队、扫描和返回结果的时间。legacyInventoryMs覆盖旧版文件清单、过滤和排序。
所有持续时间都是墙钟时间,包括异步等待,而不是 CPU 测量。completed: false 在修剪抛出时保留部分观察;缺失的阶段计时字段表示该阶段未进入。completed: true 表示修剪遍次正常返回。它不会证明每个检查点都已完成、每个移除都成功,或已达到高水位目标。舍入和未测量的工作可能相对于 writerExecutionMs 留下余量;checkpointMaxMs 已包含在 checkpointMs 中。
这些字段复用现有操作,不会增加额外的存储读取、逐文件记录、路径、名称或内容。它们不会更改警告阈值、检查点模式或超时,或存档保留行为。
慢速回复准备¶
当回复花费很长时间准备时,检查常规 Gateway 日志:
回复解析器、分发和 agent-turn 准备里程碑包含阶段持续时间、经过时间以及可用的运行/会话标识符。在没有分析器标志的情况下,它们在经过 10 秒或单个准备阶段 5 秒时发出警告。Codex 准备还会立即记录每个已完成的慢速阶段,包括失败,并在提交原生 turn 之前发出 native-turn-handoff 摘要。计时记录包含阶段名称和标识符,不包含提示或工具参数。
调度准备将 reply.wait_admission_ticket 与
reply.admit_pre_dispatch、reply.admit_dispatch 以及
reply.admit_command_resolution 区分开来。这些 span 用于区分等待更早输入之后的排队,以及等待会话的执行所有者。即使已取消或失败且从未到达 reply resolver 的请求,也会在相同阈值下报告准备缓慢。
嵌入式运行启动、准备、core-plugin-tool 和 auth 阶段摘要会在消息中包含
pid、threadId 和 isMainThread,以区分共享同一日志文件的发射器。这些字段标识的是摘要发射器,而不是每个计时操作实际运行的位置。阶段耗时可能包含异步等待,并不是 CPU 时间。
使用第一个 turn_accepted、model_call_started、tool_execution_started 和
assistant_output_started 里程碑来区分启动与后续活动。默认情况下,首次 assistant/工具活动延迟会记录一次 info 日志,因为 provider 和工具延迟本身并不是准备警告。这些是运行时观察:原生 turn 接受并不能证明 provider 请求已经开始。整个 turn 的摘要仍仅限 profiler 使用,因为其总时间包含模型和工具时间。在将较长的 turn 归因于 Gateway 启动之前,请比较各个准备阶段。同时出现高事件循环延迟的
liveness warning 可以解释多个会话中的延迟。
对于较短的延迟,profiler 标志 会降低 警告阈值。诊断多秒级启动停滞时并不需要它们。
模型调用大小与计时¶
模型调用诊断会记录有界的请求/响应测量值,而不会捕获原始 prompt 或响应内容:
requestPayloadBytes: 最终模型请求 payload 的 UTF-8 字节大小responseStreamBytes: 流式模型响应块 payload 的 UTF-8 字节大小。高频 text、thinking 和 tool-call delta 事件只统计增量delta字节,而不是完整的partial快照。timeToFirstByteMs: 首个流式响应事件之前的经过时间durationMs: 模型调用总时长
启用诊断导出时,这些字段可用于诊断快照、模型调用插件钩子以及 OTEL 模型调用 span/指标。
控制台样式¶
logging.consoleStyle 接受 pretty 或 json:
pretty: 人类友好、带颜色、包含时间戳。json: 每行一个 JSON(用于日志处理器)。
第三种渲染样式 compact(输出更紧凑,最适合长会话)会在 stdout 不是 TTY 时自动应用。它不再是可设置的配置值;openclaw doctor --fix 会将已存储的 consoleStyle: "compact" 映射为 "pretty"。
脱敏¶
OpenClaw 可以在敏感 token 进入控制台输出、文件日志、OTLP 日志记录、持久化的会话 transcript 文本或 Control UI 工具事件 payload(工具启动参数、部分/最终结果 payload、派生 exec 输出以及 patch 摘要)之前对其进行脱敏:
- 敏感值脱敏始终启用。
logging.redactPatterns: 正则字符串列表,用于替换日志/transcript 输出的默认字符串列表。针对表单主体、结构化授权头和裸 AWS 秘密访问密钥的内置结构保护始终适用,即使复制或自定义此列表也是如此。对于 Control UI 工具 payload,自定义模式会在内置默认模式之上应用,因此添加模式不会削弱默认模式已经捕获的值的脱敏。
文件日志使用 JSONL;活动会话 transcript 位于 每个 agent 的 SQLite 数据库。匹配的 secret 值会在行或消息持久化之前被掩码。脱敏是尽力而为的: 它适用于包含文本的消息内容和日志字符串,而不是每个 标识符或二进制 payload 字段。
Transcript 脱敏不会替换用于执行工具的实时参数。 规范的 assistant tool-call ID 和匹配的 tool-result ID 保持不变, 以便存储的历史记录能够与实时工具事件关联。此豁免仅适用于 协议元数据;参数、结果或嵌套 payload 中的相同值仍会经过脱敏。
在 OpenClaw harness 中,已确定的 tool-result 文本会在中间件之后、进入实时模型上下文之前被掩码。这也涵盖 exec 输出和工具错误;它会保留媒体字节以及用于执行工具的原始参数。脱敏发生在结果被添加时,从而保持后续 prompt 重放稳定。模型可见的 tool-result 文本使用更窄的赋值匹配,以便源代码保持完整。已注册的 secret 和显式凭据形式(包括结构化字段、授权头、URL 凭据以及已知 token 格式)仍会被掩码。直接读取 .env 文件会在其内容成为工具结果之前应用更宽的赋值掩码。其他配置和源代码读取会保留不透明值;应注册实际 secret,而不是依赖键名匹配。诸如 token = timeObserverToken 这样的裸源代码赋值保持不变。
内置默认值涵盖常见的 API 凭据和支付凭据字段名称,例如卡号、CVC/CVV、共享支付 token 和支付凭据,当它们以 JSON 字段、URL 参数、CLI 标志或赋值形式出现时。
OpenClaw 还会对显示给 UI 客户端、支持包、诊断观察者、审批 prompt 或 agent 工具的安全边界 payload 进行脱敏。自定义 logging.redactPatterns 可以在这些界面上添加项目特定模式。
诊断与 OpenTelemetry¶
诊断是用于模型运行和消息流遥测(webhooks、排队、会话状态)的结构化、机器可读事件。它们不
替代日志——它们为指标、追踪和导出器提供数据。事件默认在进程内发出(设置 diagnostics.enabled: false 可关闭);
导出它们是独立操作。
当会话指令在模型执行之前拒绝一个 turn 时,其现有的
message.processed 事件会报告 outcome: "skipped",并带有封闭的 reason
代码以及通常的 channel、message 和 session 关联。该拒绝
不会将用户消息、模型 token 或错误回复添加到该事件中。
两个相邻的功能:
- OpenTelemetry 导出 — 通过 OTLP/HTTP 将指标、追踪和日志发送到任何兼容 OpenTelemetry 的收集器或后端(Datadog、Grafana、Honeycomb、New Relic、Tempo 等)。完整配置、信号目录、指标/跨度名称、环境变量和隐私模型位于专用页面:OpenTelemetry 导出。
- 诊断标志 — 用于将额外日志路由到
logging.file的针对性调试日志标志,而无需提高logging.level。标志不区分大小写,并支持通配符(telegram.*、*)。在diagnostics.flags下配置,或通过OPENCLAW_DIAGNOSTICS=...环境变量覆盖。完整指南:诊断标志。
如需将 OTLP 导出到收集器,请参阅 OpenTelemetry 导出。
故障排查技巧¶
- 无法访问 Gateway? 请先运行
openclaw doctor。 - 日志为空? 检查 Gateway 是否正在运行,并写入
logging.file中的文件路径。 - 需要更多详细信息? 将
logging.level设置为debug或trace,然后重试。
相关¶
- OpenTelemetry 导出 — OTLP/HTTP 导出、指标/跨度目录、隐私模型
- 诊断标志 — 针对性调试日志标志
- Gateway 日志内部机制 — WS 日志样式、子系统前缀和控制台捕获
- 配置参考 — 完整的
diagnostics.*字段参考 openclaw logs— 从 CLI 通过 RPC 跟踪 Gateway 日志
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw