Repository navigation
feat: expose garbage collection duration metrics - #139592
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs maintainer review before merge. Reviewed September 5, 2026, 10:09 PM ET / September 6, 2026, 02:09 UTC. ClawSweeper reviewWhat this changesAdds garbage-collection duration histograms to the existing Prometheus and OpenTelemetry exporters, with demand-driven collection, lifecycle coverage, and operator documentation. Merge readiness✅ Ready for maintainer review The PR remains useful and has no actionable correctness findings. The updated evidence addresses the previous Gateway hot-toggle and overhead qualification request; maintainer-authored, protected work also remains outside automatic cleanup. Priority: P2 Review scores
Verification
How this fits togetherOpenClaw diagnostics collects runtime measurements and sends them through a bounded internal event queue. The existing metrics plugins turn these observations into Prometheus scrapes and OpenTelemetry metrics for operators. flowchart LR
A[Diagnostics heartbeat] --> B{Enabled and consumer interested?}
B -->|Yes| C[Node GC observer]
B -->|No| D[Disconnect observer]
C --> E[Bounded internal event queue]
E --> F[Prometheus histogram]
E --> G[OpenTelemetry histogram]
Before mergeNone. Agent review detailsSecurityNone. PR surfaceSource +101, Tests +134, Docs +37. Total +272 across 15 files. View PR surface stats
Review metrics
Root-cause clusterRelationship: Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Technical reviewBest possible solution: Keep GC collection owned by the existing diagnostics lifecycle, with cumulative exporter histograms and explicit documentation of observation gaps and attribution limits. Do we have a high-confidence way to reproduce the issue? Not applicable: this adds an observability capability rather than repairing an established behavior; the inspected main exporter paths lack the requested GC histograms. Is this the best way to solve the issue? Yes. Reusing the heartbeat, bounded dispatcher, and existing exporters avoids a competing telemetry lifecycle while preserving current settings and counter behavior. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 4da5d447f695. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (1 earlier review cycle)
|
f00f29c to
e380571
Compare
|
Merged via squash.
|
* commit '6c55a99226ed0611ca088004c81b00fb296f1f71': (182 commits) test(ui): scope dashboard settings setup to the top frame (openclaw#139618) refactor(skills): share pending proposal creation (openclaw#139617) fix(release): accept frozen targets before worker bundles (openclaw#136699) fix(gateway): preserve percent sequences in media filenames (openclaw#139508) fix: preserve current update availability alongside update history (openclaw#139501) feat(diagnostics): expose garbage collection duration metrics (openclaw#139592) fix(ui): keep Logbook timestamps clear of the activity stripe (openclaw#139539) fix(ui): keep Swarm outcomes visible after completion (openclaw#139490) test: check file accessibility without runtime-specific return values (openclaw#139590) refactor(sdk): keep helper types private (openclaw#139601) fix(cron): preserve current-session delivery intent (openclaw#139491) fix: prevent browser profile permission hangs in Doctor (openclaw#139612) fix(agents): repair storage-failure test fixture after failover owner move (openclaw#139531) fix(cli): keep note text with Windows and Unicode line endings (openclaw#139512) fix(agents): keep isolated completion context on its admitted generation (openclaw#139607) fix: avoid declaration builds during source-server updates (openclaw#139392) fix(models): keep discovered models after catalog refresh failures (openclaw#139357) fix(gateway): record a transcript notice when a run fails before replying (openclaw#139439) refactor(ios): reuse shared integer conversion (openclaw#139581) fix(sessions): prevent database lock failures during reclamation (openclaw#139469) ...
* commit 'refs/openclaw/tasks/pr-135167-main-latest': test(ui): scope dashboard settings setup to the top frame (#139618) refactor(skills): share pending proposal creation (#139617) fix(release): accept frozen targets before worker bundles (#136699) fix(gateway): preserve percent sequences in media filenames (#139508) fix: preserve current update availability alongside update history (#139501) feat(diagnostics): expose garbage collection duration metrics (#139592) fix(ui): keep Logbook timestamps clear of the activity stripe (#139539) fix(ui): keep Swarm outcomes visible after completion (#139490) test: check file accessibility without runtime-specific return values (#139590) refactor(sdk): keep helper types private (#139601) fix(cron): preserve current-session delivery intent (#139491) fix: prevent browser profile permission hangs in Doctor (#139612) fix(agents): repair storage-failure test fixture after failover owner move (#139531) fix(cli): keep note text with Windows and Unicode line endings (#139512) fix(agents): keep isolated completion context on its admitted generation (#139607) fix: avoid declaration builds during source-server updates (#139392) fix(models): keep discovered models after catalog refresh failures (#139357) fix(gateway): record a transcript notice when a run fails before replying (#139439)
Closes #139547
What Problem This Solves
Operators investigating intermittent event-loop stalls can see memory and delay metrics, but have no GC-duration distribution covering the gaps between short CPU profiles. Sampled GC frames cannot establish actual GC-entry counts or elapsed durations.
Why This Change Was Made
The existing diagnostics heartbeat now owns one demand-driven Node GC observer. It reconciles demand at startup and on its existing 30-second tick, stops observation on diagnostics teardown, and fences stale callbacks and entries when observation restarts. A duration-only internal event uses the existing bounded diagnostic queue and the existing Prometheus and OpenTelemetry histogram implementations.
There is no new configuration, dependency, persistent store, public RPC, timer, or registry. Readiness/recovery policy and exporter counter-reset behavior are unchanged. The change adds about 101 production lines for the missing observation and both exporter adapters.
User Impact
Metrics consumers gain
openclaw_gc_duration_secondsandopenclaw.gc.duration_ms. These measure elapsed GC duration for the hosting JavaScript isolate, not CPU time, allocation ownership, or guaranteed stop-the-world pauses. Bucket counts provide co-evidence when compared with event-loop windows; they do not establish request-level causality.Collection can begin at the next heartbeat after a consumer registers, with no backfill before observer activation. Brief subscriber gaps, queue drops and series limits constrain coverage. Runtimes that do not advertise GC performance entries leave this observer inactive.
Evidence
pnpm buildpassed. All four type lanes and Knip scans passed; two test-only lint findings were corrected and both lint scopes plus the affected canonical services test graph passed. Remaining runtime guards and the 753-page MDX check passed.f00f29cb6374e1b274bc144133ebb6c5ca0f410c. The current-main rebase preserves the identical GC patch; the only changed GC-owner file inherits main's already-landed Prometheus rendering allocation improvement (perf(prometheus): reduce temporary scrape allocations #139535). All thirteen combined lifecycle/exporter tests passed again on the refreshed head. Main also supplies the unrelated native-report test mock repair (refactor(test): simplify catalog guards and fix native report fixture #139496) for fresh CI.