@vulcanen/openclaw-monitor
v0.9.8
Published
Self-contained real-time monitoring console for OpenClaw
Readme
OpenClaw Monitor
English | 中文
OpenClaw 实时监控插件。订阅 OpenClaw 内部诊断事件总线,做指标聚合、对话内容审计与日志记录;通过 SSE 提供实时事件流,并内置一个 React 仪表板(中英文)开箱即用——不依赖任何外部 Grafana / Prometheus / OTel Collector。
功能
- 总览:顶部健康横幅(正常 / 需要关注 / 故障三档)+ 1m / 5m / 15m / 1h 滑动窗口的模型调用量、错误率、P95 延迟、会话告警;第二排生命周期 stat card(活跃 session、今日 context 压缩次数、上次 gateway 启动时间、工具结果落盘次数);当 host ≥ 2026.5.14 在
llm_output上发送contextTokenBudget时,额外渲染上下文利用率(平均 / 峰值) stat card;今日 Top 入口来源面板 - 维度统计:按 channel、provider × model、tool、入口来源(OpenAI 兼容 API / Control UI / channel 插件)维度的调用计数、错误率、token 用量、耗时分位、以及(host ≥ 2026.5.14 起)上下文预算利用率;新增执行框架(Harness)维度(
pi/codex-app-server/ …),单独 Harnesses 页查看 - 运行追踪:harness 运行列表 + 单次运行完整事件 trace 下钻
- 诊断事件流:每条捕获事件按推断的严重度(error / warn / info / debug)展示,支持按 level、component 子串、事件类型前缀(如
model.*、tool.*、session.*、gateway.*)过滤 - 对话内容审计 (可选):列表按 sessionKey 折叠分组,支持状态过滤(全部 / 仅失败 / 仅成功);详情页用时间线 + 配对卡片呈现——入站 / 每次 LLM 调用(input+output 同卡)/ 出站 / 错误按时间排序,只渲染有数据的卡片,半捕获跳会内嵌诊断 hint(默认 1 MiB 单段上限)。30 分钟无 host 更新的卡死 record(发送方掉线、host 中途崩溃)会被自动 sweep 并标记为
abandoned,内存有界。 - 告警引擎 (可选):定时评估滑动窗口指标(错误率、P95 延迟、调用量、以及 host ≥ 2026.5.14 起的
avgContextUtilizationPct/peakContextUtilizationPct),命中阈值时推送到通用 webhook 或钉钉自定义机器人;带冷却 + 恢复通知;活跃告警 / 规则状态 / 24h 历史在 Alerts 页查看 - 成本 / Token 经济学 (需要 audit 安全门 + 上游返回 usage):按 provider/model 配置价格表(input/output/cacheRead/cacheWrite per 1k tokens);滑动窗口实时成本 + 今日 / 本周 / 本月 / 近 30 天的持久化日级累计 (UTC);按 model / channel / source 拆分。Token 数据来自
llm_outputhook 的usage字段——如果上游 LLM provider 在 OpenAI 兼容响应里不返回 usage(部分自建网关 / 代理会忽略),Costs 页会一直为 0(页面会自动检测并提示) - 诊断 / Top-N 下钻:把聚合指标变成可点击的个案——最慢的
model.call.completed、Token 消耗最多的对话、按 provider × model × errorCategory 聚类的错误、按工具失败率排序;每行可跳到 Run Detail / Conversation Detail。时间窗可选 15m / 1h / 6h / 24h。 - 实时流:SSE 推送
/api/monitor/stream,仪表板自动订阅 - 生命周期可视化:session 起 / 结、agent 上下文压缩(before / after)、tool 结果持久化、gateway 启 / 停作为合成事件出现在 Logs / Events 页——配合事件类型前缀过滤可单独下钻任一类。专门的 会话 页直接展示 start / end / 时长 / 结束原因。
- 全局时间窗选择器:顶部一个下拉,所有支持时间窗的页面共用;URL hash (
?window=15m) 同步,深链能复现视图 - 零外部依赖:JSONL 文件持久化,按日期分区 + 后台 retention,无原生模块
- i18n:中文默认,可一键切英文
兼容性
| 项 | 要求 |
|---|---|
| OpenClaw host | >=2026.5.7 |
| Plugin API | >=2026.5.7 |
| Node | >=22 |
安装
在部署 OpenClaw 的主机上:
openclaw plugins install npm:@vulcanen/openclaw-monitor
openclaw monitor setup --audit # 信任插件 + 启用内容审计
openclaw gateway restart仅启用指标 / 仪表板,不启用内容审计:
openclaw plugins install npm:@vulcanen/openclaw-monitor
openclaw monitor setup # 不带 --audit
openclaw gateway restart随时查看状态:openclaw monitor status
配置
完整配置项及默认值(写入 OpenClaw 的 ~/.openclaw/openclaw.json):
{
"plugins": {
"allow": ["openclaw-monitor"],
"entries": {
"openclaw-monitor": {
"hooks": {
"allowConversationAccess": true // host 安全门:放行 llm_input / llm_output / agent_end hook
},
"config": {
"buffer": { "maxPerType": 1024 },
"storage": {
"kind": "jsonl", // 或 "memory"
"path": null // 默认 <stateDir>/openclaw-monitor
},
"retention": {
"eventsDays": 7,
"runsDays": 90
},
"stream": {
"maxSubscribers": 16,
"heartbeatMs": 15000
},
"audit": {
"enabled": true, // 默认开
"contentMaxBytes": 1048576, // 单条文本上限(1 MiB,cap 16 MiB)
"retainDays": 3, // 对话 JSONL 保留天数
"captureSystemPrompt": true
},
"pricing": {
"currency": "CNY", // 自由文本货币单位,不做汇率换算
"models": {
"qwen/qwen3-5-397b-a17b": { "input": 0.0008, "output": 0.002 },
"openai/gpt-4": { "input": 0.03, "output": 0.06 },
"anthropic/claude-3.5-sonnet": {
"input": 0.003,
"output": 0.015,
"cacheRead": 0.0003, // 可选;省略则用 input 价格
"cacheWrite": 0.00375 // 可选;省略则用 input 价格
}
}
},
"alerts": {
"enabled": false, // 默认关。开启需同时配 channels 和 rules
"evaluationIntervalSec": 30,
"channels": {
"ops-webhook": {
"kind": "webhook",
"url": "https://example.com/alert-receiver"
},
"ops-dingtalk": {
"kind": "dingtalk",
"url": "https://oapi.dingtalk.com/robot/send?access_token=XXX",
"secret": "SEC_xxx" // 可选,钉钉自定义机器人 HMAC-SHA256 签名密钥
}
},
"rules": [
{
"id": "model-errors-spike",
"name": "LLM 调用 5m 内错误数 > 5",
"metric": "modelErrors",
"window": "5m",
"op": ">",
"threshold": 5,
"severity": "error",
"cooldownSec": 600,
"channels": ["ops-webhook", "ops-dingtalk"]
},
{
"id": "model-p95-too-slow",
"name": "LLM P95 延迟 > 5s",
"metric": "modelP95Ms",
"window": "5m",
"op": ">",
"threshold": 5000,
"severity": "warn",
"cooldownSec": 300,
"channels": ["ops-webhook"]
}
]
}
}
}
}
}
}
openclaw monitor setup [--audit]命令会自动写入plugins.allow和hooks.allowConversationAccess。这两个键由 OpenClaw host 安全模型管理,不能由插件自动写盘——必须由操作者显式触发。
仪表板
http://<gateway-host>:<port>/monitor/首次进入会提示输入 OpenClaw gateway operator token(可用 openclaw config get gateway.auth.token 获取)。Token 仅存浏览器 localStorage,后续 API 请求自动附 Authorization: Bearer ... 头。右上角可切换中 / EN。
HTTP 端点
所有 /api/monitor/* 路由均需 Authorization: Bearer <gateway-operator-token>;/monitor/* 静态资源公开(数据接口仍受保护)。
| 路径 | 用途 |
|---|---|
| GET /api/monitor/overview | 4 个滑动窗口指标 + 错误列表 + 类型计数 |
| GET /api/monitor/events?type=&limit= | 原始事件流 |
| GET /api/monitor/health | 健康检查 |
| GET /api/monitor/channels | 每通道调用统计 |
| GET /api/monitor/models | 每 provider × model 调用统计 + token |
| GET /api/monitor/tools | 每 tool 执行统计 |
| GET /api/monitor/sources | 按入口来源(openai-api / control-ui / channel:*)统计 |
| GET /api/monitor/harnesses | 按 harness 后端聚合(如 pi、codex-app-server);host < 2026.5.14 时返回空 |
| GET /api/monitor/runs?limit= | harness 运行列表 |
| GET /api/monitor/runs/:runId | 单次运行详情 + 事件 trace |
| GET /api/monitor/logs?level=&component=&type=&typePrefix= | 诊断事件流(按推断 level / 子串 component / 精确 event type / 事件类型前缀如 model. 过滤) |
| GET /api/monitor/series?metric=&windowSec= | 10 秒粒度时序数据 |
| GET /api/monitor/stream | SSE 实时事件推送 |
| GET /api/monitor/conversations?limit=&groupBy=sessionKey&hasError=true\|false | 对话审计列表(加 groupBy=sessionKey 返回按 session 分组的嵌套结构;加 hasError 服务端过滤成功/失败) |
| GET /api/monitor/conversations/:runId | 单次对话四段完整内容 |
| GET /api/monitor/alerts/rules | 当前生效的告警规则列表 + 引擎运行状态 |
| GET /api/monitor/alerts/active | 当前正在触发的告警 |
| GET /api/monitor/alerts/history?limit= | 最近 24h 告警事件(fired / renotified / resolved) |
| GET /api/monitor/costs | 成本快照:sinceStart / windows / 今日 / 本周 / 本月 / 近 30 天每日趋势 + 按 model / channel / source 拆分 |
| GET /api/monitor/insights/slow-calls?windowSec=&limit= | 时间窗内最慢的 model.call.completed Top-N |
| GET /api/monitor/insights/heavy-conversations?windowSec=&limit= | 按总 token 排序的对话 Top-N |
| GET /api/monitor/insights/error-clusters?windowSec=&limit= | model.call.error 按 provider × model × errorCategory 聚类 |
| GET /api/monitor/insights/tool-failures?windowSec=&limit= | 工具失败次数 + 失败率 Top-N |
| GET /monitor/* | 内置仪表板 |
自建 LLM 上游的已知配置注意点
Costs 页 token 一直显示 0 —— 给 model 加 compat.supportsUsageInStreaming: true
OpenClaw 转发请求时已经带了 stream_options.include_usage: true(host 源码 src/agents/openai-transport-stream.ts 写死的)。问题在 parser:host 对未知 baseUrl 的 OpenAI-compat provider(任何自建的 vLLM / SGLang / TGI / 自建 proxy)默认把 model.compat.supportsUsageInStreaming 设成 false(src/plugins/provider-model-compat.ts),导致 stream parser 静默丢弃上游真实发回来的 usage 帧。结果就是 Monitor 的 Costs 页 token / cost 永远是 0。
按模型覆盖默认:
"models": {
"providers": {
"qwen": {
"baseUrl": "http://your-internal-gateway/v1",
"apiKey": "...",
"api": "openai-completions",
"models": [
{
"id": "qwen3-5-397b-a17b",
"name": "Qwen 3.5",
// ...原有字段...
"compat": {
"supportsUsageInStreaming": true
}
}
]
}
}
}重启 gateway。几次请求后 Costs 页就有 token 了。要看人民币成本,再在 plugins.entries.openclaw-monitor.config.pricing.models["provider/model"] 里填每 1k token 的单价。
排错时先验证上游本身正常(绕过 OpenClaw):
curl -s "$BASE_URL/chat/completions" -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"...", "messages":[{"role":"user","content":"hi"}],
"stream": true,
"stream_options": {"include_usage": true}}'[DONE] 前的最后一个 data: 块带非空 "usage" 字段 → 上游是好的,只需要上面那个 compat flag。
隐私与存储
- 内容审计抓取的是原始 prompt / assistant 文本,可能含 PII / 业务密钥;落盘为明文 JSONL,请控制运维角色访问
- 单条对话约 1–50 KB(开启全量内容后可上到 MB 级),按业务流量估算容量;retention 默认 3 天可调
- 仪表板限定
trusted-operator权限,不要把 OpenClaw gateway 暴露公网 - 不需要内容审计时,将
config.audit.enabled设为false即可关闭
许可
MIT — 见 LICENSE。
