@openclaw/diagnostics-prometheus 2026.10.5-beta.4 → 2026.10.10-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +170 -11
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -166,7 +166,7 @@ function createPrometheusMetricStore() {
166
166
  }
167
167
  //#endregion
168
168
  //#region extensions/diagnostics-prometheus/src/service-child-process.ts
169
- /** Git launches carry a bounded owner label; every other executable family reports `none`. */
169
+ /** Git owners and SQLite session transports carry bounded operation labels. */
170
170
  function recordChildProcessSpawn(store, evt) {
171
171
  store.counter("openclaw_child_process_spawn_total", "Successful child launches through the shared spawn and exec owners.", {
172
172
  family: normalizeDiagnosticValue(evt.family),
@@ -176,6 +176,15 @@ function recordChildProcessSpawn(store, evt) {
176
176
  //#endregion
177
177
  //#region extensions/diagnostics-prometheus/src/service-memory.ts
178
178
  function recordMemorySample(store, memory, byteBuckets) {
179
+ for (const message of memory.workerMessages ?? []) {
180
+ const labels = {
181
+ kind: message.kind,
182
+ direction: message.direction
183
+ };
184
+ store.counterValue("openclaw_worker_messages_total", "Messages crossing the Gateway main-thread worker boundary.", labels, message.messages);
185
+ store.counterValue("openclaw_worker_message_payload_bytes_total", "Known worker payload bytes, excluding transport framing and unmeasured object graphs.", labels, message.payloadBytes);
186
+ store.counterValue("openclaw_worker_message_unmeasured_total", "Worker messages without a known payload size; these do not contribute to payload bytes.", labels, message.unmeasuredMessages);
187
+ }
179
188
  for (const worker of memory.workerLifecycle ?? []) {
180
189
  store.counterValue("openclaw_worker_started_total", "Worker isolates created by bounded script basename.", { script: worker.script }, worker.started);
181
190
  for (const { reason, count } of worker.retired) store.counterValue("openclaw_worker_retired_total", "Worker isolates confirmed exited by owner retirement reason.", {
@@ -192,7 +201,10 @@ function recordMemorySample(store, memory, byteBuckets) {
192
201
  ["worker_heap_total", "workerHeapTotalBytes"],
193
202
  ["worker_heap_used", "workerHeapUsedBytes"]
194
203
  ]) store.gauge("openclaw_memory_bytes", "Latest process memory usage by memory kind.", { kind }, asNonNegativeFiniteNumber(memory[field]));
195
- for (const [name, field] of [["openclaw_worker_count", "workerCount"], ["openclaw_worker_heap_sampled_count", "workerHeapSampledCount"]]) store.gauge(name, "Worker isolate counts.", {}, asNonNegativeFiniteNumber(memory[field]));
204
+ for (const [name, field] of [["openclaw_worker_count", "workerCount"], ["openclaw_worker_heap_sampled_count", "workerHeapSampledCount"]]) {
205
+ store.clearGauges(name);
206
+ store.gauge(name, "Worker isolate counts.", {}, asNonNegativeFiniteNumber(memory[field]));
207
+ }
196
208
  store.clearGauges("openclaw_heap_space_bytes");
197
209
  for (const space of memory.heapSpaces ?? []) for (const [stat, field] of [
198
210
  ["used", "space_used_size"],
@@ -203,13 +215,39 @@ function recordMemorySample(store, memory, byteBuckets) {
203
215
  space: space.space_name,
204
216
  stat
205
217
  }, space[field]);
206
- const workerHeaps = /* @__PURE__ */ new Map();
218
+ const workers = /* @__PURE__ */ new Map();
219
+ store.clearGauges("openclaw_code_mode_worker_heap_bytes");
207
220
  for (const worker of memory.workerHeaps ?? []) {
221
+ if (worker.workerSlot !== void 0) for (const [kind, value] of [["used", worker.heapUsed], ["limit", worker.heapSizeLimitBytes]]) store.gauge("openclaw_code_mode_worker_heap_bytes", "Latest live Code Mode isolate heap usage and limit by reusable worker slot.", {
222
+ slot: String(worker.workerSlot),
223
+ kind
224
+ }, value);
225
+ const totals = workers.get(worker.script) ?? {
226
+ count: 0,
227
+ sampled: 0,
228
+ heapUsed: void 0
229
+ };
230
+ totals.count++;
231
+ totals.sampled++;
208
232
  const heapUsed = asNonNegativeFiniteNumber(worker.heapUsed);
209
- if (heapUsed !== void 0) workerHeaps.set(worker.script, (workerHeaps.get(worker.script) ?? 0) + heapUsed);
233
+ if (heapUsed !== void 0) totals.heapUsed = (totals.heapUsed ?? 0) + heapUsed;
234
+ workers.set(worker.script, totals);
235
+ }
236
+ for (const worker of memory.workerMemoryMissing ?? []) {
237
+ const totals = workers.get(worker.script) ?? {
238
+ count: 0,
239
+ sampled: 0,
240
+ heapUsed: void 0
241
+ };
242
+ totals.count++;
243
+ workers.set(worker.script, totals);
210
244
  }
211
245
  store.clearGauges("openclaw_worker_heap_used_bytes");
212
- for (const [script, heapUsed] of workerHeaps) store.gauge("openclaw_worker_heap_used_bytes", "Latest live Worker heap usage by bounded script basename.", { script }, heapUsed);
246
+ for (const [script, totals] of workers) {
247
+ store.gauge("openclaw_worker_count", "Worker isolate counts.", { script }, totals.count);
248
+ store.gauge("openclaw_worker_heap_sampled_count", "Worker isolate counts.", { script }, totals.sampled);
249
+ store.gauge("openclaw_worker_heap_used_bytes", "Latest live Worker heap usage by bounded script basename.", { script }, totals.heapUsed);
250
+ }
213
251
  store.histogram("openclaw_memory_rss_bytes", "RSS memory sample distribution in bytes.", {}, asNonNegativeFiniteNumber(memory.rssBytes), byteBuckets);
214
252
  }
215
253
  //#endregion
@@ -259,6 +297,49 @@ function recordModelUsage(store, evt) {
259
297
  }
260
298
  //#endregion
261
299
  //#region extensions/diagnostics-prometheus/src/service-operation-timing.ts
300
+ const RPC_DURATION_BUCKETS_SECONDS = [
301
+ .005,
302
+ .01,
303
+ .0125,
304
+ .015,
305
+ .02,
306
+ .025,
307
+ .03,
308
+ .04,
309
+ .05,
310
+ .06,
311
+ .08,
312
+ .1,
313
+ .125,
314
+ .15,
315
+ .2,
316
+ .25,
317
+ .3,
318
+ .4,
319
+ .5,
320
+ .6,
321
+ .8,
322
+ 1,
323
+ 1.25,
324
+ 1.5,
325
+ 2,
326
+ 2.5,
327
+ 3,
328
+ 4,
329
+ 5,
330
+ 6,
331
+ 8,
332
+ 10,
333
+ 12.5,
334
+ 15,
335
+ 20,
336
+ 25,
337
+ 30,
338
+ 60,
339
+ 120,
340
+ 300,
341
+ 600
342
+ ];
262
343
  const RESPONSE_BYTE_BUCKETS = Array.from({ length: 17 }, (_, index) => 1024 * 2 ** index);
263
344
  const HEAP_DELTA_BYTE_BUCKETS = [
264
345
  ...RESPONSE_BYTE_BUCKETS.toReversed().map((bytes) => -bytes),
@@ -278,11 +359,30 @@ const CATALOG_LIST_PHASES = /* @__PURE__ */ new Set([
278
359
  const CHAT_SEND_PHASE = /^chat\.send\.(authority|admission|preparation|attachments|replyContext|authoring|persist|runAdmission|replyInitialization|snapshot|worktree|effects|response|dispatch)$/;
279
360
  function recordOperationTimingEvent(store, evt, metadata) {
280
361
  switch (evt.type) {
362
+ case "secret.egress":
363
+ store.counter("openclaw_secret_egress_requests_total", "Secret egress proxy requests by outcome and credential substitution.", {
364
+ outcome: evt.outcome,
365
+ substituted: String(evt.substituted)
366
+ });
367
+ return;
368
+ case "tool.catalog": {
369
+ const labels = {
370
+ source: evt.source,
371
+ mode: evt.mode
372
+ };
373
+ store.counter("openclaw_tool_catalog_total", "Tool catalogs prepared.", labels);
374
+ store.counter("openclaw_tool_catalog_tools_total", "Tools cataloged during preparation.", labels, evt.toolCount);
375
+ return;
376
+ }
281
377
  case "gateway.http.cancelled":
282
378
  store.counter("openclaw_gateway_http_cancelled_total", "Gateway HTTP requests cancelled before completion.", { source: evt.source });
283
379
  return;
284
380
  case "diagnostic.gc":
285
- store.histogram("openclaw_gc_duration_seconds", "Elapsed garbage collection duration in seconds for the hosting JavaScript isolate.", {}, seconds(evt.durationMs));
381
+ store.histogram("openclaw_gc_duration_seconds", "Elapsed garbage collection duration in seconds by collection kind and isolate role.", {
382
+ kind: evt.kind ?? "unknown",
383
+ thread: evt.thread ?? "main",
384
+ ...evt.workerSlot === void 0 ? {} : { slot: String(evt.workerSlot) }
385
+ }, seconds(evt.durationMs));
286
386
  return;
287
387
  case "gateway.event_loop.sample":
288
388
  store.histogram("openclaw_gateway_event_loop_delay_max_seconds", "Maximum event-loop delay per completed Gateway observation window in seconds.", {}, seconds(evt.delayMaxMs));
@@ -297,7 +397,7 @@ function recordOperationTimingEvent(store, evt, metadata) {
297
397
  const sendPhase = CHAT_SEND_PHASE.exec(evt.name)?.[1];
298
398
  if (sendPhase) {
299
399
  const stage = evt.details?.stage;
300
- if (stage === "request" || stage === "startup") store.histogram("openclaw_chat_send_phase_seconds", "Elapsed chat.send owner phases before acknowledgement and during run startup.", {
400
+ if (stage === "request" || stage === "startup" || stage === "steer" || stage === "queued") store.histogram("openclaw_chat_send_phase_seconds", "Elapsed chat.send owner phases before acknowledgement, during startup, or awaiting steering and queued follow-up delivery.", {
301
401
  phase: sendPhase,
302
402
  stage
303
403
  }, seconds(evt.durationMs));
@@ -320,6 +420,17 @@ function recordOperationTimingEvent(store, evt, metadata) {
320
420
  const labels = { method: evt.method };
321
421
  if (evt.phase === "received") {
322
422
  store.counter("openclaw_gateway_rpc_requests_total", "Authenticated Gateway WebSocket requests received.", labels);
423
+ if (evt.method === "models.list" && evt.modelsList) {
424
+ const catalog = evt.modelsList;
425
+ store.counter("openclaw_models_list_requests_total", "Model catalog requests by client kind and bounded request shape.", {
426
+ client_kind: catalog.clientKind,
427
+ source: catalog.source,
428
+ view: catalog.view,
429
+ scope: catalog.scope,
430
+ refresh: String(catalog.refresh),
431
+ prepared_only: String(catalog.preparedOnly)
432
+ });
433
+ }
323
434
  return;
324
435
  }
325
436
  if (evt.phase === "response" && (evt.outcome === "ok" || evt.outcome === "error")) {
@@ -330,13 +441,13 @@ function recordOperationTimingEvent(store, evt, metadata) {
330
441
  phase: evt.phase,
331
442
  outcome: evt.outcome
332
443
  });
333
- if (evt.phase === "response" && (evt.outcome === "ok" || evt.outcome === "error")) store.histogram("openclaw_gateway_rpc_first_response_seconds", "Elapsed time until the first Gateway RPC response is sent.", labels, seconds(evt.durationMs));
444
+ if (evt.phase === "response" && (evt.outcome === "ok" || evt.outcome === "error")) store.histogram("openclaw_gateway_rpc_first_response_seconds", "Elapsed time until the first Gateway RPC response is sent.", labels, seconds(evt.durationMs), RPC_DURATION_BUCKETS_SECONDS);
334
445
  else if (evt.phase === "handler") {
335
446
  if (evt.heapDeltaBytes !== void 0) store.counter("openclaw_gateway_rpc_handler_heap_delta_exclusive_total", "Gateway RPC handlers with an exclusive main-thread heap-change sample.", labels);
336
447
  store.histogram("openclaw_gateway_rpc_handler_heap_delta_bytes", "Exclusive RPC handler heap change; background work and GC can affect signed samples.", labels, evt.heapDeltaBytes, HEAP_DELTA_BYTE_BUCKETS);
337
- store.histogram("openclaw_gateway_rpc_handler_seconds", "Gateway RPC handler duration until return or throw.", labels, seconds(evt.durationMs));
338
- store.histogram("openclaw_gateway_rpc_admission_seconds", "Elapsed time from Gateway RPC receipt until handler invocation.", labels, seconds(evt.admissionMs));
339
- } else if (evt.phase === "dispatch") store.histogram("openclaw_gateway_rpc_queue_wait_seconds", "Gateway operator request start queue wait.", labels, seconds(evt.queueWaitMs));
448
+ store.histogram("openclaw_gateway_rpc_handler_seconds", "Gateway RPC handler duration until return or throw.", labels, seconds(evt.durationMs), RPC_DURATION_BUCKETS_SECONDS);
449
+ store.histogram("openclaw_gateway_rpc_admission_seconds", "Elapsed time from Gateway RPC receipt until handler invocation.", labels, seconds(evt.admissionMs), RPC_DURATION_BUCKETS_SECONDS);
450
+ } else if (evt.phase === "dispatch") store.histogram("openclaw_gateway_rpc_queue_wait_seconds", "Gateway operator request start queue wait.", labels, seconds(evt.queueWaitMs), RPC_DURATION_BUCKETS_SECONDS);
340
451
  }
341
452
  }
342
453
  }
@@ -434,6 +545,52 @@ function recordWorkerRequest(store, event) {
434
545
  };
435
546
  store.histogram("openclaw_worker_queue_wait_seconds", "Elapsed time from worker request enqueue to dispatch.", labels, seconds(event.queueWaitMs));
436
547
  store.histogram("openclaw_worker_request_seconds", "Elapsed time from worker dispatch to reply or failure, including preparation and transport.", labels, seconds(event.durationMs));
548
+ if (event.phase !== "completed" || !event.timing) return;
549
+ for (const [phase, start, end] of [
550
+ [
551
+ "dispatch",
552
+ "dispatched",
553
+ "posted"
554
+ ],
555
+ [
556
+ "delivery",
557
+ "posted",
558
+ "received"
559
+ ],
560
+ [
561
+ "input",
562
+ "received",
563
+ "inputReady"
564
+ ],
565
+ [
566
+ "prepare",
567
+ "inputReady",
568
+ "executeStarted"
569
+ ],
570
+ [
571
+ "execute",
572
+ "executeStarted",
573
+ "executeFinished"
574
+ ],
575
+ [
576
+ "result",
577
+ "executeFinished",
578
+ "replied"
579
+ ],
580
+ [
581
+ "reply",
582
+ "replied",
583
+ "replyReceived"
584
+ ]
585
+ ]) {
586
+ const started = event.timing[start];
587
+ const finished = event.timing[end];
588
+ if (started === void 0 || finished === void 0) continue;
589
+ store.histogram("openclaw_worker_request_phase_seconds", "Elapsed time within an observed SQLite worker request phase, including transport.", {
590
+ ...labels,
591
+ phase
592
+ }, seconds(finished - started));
593
+ }
437
594
  }
438
595
  //#endregion
439
596
  //#region extensions/diagnostics-prometheus/src/service.ts
@@ -512,6 +669,8 @@ function recordDiagnosticEvent(store, evt, metadata) {
512
669
  if (metadata.trusted) recordWorkerRequest(store, evt);
513
670
  return;
514
671
  case "diagnostic.phase.completed":
672
+ case "secret.egress":
673
+ case "tool.catalog":
515
674
  case "gateway.rpc":
516
675
  case "gateway.http.cancelled":
517
676
  case "diagnostic.gc":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/diagnostics-prometheus",
3
- "version": "2026.10.5-beta.4",
3
+ "version": "2026.10.10-beta.1",
4
4
  "description": "OpenClaw diagnostics Prometheus exporter for runtime metrics.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,10 +18,10 @@
18
18
  "minHostVersion": ">=2026.4.25"
19
19
  },
20
20
  "compat": {
21
- "pluginApi": ">=2026.10.5-beta.4"
21
+ "pluginApi": ">=2026.10.10-beta.1"
22
22
  },
23
23
  "build": {
24
- "openclawVersion": "2026.10.5-beta.4"
24
+ "openclawVersion": "2026.10.10-beta.1"
25
25
  },
26
26
  "release": {
27
27
  "publishToClawHub": true,
@@ -39,7 +39,7 @@
39
39
  "assets/activity.svg"
40
40
  ],
41
41
  "peerDependencies": {
42
- "openclaw": ">=2026.10.5-beta.4"
42
+ "openclaw": ">=2026.10.10-beta.1"
43
43
  },
44
44
  "peerDependenciesMeta": {
45
45
  "openclaw": {