@senpi/runtime 3.0.6-dev.runtime-phase-2.20260630134327 → 3.0.6-dev.runtime-phase-2.20260630134410
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/actions/llm-decision/anthropic-llm-decision.d.ts +5 -9
- package/dist/actions/llm-decision/anthropic-llm-decision.d.ts.map +1 -1
- package/dist/actions/llm-decision/anthropic-llm-decision.js +6 -86
- package/dist/actions/llm-decision/anthropic-llm-decision.js.map +1 -1
- package/dist/actions/llm-decision/factory.d.ts +0 -6
- package/dist/actions/llm-decision/factory.d.ts.map +1 -1
- package/dist/actions/llm-decision/factory.js +0 -2
- package/dist/actions/llm-decision/factory.js.map +1 -1
- package/dist/actions/llm-decision/openclaw-llm-decision.d.ts.map +1 -1
- package/dist/actions/llm-decision/openclaw-llm-decision.js +20 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -11
- package/dist/index.js.map +1 -1
- package/dist/recording/wiring/emitter-factory.d.ts +0 -5
- package/dist/recording/wiring/emitter-factory.d.ts.map +1 -1
- package/dist/recording/wiring/emitter-factory.js +0 -18
- package/dist/recording/wiring/emitter-factory.js.map +1 -1
- package/dist/recording/wiring/index.d.ts +1 -1
- package/dist/recording/wiring/index.d.ts.map +1 -1
- package/dist/recording/wiring/index.js +1 -1
- package/dist/recording/wiring/index.js.map +1 -1
- package/dist/runtime/runtime-schema.d.ts +4 -53
- package/dist/runtime/runtime-schema.d.ts.map +1 -1
- package/dist/runtime/runtime-schema.js +4 -4
- package/dist/runtime/runtime-schema.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +9 -15
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/senpi/client.d.ts +10 -0
- package/dist/senpi/client.d.ts.map +1 -1
- package/dist/senpi/client.js +69 -49
- package/dist/senpi/client.js.map +1 -1
- package/dist/telemetry/metrics.d.ts +47 -0
- package/dist/telemetry/metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics.js +154 -0
- package/dist/telemetry/metrics.js.map +1 -0
- package/dist/telemetry/otel-sdk.d.ts +21 -33
- package/dist/telemetry/otel-sdk.d.ts.map +1 -1
- package/dist/telemetry/otel-sdk.js +77 -50
- package/dist/telemetry/otel-sdk.js.map +1 -1
- package/dist/telemetry/tracing.d.ts +2 -1
- package/dist/telemetry/tracing.d.ts.map +1 -1
- package/dist/telemetry/tracing.js +1 -1
- package/dist/telemetry/tracing.js.map +1 -1
- package/dist/tracking/spans/constants.d.ts +4 -11
- package/dist/tracking/spans/constants.d.ts.map +1 -1
- package/dist/tracking/spans/constants.js +4 -23
- package/dist/tracking/spans/constants.js.map +1 -1
- package/dist/tracking/spans/gen-ai.d.ts +70 -0
- package/dist/tracking/spans/gen-ai.d.ts.map +1 -0
- package/dist/tracking/spans/gen-ai.js +330 -0
- package/dist/tracking/spans/gen-ai.js.map +1 -0
- package/dist/tracking/spans/index.d.ts +6 -8
- package/dist/tracking/spans/index.d.ts.map +1 -1
- package/dist/tracking/spans/index.js +6 -11
- package/dist/tracking/spans/index.js.map +1 -1
- package/dist/tracking/spans/redact-pii.d.ts +18 -20
- package/dist/tracking/spans/redact-pii.d.ts.map +1 -1
- package/dist/tracking/spans/redact-pii.js +30 -29
- package/dist/tracking/spans/redact-pii.js.map +1 -1
- package/dist/tracking/spans/span-hooks.d.ts +0 -17
- package/dist/tracking/spans/span-hooks.d.ts.map +1 -1
- package/dist/tracking/spans/span-hooks.js +407 -207
- package/dist/tracking/spans/span-hooks.js.map +1 -1
- package/package.json +1 -1
- package/dist/tracking/spans/fan-out-span-transport.d.ts +0 -22
- package/dist/tracking/spans/fan-out-span-transport.d.ts.map +0 -1
- package/dist/tracking/spans/fan-out-span-transport.js +0 -49
- package/dist/tracking/spans/fan-out-span-transport.js.map +0 -1
- package/dist/tracking/spans/otel/fit-row-budget.d.ts +0 -22
- package/dist/tracking/spans/otel/fit-row-budget.d.ts.map +0 -1
- package/dist/tracking/spans/otel/fit-row-budget.js +0 -91
- package/dist/tracking/spans/otel/fit-row-budget.js.map +0 -1
- package/dist/tracking/spans/otel/map-span-to-trace-row.d.ts +0 -16
- package/dist/tracking/spans/otel/map-span-to-trace-row.d.ts.map +0 -1
- package/dist/tracking/spans/otel/map-span-to-trace-row.js +0 -227
- package/dist/tracking/spans/otel/map-span-to-trace-row.js.map +0 -1
- package/dist/tracking/spans/otel/recording-span-transport.d.ts +0 -43
- package/dist/tracking/spans/otel/recording-span-transport.d.ts.map +0 -1
- package/dist/tracking/spans/otel/recording-span-transport.js +0 -67
- package/dist/tracking/spans/otel/recording-span-transport.js.map +0 -1
- package/dist/tracking/spans/otel/span-ids.d.ts +0 -22
- package/dist/tracking/spans/otel/span-ids.d.ts.map +0 -1
- package/dist/tracking/spans/otel/span-ids.js +0 -32
- package/dist/tracking/spans/otel/span-ids.js.map +0 -1
- package/dist/tracking/spans/plugin-span-tracker.d.ts +0 -9
- package/dist/tracking/spans/plugin-span-tracker.d.ts.map +0 -1
- package/dist/tracking/spans/plugin-span-tracker.js +0 -115
- package/dist/tracking/spans/plugin-span-tracker.js.map +0 -1
- package/dist/tracking/spans/span-tracker.d.ts +0 -133
- package/dist/tracking/spans/span-tracker.d.ts.map +0 -1
- package/dist/tracking/spans/span-tracker.js +0 -721
- package/dist/tracking/spans/span-tracker.js.map +0 -1
- package/dist/tracking/spans/span-transport.d.ts +0 -71
- package/dist/tracking/spans/span-transport.d.ts.map +0 -1
- package/dist/tracking/spans/span-transport.js +0 -240
- package/dist/tracking/spans/span-transport.js.map +0 -1
- package/dist/tracking/spans/types.d.ts +0 -101
- package/dist/tracking/spans/types.d.ts.map +0 -1
- package/dist/tracking/spans/types.js +0 -6
- package/dist/tracking/spans/types.js.map +0 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GenAI client metrics, mirroring `tracing.ts`: instruments are obtained through the
|
|
3
|
+
* `@opentelemetry/api` proxy meter, so they no-op before the SDK initialises and resolve
|
|
4
|
+
* the real meter afterwards. Histograms are created lazily and cached on first use so they
|
|
5
|
+
* bind after SDK init (not at module load). Every record helper is fully guarded — metrics
|
|
6
|
+
* must never throw into a caller path.
|
|
7
|
+
*
|
|
8
|
+
* Names/units/attributes follow the GenAI semantic conventions:
|
|
9
|
+
* - gen_ai.client.token.usage Histogram {token}
|
|
10
|
+
* - gen_ai.client.operation.duration Histogram s
|
|
11
|
+
* - gen_ai.execute_tool.duration Histogram s
|
|
12
|
+
* - gen_ai.invoke_agent.duration Histogram s
|
|
13
|
+
*/
|
|
14
|
+
import { type Meter } from "@opentelemetry/api";
|
|
15
|
+
/** The single meter for our manual instruments. Resolves the no-op meter pre-init. */
|
|
16
|
+
export declare function getMeter(): Meter;
|
|
17
|
+
/** Reset cached instruments (tests only). */
|
|
18
|
+
export declare function __resetMetricsForTest(): void;
|
|
19
|
+
/** Elapsed seconds from a `Date.now()` start, clamped to non-negative. */
|
|
20
|
+
export declare function elapsedSeconds(startMs: number | undefined): number | undefined;
|
|
21
|
+
export interface GenAiOperationDims {
|
|
22
|
+
provider?: string;
|
|
23
|
+
model?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Record token usage at chat finalize: one data point per token type present.
|
|
27
|
+
* Skips a dimension when its count is undefined.
|
|
28
|
+
*/
|
|
29
|
+
export declare function recordTokenUsage(dims: GenAiOperationDims, tokens: {
|
|
30
|
+
input?: number;
|
|
31
|
+
output?: number;
|
|
32
|
+
}): void;
|
|
33
|
+
/** Record the chat operation duration (seconds); stamps `error.type` when set. */
|
|
34
|
+
export declare function recordOperationDuration(seconds: number | undefined, dims: GenAiOperationDims & {
|
|
35
|
+
errorType?: string;
|
|
36
|
+
}): void;
|
|
37
|
+
/** Record the tool execution duration (seconds); stamps `error.type` when set. */
|
|
38
|
+
export declare function recordExecuteToolDuration(seconds: number | undefined, dims: {
|
|
39
|
+
toolName?: string;
|
|
40
|
+
errorType?: string;
|
|
41
|
+
}): void;
|
|
42
|
+
/** Record the sub-agent invocation duration (seconds); stamps `error.type` when set. */
|
|
43
|
+
export declare function recordInvokeAgentDuration(seconds: number | undefined, dims: {
|
|
44
|
+
agentName?: string;
|
|
45
|
+
errorType?: string;
|
|
46
|
+
}): void;
|
|
47
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAA2B,KAAK,KAAK,EAAmB,MAAM,oBAAoB,CAAC;AAK1F,sFAAsF;AACtF,wBAAgB,QAAQ,IAAI,KAAK,CAEhC;AASD,6CAA6C;AAC7C,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C;AAmDD,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAG9E;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1C,IAAI,CAiBN;AAED,kFAAkF;AAClF,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,IAAI,EAAE,kBAAkB,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD,IAAI,CAeN;AAED,kFAAkF;AAClF,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C,IAAI,CAcN;AAED,wFAAwF;AACxF,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,IAAI,CAcN"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GenAI client metrics, mirroring `tracing.ts`: instruments are obtained through the
|
|
3
|
+
* `@opentelemetry/api` proxy meter, so they no-op before the SDK initialises and resolve
|
|
4
|
+
* the real meter afterwards. Histograms are created lazily and cached on first use so they
|
|
5
|
+
* bind after SDK init (not at module load). Every record helper is fully guarded — metrics
|
|
6
|
+
* must never throw into a caller path.
|
|
7
|
+
*
|
|
8
|
+
* Names/units/attributes follow the GenAI semantic conventions:
|
|
9
|
+
* - gen_ai.client.token.usage Histogram {token}
|
|
10
|
+
* - gen_ai.client.operation.duration Histogram s
|
|
11
|
+
* - gen_ai.execute_tool.duration Histogram s
|
|
12
|
+
* - gen_ai.invoke_agent.duration Histogram s
|
|
13
|
+
*/
|
|
14
|
+
import { metrics } from "@opentelemetry/api";
|
|
15
|
+
/** Instrumentation scope; matches the tracer/logger scope. */
|
|
16
|
+
const METER_NAME = "senpi-trading-runtime";
|
|
17
|
+
/** The single meter for our manual instruments. Resolves the no-op meter pre-init. */
|
|
18
|
+
export function getMeter() {
|
|
19
|
+
return metrics.getMeter(METER_NAME);
|
|
20
|
+
}
|
|
21
|
+
// Lazily created + cached histograms — built on first record so they bind to the real
|
|
22
|
+
// meter after SDK init rather than to the no-op meter at module load.
|
|
23
|
+
let tokenUsage;
|
|
24
|
+
let operationDuration;
|
|
25
|
+
let executeToolDuration;
|
|
26
|
+
let invokeAgentDuration;
|
|
27
|
+
/** Reset cached instruments (tests only). */
|
|
28
|
+
export function __resetMetricsForTest() {
|
|
29
|
+
tokenUsage = undefined;
|
|
30
|
+
operationDuration = undefined;
|
|
31
|
+
executeToolDuration = undefined;
|
|
32
|
+
invokeAgentDuration = undefined;
|
|
33
|
+
}
|
|
34
|
+
function tokenUsageInstrument() {
|
|
35
|
+
if (!tokenUsage) {
|
|
36
|
+
tokenUsage = getMeter().createHistogram("gen_ai.client.token.usage", {
|
|
37
|
+
description: "Number of input/output tokens used by a GenAI request",
|
|
38
|
+
unit: "{token}",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return tokenUsage;
|
|
42
|
+
}
|
|
43
|
+
function operationDurationInstrument() {
|
|
44
|
+
if (!operationDuration) {
|
|
45
|
+
operationDuration = getMeter().createHistogram("gen_ai.client.operation.duration", {
|
|
46
|
+
description: "Duration of a GenAI client operation",
|
|
47
|
+
unit: "s",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return operationDuration;
|
|
51
|
+
}
|
|
52
|
+
function executeToolDurationInstrument() {
|
|
53
|
+
if (!executeToolDuration) {
|
|
54
|
+
executeToolDuration = getMeter().createHistogram("gen_ai.execute_tool.duration", {
|
|
55
|
+
description: "Duration of a GenAI tool execution",
|
|
56
|
+
unit: "s",
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return executeToolDuration;
|
|
60
|
+
}
|
|
61
|
+
function invokeAgentDurationInstrument() {
|
|
62
|
+
if (!invokeAgentDuration) {
|
|
63
|
+
invokeAgentDuration = getMeter().createHistogram("gen_ai.invoke_agent.duration", {
|
|
64
|
+
description: "Duration of a GenAI sub-agent invocation",
|
|
65
|
+
unit: "s",
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return invokeAgentDuration;
|
|
69
|
+
}
|
|
70
|
+
/** Drop undefined/null attributes so we never stamp hollow dimensions. */
|
|
71
|
+
function defined(attrs) {
|
|
72
|
+
const out = {};
|
|
73
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
74
|
+
if (v !== undefined && v !== null)
|
|
75
|
+
out[k] = v;
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
/** Elapsed seconds from a `Date.now()` start, clamped to non-negative. */
|
|
80
|
+
export function elapsedSeconds(startMs) {
|
|
81
|
+
if (typeof startMs !== "number" || !Number.isFinite(startMs))
|
|
82
|
+
return undefined;
|
|
83
|
+
return Math.max(0, (Date.now() - startMs) / 1000);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Record token usage at chat finalize: one data point per token type present.
|
|
87
|
+
* Skips a dimension when its count is undefined.
|
|
88
|
+
*/
|
|
89
|
+
export function recordTokenUsage(dims, tokens) {
|
|
90
|
+
try {
|
|
91
|
+
const base = {
|
|
92
|
+
"gen_ai.operation.name": "chat",
|
|
93
|
+
"gen_ai.provider.name": dims.provider,
|
|
94
|
+
"gen_ai.request.model": dims.model,
|
|
95
|
+
};
|
|
96
|
+
const inst = tokenUsageInstrument();
|
|
97
|
+
if (typeof tokens.input === "number" && Number.isFinite(tokens.input)) {
|
|
98
|
+
inst.record(tokens.input, defined({ ...base, "gen_ai.token.type": "input" }));
|
|
99
|
+
}
|
|
100
|
+
if (typeof tokens.output === "number" && Number.isFinite(tokens.output)) {
|
|
101
|
+
inst.record(tokens.output, defined({ ...base, "gen_ai.token.type": "output" }));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Metrics must never break the caller.
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** Record the chat operation duration (seconds); stamps `error.type` when set. */
|
|
109
|
+
export function recordOperationDuration(seconds, dims) {
|
|
110
|
+
if (seconds === undefined)
|
|
111
|
+
return;
|
|
112
|
+
try {
|
|
113
|
+
operationDurationInstrument().record(seconds, defined({
|
|
114
|
+
"gen_ai.operation.name": "chat",
|
|
115
|
+
"gen_ai.provider.name": dims.provider,
|
|
116
|
+
"gen_ai.request.model": dims.model,
|
|
117
|
+
"error.type": dims.errorType,
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Metrics must never break the caller.
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/** Record the tool execution duration (seconds); stamps `error.type` when set. */
|
|
125
|
+
export function recordExecuteToolDuration(seconds, dims) {
|
|
126
|
+
if (seconds === undefined)
|
|
127
|
+
return;
|
|
128
|
+
try {
|
|
129
|
+
executeToolDurationInstrument().record(seconds, defined({
|
|
130
|
+
"gen_ai.operation.name": "execute_tool",
|
|
131
|
+
"gen_ai.tool.name": dims.toolName,
|
|
132
|
+
"error.type": dims.errorType,
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// Metrics must never break the caller.
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** Record the sub-agent invocation duration (seconds); stamps `error.type` when set. */
|
|
140
|
+
export function recordInvokeAgentDuration(seconds, dims) {
|
|
141
|
+
if (seconds === undefined)
|
|
142
|
+
return;
|
|
143
|
+
try {
|
|
144
|
+
invokeAgentDurationInstrument().record(seconds, defined({
|
|
145
|
+
"gen_ai.operation.name": "invoke_agent",
|
|
146
|
+
"gen_ai.agent.name": dims.agentName,
|
|
147
|
+
"error.type": dims.errorType,
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Metrics must never break the caller.
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,32 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenTelemetry SDK stand-up:
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* standardised resource-attribute set.
|
|
2
|
+
* OpenTelemetry SDK stand-up: HyperDX's OTel distribution (`@hyperdx/node-opentelemetry`)
|
|
3
|
+
* — auto-instrumentation + uncaught-exception capture — against a self-hosted OTLP collector,
|
|
4
|
+
* with a process-stable resource-attribute set.
|
|
6
5
|
*
|
|
7
|
-
* Init runs from `
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* On Node >= 22 the diagnostics_channel HTTP instrumentation hooks lazily, so
|
|
11
|
-
* deferring init still instruments outbound HTTP.
|
|
6
|
+
* Init runs from plugin `register()` (process scope): the agent hooks register there, before
|
|
7
|
+
* any runtime, and emit through this SDK's tracer. Only process-stable values ride the resource
|
|
8
|
+
* (`service.*`, `deployment.environment`, `user.id`), so init need not wait for a runtime.
|
|
12
9
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
10
|
+
* Gated by OTLP-config presence: inits iff an OTLP endpoint env is set (no enable flag, no
|
|
11
|
+
* localhost default). No endpoint ⇒ no SDK and the global tracer/logger no-op. If a non-noop
|
|
12
|
+
* global `TracerProvider` already exists (the gateway's `diagnostics-otel` owns it), we stand
|
|
13
|
+
* down and emit through the global API — one SDK per process, first writer wins.
|
|
17
14
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* OTEL_EXPORTER_OTLP_METRICS_ENDPOINT (.../v1/metrics)
|
|
24
|
-
* OTEL_EXPORTER_OTLP_HEADERS (e.g. Authorization=<collector-token>)
|
|
25
|
-
* See docs/runtime-docs/runtime-api.md (Tracing) for why each is required.
|
|
15
|
+
* The package is imported dynamically: it reads `OTEL_EXPORTER_OTLP_*` at module-load and
|
|
16
|
+
* exposes no init() option for them, so the env must be set first. Under openclaw the operator
|
|
17
|
+
* sets all of these (the SDK derives none):
|
|
18
|
+
* OTEL_EXPORTER_OTLP_ENDPOINT / _TRACES_ENDPOINT / _LOGS_ENDPOINT / _METRICS_ENDPOINT / _HEADERS
|
|
19
|
+
* See docs/runtime-docs/runtime-api.md (Tracing).
|
|
26
20
|
*/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
export declare const DEFAULT_OTLP_ENDPOINT = "http://localhost:4318";
|
|
21
|
+
/** True when any OTLP endpoint env is set — the gate for standing up the plugin's SDK. */
|
|
22
|
+
export declare function isOtlpEndpointConfigured(): boolean;
|
|
30
23
|
/**
|
|
31
24
|
* Whether {@link initOtelSdk} has completed. Code that loads `@hyperdx/node-opentelemetry`
|
|
32
25
|
* lazily (e.g. per-trace attribute stamping) gates on this so the package — which captures
|
|
@@ -72,22 +65,17 @@ export interface OtelResourceExtras {
|
|
|
72
65
|
* emit-time identity stamp (both reading the same per-runtime identity context).
|
|
73
66
|
*/
|
|
74
67
|
export declare function buildOtelResourceAttributes(serviceName: string, extras: OtelResourceExtras): string;
|
|
75
|
-
/**
|
|
76
|
-
* Resolve the OTLP endpoint: `OTEL_EXPORTER_OTLP_ENDPOINT` env >
|
|
77
|
-
* {@link DEFAULT_OTLP_ENDPOINT}.
|
|
78
|
-
*/
|
|
79
|
-
export declare function resolveOtlpEndpoint(): string;
|
|
80
68
|
export interface InitOtelSdkParams {
|
|
81
|
-
readonly enabled: boolean;
|
|
82
|
-
/** Built only on the live path to preserve laziness. */
|
|
83
|
-
readonly identity: () => IdentityEnvelope;
|
|
84
69
|
/** SENPI_API_KEY JWT (the MCP bearer) — decoded locally for `user.id`. */
|
|
85
70
|
readonly userToken?: string;
|
|
71
|
+
/** Plugin version → `service.version`. */
|
|
86
72
|
readonly serviceVersion: string;
|
|
87
73
|
}
|
|
88
74
|
/**
|
|
89
75
|
* Initialise the OTel SDK. Idempotent, side-effecting, and never crashes boot:
|
|
90
|
-
* no-ops when
|
|
76
|
+
* no-ops when no OTLP endpoint is configured, when a real global TracerProvider
|
|
77
|
+
* already exists (the gateway owns it — we emit through the global API instead),
|
|
78
|
+
* when already initialised, or under test.
|
|
91
79
|
*/
|
|
92
80
|
export declare function initOtelSdk(params: InitOtelSdkParams): Promise<void>;
|
|
93
81
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otel-sdk.d.ts","sourceRoot":"","sources":["../../src/telemetry/otel-sdk.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"otel-sdk.d.ts","sourceRoot":"","sources":["../../src/telemetry/otel-sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAgBH,0FAA0F;AAC1F,wBAAgB,wBAAwB,IAAI,OAAO,CAKlD;AAoGD;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAkB/E;AAED,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,uFAAuF;IACvF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,2BAA2B;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,kCAAkC;IAClC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,kBAAkB,GACzB,MAAM,CAaR;AAED,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAKD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuF1E;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAcrD"}
|
|
@@ -1,34 +1,66 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenTelemetry SDK stand-up:
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* standardised resource-attribute set.
|
|
2
|
+
* OpenTelemetry SDK stand-up: HyperDX's OTel distribution (`@hyperdx/node-opentelemetry`)
|
|
3
|
+
* — auto-instrumentation + uncaught-exception capture — against a self-hosted OTLP collector,
|
|
4
|
+
* with a process-stable resource-attribute set.
|
|
6
5
|
*
|
|
7
|
-
* Init runs from `
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* On Node >= 22 the diagnostics_channel HTTP instrumentation hooks lazily, so
|
|
11
|
-
* deferring init still instruments outbound HTTP.
|
|
6
|
+
* Init runs from plugin `register()` (process scope): the agent hooks register there, before
|
|
7
|
+
* any runtime, and emit through this SDK's tracer. Only process-stable values ride the resource
|
|
8
|
+
* (`service.*`, `deployment.environment`, `user.id`), so init need not wait for a runtime.
|
|
12
9
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
10
|
+
* Gated by OTLP-config presence: inits iff an OTLP endpoint env is set (no enable flag, no
|
|
11
|
+
* localhost default). No endpoint ⇒ no SDK and the global tracer/logger no-op. If a non-noop
|
|
12
|
+
* global `TracerProvider` already exists (the gateway's `diagnostics-otel` owns it), we stand
|
|
13
|
+
* down and emit through the global API — one SDK per process, first writer wins.
|
|
17
14
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* OTEL_EXPORTER_OTLP_METRICS_ENDPOINT (.../v1/metrics)
|
|
24
|
-
* OTEL_EXPORTER_OTLP_HEADERS (e.g. Authorization=<collector-token>)
|
|
25
|
-
* See docs/runtime-docs/runtime-api.md (Tracing) for why each is required.
|
|
15
|
+
* The package is imported dynamically: it reads `OTEL_EXPORTER_OTLP_*` at module-load and
|
|
16
|
+
* exposes no init() option for them, so the env must be set first. Under openclaw the operator
|
|
17
|
+
* sets all of these (the SDK derives none):
|
|
18
|
+
* OTEL_EXPORTER_OTLP_ENDPOINT / _TRACES_ENDPOINT / _LOGS_ENDPOINT / _METRICS_ENDPOINT / _HEADERS
|
|
19
|
+
* See docs/runtime-docs/runtime-api.md (Tracing).
|
|
26
20
|
*/
|
|
27
21
|
import { randomUUID } from "node:crypto";
|
|
22
|
+
import { trace } from "@opentelemetry/api";
|
|
28
23
|
import { createLogger } from "../utils/logger.js";
|
|
29
24
|
const logger = createLogger("telemetry/otel-sdk");
|
|
30
|
-
/**
|
|
31
|
-
|
|
25
|
+
/** Per-signal OTLP endpoint env vars; presence of any (or the base) is the on-switch. */
|
|
26
|
+
const OTLP_ENDPOINT_ENV_VARS = [
|
|
27
|
+
"OTEL_EXPORTER_OTLP_ENDPOINT",
|
|
28
|
+
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",
|
|
29
|
+
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT",
|
|
30
|
+
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT",
|
|
31
|
+
];
|
|
32
|
+
/** True when any OTLP endpoint env is set — the gate for standing up the plugin's SDK. */
|
|
33
|
+
export function isOtlpEndpointConfigured() {
|
|
34
|
+
return OTLP_ENDPOINT_ENV_VARS.some((name) => {
|
|
35
|
+
const value = process.env[name];
|
|
36
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* True when a real (non-noop) global `TracerProvider` is already registered — i.e.
|
|
41
|
+
* another SDK (the gateway's `diagnostics-otel`) owns the slot. The global API hands
|
|
42
|
+
* back a `ProxyTracerProvider` until `setGlobalTracerProvider` runs; before that its
|
|
43
|
+
* delegate is the no-op provider. We detect "real" by checking whether a delegate
|
|
44
|
+
* provider has been set: `getDelegate()` exists on the proxy and differs from the
|
|
45
|
+
* no-op. Best-effort — on any uncertainty we treat it as "not owned" and init our own.
|
|
46
|
+
*/
|
|
47
|
+
function globalTracerProviderIsReal() {
|
|
48
|
+
try {
|
|
49
|
+
const provider = trace.getTracerProvider();
|
|
50
|
+
if (typeof provider?.getDelegate !== "function") {
|
|
51
|
+
// Not a ProxyTracerProvider — a concrete provider is registered directly.
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
const delegate = provider.getDelegate();
|
|
55
|
+
if (delegate == null)
|
|
56
|
+
return false;
|
|
57
|
+
// The proxy's default delegate is the NoopTracerProvider; anything else is real.
|
|
58
|
+
return delegate.constructor?.name !== "NoopTracerProvider";
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
32
64
|
/**
|
|
33
65
|
* Process-level instance id for `service.instance.id`. Distinct from the
|
|
34
66
|
* per-runtime `IdentityEnvelope.bootId`: resource attributes are process-global,
|
|
@@ -50,7 +82,7 @@ const PROCESS_INSTANCE_ID = randomUUID();
|
|
|
50
82
|
* Fix: enable our own `UndiciInstrumentation`; with no provider set it resolves the
|
|
51
83
|
* global one `init()` registered, and HyperDX's instance stays disabled (no double
|
|
52
84
|
* instrumentation). Best-effort — a failure must not fail boot. Also a prerequisite
|
|
53
|
-
* for the manual `mcp.*`/`dsl.*` spans
|
|
85
|
+
* for the manual `mcp.*`/`dsl.*` spans, which assume outbound `fetch` calls
|
|
54
86
|
* auto-nest as HTTP children.
|
|
55
87
|
*
|
|
56
88
|
* Seen with `@hyperdx/node-opentelemetry` 0.11 / `instrumentation-undici` 0.28, Node 24
|
|
@@ -147,38 +179,37 @@ export function buildOtelResourceAttributes(serviceName, extras) {
|
|
|
147
179
|
.map(([key, value]) => `${key}=${encodeURIComponent(String(value))}`)
|
|
148
180
|
.join(",");
|
|
149
181
|
}
|
|
150
|
-
/**
|
|
151
|
-
|
|
152
|
-
* {@link DEFAULT_OTLP_ENDPOINT}.
|
|
153
|
-
*/
|
|
154
|
-
export function resolveOtlpEndpoint() {
|
|
155
|
-
const envOverride = process.env.OTEL_EXPORTER_OTLP_ENDPOINT?.trim();
|
|
156
|
-
if (envOverride)
|
|
157
|
-
return envOverride;
|
|
158
|
-
return DEFAULT_OTLP_ENDPOINT;
|
|
159
|
-
}
|
|
182
|
+
/** `service.name` for the plugin-owned resource; matches the tracer/logger scope. */
|
|
183
|
+
const SERVICE_NAME = "senpi-trading-runtime";
|
|
160
184
|
/**
|
|
161
185
|
* Initialise the OTel SDK. Idempotent, side-effecting, and never crashes boot:
|
|
162
|
-
* no-ops when
|
|
186
|
+
* no-ops when no OTLP endpoint is configured, when a real global TracerProvider
|
|
187
|
+
* already exists (the gateway owns it — we emit through the global API instead),
|
|
188
|
+
* when already initialised, or under test.
|
|
163
189
|
*/
|
|
164
190
|
export async function initOtelSdk(params) {
|
|
165
191
|
if (initialized)
|
|
166
192
|
return;
|
|
167
|
-
|
|
168
|
-
|
|
193
|
+
// Presence of OTLP config is the on-switch — no endpoint means telemetry off.
|
|
194
|
+
if (!isOtlpEndpointConfigured()) {
|
|
195
|
+
logger.debug("OTel SDK init skipped: no OTLP endpoint configured");
|
|
169
196
|
return;
|
|
170
197
|
}
|
|
171
|
-
//
|
|
172
|
-
//
|
|
198
|
+
// Stand down if another SDK (the gateway's diagnostics-otel) already owns the
|
|
199
|
+
// global provider — a second registration drops spans and splits resource identity.
|
|
200
|
+
if (globalTracerProviderIsReal()) {
|
|
201
|
+
logger.info("OTel SDK init skipped: a global TracerProvider already exists; emitting through the global API");
|
|
202
|
+
initialized = true;
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// Skip under test: the SDK would start exporters and patch core modules during vitest.
|
|
173
206
|
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
|
174
207
|
logger.debug("OTel SDK init skipped: running under test");
|
|
175
208
|
return;
|
|
176
209
|
}
|
|
177
210
|
try {
|
|
178
|
-
const identity = params.identity();
|
|
179
211
|
// Commit the guard before any fallible work: a failed init must not let a
|
|
180
|
-
// later
|
|
181
|
-
// identity() above threw before this, so env is still untouched on that path.
|
|
212
|
+
// later caller re-enter and double-append OTEL_RESOURCE_ATTRIBUTES.
|
|
182
213
|
initialized = true;
|
|
183
214
|
// Source the environment label from NODE_ENV (Node-standard). Pass the value
|
|
184
215
|
// through verbatim (so `staging`/custom envs are faithful), defaulting to
|
|
@@ -188,7 +219,7 @@ export async function initOtelSdk(params) {
|
|
|
188
219
|
const deploymentEnvironment = nodeEnv && nodeEnv.length > 0 ? nodeEnv : "development";
|
|
189
220
|
const userId = decodeSenpiUserId(params.userToken);
|
|
190
221
|
// Append to any host-set value rather than clobber operator attrs.
|
|
191
|
-
const ourAttrs = buildOtelResourceAttributes(
|
|
222
|
+
const ourAttrs = buildOtelResourceAttributes(SERVICE_NAME, {
|
|
192
223
|
serviceInstanceId: PROCESS_INSTANCE_ID,
|
|
193
224
|
serviceVersion: params.serviceVersion,
|
|
194
225
|
deploymentEnvironment,
|
|
@@ -198,18 +229,14 @@ export async function initOtelSdk(params) {
|
|
|
198
229
|
process.env.OTEL_RESOURCE_ATTRIBUTES = existingAttrs
|
|
199
230
|
? `${existingAttrs},${ourAttrs}`
|
|
200
231
|
: ourAttrs;
|
|
201
|
-
//
|
|
202
|
-
if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) {
|
|
203
|
-
process.env.OTEL_EXPORTER_OTLP_ENDPOINT = resolveOtlpEndpoint();
|
|
204
|
-
}
|
|
205
|
-
// Dynamic import: loads only now, after the env var above is set.
|
|
232
|
+
// Dynamic import: loads only now, after the endpoint env is confirmed set.
|
|
206
233
|
const hyperdx = (await import("@hyperdx/node-opentelemetry"));
|
|
207
234
|
hyperdxModule = hyperdx;
|
|
208
235
|
hyperdx.init({
|
|
209
236
|
// No apiKey on init(): the exporter authenticates to the collector via the
|
|
210
237
|
// Authorization header in OTEL_EXPORTER_OTLP_HEADERS (read from env at
|
|
211
238
|
// module-load), not through the SDK's HyperDX apiKey field.
|
|
212
|
-
service:
|
|
239
|
+
service: SERVICE_NAME,
|
|
213
240
|
// Off: createLogger() emits structured LogRecords through the OTel Logs API directly,
|
|
214
241
|
// so capturing console.* would duplicate every log (flattened, lossy) into the collector.
|
|
215
242
|
// stdout is untouched — the local human line still prints.
|
|
@@ -228,7 +255,7 @@ export async function initOtelSdk(params) {
|
|
|
228
255
|
});
|
|
229
256
|
await reinstrumentUndici();
|
|
230
257
|
logger.info("OTel SDK initialised", {
|
|
231
|
-
service:
|
|
258
|
+
service: SERVICE_NAME,
|
|
232
259
|
endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
|
233
260
|
deploymentEnvironment,
|
|
234
261
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otel-sdk.js","sourceRoot":"","sources":["../../src/telemetry/otel-sdk.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"otel-sdk.js","sourceRoot":"","sources":["../../src/telemetry/otel-sdk.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* is not initialised (telemetry off, or under test) the API resolves a no-op tracer,
|
|
6
6
|
* so `withSpan` runs the callback with near-zero overhead — no `enabled` gate needed.
|
|
7
7
|
*/
|
|
8
|
-
import { type Span, type Attributes, type Tracer } from "@opentelemetry/api";
|
|
8
|
+
import { type Span, type SpanKind, type Attributes, type Tracer } from "@opentelemetry/api";
|
|
9
9
|
/** The single tracer for our manual spans. Resolves the no-op tracer pre-init. */
|
|
10
10
|
export declare function getTracer(): Tracer;
|
|
11
11
|
/**
|
|
@@ -28,5 +28,6 @@ export declare function getTracer(): Tracer;
|
|
|
28
28
|
*/
|
|
29
29
|
export declare function withSpan<T>(name: string, attributes: Attributes, fn: (span: Span) => Promise<T>, options?: {
|
|
30
30
|
expected?: (err: unknown) => boolean;
|
|
31
|
+
kind?: SpanKind;
|
|
31
32
|
}): Promise<T>;
|
|
32
33
|
//# sourceMappingURL=tracing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/telemetry/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAGL,KAAK,IAAI,EACT,KAAK,UAAU,EACf,KAAK,MAAM,EACZ,MAAM,oBAAoB,CAAC;AAK5B,kFAAkF;AAClF,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,UAAU,EACtB,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAC9B,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/telemetry/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAGL,KAAK,IAAI,EACT,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,MAAM,EACZ,MAAM,oBAAoB,CAAC;AAK5B,kFAAkF;AAClF,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,UAAU,EACtB,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAC9B,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,GAClE,OAAO,CAAC,CAAC,CAAC,CA8BZ"}
|
|
@@ -31,7 +31,7 @@ export function getTracer() {
|
|
|
31
31
|
* error nor corrupt its result.
|
|
32
32
|
*/
|
|
33
33
|
export function withSpan(name, attributes, fn, options) {
|
|
34
|
-
return getTracer().startActiveSpan(name, { attributes }, async (span) => {
|
|
34
|
+
return getTracer().startActiveSpan(name, { attributes, kind: options?.kind }, async (span) => {
|
|
35
35
|
try {
|
|
36
36
|
return await fn(span);
|
|
37
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../src/telemetry/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,KAAK,EACL,cAAc,
|
|
1
|
+
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../src/telemetry/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,KAAK,EACL,cAAc,GAKf,MAAM,oBAAoB,CAAC;AAE5B,iEAAiE;AACjE,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAE5C,kFAAkF;AAClF,MAAM,UAAU,SAAS;IACvB,OAAO,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAY,EACZ,UAAsB,EACtB,EAA8B,EAC9B,OAAmE;IAEnE,OAAO,SAAS,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAC3F,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC;gBACH,QAAQ,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,4EAA4E;YAC9E,CAAC;YACD,IAAI,QAAQ;gBAAE,MAAM,GAAG,CAAC;YACxB,IAAI,CAAC;gBACH,IAAI,CAAC,eAAe,CAAC,GAAY,CAAC,CAAC;gBACnC,IAAI,CAAC,SAAS,CAAC;oBACb,IAAI,EAAE,cAAc,CAAC,KAAK;oBAC1B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBAC1D,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,wEAAwE;YAC1E,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC;gBACH,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,CAAC;YAAC,MAAM,CAAC;gBACP,+DAA+D;YACjE,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Span telemetry constants
|
|
2
|
+
* Span telemetry constants.
|
|
3
|
+
*
|
|
4
|
+
* Header names used to cross the runtime → OpenClaw HTTP boundary so the
|
|
5
|
+
* gateway-side hooks can stamp senpi identity onto the gen_ai spans.
|
|
3
6
|
*/
|
|
4
|
-
export declare const SPANS_API_PATH = "/api/v1/tracking/spans";
|
|
5
|
-
export declare const FLUSH_INTERVAL_MS = 10000;
|
|
6
|
-
export declare const FLUSH_THRESHOLD = 50;
|
|
7
|
-
export declare const MAX_BUFFER_SIZE = 500;
|
|
8
|
-
export declare const STALE_TIMEOUT_MS: number;
|
|
9
|
-
export declare const SWEEP_INTERVAL_MS = 60000;
|
|
10
|
-
export declare const MAX_BATCH_BYTES = 8000000;
|
|
11
|
-
export declare const MAX_SPAN_FIELD_BYTES = 2000000;
|
|
12
|
-
/** First N chars of each truncated value retained for debugging context. */
|
|
13
|
-
export declare const TRUNCATED_PREVIEW_BYTES = 2000;
|
|
14
7
|
export declare const HEADER_CORRELATION_ID = "x-senpi-correlation-id";
|
|
15
8
|
export declare const HEADER_ADDRESS = "x-senpi-address";
|
|
16
9
|
export declare const HEADER_RECIPE_NAME = "x-senpi-recipe-name";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/tracking/spans/constants.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/tracking/spans/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,qBAAqB,2BAA2B,CAAC;AAC9D,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAChD,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AACxD,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AACtD,eAAO,MAAM,sBAAsB,4BAA4B,CAAC"}
|