@openclaw/diagnostics-otel 2026.9.1 → 2026.9.3
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.
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createDiagnosticsOtelService } from "./runtime-api-
|
|
1
|
+
import { t as createDiagnosticsOtelService } from "./runtime-api-B9-DLHbi.js";
|
|
2
2
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
3
3
|
//#region extensions/diagnostics-otel/index.ts
|
|
4
4
|
var diagnostics_otel_default = definePluginEntry({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isValidDiagnosticSpanId, isValidDiagnosticTraceFlags, isValidDiagnosticTraceId, redactSensitiveText } from "./api.js";
|
|
2
|
-
import { ROOT_CONTEXT, SpanKind, SpanStatusCode, TraceFlags, context, createContextKey, diag, isSpanContextValid, metrics, propagation, trace } from "@opentelemetry/api";
|
|
2
|
+
import { ROOT_CONTEXT, SpanKind, SpanStatusCode, TraceFlags, context, createContextKey, createNoopMeter, diag, isSpanContextValid, metrics, propagation, trace } from "@opentelemetry/api";
|
|
3
3
|
import * as otelCore from "@opentelemetry/core";
|
|
4
4
|
import { CompositePropagator, ExportResultCode, W3CBaggagePropagator, W3CTraceContextPropagator, getStringListFromEnv } from "@opentelemetry/core";
|
|
5
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-proto";
|
|
@@ -10,7 +10,7 @@ import { BasicTracerProvider, BatchSpanProcessor, ParentBasedSampler, TraceIdRat
|
|
|
10
10
|
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
11
11
|
import { registerUnhandledRejectionHandler } from "openclaw/plugin-sdk/runtime-env";
|
|
12
12
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
13
|
-
import { normalizeDiagnosticLane, normalizeDiagnosticValue } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
13
|
+
import { isInternalDiagnosticEventMetadata, normalizeDiagnosticLane, normalizeDiagnosticValue } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
14
14
|
import { readFileSync } from "node:fs";
|
|
15
15
|
import nodePath from "node:path";
|
|
16
16
|
import { collectErrorGraphCandidates } from "openclaw/plugin-sdk/error-runtime";
|
|
@@ -443,10 +443,19 @@ function findOtlpExporterError(reason) {
|
|
|
443
443
|
//#region extensions/diagnostics-otel/src/service-events.ts
|
|
444
444
|
function createDiagnosticsEventHandler(params) {
|
|
445
445
|
const { logger, recorders, recordLogRecord, recordSecurityEvent } = params;
|
|
446
|
-
const { recordModelUsage, recordWebhookReceived, recordWebhookProcessed, recordWebhookError, recordMessageQueued, recordMessageReceived, recordMessageDispatchStarted, recordMessageDispatchCompleted, recordMessageProcessed, recordMessageDeliveryStarted, recordMessageDeliveryCompleted, recordMessageDeliveryError, recordTalkEvent, recordLaneEnqueue, recordLaneDequeue, recordSessionState, recordSessionTurnCreated, recordSessionStuck, recordSessionRecoveryRequested, recordSessionRecoveryCompleted, recordRunAttempt, recordHeartbeat, recordLivenessWarning, recordDiagnosticPhaseCompleted, recordRunStarted, recordRunCompleted, recordHarnessRunStarted, recordHarnessRunCompleted, recordHarnessRunError, recordContextAssembled, recordModelCallStarted,
|
|
446
|
+
const { recordGcDuration, recordGatewayEventLoopSample, recordGatewayRpc, recordModelUsage, recordWebhookReceived, recordWebhookProcessed, recordWebhookError, recordMessageQueued, recordMessageReceived, recordMessageDispatchStarted, recordMessageDispatchCompleted, recordMessageProcessed, recordMessageDeliveryStarted, recordMessageDeliveryCompleted, recordMessageDeliveryError, recordTalkEvent, recordLaneEnqueue, recordLaneDequeue, recordSessionState, recordSessionTurnCreated, recordSessionStuck, recordSessionRecoveryRequested, recordSessionRecoveryCompleted, recordRunAttempt, recordHeartbeat, recordLivenessWarning, recordDiagnosticPhaseCompleted, recordRunStarted, recordRunCompleted, recordHarnessRunStarted, recordHarnessRunCompleted, recordHarnessRunError, recordContextAssembled, recordModelCallStarted, recordModelCallFinished, recordToolExecutionStarted, recordToolExecutionFinished, recordToolExecutionBlocked, recordSkillUsed, recordExecProcessCompleted, recordToolLoop, recordMemorySample, recordMemoryPressure, recordAsyncQueueDropped, recordTelemetryExporter, recordPayloadLarge, recordModelFailover } = recorders;
|
|
447
447
|
return (evt, metadata, privateData) => {
|
|
448
448
|
try {
|
|
449
449
|
switch (evt.type) {
|
|
450
|
+
case "diagnostic.gc":
|
|
451
|
+
recordGcDuration(evt, metadata);
|
|
452
|
+
return;
|
|
453
|
+
case "gateway.event_loop.sample":
|
|
454
|
+
recordGatewayEventLoopSample(evt, metadata);
|
|
455
|
+
return;
|
|
456
|
+
case "gateway.rpc":
|
|
457
|
+
recordGatewayRpc(evt, metadata);
|
|
458
|
+
return;
|
|
450
459
|
case "model.usage":
|
|
451
460
|
recordModelUsage(evt, metadata, privateData.hostPluginId);
|
|
452
461
|
return;
|
|
@@ -545,19 +554,15 @@ function createDiagnosticsEventHandler(params) {
|
|
|
545
554
|
recordModelCallStarted(evt, metadata);
|
|
546
555
|
return;
|
|
547
556
|
case "model.call.completed":
|
|
548
|
-
recordModelCallCompleted(evt, metadata, privateData.modelContent);
|
|
549
|
-
return;
|
|
550
557
|
case "model.call.error":
|
|
551
|
-
|
|
558
|
+
recordModelCallFinished(evt, metadata, privateData.modelContent);
|
|
552
559
|
return;
|
|
553
560
|
case "tool.execution.started":
|
|
554
561
|
recordToolExecutionStarted(evt, metadata);
|
|
555
562
|
return;
|
|
556
563
|
case "tool.execution.completed":
|
|
557
|
-
recordToolExecutionCompleted(evt, metadata, privateData.toolContent);
|
|
558
|
-
return;
|
|
559
564
|
case "tool.execution.error":
|
|
560
|
-
|
|
565
|
+
recordToolExecutionFinished(evt, metadata, privateData.toolContent);
|
|
561
566
|
return;
|
|
562
567
|
case "tool.execution.blocked":
|
|
563
568
|
recordToolExecutionBlocked(evt, metadata);
|
|
@@ -1056,6 +1061,48 @@ function createDiagnosticsMetrics(meter, metricNamePrefix = DEFAULT_METRIC_NAME_
|
|
|
1056
1061
|
const createCounter = (name, options) => meter.createCounter(resolveMetricName(name), options);
|
|
1057
1062
|
const createHistogram = (name, options) => meter.createHistogram(resolveMetricName(name), options);
|
|
1058
1063
|
return {
|
|
1064
|
+
gcDurationHistogram: createHistogram("openclaw.gc.duration_ms", {
|
|
1065
|
+
unit: "ms",
|
|
1066
|
+
description: "Elapsed garbage collection duration for the hosting JavaScript isolate",
|
|
1067
|
+
advice: { explicitBucketBoundaries: AGENT_DURATION_MS_BUCKETS }
|
|
1068
|
+
}),
|
|
1069
|
+
gatewayEventLoopDelayMaxHistogram: createHistogram("openclaw.gateway.event_loop.delay_max_ms", {
|
|
1070
|
+
unit: "ms",
|
|
1071
|
+
description: "Maximum event-loop delay per completed Gateway observation window",
|
|
1072
|
+
advice: { explicitBucketBoundaries: AGENT_DURATION_MS_BUCKETS }
|
|
1073
|
+
}),
|
|
1074
|
+
gatewayEventLoopObservedCounter: createCounter("openclaw.gateway.event_loop.observed_ms", {
|
|
1075
|
+
unit: "ms",
|
|
1076
|
+
description: "Elapsed time covered by completed Gateway event-loop observation windows"
|
|
1077
|
+
}),
|
|
1078
|
+
gatewayRpcRequestsCounter: createCounter("openclaw.gateway.rpc.requests", {
|
|
1079
|
+
unit: "1",
|
|
1080
|
+
description: "Authenticated Gateway WebSocket requests received"
|
|
1081
|
+
}),
|
|
1082
|
+
gatewayRpcOutcomesCounter: createCounter("openclaw.gateway.rpc.outcomes", {
|
|
1083
|
+
unit: "1",
|
|
1084
|
+
description: "Gateway RPC observations by phase and outcome"
|
|
1085
|
+
}),
|
|
1086
|
+
gatewayRpcFirstResponseHistogram: createHistogram("openclaw.gateway.rpc.first_response_ms", {
|
|
1087
|
+
unit: "ms",
|
|
1088
|
+
description: "Elapsed time until the first Gateway RPC response is sent",
|
|
1089
|
+
advice: { explicitBucketBoundaries: AGENT_DURATION_MS_BUCKETS }
|
|
1090
|
+
}),
|
|
1091
|
+
gatewayRpcHandlerHistogram: createHistogram("openclaw.gateway.rpc.handler_ms", {
|
|
1092
|
+
unit: "ms",
|
|
1093
|
+
description: "Gateway RPC handler duration until return or throw",
|
|
1094
|
+
advice: { explicitBucketBoundaries: AGENT_DURATION_MS_BUCKETS }
|
|
1095
|
+
}),
|
|
1096
|
+
gatewayRpcAdmissionHistogram: createHistogram("openclaw.gateway.rpc.admission_ms", {
|
|
1097
|
+
unit: "ms",
|
|
1098
|
+
description: "Elapsed time from Gateway RPC receipt until handler invocation",
|
|
1099
|
+
advice: { explicitBucketBoundaries: AGENT_DURATION_MS_BUCKETS }
|
|
1100
|
+
}),
|
|
1101
|
+
gatewayRpcQueueWaitHistogram: createHistogram("openclaw.gateway.rpc.queue_wait_ms", {
|
|
1102
|
+
unit: "ms",
|
|
1103
|
+
description: "Gateway operator request start queue wait",
|
|
1104
|
+
advice: { explicitBucketBoundaries: AGENT_DURATION_MS_BUCKETS }
|
|
1105
|
+
}),
|
|
1059
1106
|
tokensCounter: createCounter("openclaw.tokens", {
|
|
1060
1107
|
unit: "1",
|
|
1061
1108
|
description: "Token usage by type"
|
|
@@ -1291,7 +1338,7 @@ function createDiagnosticsMetrics(meter, metricNamePrefix = DEFAULT_METRIC_NAME_
|
|
|
1291
1338
|
}),
|
|
1292
1339
|
livenessCpuCoreRatioHistogram: createHistogram("openclaw.liveness.cpu_core_ratio", {
|
|
1293
1340
|
unit: "1",
|
|
1294
|
-
description: "CPU core
|
|
1341
|
+
description: "Whole-process CPU usage in core equivalents, including worker and native threads; can exceed 1."
|
|
1295
1342
|
}),
|
|
1296
1343
|
telemetryExporterCounter: createCounter("openclaw.telemetry.exporter.events", {
|
|
1297
1344
|
unit: "1",
|
|
@@ -1868,15 +1915,6 @@ function createModelRecorders(runtime) {
|
|
|
1868
1915
|
"openclaw.transport": normalizeDiagnosticValue(evt.transport),
|
|
1869
1916
|
"openclaw.model_call.observation_unit": modelCallObservationUnit(evt)
|
|
1870
1917
|
});
|
|
1871
|
-
const genAiModelCallMetricAttrs = (evt, errorType) => ({
|
|
1872
|
-
"gen_ai.operation.name": genAiOperationName(evt.api, evt.observationUnit),
|
|
1873
|
-
"gen_ai.provider.name": normalizeDiagnosticValue(evt.provider),
|
|
1874
|
-
"gen_ai.request.model": normalizeDiagnosticValue(evt.model),
|
|
1875
|
-
...errorType ? { "error.type": errorType } : {}
|
|
1876
|
-
});
|
|
1877
|
-
const recordGenAiModelCallDuration = (evt, errorType) => {
|
|
1878
|
-
genAiOperationDurationHistogram.record(evt.durationMs / 1e3, genAiModelCallMetricAttrs(evt, errorType));
|
|
1879
|
-
};
|
|
1880
1918
|
const recordModelCallSizeTimingMetrics = (evt, attrs) => {
|
|
1881
1919
|
const requestPayloadBytes = positiveFiniteNumber(evt.requestPayloadBytes);
|
|
1882
1920
|
if (requestPayloadBytes !== void 0) modelCallRequestBytesHistogram.record(requestPayloadBytes, attrs);
|
|
@@ -1903,50 +1941,31 @@ function createModelRecorders(runtime) {
|
|
|
1903
1941
|
startTimeMs: evt.ts
|
|
1904
1942
|
})).spanContext();
|
|
1905
1943
|
};
|
|
1906
|
-
const
|
|
1907
|
-
const
|
|
1908
|
-
modelCallDurationHistogram.record(evt.durationMs, metricAttrs);
|
|
1909
|
-
recordModelCallSizeTimingMetrics(evt, metricAttrs);
|
|
1910
|
-
recordGenAiModelCallDuration(evt);
|
|
1911
|
-
if (!tracesEnabled) return;
|
|
1912
|
-
const spanAttrs = {
|
|
1913
|
-
"openclaw.provider": evt.provider,
|
|
1914
|
-
"openclaw.model": evt.model
|
|
1915
|
-
};
|
|
1916
|
-
assignGenAiModelCallAttrs(spanAttrs, evt);
|
|
1917
|
-
if (evt.api) spanAttrs["openclaw.api"] = evt.api;
|
|
1918
|
-
if (evt.transport) spanAttrs["openclaw.transport"] = evt.transport;
|
|
1919
|
-
assignModelCallSizeTimingAttrs(spanAttrs, evt);
|
|
1920
|
-
assignModelCallPromptStatsAttrs(spanAttrs, evt);
|
|
1921
|
-
assignModelCallUsageAttrs(spanAttrs, evt);
|
|
1922
|
-
assignOtelModelContentAttributes(spanAttrs, modelContent, contentCapturePolicy);
|
|
1923
|
-
const span = takeTrackedTrustedSpan(evt, metadata) ?? spanWithDuration(modelCallSpanName(evt), spanAttrs, evt.durationMs, {
|
|
1924
|
-
kind: modelCallSpanKind(),
|
|
1925
|
-
parentContext: activeTrustedParentContext(evt, metadata),
|
|
1926
|
-
endTimeMs: evt.ts
|
|
1927
|
-
});
|
|
1928
|
-
setSpanAttrs(span, spanAttrs);
|
|
1929
|
-
addUpstreamRequestIdSpanEvent(span, evt.upstreamRequestIdHash);
|
|
1930
|
-
span.end(evt.ts);
|
|
1931
|
-
};
|
|
1932
|
-
const recordModelCallError = (evt, metadata, modelContent) => {
|
|
1933
|
-
const errorType = normalizeDiagnosticValue(evt.errorCategory, "other");
|
|
1944
|
+
const recordModelCallFinished = (evt, metadata, modelContent) => {
|
|
1945
|
+
const errorType = evt.type === "model.call.error" ? normalizeDiagnosticValue(evt.errorCategory, "other") : void 0;
|
|
1934
1946
|
const metricAttrs = {
|
|
1935
1947
|
...modelCallMetricAttrs(evt),
|
|
1936
|
-
"openclaw.errorCategory": errorType,
|
|
1937
|
-
...evt.failureKind ? { "openclaw.failureKind": normalizeDiagnosticValue(evt.failureKind, "other") } : {}
|
|
1948
|
+
...errorType !== void 0 ? { "openclaw.errorCategory": errorType } : {},
|
|
1949
|
+
...evt.type === "model.call.error" && evt.failureKind ? { "openclaw.failureKind": normalizeDiagnosticValue(evt.failureKind, "other") } : {}
|
|
1938
1950
|
};
|
|
1939
1951
|
modelCallDurationHistogram.record(evt.durationMs, metricAttrs);
|
|
1940
1952
|
recordModelCallSizeTimingMetrics(evt, metricAttrs);
|
|
1941
|
-
|
|
1953
|
+
genAiOperationDurationHistogram.record(evt.durationMs / 1e3, {
|
|
1954
|
+
"gen_ai.operation.name": genAiOperationName(evt.api, evt.observationUnit),
|
|
1955
|
+
"gen_ai.provider.name": normalizeDiagnosticValue(evt.provider),
|
|
1956
|
+
"gen_ai.request.model": normalizeDiagnosticValue(evt.model),
|
|
1957
|
+
...errorType ? { "error.type": errorType } : {}
|
|
1958
|
+
});
|
|
1942
1959
|
if (!tracesEnabled) return;
|
|
1943
1960
|
const spanAttrs = {
|
|
1944
1961
|
"openclaw.provider": evt.provider,
|
|
1945
1962
|
"openclaw.model": evt.model,
|
|
1946
|
-
|
|
1947
|
-
|
|
1963
|
+
...errorType !== void 0 ? {
|
|
1964
|
+
"openclaw.errorCategory": errorType,
|
|
1965
|
+
"error.type": errorType
|
|
1966
|
+
} : {}
|
|
1948
1967
|
};
|
|
1949
|
-
if (evt.failureKind) spanAttrs["openclaw.failureKind"] = normalizeDiagnosticValue(evt.failureKind, "other");
|
|
1968
|
+
if (evt.type === "model.call.error" && evt.failureKind) spanAttrs["openclaw.failureKind"] = normalizeDiagnosticValue(evt.failureKind, "other");
|
|
1950
1969
|
assignGenAiModelCallAttrs(spanAttrs, evt);
|
|
1951
1970
|
if (evt.api) spanAttrs["openclaw.api"] = evt.api;
|
|
1952
1971
|
if (evt.transport) spanAttrs["openclaw.transport"] = evt.transport;
|
|
@@ -1961,23 +1980,56 @@ function createModelRecorders(runtime) {
|
|
|
1961
1980
|
});
|
|
1962
1981
|
setSpanAttrs(span, spanAttrs);
|
|
1963
1982
|
addUpstreamRequestIdSpanEvent(span, evt.upstreamRequestIdHash);
|
|
1964
|
-
span.setStatus({
|
|
1983
|
+
if (evt.type === "model.call.error") span.setStatus({
|
|
1965
1984
|
code: SpanStatusCode.ERROR,
|
|
1966
1985
|
message: redactSensitiveText(evt.errorCategory)
|
|
1967
1986
|
});
|
|
1968
1987
|
span.end(evt.ts);
|
|
1969
1988
|
};
|
|
1970
1989
|
return {
|
|
1971
|
-
recordModelCallSizeTimingMetrics,
|
|
1972
1990
|
recordModelCallStarted,
|
|
1973
|
-
|
|
1974
|
-
recordModelCallError
|
|
1991
|
+
recordModelCallFinished
|
|
1975
1992
|
};
|
|
1976
1993
|
}
|
|
1977
1994
|
//#endregion
|
|
1978
1995
|
//#region extensions/diagnostics-otel/src/service-recorders-operations.ts
|
|
1979
1996
|
function createOperationsRecorders(runtime) {
|
|
1980
|
-
const { durationHistogram, queueDepthHistogram, queueWaitHistogram, laneEnqueueCounter, laneDequeueCounter, sessionStateCounter, sessionTurnCreatedCounter, sessionStuckCounter, sessionStuckAgeHistogram, sessionRecoveryRequestedCounter, sessionRecoveryCompletedCounter, sessionRecoveryAgeHistogram, talkEventCounter, talkEventDurationHistogram, talkAudioBytesHistogram, runAttemptCounter, toolLoopCounter, memoryRssHistogram, memoryHeapUsedHistogram, memoryHeapTotalHistogram, memoryExternalHistogram, memoryArrayBuffersHistogram, memoryPressureCounter, asyncQueueDroppedCounter, tracer, activeTrustedSpans, spanWithDuration, trustedTraceContext, activeTrustedParentContext, setSpanAttrs, completeTrackedLifecycleSpan, addRunAttrs, tracesEnabled } = runtime;
|
|
1997
|
+
const { durationHistogram, gatewayRpcRequestsCounter, gatewayRpcOutcomesCounter, gatewayRpcFirstResponseHistogram, gatewayRpcHandlerHistogram, gatewayRpcAdmissionHistogram, gatewayRpcQueueWaitHistogram, queueDepthHistogram, queueWaitHistogram, laneEnqueueCounter, laneDequeueCounter, sessionStateCounter, sessionTurnCreatedCounter, sessionStuckCounter, sessionStuckAgeHistogram, sessionRecoveryRequestedCounter, sessionRecoveryCompletedCounter, sessionRecoveryAgeHistogram, talkEventCounter, talkEventDurationHistogram, talkAudioBytesHistogram, runAttemptCounter, toolLoopCounter, memoryRssHistogram, memoryHeapUsedHistogram, memoryHeapTotalHistogram, memoryExternalHistogram, memoryArrayBuffersHistogram, memoryPressureCounter, asyncQueueDroppedCounter, tracer, activeTrustedSpans, spanWithDuration, trustedTraceContext, activeTrustedParentContext, internalOrTrustedExplicitParentContext, setSpanAttrs, completeTrackedLifecycleSpan, addRunAttrs, tracesEnabled } = runtime;
|
|
1998
|
+
const recordGatewayRpc = (evt, metadata) => {
|
|
1999
|
+
if (!metadata.trusted) return;
|
|
2000
|
+
const attrs = { "openclaw.gateway.rpc.method": evt.method };
|
|
2001
|
+
if (evt.phase === "received") {
|
|
2002
|
+
gatewayRpcRequestsCounter.add(1, attrs);
|
|
2003
|
+
return;
|
|
2004
|
+
}
|
|
2005
|
+
const outcomeAttrs = {
|
|
2006
|
+
"openclaw.gateway.rpc.phase": evt.phase,
|
|
2007
|
+
"openclaw.gateway.rpc.outcome": evt.outcome
|
|
2008
|
+
};
|
|
2009
|
+
gatewayRpcOutcomesCounter.add(1, outcomeAttrs);
|
|
2010
|
+
switch (evt.phase) {
|
|
2011
|
+
case "response":
|
|
2012
|
+
if (evt.outcome === "ok" || evt.outcome === "error") gatewayRpcFirstResponseHistogram.record(evt.durationMs, attrs);
|
|
2013
|
+
break;
|
|
2014
|
+
case "handler":
|
|
2015
|
+
gatewayRpcHandlerHistogram.record(evt.durationMs, attrs);
|
|
2016
|
+
gatewayRpcAdmissionHistogram.record(evt.admissionMs, attrs);
|
|
2017
|
+
break;
|
|
2018
|
+
case "dispatch": if (evt.queueWaitMs !== void 0) gatewayRpcQueueWaitHistogram.record(evt.queueWaitMs, attrs);
|
|
2019
|
+
}
|
|
2020
|
+
if (!tracesEnabled) return;
|
|
2021
|
+
const span = spanWithDuration(`openclaw.gateway.rpc.${evt.phase}`, {
|
|
2022
|
+
...attrs,
|
|
2023
|
+
...outcomeAttrs,
|
|
2024
|
+
...evt.phase === "handler" ? { "openclaw.gateway.rpc.admission_ms": evt.admissionMs } : {},
|
|
2025
|
+
...evt.phase === "dispatch" ? { "openclaw.gateway.rpc.response": evt.response } : {}
|
|
2026
|
+
}, evt.durationMs, {
|
|
2027
|
+
endTimeMs: evt.ts,
|
|
2028
|
+
parentContext: internalOrTrustedExplicitParentContext(evt, metadata) ?? ROOT_CONTEXT
|
|
2029
|
+
});
|
|
2030
|
+
if (evt.outcome === "error" || evt.outcome === "threw") span.setStatus({ code: SpanStatusCode.ERROR });
|
|
2031
|
+
span.end(evt.ts);
|
|
2032
|
+
};
|
|
1981
2033
|
const recordLaneEnqueue = (evt) => {
|
|
1982
2034
|
const attrs = { "openclaw.lane": normalizeDiagnosticLane(evt.lane) };
|
|
1983
2035
|
laneEnqueueCounter.add(1, attrs);
|
|
@@ -2151,6 +2203,7 @@ function createOperationsRecorders(runtime) {
|
|
|
2151
2203
|
span.end(evt.ts);
|
|
2152
2204
|
};
|
|
2153
2205
|
return {
|
|
2206
|
+
recordGatewayRpc,
|
|
2154
2207
|
recordLaneEnqueue,
|
|
2155
2208
|
recordLaneDequeue,
|
|
2156
2209
|
recordSessionState,
|
|
@@ -2171,7 +2224,7 @@ function createOperationsRecorders(runtime) {
|
|
|
2171
2224
|
//#endregion
|
|
2172
2225
|
//#region extensions/diagnostics-otel/src/service-recorders-tools.ts
|
|
2173
2226
|
function createToolAndSystemRecorders(runtime) {
|
|
2174
|
-
const { queueDepthHistogram, skillUsedCounter, toolExecutionDurationHistogram, toolExecutionBlockedCounter, execProcessDurationHistogram, payloadLargeCounter, payloadLargeBytesHistogram, livenessWarningCounter, livenessEventLoopDelayP99Histogram, livenessEventLoopDelayMaxHistogram, livenessEventLoopUtilizationHistogram, livenessCpuCoreRatioHistogram, telemetryExporterCounter, spanWithDuration, activeTrustedParentContext, exportedInternalOrTrustedContext, trackTrustedSpan, getTrackedInternalOrTrustedSpan, takeTrackedTrustedSpan, setSpanAttrs, addRunAttrs, paramsSummaryAttrs, contentCapturePolicy, tracesEnabled } = runtime;
|
|
2227
|
+
const { gcDurationHistogram, gatewayEventLoopDelayMaxHistogram, gatewayEventLoopObservedCounter, queueDepthHistogram, skillUsedCounter, toolExecutionDurationHistogram, toolExecutionBlockedCounter, execProcessDurationHistogram, payloadLargeCounter, payloadLargeBytesHistogram, livenessWarningCounter, livenessEventLoopDelayP99Histogram, livenessEventLoopDelayMaxHistogram, livenessEventLoopUtilizationHistogram, livenessCpuCoreRatioHistogram, telemetryExporterCounter, spanWithDuration, activeTrustedParentContext, exportedInternalOrTrustedContext, trackTrustedSpan, getTrackedInternalOrTrustedSpan, takeTrackedTrustedSpan, setSpanAttrs, addRunAttrs, paramsSummaryAttrs, contentCapturePolicy, tracesEnabled } = runtime;
|
|
2175
2228
|
const toolExecutionBaseAttrs = (evt) => ({
|
|
2176
2229
|
"openclaw.toolName": evt.toolName,
|
|
2177
2230
|
"openclaw.tool.source": normalizeDiagnosticValue(evt.toolSource, "core"),
|
|
@@ -2212,39 +2265,22 @@ function createToolAndSystemRecorders(runtime) {
|
|
|
2212
2265
|
startTimeMs: toolTimestampMs(evt)
|
|
2213
2266
|
})).spanContext();
|
|
2214
2267
|
};
|
|
2215
|
-
const
|
|
2268
|
+
const recordToolExecutionFinished = (evt, metadata, toolContent) => {
|
|
2216
2269
|
const attrs = toolExecutionBaseAttrs(evt);
|
|
2270
|
+
if (evt.type === "tool.execution.error") attrs["openclaw.errorCategory"] = normalizeDiagnosticValue(evt.errorCategory, "other");
|
|
2217
2271
|
toolExecutionDurationHistogram.record(evt.durationMs, attrs);
|
|
2218
2272
|
if (!tracesEnabled) return;
|
|
2219
2273
|
const spanAttrs = { ...attrs };
|
|
2220
2274
|
addRunAttrs(spanAttrs, evt);
|
|
2221
2275
|
assignOtelToolIdentityAttributes(spanAttrs, evt);
|
|
2276
|
+
if (evt.type === "tool.execution.error" && evt.errorCode) spanAttrs["openclaw.errorCode"] = normalizeDiagnosticValue(evt.errorCode, "other");
|
|
2222
2277
|
assignOtelToolContentAttributes(spanAttrs, toolContent, contentCapturePolicy);
|
|
2223
2278
|
const span = takeTrackedTrustedSpan(evt, metadata) ?? spanWithDuration("openclaw.tool.execution", spanAttrs, evt.durationMs, {
|
|
2224
2279
|
parentContext: activeTrustedParentContext(evt, metadata),
|
|
2225
2280
|
endTimeMs: toolTimestampMs(evt)
|
|
2226
2281
|
});
|
|
2227
2282
|
setSpanAttrs(span, spanAttrs);
|
|
2228
|
-
span.
|
|
2229
|
-
};
|
|
2230
|
-
const recordToolExecutionError = (evt, metadata, toolContent) => {
|
|
2231
|
-
const attrs = {
|
|
2232
|
-
...toolExecutionBaseAttrs(evt),
|
|
2233
|
-
"openclaw.errorCategory": normalizeDiagnosticValue(evt.errorCategory, "other")
|
|
2234
|
-
};
|
|
2235
|
-
toolExecutionDurationHistogram.record(evt.durationMs, attrs);
|
|
2236
|
-
if (!tracesEnabled) return;
|
|
2237
|
-
const spanAttrs = { ...attrs };
|
|
2238
|
-
addRunAttrs(spanAttrs, evt);
|
|
2239
|
-
assignOtelToolIdentityAttributes(spanAttrs, evt);
|
|
2240
|
-
if (evt.errorCode) spanAttrs["openclaw.errorCode"] = normalizeDiagnosticValue(evt.errorCode, "other");
|
|
2241
|
-
assignOtelToolContentAttributes(spanAttrs, toolContent, contentCapturePolicy);
|
|
2242
|
-
const span = takeTrackedTrustedSpan(evt, metadata) ?? spanWithDuration("openclaw.tool.execution", spanAttrs, evt.durationMs, {
|
|
2243
|
-
parentContext: activeTrustedParentContext(evt, metadata),
|
|
2244
|
-
endTimeMs: toolTimestampMs(evt)
|
|
2245
|
-
});
|
|
2246
|
-
setSpanAttrs(span, spanAttrs);
|
|
2247
|
-
span.setStatus({
|
|
2283
|
+
if (evt.type === "tool.execution.error") span.setStatus({
|
|
2248
2284
|
code: SpanStatusCode.ERROR,
|
|
2249
2285
|
message: redactSensitiveText(evt.errorCategory)
|
|
2250
2286
|
});
|
|
@@ -2308,6 +2344,15 @@ function createToolAndSystemRecorders(runtime) {
|
|
|
2308
2344
|
});
|
|
2309
2345
|
span.end(evt.ts);
|
|
2310
2346
|
};
|
|
2347
|
+
const recordGcDuration = (evt, metadata) => {
|
|
2348
|
+
if (!metadata.trusted && !isInternalDiagnosticEventMetadata(metadata)) return;
|
|
2349
|
+
gcDurationHistogram.record(evt.durationMs, void 0, ROOT_CONTEXT);
|
|
2350
|
+
};
|
|
2351
|
+
const recordGatewayEventLoopSample = (evt, metadata) => {
|
|
2352
|
+
if (!metadata.trusted && !isInternalDiagnosticEventMetadata(metadata)) return;
|
|
2353
|
+
gatewayEventLoopDelayMaxHistogram.record(evt.delayMaxMs, void 0, ROOT_CONTEXT);
|
|
2354
|
+
gatewayEventLoopObservedCounter.add(evt.intervalMs, void 0, ROOT_CONTEXT);
|
|
2355
|
+
};
|
|
2311
2356
|
const recordHeartbeat = (evt) => {
|
|
2312
2357
|
queueDepthHistogram.record(evt.queued, { "openclaw.channel": "heartbeat" });
|
|
2313
2358
|
};
|
|
@@ -2365,10 +2410,11 @@ function createToolAndSystemRecorders(runtime) {
|
|
|
2365
2410
|
});
|
|
2366
2411
|
};
|
|
2367
2412
|
return {
|
|
2413
|
+
recordGcDuration,
|
|
2414
|
+
recordGatewayEventLoopSample,
|
|
2368
2415
|
recordSkillUsed,
|
|
2369
2416
|
recordToolExecutionStarted,
|
|
2370
|
-
|
|
2371
|
-
recordToolExecutionError,
|
|
2417
|
+
recordToolExecutionFinished,
|
|
2372
2418
|
recordToolExecutionBlocked,
|
|
2373
2419
|
recordPayloadLarge,
|
|
2374
2420
|
recordExecProcessCompleted,
|
|
@@ -2910,56 +2956,34 @@ function diagnosticTraceContextFromSpanContext(spanContext) {
|
|
|
2910
2956
|
};
|
|
2911
2957
|
}
|
|
2912
2958
|
function createDiagnosticsOtelService() {
|
|
2913
|
-
let
|
|
2914
|
-
let meterProvider = null;
|
|
2915
|
-
let logProvider = null;
|
|
2916
|
-
let unsubscribe = null;
|
|
2917
|
-
let unregisterTracePropagationBridge = null;
|
|
2918
|
-
let stopActiveTrustedSpans = null;
|
|
2919
|
-
let unregisterOwnedSdkRuntime = null;
|
|
2920
|
-
let unregisterUnhandledRejectionHandler = null;
|
|
2921
|
-
let retireExporterRoutes = null;
|
|
2959
|
+
let state = {};
|
|
2922
2960
|
let preserveExporterRoutesOnNextStop = false;
|
|
2923
2961
|
const stopStarted = async (options) => {
|
|
2924
|
-
const
|
|
2925
|
-
|
|
2926
|
-
const currentLogProvider = logProvider;
|
|
2927
|
-
const currentTraceProvider = traceProvider;
|
|
2928
|
-
const currentMeterProvider = meterProvider;
|
|
2929
|
-
const currentStopActiveTrustedSpans = stopActiveTrustedSpans;
|
|
2930
|
-
const currentUnregisterOwnedSdkRuntime = unregisterOwnedSdkRuntime;
|
|
2931
|
-
const currentUnregisterUnhandledRejectionHandler = unregisterUnhandledRejectionHandler;
|
|
2932
|
-
const currentRetireExporterRoutes = retireExporterRoutes;
|
|
2933
|
-
unsubscribe = null;
|
|
2934
|
-
unregisterTracePropagationBridge = null;
|
|
2935
|
-
logProvider = null;
|
|
2936
|
-
traceProvider = null;
|
|
2937
|
-
meterProvider = null;
|
|
2938
|
-
stopActiveTrustedSpans = null;
|
|
2939
|
-
unregisterOwnedSdkRuntime = null;
|
|
2940
|
-
unregisterUnhandledRejectionHandler = null;
|
|
2941
|
-
retireExporterRoutes = options?.preserveExporterRoutes ? currentRetireExporterRoutes : null;
|
|
2962
|
+
const current = state;
|
|
2963
|
+
state = options?.preserveExporterRoutes ? { retireExporterRoutes: current.retireExporterRoutes } : {};
|
|
2942
2964
|
const settle = async (...stops) => (await Promise.allSettled(stops.map((stop) => Promise.resolve().then(() => stop?.())))).flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
2943
|
-
const failures = await settle(
|
|
2944
|
-
const providerFailures = await settle(
|
|
2965
|
+
const failures = await settle(current.unregisterTracePropagationBridge, current.unsubscribe, current.stopActiveTrustedSpans, current.unregisterOwnedSdkRuntime);
|
|
2966
|
+
const providerFailures = await settle(() => current.logProvider?.shutdown(), () => current.traceProvider?.shutdown(), () => current.meterProvider?.shutdown());
|
|
2945
2967
|
failures.push(...providerFailures);
|
|
2946
|
-
if (!options?.preserveExporterRoutes)
|
|
2947
|
-
if (providerFailures.length > 0) retireExporterRoutes =
|
|
2948
|
-
failures.push(...await settle(
|
|
2968
|
+
if (!options?.preserveExporterRoutes) current.retireExporterRoutes?.(providerFailures.length > 0);
|
|
2969
|
+
if (providerFailures.length > 0) state.retireExporterRoutes = current.retireExporterRoutes;
|
|
2970
|
+
failures.push(...await settle(current.unregisterUnhandledRejectionHandler));
|
|
2949
2971
|
if (failures.length === 1) throw failures[0];
|
|
2950
2972
|
if (failures.length > 1) throw new AggregateError(failures, `diagnostics-otel shutdown failed: ${failures.join("; ")}`);
|
|
2951
2973
|
};
|
|
2952
2974
|
return {
|
|
2953
2975
|
id: "diagnostics-otel",
|
|
2976
|
+
reload: { configPrefixes: ["diagnostics.otel", "diagnostics.enabled"] },
|
|
2954
2977
|
async start(ctx) {
|
|
2955
2978
|
preserveExporterRoutesOnNextStop = false;
|
|
2956
2979
|
await stopStarted();
|
|
2980
|
+
const active = state;
|
|
2957
2981
|
const cfg = ctx.config.diagnostics;
|
|
2958
2982
|
const otel = cfg?.otel;
|
|
2959
2983
|
if (!cfg || cfg.enabled === false || !otel?.enabled) return;
|
|
2960
2984
|
const sdkDisabled = isOtelSdkDisabled(ctx.logger);
|
|
2961
2985
|
const sdkPreloaded = hasPreloadedOtelSdk();
|
|
2962
|
-
if (!sdkPreloaded) unregisterOwnedSdkRuntime = registerOwnedSdkRuntime((message) => ctx.logger.warn(message));
|
|
2986
|
+
if (!sdkPreloaded) active.unregisterOwnedSdkRuntime = registerOwnedSdkRuntime((message) => ctx.logger.warn(message));
|
|
2963
2987
|
if (!sdkPreloaded && sdkDisabled) return;
|
|
2964
2988
|
const exporterRoutes = /* @__PURE__ */ new Map();
|
|
2965
2989
|
const internalDiagnostics = ctx.internalDiagnostics;
|
|
@@ -3004,7 +3028,7 @@ function createDiagnosticsOtelService() {
|
|
|
3004
3028
|
ctx.logger.error("diagnostics-otel: internal diagnostics capability unavailable");
|
|
3005
3029
|
return;
|
|
3006
3030
|
}
|
|
3007
|
-
retireExporterRoutes = (preserveFailures = false) => {
|
|
3031
|
+
active.retireExporterRoutes = (preserveFailures = false) => {
|
|
3008
3032
|
for (const route of exporterRoutes.values()) {
|
|
3009
3033
|
if (preserveFailures && route.status === "failure") continue;
|
|
3010
3034
|
emitExporterEvent({
|
|
@@ -3106,7 +3130,7 @@ function createDiagnosticsOtelService() {
|
|
|
3106
3130
|
exportIntervalMillis: metricInterval,
|
|
3107
3131
|
exportTimeoutMillis: metricTimeout
|
|
3108
3132
|
}) : void 0;
|
|
3109
|
-
if (metricReader) meterProvider = new MeterProvider({
|
|
3133
|
+
if (metricReader) active.meterProvider = new MeterProvider({
|
|
3110
3134
|
resource: detectedResource,
|
|
3111
3135
|
readers: [metricReader],
|
|
3112
3136
|
sdkMetricsEnabled
|
|
@@ -3126,13 +3150,13 @@ function createDiagnosticsOtelService() {
|
|
|
3126
3150
|
maxExportBatchSize: Math.min(readPositiveOtelNumber("OTEL_BSP_MAX_EXPORT_BATCH_SIZE", 512), maxQueueSize),
|
|
3127
3151
|
scheduledDelayMillis: typeof otel.flushIntervalMs === "number" ? Math.max(1e3, otel.flushIntervalMs) : readPositiveOtelNumber("OTEL_BSP_SCHEDULE_DELAY", 5e3),
|
|
3128
3152
|
exportTimeoutMillis: readPositiveOtelNumber("OTEL_BSP_EXPORT_TIMEOUT", 3e4),
|
|
3129
|
-
...sdkMetricsEnabled && meterProvider ? { selfObsMeterProvider: meterProvider } : {}
|
|
3153
|
+
...sdkMetricsEnabled && active.meterProvider ? { selfObsMeterProvider: active.meterProvider } : {}
|
|
3130
3154
|
});
|
|
3131
|
-
traceProvider = new BasicTracerProvider({
|
|
3155
|
+
active.traceProvider = new BasicTracerProvider({
|
|
3132
3156
|
resource: detectedResource,
|
|
3133
3157
|
spanProcessors: [spanProcessor],
|
|
3134
3158
|
...sampleRate !== void 0 ? { sampler: new ParentBasedSampler({ root: new TraceIdRatioBasedSampler(sampleRate) }) } : {},
|
|
3135
|
-
...sdkMetricsEnabled && meterProvider ? { meterProvider } : {}
|
|
3159
|
+
...sdkMetricsEnabled && active.meterProvider ? { meterProvider: active.meterProvider } : {}
|
|
3136
3160
|
});
|
|
3137
3161
|
}
|
|
3138
3162
|
} catch (err) {
|
|
@@ -3156,9 +3180,9 @@ function createDiagnosticsOtelService() {
|
|
|
3156
3180
|
throw err;
|
|
3157
3181
|
}
|
|
3158
3182
|
else if (sdkPreloaded && (tracesEnabled || metricsEnabled)) ctx.logger.info("diagnostics-otel: using preloaded OpenTelemetry SDK");
|
|
3159
|
-
const meter = meterProvider ? meterProvider.getMeter("openclaw") : metrics.getMeter("openclaw");
|
|
3160
|
-
const diagnosticsTrace = createDiagnosticsTraceRuntime(traceProvider ? traceProvider.getTracer("openclaw") : trace.getTracer("openclaw"));
|
|
3161
|
-
stopActiveTrustedSpans = diagnosticsTrace.stopActiveTrustedSpans;
|
|
3183
|
+
const meter = !metricsActive ? createNoopMeter() : active.meterProvider ? active.meterProvider.getMeter("openclaw") : metrics.getMeter("openclaw");
|
|
3184
|
+
const diagnosticsTrace = createDiagnosticsTraceRuntime(active.traceProvider ? active.traceProvider.getTracer("openclaw") : trace.getTracer("openclaw"));
|
|
3185
|
+
active.stopActiveTrustedSpans = diagnosticsTrace.stopActiveTrustedSpans;
|
|
3162
3186
|
const diagnosticMetrics = createDiagnosticsMetrics(meter, otel.metricNamePrefix);
|
|
3163
3187
|
const diagnosticsLogs = createDiagnosticsLogExporter({
|
|
3164
3188
|
contentCapturePolicy,
|
|
@@ -3174,7 +3198,7 @@ function createDiagnosticsOtelService() {
|
|
|
3174
3198
|
resource,
|
|
3175
3199
|
serviceName
|
|
3176
3200
|
});
|
|
3177
|
-
logProvider = diagnosticsLogs.logProvider;
|
|
3201
|
+
active.logProvider = diagnosticsLogs.logProvider;
|
|
3178
3202
|
const { recordLogRecord, recordSecurityEvent } = diagnosticsLogs;
|
|
3179
3203
|
const recorderRuntime = createDiagnosticsRecorderRuntime({
|
|
3180
3204
|
contentCapturePolicy,
|
|
@@ -3189,13 +3213,13 @@ function createDiagnosticsOtelService() {
|
|
|
3189
3213
|
...createModelRecorders(recorderRuntime),
|
|
3190
3214
|
...createToolAndSystemRecorders(recorderRuntime)
|
|
3191
3215
|
};
|
|
3192
|
-
unsubscribe = subscribe(createDiagnosticsEventHandler({
|
|
3216
|
+
active.unsubscribe = subscribe(createDiagnosticsEventHandler({
|
|
3193
3217
|
logger: ctx.logger,
|
|
3194
3218
|
recorders,
|
|
3195
3219
|
recordLogRecord,
|
|
3196
3220
|
recordSecurityEvent
|
|
3197
|
-
}));
|
|
3198
|
-
if (tracesActive) unregisterTracePropagationBridge = ctx.internalDiagnostics?.registerTracePropagationBridge?.({
|
|
3221
|
+
}), metricsActive ? void 0 : tracesActive ? { exclude: ["gateway.event_loop.sample", "diagnostic.gc"] } : { include: ["log.record", "security.event"] });
|
|
3222
|
+
if (tracesActive) active.unregisterTracePropagationBridge = ctx.internalDiagnostics?.registerTracePropagationBridge?.({
|
|
3199
3223
|
shouldPrepareEvent(event) {
|
|
3200
3224
|
return event.type === "model.call.started" || event.type === "tool.execution.started";
|
|
3201
3225
|
},
|
|
@@ -3208,7 +3232,7 @@ function createDiagnosticsOtelService() {
|
|
|
3208
3232
|
return spanContext ? diagnosticTraceContextFromSpanContext(spanContext) : void 0;
|
|
3209
3233
|
}
|
|
3210
3234
|
}) ?? null;
|
|
3211
|
-
if (hasOwnedOtlpSignal || sdkPreloaded && !sdkDisabled) unregisterUnhandledRejectionHandler = registerUnhandledRejectionHandler((reason) => {
|
|
3235
|
+
if (hasOwnedOtlpSignal || sdkPreloaded && !sdkDisabled) active.unregisterUnhandledRejectionHandler = registerUnhandledRejectionHandler((reason) => {
|
|
3212
3236
|
const otlpError = findOtlpExporterError(reason);
|
|
3213
3237
|
if (!otlpError) return false;
|
|
3214
3238
|
const code = readErrorCode(otlpError) ?? "unknown";
|
package/dist/runtime-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createDiagnosticsOtelService } from "./runtime-api-
|
|
1
|
+
import { t as createDiagnosticsOtelService } from "./runtime-api-B9-DLHbi.js";
|
|
2
2
|
export { createDiagnosticsOtelService };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/diagnostics-otel",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.3",
|
|
4
4
|
"description": "OpenClaw diagnostics OpenTelemetry exporter for metrics, traces, and logs.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"minHostVersion": ">=2026.4.25"
|
|
35
35
|
},
|
|
36
36
|
"compat": {
|
|
37
|
-
"pluginApi": ">=2026.9.
|
|
37
|
+
"pluginApi": ">=2026.9.3"
|
|
38
38
|
},
|
|
39
39
|
"build": {
|
|
40
|
-
"openclawVersion": "2026.9.
|
|
40
|
+
"openclawVersion": "2026.9.3"
|
|
41
41
|
},
|
|
42
42
|
"release": {
|
|
43
43
|
"publishToClawHub": true,
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"README.md"
|
|
54
54
|
],
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"openclaw": ">=2026.9.
|
|
56
|
+
"openclaw": ">=2026.9.3"
|
|
57
57
|
},
|
|
58
58
|
"peerDependenciesMeta": {
|
|
59
59
|
"openclaw": {
|