Skip to content

fix: share one TelemetryService across repeated register() calls#8

Open
yzdong wants to merge 1 commit intoknostic:mainfrom
getnenai:fix/svc-singleton-and-config-doc
Open

fix: share one TelemetryService across repeated register() calls#8
yzdong wants to merge 1 commit intoknostic:mainfrom
getnenai:fix/svc-singleton-and-config-doc

Conversation

@yzdong
Copy link
Copy Markdown

@yzdong yzdong commented Apr 18, 2026

Problem

In index.ts, svc is instantiated inside register(api):

register(api) {
  const svc = createTelemetryService();
  ...
  api.on("before_tool_call", (evt, ctx) => { svc.write(...) });
  ...
}

OpenClaw calls register() multiple times per plugin lifetime (CLI metadata load, then gateway full load — observed 4+ calls in 2026.4.15). The result:

  • start(ctx) sets fileWriter on instance A
  • before_tool_call / after_tool_call / etc. hooks fire on instance B, whose fileWriter is still null
  • Every write() silently no-ops; ~/.openclaw/logs/telemetry.jsonl is never created

No error surfaces — users see "plugin loaded" in openclaw plugins list, no events.

Fix

Hoist svc to module scope with a null-coalescing init. All register() calls wire hooks to the same service that receives start() / stop().

Verification

Bounded 20-second agent session after applying the fix:

  • telemetry.jsonl created, 5 events (agent.start ×2, tool.start read, tool.end read, agent.end)
  • Hash chain validates
  • No change in steady-state behavior for non-re-registered lifetimes (backward compatible)

Also included

  • README: config.jsonopenclaw.json (the actual file name)
  • README: clarifies that plugins.entries.telemetry.config.enabled (the nested field) must be true, not just the outer plugins.entries.telemetry.enabled. Misconfiguring this was the most common silent-failure mode we saw during a real experiment setup; adding a troubleshooting note up front.

Update (2026-04-21) — field evidence

This fix has been used in a real multi-day production run: CRUX-Windows (reproduction of the CRUX #1 capability eval on the Microsoft Store). 77h 48m of wall-clock, ~2,700 agent messages, ran cleanly with telemetry capture the whole way. Full scrubbed traces are public on Docent: https://docent.transluce.org/dashboard/0c8eb800-22da-49ae-b017-2315382ed539

A separate regression we noticed during that run

Tool events (tool.start / tool.end) flow correctly in the post-fix plugin, but agent.usage events are not being captured. Across 140M+ tokens of model usage, zero agent.usage events appear in telemetry.jsonl. This means cost telemetry via the plugin is incomplete in current OpenClaw versions.

This is a different bug from the svc-singleton issue this PR fixes — likely a missing or broken hook registration on the llm.usage / agent.usage path. I have not isolated the root cause yet, but wanted to flag it here in case it's within scope to fix in the same pass. Happy to open a separate issue/PR if preferred.

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

OpenClaw may call plugin.register(api) multiple times per plugin
lifetime — e.g. once for CLI plugin metadata, once for the full
gateway load. The previous code instantiated a fresh svc inside
register(), so:

- start(ctx) sets fileWriter on instance A
- api.on("before_tool_call", ...) hooks fire on instance B, whose
  fileWriter is still null
- every write() silently no-ops, and ~/.openclaw/logs/telemetry.jsonl
  is never created

Hoist svc to module scope with a null-coalescing init so every
register() call wires hooks to the same service that receives
start()/stop(). Verified via a 20s bounded agent session: events
land in telemetry.jsonl as expected.

Also updates README to:
- Fix the config file path (openclaw.json, not config.json)
- Clarify that plugins.entries.telemetry.config MUST contain a
  nested `{"enabled": true}`; without the inner config object
  start() bails silently and no events are written. This was the
  most common misconfiguration we hit during CRUX-Windows setup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant