@openclaw/diagnostics-otel 2026.5.7-beta.1 → 2026.5.9-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 +87 -0
  2. package/package.json +10 -10
package/dist/index.js CHANGED
@@ -514,6 +514,30 @@ function createDiagnosticsOtelService() {
514
514
  unit: "ms",
515
515
  description: "Age of stuck sessions"
516
516
  });
517
+ const sessionRecoveryRequestedCounter = meter.createCounter("openclaw.session.recovery.requested", {
518
+ unit: "1",
519
+ description: "Session recovery attempts requested"
520
+ });
521
+ const sessionRecoveryCompletedCounter = meter.createCounter("openclaw.session.recovery.completed", {
522
+ unit: "1",
523
+ description: "Session recovery attempts completed"
524
+ });
525
+ const sessionRecoveryAgeHistogram = meter.createHistogram("openclaw.session.recovery.age_ms", {
526
+ unit: "ms",
527
+ description: "Age of sessions selected for recovery"
528
+ });
529
+ const talkEventCounter = meter.createCounter("openclaw.talk.event", {
530
+ unit: "1",
531
+ description: "Talk events emitted by type"
532
+ });
533
+ const talkEventDurationHistogram = meter.createHistogram("openclaw.talk.event.duration_ms", {
534
+ unit: "ms",
535
+ description: "Talk event duration when reported"
536
+ });
537
+ const talkAudioBytesHistogram = meter.createHistogram("openclaw.talk.audio.bytes", {
538
+ unit: "By",
539
+ description: "Talk audio frame byte lengths"
540
+ });
517
541
  const runAttemptCounter = meter.createCounter("openclaw.run.attempt", {
518
542
  unit: "1",
519
543
  description: "Run attempts"
@@ -914,6 +938,40 @@ function createDiagnosticsOtelService() {
914
938
  });
915
939
  span.end();
916
940
  };
941
+ const sessionRecoveryAttrs = (evt) => {
942
+ const attrs = { "openclaw.state": evt.state };
943
+ if (evt.reason) attrs["openclaw.reason"] = redactSensitiveText(evt.reason);
944
+ if (evt.activeWorkKind) attrs["openclaw.active_work_kind"] = evt.activeWorkKind;
945
+ return attrs;
946
+ };
947
+ const recordSessionRecoveryRequested = (evt) => {
948
+ const attrs = sessionRecoveryAttrs(evt);
949
+ attrs["openclaw.action"] = evt.allowActiveAbort ? "abort" : "recover";
950
+ sessionRecoveryRequestedCounter.add(1, attrs);
951
+ sessionRecoveryAgeHistogram.record(evt.ageMs, attrs);
952
+ };
953
+ const recordSessionRecoveryCompleted = (evt) => {
954
+ const attrs = sessionRecoveryAttrs(evt);
955
+ attrs["openclaw.status"] = evt.status;
956
+ attrs["openclaw.action"] = lowCardinalityAttr(evt.action, "unknown");
957
+ if (evt.outcomeReason) attrs["openclaw.reason"] = redactSensitiveText(evt.outcomeReason);
958
+ sessionRecoveryCompletedCounter.add(1, attrs);
959
+ sessionRecoveryAgeHistogram.record(evt.ageMs, attrs);
960
+ };
961
+ const talkEventAttrs = (evt) => ({
962
+ "openclaw.talk.brain": lowCardinalityAttr(evt.brain),
963
+ "openclaw.talk.event_type": lowCardinalityAttr(evt.talkEventType),
964
+ "openclaw.talk.mode": lowCardinalityAttr(evt.mode),
965
+ "openclaw.talk.provider": lowCardinalityAttr(evt.provider),
966
+ "openclaw.talk.transport": lowCardinalityAttr(evt.transport)
967
+ });
968
+ const recordTalkEvent = (evt, metadata) => {
969
+ if (!metadata.trusted) return;
970
+ const attrs = talkEventAttrs(evt);
971
+ talkEventCounter.add(1, attrs);
972
+ if (typeof evt.durationMs === "number") talkEventDurationHistogram.record(evt.durationMs, attrs);
973
+ if (typeof evt.byteLength === "number") talkAudioBytesHistogram.record(evt.byteLength, attrs);
974
+ };
917
975
  const recordRunAttempt = (evt) => {
918
976
  runAttemptCounter.add(1, { "openclaw.attempt": evt.attempt });
919
977
  };
@@ -978,10 +1036,12 @@ function createDiagnosticsOtelService() {
978
1036
  "openclaw.model": evt.model ?? "unknown"
979
1037
  };
980
1038
  if (evt.channel) attrs["openclaw.channel"] = evt.channel;
1039
+ if (evt.blockedBy) attrs["openclaw.blocked_by"] = lowCardinalityAttr(evt.blockedBy, "unknown");
981
1040
  durationHistogram.record(evt.durationMs, attrs);
982
1041
  if (!tracesEnabled) return;
983
1042
  const spanAttrs = { "openclaw.outcome": evt.outcome };
984
1043
  addRunAttrs(spanAttrs, evt);
1044
+ if (evt.blockedBy) spanAttrs["openclaw.blocked_by"] = lowCardinalityAttr(evt.blockedBy, "unknown");
985
1045
  if (evt.errorCategory) spanAttrs["openclaw.errorCategory"] = lowCardinalityAttr(evt.errorCategory, "other");
986
1046
  const trustedTrace = trustedTraceContext(evt, metadata);
987
1047
  const trackedSpan = trustedTrace?.spanId ? activeTrustedSpans.get(trustedTrace.spanId) : void 0;
@@ -1081,6 +1141,21 @@ function createDiagnosticsOtelService() {
1081
1141
  endTimeMs: evt.ts
1082
1142
  }).end(evt.ts);
