Skip to content

Repository files navigation

OpenClaw Usage Observer

A reusable OpenClaw usage library with two entrypoints: an interactive Streamlit dashboard and a short-report skill CLI.

简体中文 · English


简体中文

目录

项目简介

Overview Chinese

OpenClaw Usage Observer 现在明确是一个“核心库 + 多入口”项目:

  • Streamlit 入口:适合人来观察、筛选、归因、下钻
  • skill 入口:适合 OpenClaw / cron / 自动化流程生成简短汇报

共享链路如下:

OpenClaw JSON / JSONL -> src.ingest -> SQLite -> src.analytics -> src.reporting -> Streamlit UI / Skill CLI

核心能力

能力 说明
监控 查看总 token、总 cost、时间趋势和高消耗 turn
统计 skillmodelsessionchannel 聚合
分析 发现上下文膨胀、异常 cron job、增长来源
钻取 按单个 session 查看 turn usage、上下文历史和对话内容
汇报 生成短 Markdown 简报或结构化 JSON 汇报

GitHub 安装与使用

1. 作为核心库 / skill 运行时安装

直接从 GitHub 安装核心能力:

pip install "openclaw-usage-observer @ git+https://github.com/wanng-ide/openclaw-usage-observer.git"

安装后可直接运行:

openclaw-usage-brief --output-format markdown --output ./out/openclaw-usage-report.md

如果你需要结构化 JSON:

openclaw-usage-brief --output-format json --output ./out/openclaw-usage-report.json --state ./out/openclaw-usage-state.json

2. 作为 Streamlit 看板使用

如果你是本地克隆仓库后使用 UI,推荐安装 streamlit 扩展依赖:

pip install -e ".[streamlit]"
streamlit run app.py

默认访问地址通常是 http://localhost:8501

3. 作为 OpenClaw skill 的 canonical 文档

推荐把 GitHub Raw 作为 skill 文档入口:

https://raw.githubusercontent.com/wanng-ide/openclaw-usage-observer/main/skills/openclaw-usage-brief/SKILL.md

这样 GitHub 就是唯一正式分发入口,文档、代码和输出契约始终保持同源。 如果仓库保持私有,则 git+https 安装和 Raw 文档访问都需要 GitHub 认证。

JSON 配置与初始化

除了环境变量,这个项目现在也支持一个可直接编辑的 JSON 配置文件。

默认优先读取:

  1. --config /path/to/config.json
  2. OPENCLAW_USAGE_CONFIG
  3. 当前工作目录下的 ./config/openclaw-usage-observer.json
  4. 用户级配置 ~/.config/openclaw-usage-observer/config.json

配置示例:

{
  "openclaw_root": "/path/to/openclaw-root",
  "db_path": "/path/to/openclaw_usage.sqlite",
  "lookback_days": 7,
  "top_n": 3,
  "refresh": true,
  "output_format": "markdown",
  "report_path": "./out/openclaw-usage-report.md",
  "state_path": "./out/openclaw-usage-state.json"
}

如果你希望只初始化配置文件:

openclaw-usage-brief --init-config --yes

如果你希望首次运行时确认默认路径是否正确:

openclaw-usage-brief --interactive-setup

当 CLI 检测到尚无配置文件,且当前终端可交互时,也会主动询问是否用默认 OpenClaw 路径和 SQLite 路径初始化配置。

一键 bootstrap

本地克隆仓库后,可以直接执行:

python scripts/bootstrap.py --profile streamlit

它会:

  • 自动安装对应依赖
  • 生成配置文件
  • 在可交互终端中确认默认路径

如果你只想初始化而不安装依赖:

python scripts/bootstrap.py --skip-install --yes

环境变量

所有关键配置都支持统一读取顺序:

  • CLI 参数优先
  • 环境变量次之
  • JSON 配置文件再次之
  • 代码默认值最后兜底

推荐变量如下:

export OPENCLAW_ROOT=/path/to/openclaw-root
export OPENCLAW_USAGE_DB_PATH=/path/to/openclaw_usage.sqlite
export OPENCLAW_USAGE_LOOKBACK_DAYS=7
export OPENCLAW_USAGE_TOP_N=3
export OPENCLAW_USAGE_REFRESH=true
export OPENCLAW_USAGE_OUTPUT_FORMAT=json
export OPENCLAW_USAGE_REPORT_PATH=./out/openclaw-usage-report.json
export OPENCLAW_USAGE_STATE_PATH=./out/openclaw-usage-state.json

例如:

openclaw-usage-brief

在没有额外 CLI 参数时,会自动读取上述环境变量。

如果你更希望手动执行摄取:

python -m src.ingest --openclaw-root "$OPENCLAW_ROOT" --db-path "$OPENCLAW_USAGE_DB_PATH"

