Files
2026-07-09 10:21:37 +00:00

6.5 KiB

OpenClaw Usage Exporter

FastAPI Prometheus exporter for OpenClaw usage, session, and runtime-adjacent metrics.

What it exports

Reads OpenClaw session data from disk and exposes /metrics with as much non-sensitive data as possible.

Why timeframe switching looked wrong before

Prometheus scrapes snapshots. The old exporter leaned heavily on "today so far" gauges, so a Grafana timeframe change could look almost unchanged unless the panel query explicitly used range math.

The exporter now also exposes:

  • monotonic all-time counters for tokens, cost, and usage entries
  • retained daily buckets
  • retained hourly buckets

That gives dashboards something real to aggregate over a selected time range.

Daily usage metrics

  • openclaw_daily_total_tokens
  • openclaw_daily_input_tokens
  • openclaw_daily_output_tokens
  • openclaw_daily_cache_read_tokens
  • openclaw_daily_cache_write_tokens
  • openclaw_daily_reasoning_tokens
  • openclaw_daily_usage_entries
  • openclaw_daily_cost_input
  • openclaw_daily_cost_output
  • openclaw_daily_cost_cache_read
  • openclaw_daily_cost_cache_write
  • openclaw_daily_cost_total
  • openclaw_daily_message_records
  • openclaw_daily_non_message_records
  • openclaw_daily_unique_sessions
  • openclaw_daily_unique_models
  • openclaw_daily_unique_providers

Daily breakdowns

  • openclaw_daily_messages_total{role=...}
  • openclaw_daily_stop_reasons_total{stop_reason=...,model=...,provider=...}
  • openclaw_daily_tool_calls_total{tool_name=...}
  • openclaw_daily_errors_total{error_type=...}
  • openclaw_daily_model_total_tokens{model=...,provider=...}
  • openclaw_daily_model_input_tokens{model=...,provider=...}
  • openclaw_daily_model_output_tokens{model=...,provider=...}
  • openclaw_daily_model_reasoning_tokens{model=...,provider=...}
  • openclaw_daily_session_total_tokens{session_id=...}
  • openclaw_daily_session_input_tokens{session_id=...}
  • openclaw_daily_session_output_tokens{session_id=...}
  • openclaw_daily_session_messages_total{session_id=...,role=...}
  • openclaw_daily_session_errors_total{session_id=...}
  • openclaw_daily_session_tool_calls_total{session_id=...,tool_name=...}

Session inventory metrics

Derived from sessions.json:

  • openclaw_sessions_visible_count
  • openclaw_sessions_total_count
  • openclaw_sessions_has_more
  • openclaw_session_info{session_id=...,status=...,chat_type=...,last_channel=...,model=...,provider=...,auth_profile_override=...,system_sent=...,aborted_last_run=...,total_tokens_fresh=...}
  • openclaw_session_age_seconds{session_id=...}
  • openclaw_session_updated_timestamp_seconds{session_id=...}
  • openclaw_session_started_timestamp_seconds{session_id=...}
  • openclaw_session_last_interaction_timestamp_seconds{session_id=...}
  • openclaw_session_total_tokens{session_id=...}
  • openclaw_session_input_tokens{session_id=...}
  • openclaw_session_output_tokens{session_id=...}
  • openclaw_session_context_tokens{session_id=...}
  • openclaw_session_runtime_seconds{session_id=...}
  • openclaw_session_estimated_cost_usd{session_id=...}
  • openclaw_session_compaction_count{session_id=...}
  • openclaw_session_usage_family_session_count{session_id=...}

Time-range-friendly counters and buckets

  • openclaw_total_tokens_total
  • openclaw_input_tokens_total
  • openclaw_output_tokens_total
  • openclaw_cache_read_tokens_total
  • openclaw_cache_write_tokens_total
  • openclaw_reasoning_tokens_total
  • openclaw_usage_entries_total
  • openclaw_cost_input_usd_total
  • openclaw_cost_output_usd_total
  • openclaw_cost_cache_read_usd_total
  • openclaw_cost_cache_write_usd_total
  • openclaw_cost_total_usd_total
  • openclaw_message_records_total
  • openclaw_non_message_records_total
  • openclaw_model_total_tokens_total{model=...,provider=...}
  • openclaw_model_input_tokens_total{model=...,provider=...}
  • openclaw_model_output_tokens_total{model=...,provider=...}
  • openclaw_session_total_tokens_total{session_id=...}
  • openclaw_day_total_tokens{date=...,tz=...}
  • openclaw_day_cost_total{date=...,tz=...}
  • openclaw_day_usage_entries{date=...,tz=...}
  • openclaw_hour_total_tokens{hour=...,tz=...}
  • openclaw_hour_cost_total{hour=...,tz=...}
  • openclaw_hour_usage_entries{hour=...,tz=...}

Exporter/runtime metrics

  • openclaw_exporter_files_scanned
  • openclaw_exporter_lines_scanned
  • openclaw_exporter_parse_errors
  • openclaw_exporter_negative_cost_entries_skipped
  • openclaw_exporter_negative_cost_fields_skipped{cost_field=...}
  • openclaw_exporter_negative_cost_amount_skipped{cost_field=...}
  • openclaw_exporter_history_days_retained
  • openclaw_exporter_history_hours_retained
  • openclaw_usage_cost_cache_files_tracked
  • openclaw_usage_cost_cache_version
  • openclaw_usage_cost_cache_updated_timestamp_seconds

Privacy boundary

This exporter intentionally skips obvious revealing fields like message content, sender labels, sender ids, phone numbers, response ids, idempotency keys, and session keys.

Session ids are exported.

It also ignores invalid negative cost values found in some legacy/raw usage records and exposes exporter metrics for how many were skipped.

Code layout

  • app.py keeps the uvicorn entrypoint tiny
  • openclaw_usage_exporter/config.py holds env-driven paths and retention settings
  • openclaw_usage_exporter/models.py holds report dataclasses and cost handling
  • openclaw_usage_exporter/collectors.py reads session files and cache/index data
  • openclaw_usage_exporter/metrics.py renders Prometheus output
  • openclaw_usage_exporter/utils.py keeps shared helpers small

Run locally

python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
uvicorn app:app --host 0.0.0.0 --port 9487

Runtime

  • Canonical repo path: /root/projects/openclaw-usage-exporter
  • Compatibility workspace path: /root/.openclaw/workspace/openclaw-daily-tokens-exporter
  • systemd user unit: ~/.config/systemd/user/openclaw-daily-tokens-exporter.service
  • Direct metrics: http://100.74.255.106:9487/metrics
  • Tailscale Serve path: https://luna.taile7522.ts.net/openclaw-daily-tokens

Env

  • OPENCLAW_SESSIONS_DIR default: /root/.openclaw/agents/main/sessions
  • OPENCLAW_EXPORTER_TZ default: Europe/Berlin
  • OPENCLAW_SESSIONS_INDEX default: /root/.openclaw/agents/main/sessions/sessions.json
  • OPENCLAW_USAGE_COST_CACHE default: /root/.openclaw/agents/main/sessions/.usage-cost-cache.json
  • OPENCLAW_HISTORY_DAYS default: 30
  • OPENCLAW_HISTORY_HOURS default: 168
  • PORT ignored by app directly; set it in the service or uvicorn command