1083
1143
  };
1144
+ const recordModelFailover = (evt, metadata) => {
1145
+ if (!tracesEnabled) return;
1146
+ const spanAttrs = { "openclaw.failover.reason": lowCardinalityAttr(evt.reason, "unknown") };
1147
+ if (evt.fromProvider) spanAttrs["openclaw.provider"] = evt.fromProvider;
1148
+ if (evt.fromModel) spanAttrs["openclaw.model"] = evt.fromModel;
1149
+ if (evt.toProvider) spanAttrs["openclaw.failover.to_provider"] = evt.toProvider;
1150
+ if (evt.toModel) spanAttrs["openclaw.failover.to_model"] = evt.toModel;
1151
+ if (evt.lane) spanAttrs["openclaw.lane"] = lowCardinalityAttr(evt.lane, "unknown");
1152
+ if (evt.suspended !== void 0) spanAttrs["openclaw.failover.suspended"] = evt.suspended;
1153
+ if (evt.cascadeDepth !== void 0) spanAttrs["openclaw.failover.cascade_depth"] = evt.cascadeDepth;
1154
+ spanWithDuration("openclaw.model.failover", spanAttrs, 0, {
1155
+ parentContext: activeTrustedParentContext(evt, metadata),
1156
+ endTimeMs: evt.ts
1157
+ }).end(evt.ts);
1158
+ };
1084
1159
  const modelCallMetricAttrs = (evt) => ({
1085
1160
  "openclaw.provider": evt.provider,
1086
1161
  "openclaw.model": evt.model,
@@ -1356,6 +1431,9 @@ function createDiagnosticsOtelService() {
1356
1431
  case "message.delivery.error":
1357
1432
  recordMessageDeliveryError(evt);
1358
1433
  return;
1434
+ case "talk.event":
1435
+ recordTalkEvent(evt, metadata);
1436
+ return;
1359
1437
  case "queue.lane.enqueue":
1360
1438
  recordLaneEnqueue(evt);
1361
1439
  return;
@@ -1370,6 +1448,12 @@ function createDiagnosticsOtelService() {
1370
1448
  case "session.stuck":
1371
1449
  recordSessionStuck(evt);
1372
1450
  return;
1451
+ case "session.recovery.requested":
1452
+ recordSessionRecoveryRequested(evt);
1453
+ return;
1454
+ case "session.recovery.completed":
1455
+ recordSessionRecoveryCompleted(evt);
1456
+ return;
1373
1457
  case "run.attempt":
1374
1458
  recordRunAttempt(evt);
1375
1459
  return;
@@ -1441,6 +1525,9 @@ function createDiagnosticsOtelService() {
1441
1525
  recordTelemetryExporter(evt, metadata);
1442
1526
  return;
1443
1527
  case "payload.large": return;
1528
+ case "model.failover":
1529
+ recordModelFailover(evt, metadata);
1530
+ return;
1444
1531
  }
1445
1532
  } catch (err) {
1446
1533
  ctx.logger.error(`diagnostics-otel: event handler failed (${evt.type}): ${formatError(err)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/diagnostics-otel",
3
- "version": "2026.5.7-beta.1",
3
+ "version": "2026.5.9-beta.1",
4
4
  "description": "OpenClaw diagnostics OpenTelemetry exporter",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,14 +9,14 @@
9
9
  "type": "module",
10
10
  "dependencies": {
11
11
  "@opentelemetry/api": "^1.9.1",
12
- "@opentelemetry/api-logs": "^0.216.0",
13
- "@opentelemetry/exporter-logs-otlp-proto": "^0.216.0",
14
- "@opentelemetry/exporter-metrics-otlp-proto": "^0.216.0",
15
- "@opentelemetry/exporter-trace-otlp-proto": "^0.216.0",
12
+ "@opentelemetry/api-logs": "^0.217.0",
13
+ "@opentelemetry/exporter-logs-otlp-proto": "^0.217.0",
14
+ "@opentelemetry/exporter-metrics-otlp-proto": "^0.217.0",
15
+ "@opentelemetry/exporter-trace-otlp-proto": "^0.217.0",
16
16
  "@opentelemetry/resources": "^2.7.1",
17
- "@opentelemetry/sdk-logs": "^0.216.0",
17
+ "@opentelemetry/sdk-logs": "^0.217.0",
18
18
  "@opentelemetry/sdk-metrics": "^2.7.1",
19
- "@opentelemetry/sdk-node": "^0.216.0",
19
+ "@opentelemetry/sdk-node": "^0.217.0",
20
20
  "@opentelemetry/sdk-trace-base": "^2.7.1",
21
21
  "@opentelemetry/semantic-conventions": "^1.40.0"
22
22
  },
@@ -34,10 +34,10 @@
34
34
  "minHostVersion": ">=2026.4.25"
35
35
  },
36
36
  "compat": {
37
- "pluginApi": ">=2026.5.7-beta.1"
37
+ "pluginApi": ">=2026.5.9-beta.1"
38
38
  },
39
39
  "build": {
40
- "openclawVersion": "2026.5.7-beta.1"
40
+ "openclawVersion": "2026.5.9-beta.1"
41
41
  },
42
42
  "release": {
43
43
  "publishToClawHub": true,
@@ -52,7 +52,7 @@
52
52
  "openclaw.plugin.json"
53
53
  ],
54
54
  "peerDependencies": {
55
- "openclaw": ">=2026.5.7-beta.1"
55
+ "openclaw": ">=2026.5.9-beta.1"
56
56
  },
57
57
  "peerDependenciesMeta": {
58
58
  "openclaw": {