数据来源

当前接入以下数据源:

路径 用途
<OPENCLAW_ROOT>/agents/main/sessions/*.jsonl assistant usage、session_status、对话明细
<OPENCLAW_ROOT>/agents/main/sessions/sessions.json session 快照与元数据
<OPENCLAW_ROOT>/cron/runs/*.jsonl cron run token、状态、耗时
<OPENCLAW_ROOT>/cron/jobs.json cron job 配置与 skill 关联
<OPENCLAW_ROOT>/agents/main/agent/models.json 模型定价、上下文窗口、max tokens

Token 统计口径

这个项目不会自己重新分词,也不会用本地 tokenizer 估算 token
所有 token 数字都直接来自 OpenClaw 日志里已经存在的 usage 或 status 信息。

1. 全局 / Session / Model / Channel

主口径来自 <OPENCLAW_ROOT>/agents/main/sessions/*.jsonl 中的 assistant 消息:

  • 只处理 type == "message"
  • 只统计 message.role == "assistant"

写入 session_usage_fact 时的字段映射如下:

  • input_tokens <- message.usage.input
  • output_tokens <- message.usage.output
  • cache_read_tokens <- message.usage.cacheRead
  • cache_write_tokens <- message.usage.cacheWrite
  • total_tokens <- message.usage.totalTokens
  • total_cost <- message.usage.cost.total

因此首页和大多数图表里的:

  • 总 Tokens
  • 总 Cost
  • Session 排行
  • Model 排行
  • Channel 排行
  • Top turn 消耗

本质上都是在聚合 session_usage_fact

2. 为什么只统计 assistant usage

因为一轮真实的模型调用结果,通常会在 assistant 消息里携带完整 usage。
当前实现只把 assistant 消息记为一条 usage 事实,避免把同一轮调用在多个来源里重复累计。

核心原则:

  • 全局 token / cost 以 session_usage_fact 为准
  • cron_run_fact 不再叠加进全局总 token,避免双重统计

3. skill 维度的 token 怎么算

skill 排行来自:

  • <OPENCLAW_ROOT>/cron/runs/*.jsonl
  • <OPENCLAW_ROOT>/cron/jobs.json

其中:

  • cron_run_fact.total_tokens <- usage.total_tokens
  • cron_run_fact.input_tokens <- usage.input_tokens
  • cron_run_fact.output_tokens <- usage.output_tokens

随后再通过 cron_job_dim.parsed_skill_name 关联聚合出 skill 排行。

4. 上下文压力里的 token 是什么

上下文压力来自 session_status 工具输出文本,而不是 assistant usage。
当前会解析出以下字段并写入 session_context_fact

  • tokens_in
  • tokens_out
  • context_used_tokens
  • context_limit_tokens
  • compactions

这一部分只用于分析,不再计入全局总 token。

5. cost 怎么来

  • session cost:直接读取 message.usage.cost.total
  • cron cost:根据 cron 日志中的 input / output token,结合 models.json 中的模型单价回填近似值

6. 一句话总结

  • 总 token = assistant session 消息里 usage.totalTokens 的累计值
  • skill token = cron run 中 usage.total_tokens 按 skill 聚合后的值
  • context token = session_status 解析出的上下文指标,仅用于上下文分析

页面说明

页面 说明
监控 看总 token / cost、趋势和最高消耗 turn
统计 skillmodelsessionchannel 排行
分析 看上下文压力、cron 异常、增长来源和高消耗 session
Session 钻取 深入查看单个 session 的 usage、上下文与对话

Monitor

Stat

Analysis

Session

项目结构

openclaw-usage-observer/
├── .env.example
├── README.md
├── pyproject.toml
├── requirements-core.txt
├── requirements-streamlit.txt
├── requirements-dev.txt
├── requirements.txt
├── app.py
├── scripts/
│   └── bootstrap.py
├── skills/
│   └── openclaw-usage-brief/
│       ├── SKILL.md
│       ├── README.md
│       └── run.py
├── src/
│   ├── __init__.py
│   ├── settings.py
│   ├── db.py
│   ├── ingest.py
│   ├── analytics.py
│   ├── reporting.py
│   ├── skill_cli.py
│   └── views.py
└── data/
    └── openclaw_usage.sqlite

各模块职责如下:

文件 作用
app.py Streamlit 入口,负责页面控件、刷新和视图组织
src/ingest.py 从 OpenClaw 日志读取数据并写入 SQLite
src/analytics.py SQL 聚合、排行、异常分析、session 查询
src/reporting.py 统一生成简报文本和结构化 report payload
src/skill_cli.py 安装后可直接调用的 skill CLI 入口
skills/openclaw-usage-brief/run.py 仓库内 skill 包装器,复用同一份 CLI 逻辑
scripts/bootstrap.py 自动安装依赖并生成初始配置文件
src/views.py Streamlit 页面样式、卡片、图表和表格渲染
src/settings.py 统一配置解析、默认值和正则配置

当前边界

  • 当前 token 统计依赖日志中已有的 usage 字段,不做独立 tokenizer 校验
  • 全局 token 与 skill token 使用不同事实表,设计上避免了重复累计
  • Session 钻取 会显示真实对话内容;如果用于公开演示,建议使用匿名数据源
  • data/out/ 和 SQLite / report 文件都是运行时产物,不应提交到仓库

English

Contents

Overview

Overview English

OpenClaw Usage Observer is now explicitly a reusable core library with two entrypoints:

  • Streamlit: interactive monitoring, investigation, and drill-down
  • skill CLI: short reports for OpenClaw, cron, or other automation

Shared pipeline:

OpenClaw JSON / JSONL -> src.ingest -> SQLite -> src.analytics -> src.reporting -> Streamlit UI / Skill CLI

Highlights

Capability Description
Monitoring Track total tokens, total cost, time trends, and expensive turns
Statistics Aggregate by skill, model, session, and channel
Analysis Inspect context growth, anomalous cron jobs, and contribution spikes
Drill-down Open a single session and inspect usage, context history, and conversation text
Reporting Generate short Markdown briefs or structured JSON reports

GitHub Install And Usage

1. Install as the core library / skill runtime

Install the core runtime directly from GitHub:

pip install "openclaw-usage-observer @ git+https://github.com/wanng-ide/openclaw-usage-observer.git"

Then run the brief CLI:

openclaw-usage-brief --output-format markdown --output ./out/openclaw-usage-report.md

For structured JSON output:

openclaw-usage-brief --output-format json --output ./out/openclaw-usage-report.json --state ./out/openclaw-usage-state.json

2. Install as the Streamlit dashboard

If you cloned the repository locally and want the UI, install the streamlit extra:

pip install -e ".[streamlit]"
streamlit run app.py

By default, Streamlit opens at http://localhost:8501.

3. Canonical skill document URL

Use GitHub Raw as the canonical skill document endpoint:

https://raw.githubusercontent.com/wanng-ide/openclaw-usage-observer/main/skills/openclaw-usage-brief/SKILL.md

This keeps documentation, code, and output contracts sourced from the same GitHub repository. If the repository stays private, both git+https installation and Raw document access require GitHub authentication.

JSON Config And Initialization

Besides environment variables, the project now supports a directly editable JSON config file.

Lookup order:

  1. --config /path/to/config.json
  2. OPENCLAW_USAGE_CONFIG
  3. ./config/openclaw-usage-observer.json in the current working directory
  4. user-level config at ~/.config/openclaw-usage-observer/config.json

Example:

{
  "openclaw_root": "/path/to/openclaw-root",
  "db_path": "/path/to/openclaw_usage.sqlite",
  "lookback_days": 7,
  "top_n": 3,
  "refresh": true,
  "output_format": "markdown",
  "report_path": "./out/openclaw-usage-report.md",
  "state_path": "./out/openclaw-usage-state.json"
}

To only initialize the config file:

openclaw-usage-brief --init-config --yes

To interactively confirm detected defaults:

openclaw-usage-brief --interactive-setup

When the CLI detects that no config file exists and the terminal is interactive, it will also offer to initialize the config file automatically.

One-step bootstrap

After cloning the repository locally, run:

python scripts/bootstrap.py --profile streamlit

This will:

  • install the requested dependency profile
  • write the config file
  • confirm detected default paths in an interactive terminal

To only initialize without installing dependencies:

python scripts/bootstrap.py --skip-install --yes

Environment Variables

All key configuration now follows one precedence order:

  • CLI arguments first
  • environment variables second
  • JSON config third
  • code defaults last

Recommended variables:

export OPENCLAW_ROOT=/path/to/openclaw-root
export OPENCLAW_USAGE_DB_PATH=/path/to/openclaw_usage.sqlite
export OPENCLAW_USAGE_LOOKBACK_DAYS=7
export OPENCLAW_USAGE_TOP_N=3
export OPENCLAW_USAGE_REFRESH=true
export OPENCLAW_USAGE_OUTPUT_FORMAT=json
export OPENCLAW_USAGE_REPORT_PATH=./out/openclaw-usage-report.json
export OPENCLAW_USAGE_STATE_PATH=./out/openclaw-usage-state.json

For example:

openclaw-usage-brief

will automatically pick those values when matching CLI flags are omitted.

If you want to ingest manually:

python -m src.ingest --openclaw-root "$OPENCLAW_ROOT" --db-path "$OPENCLAW_USAGE_DB_PATH"

Data Sources

Path Purpose
<OPENCLAW_ROOT>/agents/main/sessions/*.jsonl assistant usage, session_status, and conversation details
<OPENCLAW_ROOT>/agents/main/sessions/sessions.json session snapshots and metadata
<OPENCLAW_ROOT>/cron/runs/*.jsonl cron run tokens, status, and duration
<OPENCLAW_ROOT>/cron/jobs.json cron job configuration and skill linkage
<OPENCLAW_ROOT>/agents/main/agent/models.json model pricing, context window, and max token metadata

How Token Accounting Works

This project does not re-tokenize message text locally and does not estimate token counts with a separate tokenizer.
All token numbers come directly from usage or status fields already written by OpenClaw.

1. Global / Session / Model / Channel totals

The primary source is assistant messages in <OPENCLAW_ROOT>/agents/main/sessions/*.jsonl:

  • only rows where type == "message"
  • only rows where message.role == "assistant"

Those rows are mapped into session_usage_fact as:

  • input_tokens <- message.usage.input
  • output_tokens <- message.usage.output
  • cache_read_tokens <- message.usage.cacheRead
  • cache_write_tokens <- message.usage.cacheWrite
  • total_tokens <- message.usage.totalTokens
  • total_cost <- message.usage.cost.total

That means most dashboard totals and rankings are aggregates over session_usage_fact.

2. Why only assistant usage is counted

In practice, a completed model call usually carries its full usage payload on the assistant message.
The current implementation records one usage fact per assistant response to avoid double counting the same call across multiple log sources.

Core rule:

  • global token / cost totals come from session_usage_fact
  • cron_run_fact is not added again to the global total

3. How skill-level token usage is computed

Skill ranking comes from:

  • <OPENCLAW_ROOT>/cron/runs/*.jsonl
  • <OPENCLAW_ROOT>/cron/jobs.json

Specifically:

  • cron_run_fact.total_tokens <- usage.total_tokens
  • cron_run_fact.input_tokens <- usage.input_tokens
  • cron_run_fact.output_tokens <- usage.output_tokens

4. What context-pressure tokens mean

Context pressure is derived from session_status tool output rather than assistant usage.
The parser extracts these fields into session_context_fact:

  • tokens_in
  • tokens_out
  • context_used_tokens
  • context_limit_tokens
  • compactions

These metrics are used only for context analysis and are not added again to global totals.

5. How cost is computed

  • session cost: read directly from message.usage.cost.total
  • cron cost: approximated from cron input / output tokens using model prices from models.json

6. One-line summary

  • global tokens = sum of usage.totalTokens from assistant session messages
  • skill tokens = sum of usage.total_tokens from cron runs grouped by skill
  • context tokens = parsed context metrics from session_status, used only for context analysis

Pages

Page Description
监控 (Monitoring) Total token / cost monitoring, trends, and expensive turns
统计 (Statistics) Rankings by skill, model, session, and channel
分析 (Analysis) Context pressure, cron anomalies, growth breakdowns, and high-cost sessions
Session 钻取 (Session Drill-down) Detailed inspection of one session's usage, context, and conversation

Project Structure

openclaw-usage-observer/
├── .env.example
├── README.md
├── pyproject.toml
├── requirements-core.txt
├── requirements-streamlit.txt
├── requirements-dev.txt
├── requirements.txt
├── app.py
├── scripts/
│   └── bootstrap.py
├── skills/
│   └── openclaw-usage-brief/
│       ├── SKILL.md
│       ├── README.md
│       └── run.py
├── src/
│   ├── __init__.py
│   ├── settings.py
│   ├── db.py
│   ├── ingest.py
│   ├── analytics.py
│   ├── reporting.py
│   ├── skill_cli.py
│   └── views.py
└── data/
    └── openclaw_usage.sqlite

Core responsibilities:

File Responsibility
app.py Streamlit entrypoint, controls, refresh actions, and view routing
src/ingest.py Reads OpenClaw logs and writes normalized facts into SQLite
src/analytics.py SQL aggregation, rankings, anomaly detection, and session queries
src/reporting.py Shared report payload and summary markdown generation
src/skill_cli.py Installed skill CLI entrypoint
skills/openclaw-usage-brief/run.py In-repo wrapper that reuses the same CLI logic
scripts/bootstrap.py Installs dependency profiles and writes the initial config file
src/views.py Streamlit styling, cards, charts, and tables
src/settings.py Unified config resolution, defaults, and parsing regexes

Current Boundaries

  • Token accounting depends on usage fields already present in logs and does not independently validate them with a tokenizer
  • Global totals and skill totals intentionally come from different fact tables to avoid double counting
  • Session Drill-down shows real conversation text; use anonymized logs for public demos
  • data/, out/, SQLite files, and generated reports are runtime artifacts and should not be committed

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages