@introspection-sdk/introspection-pi 0.7.1 → 0.8.0
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/README.md +9 -1
- package/dist/attributes.d.ts +15 -1
- package/dist/attributes.d.ts.map +1 -1
- package/dist/attributes.js +91 -12
- package/dist/attributes.js.map +1 -1
- package/dist/convert.d.ts +8 -0
- package/dist/convert.d.ts.map +1 -1
- package/dist/convert.js +44 -8
- package/dist/convert.js.map +1 -1
- package/dist/error-type.d.ts +16 -0
- package/dist/error-type.d.ts.map +1 -0
- package/dist/error-type.js +32 -0
- package/dist/error-type.js.map +1 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/instrument-agent.d.ts +35 -6
- package/dist/instrument-agent.d.ts.map +1 -1
- package/dist/instrument-agent.js +128 -22
- package/dist/instrument-agent.js.map +1 -1
- package/dist/instrument-stream.d.ts +11 -3
- package/dist/instrument-stream.d.ts.map +1 -1
- package/dist/instrument-stream.js +99 -30
- package/dist/instrument-stream.js.map +1 -1
- package/dist/metrics.d.ts +26 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +64 -0
- package/dist/metrics.js.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-agent.d.ts","sourceRoot":"","sources":["../src/instrument-agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"instrument-agent.d.ts","sourceRoot":"","sources":["../src/instrument-agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,OAAO,IAAI,WAAW,EAC3B,KAAK,KAAK,EAEV,KAAK,MAAM,EACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAMvE,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAKzB,MAAM,WAAW,sBAAsB;IACrC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,IAAI,EAAE,SAAS,CAAC;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACxD;;;OAGG;IACH,eAAe,CAAC,EAAE,CAChB,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,sBAAsB,CAAA;KAAE,CAAC,KACzD,UAAU,CAAC;IAChB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB;;;;OAIG;IACH,aAAa,EAAE,MAAM,WAAW,GAAG,SAAS,CAAC;CAC9C;AAeD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,sBAAsB,GAC3B,oBAAoB,CAiCtB"}
|
package/dist/instrument-agent.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Subscribe to a pi-agent {@link Agent} to emit `execute_tool` spans for every
|
|
3
|
-
* tool call the loop runs.
|
|
3
|
+
* tool call the loop runs, and (optionally) one `invoke_agent` span per run.
|
|
4
4
|
*/
|
|
5
|
-
import { context as otelContext, SpanKind, SpanStatusCode, } from "@opentelemetry/api";
|
|
6
|
-
import { GenAiSpanName, IntrospectionAttr } from "@introspection-sdk/types";
|
|
7
|
-
import { executeToolAttributes, executeToolResultAttribute, } from "./attributes.js";
|
|
5
|
+
import { context as otelContext, SpanKind, SpanStatusCode, trace, } from "@opentelemetry/api";
|
|
6
|
+
import { GenAi, GenAiSpanName, IntrospectionAttr, } from "@introspection-sdk/types";
|
|
7
|
+
import { executeToolAttributes, executeToolResultAttribute, invokeAgentAttributes, } from "./attributes.js";
|
|
8
|
+
import { semconvFinishReason } from "./convert.js";
|
|
9
|
+
import { classifyErrorType } from "./error-type.js";
|
|
10
|
+
import { genAiMetrics } from "./metrics.js";
|
|
8
11
|
/**
|
|
9
12
|
* Subscribe to {@link Agent.subscribe} and emit one `execute_tool ${name}`
|
|
10
|
-
* span per tool call
|
|
11
|
-
* finalizes any still-open
|
|
13
|
+
* span per tool call (plus one `invoke_agent` span per run when enabled).
|
|
14
|
+
* Returns a handle whose `stop()` unsubscribes and finalizes any still-open
|
|
15
|
+
* spans.
|
|
12
16
|
*
|
|
13
17
|
* Tool call IDs are assumed unique per agent run; concurrent tool execution
|
|
14
18
|
* (`ToolExecutionMode = "parallel"`) is supported because each id keys its
|
|
@@ -17,39 +21,85 @@ import { executeToolAttributes, executeToolResultAttribute, } from "./attributes
|
|
|
17
21
|
export function instrumentAgent(agent, opts) {
|
|
18
22
|
const buildSpanName = opts.spanName ?? GenAiSpanName.executeTool;
|
|
19
23
|
const activeSpans = new Map();
|
|
24
|
+
const metrics = opts.meter ? genAiMetrics(opts.meter) : undefined;
|
|
25
|
+
const state = { run: undefined };
|
|
20
26
|
const unsubscribe = agent.subscribe((event, signal) => {
|
|
21
|
-
handleEvent(event, opts, activeSpans, buildSpanName, signal);
|
|
27
|
+
handleEvent(event, agent, opts, activeSpans, state, metrics, buildSpanName, signal);
|
|
22
28
|
});
|
|
23
29
|
return {
|
|
24
30
|
stop: () => {
|
|
25
31
|
unsubscribe();
|
|
26
|
-
for (const span of activeSpans.values()) {
|
|
27
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
32
|
+
for (const { span } of activeSpans.values()) {
|
|
28
33
|
span.end();
|
|
29
34
|
}
|
|
30
35
|
activeSpans.clear();
|
|
36
|
+
if (state.run) {
|
|
37
|
+
state.run.span.end();
|
|
38
|
+
state.run = undefined;
|
|
39
|
+
}
|
|
31
40
|
},
|
|
41
|
+
getRunContext: () => state.run?.context,
|
|
32
42
|
};
|
|
33
43
|
}
|
|
34
|
-
function handleEvent(event, opts, activeSpans, buildSpanName, signal) {
|
|
44
|
+
function handleEvent(event, agent, opts, activeSpans, state, metrics, buildSpanName, signal) {
|
|
35
45
|
switch (event.type) {
|
|
36
|
-
case "
|
|
46
|
+
case "agent_start": {
|
|
47
|
+
if (!opts.runSpans)
|
|
48
|
+
return;
|
|
37
49
|
const parentContext = opts.getParentContext?.() ?? otelContext.active();
|
|
38
|
-
const span = opts.tracer.startSpan(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
const span = opts.tracer.startSpan(GenAiSpanName.invokeAgent(opts.meta.agentName), {
|
|
51
|
+
kind: SpanKind.INTERNAL,
|
|
52
|
+
attributes: invokeAgentAttributes(opts.meta),
|
|
53
|
+
}, parentContext ?? undefined);
|
|
54
|
+
state.run = {
|
|
55
|
+
span,
|
|
56
|
+
context: trace.setSpan(parentContext ?? otelContext.active(), span),
|
|
57
|
+
startedAt: Date.now(),
|
|
58
|
+
};
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
case "message_end": {
|
|
62
|
+
const run = state.run;
|
|
63
|
+
const message = event.message;
|
|
64
|
+
if (!run || message.role !== "assistant" || !("usage" in message)) {
|
|
65
|
+
return;
|
|
43
66
|
}
|
|
44
|
-
|
|
67
|
+
// Track outcome only. The run span deliberately carries NO
|
|
68
|
+
// gen_ai.usage.* attributes: platform aggregations sum usage across
|
|
69
|
+
// every span in a conversation, so aggregated usage on the run span
|
|
70
|
+
// would double-count the chat spans beneath it.
|
|
71
|
+
run.lastStopReason = message.stopReason;
|
|
72
|
+
run.errorMessage = message.errorMessage;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
case "agent_end": {
|
|
76
|
+
const run = state.run;
|
|
77
|
+
if (!run)
|
|
78
|
+
return;
|
|
79
|
+
state.run = undefined;
|
|
80
|
+
finishRunSpan(run, opts.meta, metrics, signal);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
case "tool_execution_start": {
|
|
84
|
+
const parentContext = opts.getParentContext?.() ?? state.run?.context ?? otelContext.active();
|
|
85
|
+
const description = lookupToolDescription(agent, event.toolName);
|
|
86
|
+
// Full attribute set at span creation time so samplers see
|
|
87
|
+
// gen_ai.operation.name / tool.name / tool.type.
|
|
88
|
+
const attributes = {
|
|
89
|
+
...executeToolAttributes(event.toolName, event.toolCallId, event.args, opts.meta, description),
|
|
90
|
+
...opts.extraAttributes?.(event),
|
|
91
|
+
};
|
|
92
|
+
const span = opts.tracer.startSpan(buildSpanName(event.toolName), { kind: SpanKind.INTERNAL, attributes }, parentContext ?? undefined);
|
|
93
|
+
activeSpans.set(event.toolCallId, { span, startedAt: Date.now() });
|
|
45
94
|
return;
|
|
46
95
|
}
|
|
47
96
|
case "tool_execution_end": {
|
|
48
|
-
const
|
|
49
|
-
if (!
|
|
97
|
+
const active = activeSpans.get(event.toolCallId);
|
|
98
|
+
if (!active)
|
|
50
99
|
return;
|
|
51
100
|
activeSpans.delete(event.toolCallId);
|
|
52
|
-
span
|
|
101
|
+
const { span, startedAt } = active;
|
|
102
|
+
let errorType;
|
|
53
103
|
if (event.isError && signal?.aborted) {
|
|
54
104
|
// The run's AbortSignal fired: pi synthesizes "Operation aborted"
|
|
55
105
|
// error results for tool calls cut short by a requested abort. A
|
|
@@ -58,7 +108,8 @@ function handleEvent(event, opts, activeSpans, buildSpanName, signal) {
|
|
|
58
108
|
span.setAttribute(IntrospectionAttr.TERMINATION_REASON, "cancelled");
|
|
59
109
|
}
|
|
60
110
|
else if (event.isError) {
|
|
61
|
-
|
|
111
|
+
errorType = "tool_error";
|
|
112
|
+
span.setAttribute("error.type", errorType);
|
|
62
113
|
span.setStatus({
|
|
63
114
|
code: SpanStatusCode.ERROR,
|
|
64
115
|
message: typeof event.result === "string"
|
|
@@ -69,15 +120,70 @@ function handleEvent(event, opts, activeSpans, buildSpanName, signal) {
|
|
|
69
120
|
});
|
|
70
121
|
}
|
|
71
122
|
else {
|
|
72
|
-
|
|
123
|
+
// Semconv scopes gen_ai.tool.call.result to successful executions;
|
|
124
|
+
// error text is carried on the span status instead.
|
|
125
|
+
span.setAttributes(executeToolResultAttribute(event.result));
|
|
73
126
|
}
|
|
74
127
|
span.end();
|
|
128
|
+
if (metrics) {
|
|
129
|
+
const attributes = {
|
|
130
|
+
[GenAi.TOOL_NAME]: event.toolName,
|
|
131
|
+
[GenAi.TOOL_TYPE]: "function",
|
|
132
|
+
[GenAi.AGENT_NAME]: opts.meta.agentName,
|
|
133
|
+
};
|
|
134
|
+
if (errorType)
|
|
135
|
+
attributes["error.type"] = errorType;
|
|
136
|
+
metrics.executeToolDuration.record((Date.now() - startedAt) / 1000, attributes);
|
|
137
|
+
}
|
|
75
138
|
return;
|
|
76
139
|
}
|
|
77
140
|
default:
|
|
78
141
|
return;
|
|
79
142
|
}
|
|
80
143
|
}
|
|
144
|
+
function finishRunSpan(run, meta, metrics, signal) {
|
|
145
|
+
const { span } = run;
|
|
146
|
+
if (run.lastStopReason) {
|
|
147
|
+
span.setAttribute(GenAi.RESPONSE_FINISH_REASONS, [
|
|
148
|
+
semconvFinishReason(run.lastStopReason),
|
|
149
|
+
]);
|
|
150
|
+
}
|
|
151
|
+
let errorType;
|
|
152
|
+
const aborted = run.lastStopReason === "aborted" || signal?.aborted === true;
|
|
153
|
+
if (aborted) {
|
|
154
|
+
// Mirrors the chat-span contract: a requested cancellation is an
|
|
155
|
+
// outcome, not a failure.
|
|
156
|
+
span.setAttribute(IntrospectionAttr.TERMINATION_REASON, "cancelled");
|
|
157
|
+
}
|
|
158
|
+
else if (run.lastStopReason === "error") {
|
|
159
|
+
const errorMessage = run.errorMessage ?? "Unknown error";
|
|
160
|
+
errorType = classifyErrorType(errorMessage, "model_error");
|
|
161
|
+
span.setAttribute("error.type", errorType);
|
|
162
|
+
span.recordException(new Error(errorMessage));
|
|
163
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
|
|
164
|
+
}
|
|
165
|
+
span.end();
|
|
166
|
+
if (metrics) {
|
|
167
|
+
const attributes = { [GenAi.AGENT_NAME]: meta.agentName };
|
|
168
|
+
if (errorType)
|
|
169
|
+
attributes["error.type"] = errorType;
|
|
170
|
+
metrics.invokeAgentDuration.record((Date.now() - run.startedAt) / 1000, attributes);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Best-effort `gen_ai.tool.description` lookup from the agent's tool
|
|
175
|
+
* registry. Defensive against partial Agent implementations (tests, mocks)
|
|
176
|
+
* that don't expose `state.tools`.
|
|
177
|
+
*/
|
|
178
|
+
function lookupToolDescription(agent, toolName) {
|
|
179
|
+
try {
|
|
180
|
+
return agent.state?.tools?.find((tool) => tool.name === toolName)
|
|
181
|
+
?.description;
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
81
187
|
function safeStringify(value) {
|
|
82
188
|
try {
|
|
83
189
|
return JSON.stringify(value);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-agent.js","sourceRoot":"","sources":["../src/instrument-agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,OAAO,IAAI,WAAW,EACtB,QAAQ,EACR,cAAc,
|
|
1
|
+
{"version":3,"file":"instrument-agent.js","sourceRoot":"","sources":["../src/instrument-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Wrap a pi-agent `StreamFn` so each invocation emits a `chat` span that
|
|
3
3
|
* conforms to the OTEL GenAI semantic convention.
|
|
4
4
|
*/
|
|
5
|
-
import { type Attributes, type Context as OtelContext, type Tracer } from "@opentelemetry/api";
|
|
5
|
+
import { type Attributes, type Context as OtelContext, type Meter, type Tracer } from "@opentelemetry/api";
|
|
6
6
|
import { type Api, type Context, type Model } from "@earendil-works/pi-ai";
|
|
7
7
|
import type { StreamFn } from "@earendil-works/pi-agent-core";
|
|
8
8
|
import { type AbortTerminationReason } from "@introspection-sdk/types";
|
|
@@ -12,6 +12,13 @@ export interface InstrumentStreamOptions {
|
|
|
12
12
|
tracer: Tracer;
|
|
13
13
|
/** Required metadata stamped onto every chat span. */
|
|
14
14
|
meta: AgentMeta;
|
|
15
|
+
/**
|
|
16
|
+
* Optional meter. When set, the wrapper also records the GenAI client
|
|
17
|
+
* metrics (`gen_ai.client.token.usage`, `gen_ai.client.operation.duration`,
|
|
18
|
+
* `gen_ai.client.operation.time_to_first_chunk`,
|
|
19
|
+
* `gen_ai.client.operation.time_per_output_chunk`).
|
|
20
|
+
*/
|
|
21
|
+
meter?: Meter;
|
|
15
22
|
/**
|
|
16
23
|
* Returns the parent OTel context for the next chat span. If undefined or
|
|
17
24
|
* returns null, `context.active()` is used at call time.
|
|
@@ -22,7 +29,7 @@ export interface InstrumentStreamOptions {
|
|
|
22
29
|
* on top of the GenAI semconv attributes for each chat span.
|
|
23
30
|
*/
|
|
24
31
|
extraAttributes?: (model: Model<Api>, context: Context) => Attributes;
|
|
25
|
-
/** Override the default span name builder. */
|
|
32
|
+
/** Override the default span name builder (default: `chat {model.id}`). */
|
|
26
33
|
spanName?: (model: Model<Api>, context: Context) => string;
|
|
27
34
|
/**
|
|
28
35
|
* Returns the compaction summaries known for the session, read at span
|
|
@@ -47,7 +54,8 @@ export interface InstrumentStreamOptions {
|
|
|
47
54
|
abortTerminationReason?: () => AbortTerminationReason | null;
|
|
48
55
|
}
|
|
49
56
|
/**
|
|
50
|
-
* Wrap a {@link StreamFn} to emit `chat
|
|
57
|
+
* Wrap a {@link StreamFn} to emit `chat {model}` spans (CLIENT kind — the
|
|
58
|
+
* model runs in a remote process).
|
|
51
59
|
*
|
|
52
60
|
* Reassign `agent.streamFn` with the result:
|
|
53
61
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-stream.d.ts","sourceRoot":"","sources":["../src/instrument-stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,OAAO,IAAI,WAAW,
|
|
1
|
+
{"version":3,"file":"instrument-stream.d.ts","sourceRoot":"","sources":["../src/instrument-stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,OAAO,IAAI,WAAW,EAC3B,KAAK,KAAK,EAEV,KAAK,MAAM,EACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,GAAG,EACR,KAAK,OAAO,EACZ,KAAK,KAAK,EACX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAIL,KAAK,sBAAsB,EAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAIzB,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,IAAI,EAAE,SAAS,CAAC;IAChB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACxD;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,KAAK,UAAU,CAAC;IACtE,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC;IAC3D;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IACjD;;;;;;;;;;OAUG;IACH,sBAAsB,CAAC,EAAE,MAAM,sBAAsB,GAAG,IAAI,CAAC;CAC9D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,uBAAuB,GAC5B,QAAQ,CA6CV"}
|
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { context as otelContext, SpanKind, SpanStatusCode, trace, } from "@opentelemetry/api";
|
|
6
6
|
import { createAssistantMessageEventStream, } from "@earendil-works/pi-ai";
|
|
7
|
-
import { GenAiSpanName, IntrospectionAttr, } from "@introspection-sdk/types";
|
|
8
|
-
import { chatRequestAttributes, chatResponseAttributes, } from "./attributes.js";
|
|
7
|
+
import { GenAi, GenAiSpanName, IntrospectionAttr, } from "@introspection-sdk/types";
|
|
8
|
+
import { chatRequestAttributes, chatResponseAttributes, serverAttributes, } from "./attributes.js";
|
|
9
|
+
import { classifyErrorType, classifyThrownErrorType } from "./error-type.js";
|
|
10
|
+
import { genAiMetrics } from "./metrics.js";
|
|
9
11
|
/**
|
|
10
|
-
* Wrap a {@link StreamFn} to emit `chat
|
|
12
|
+
* Wrap a {@link StreamFn} to emit `chat {model}` spans (CLIENT kind — the
|
|
13
|
+
* model runs in a remote process).
|
|
11
14
|
*
|
|
12
15
|
* Reassign `agent.streamFn` with the result:
|
|
13
16
|
*
|
|
@@ -20,18 +23,21 @@ import { chatRequestAttributes, chatResponseAttributes, } from "./attributes.js"
|
|
|
20
23
|
* `error` events, never thrown synchronously.
|
|
21
24
|
*/
|
|
22
25
|
export function instrumentStream(streamFn, opts) {
|
|
23
|
-
const buildSpanName = opts.spanName ?? ((model) => GenAiSpanName.chat(model.
|
|
26
|
+
const buildSpanName = opts.spanName ?? ((model) => GenAiSpanName.chat(model.id));
|
|
27
|
+
const metrics = opts.meter ? genAiMetrics(opts.meter) : undefined;
|
|
24
28
|
return ((model, context, options) => {
|
|
25
29
|
const parentContext = opts.getParentContext?.() ?? otelContext.active();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
// Compute the full attribute set up front and pass it at span creation
|
|
31
|
+
// time so samplers see gen_ai.operation.name / provider / model /
|
|
32
|
+
// server.*.
|
|
33
|
+
const attributes = {
|
|
34
|
+
...chatRequestAttributes(model, context, opts.meta, {
|
|
35
|
+
compactionSummaries: opts.getCompactionSummaries?.(),
|
|
36
|
+
streamOptions: options,
|
|
37
|
+
}),
|
|
38
|
+
...opts.extraAttributes?.(model, context),
|
|
39
|
+
};
|
|
40
|
+
const span = opts.tracer.startSpan(buildSpanName(model, context), { kind: SpanKind.CLIENT, attributes }, parentContext ?? undefined);
|
|
35
41
|
const proxy = createAssistantMessageEventStream();
|
|
36
42
|
const spanContext = trace.setSpan(parentContext ?? otelContext.active(), span);
|
|
37
43
|
void runUpstream({
|
|
@@ -42,26 +48,43 @@ export function instrumentStream(streamFn, opts) {
|
|
|
42
48
|
spanContext,
|
|
43
49
|
span,
|
|
44
50
|
proxy,
|
|
51
|
+
metrics,
|
|
45
52
|
abortTerminationReason: opts.abortTerminationReason,
|
|
46
53
|
});
|
|
47
54
|
return proxy;
|
|
48
55
|
});
|
|
49
56
|
}
|
|
50
|
-
async function runUpstream({ streamFn, model, context, options, spanContext, span, proxy, abortTerminationReason, }) {
|
|
57
|
+
async function runUpstream({ streamFn, model, context, options, spanContext, span, proxy, metrics, abortTerminationReason, }) {
|
|
51
58
|
let finished = false;
|
|
52
59
|
const startedAt = Date.now();
|
|
53
|
-
|
|
60
|
+
const startedAtMonotonic = performance.now();
|
|
61
|
+
let lastChunkAt;
|
|
54
62
|
try {
|
|
55
63
|
const upstream = await otelContext.with(spanContext, () => streamFn(model, context, options));
|
|
56
64
|
for await (const event of upstream) {
|
|
57
|
-
if (
|
|
58
|
-
|
|
59
|
-
|
|
65
|
+
if (isOutputChunk(event)) {
|
|
66
|
+
const now = performance.now();
|
|
67
|
+
if (lastChunkAt === undefined) {
|
|
68
|
+
const timeToFirstChunk = (now - startedAtMonotonic) / 1000;
|
|
69
|
+
span.setAttribute("gen_ai.response.time_to_first_chunk", timeToFirstChunk);
|
|
70
|
+
metrics?.timeToFirstChunk.record(timeToFirstChunk, chatMetricAttributes(model));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
metrics?.timePerOutputChunk.record((now - lastChunkAt) / 1000, chatMetricAttributes(model));
|
|
74
|
+
}
|
|
75
|
+
lastChunkAt = now;
|
|
60
76
|
}
|
|
61
77
|
proxy.push(event);
|
|
62
78
|
if (!finished && (event.type === "done" || event.type === "error")) {
|
|
63
79
|
finished = true;
|
|
64
|
-
finishSpan(
|
|
80
|
+
finishSpan({
|
|
81
|
+
span,
|
|
82
|
+
event,
|
|
83
|
+
model,
|
|
84
|
+
startedAt,
|
|
85
|
+
metrics,
|
|
86
|
+
abortTerminationReason,
|
|
87
|
+
});
|
|
65
88
|
}
|
|
66
89
|
}
|
|
67
90
|
}
|
|
@@ -73,24 +96,36 @@ async function runUpstream({ streamFn, model, context, options, spanContext, spa
|
|
|
73
96
|
error: assistantErrorMessage(model, errorMessage, options?.signal?.aborted === true),
|
|
74
97
|
};
|
|
75
98
|
if (options?.signal?.aborted !== true) {
|
|
76
|
-
recordGenAiException(span, err,
|
|
99
|
+
recordGenAiException(span, err, classifyThrownErrorType(err));
|
|
77
100
|
}
|
|
78
101
|
proxy.push(errorEvent);
|
|
79
102
|
if (!finished) {
|
|
80
103
|
finished = true;
|
|
81
|
-
finishSpan(
|
|
104
|
+
finishSpan({
|
|
105
|
+
span,
|
|
106
|
+
event: errorEvent,
|
|
107
|
+
model,
|
|
108
|
+
startedAt,
|
|
109
|
+
metrics,
|
|
110
|
+
abortTerminationReason,
|
|
111
|
+
});
|
|
82
112
|
}
|
|
83
113
|
}
|
|
84
114
|
finally {
|
|
85
115
|
if (!finished) {
|
|
86
116
|
// Upstream ended without a terminal event — close the span anyway so
|
|
87
117
|
// we don't leak.
|
|
88
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
89
118
|
span.end();
|
|
90
119
|
}
|
|
91
120
|
}
|
|
92
121
|
}
|
|
93
|
-
function
|
|
122
|
+
function isOutputChunk(event) {
|
|
123
|
+
return ((event.type === "text_delta" ||
|
|
124
|
+
event.type === "thinking_delta" ||
|
|
125
|
+
event.type === "toolcall_delta") &&
|
|
126
|
+
event.delta.length > 0);
|
|
127
|
+
}
|
|
128
|
+
function finishSpan({ span, event, model, startedAt, metrics, abortTerminationReason, }) {
|
|
94
129
|
const message = event.type === "done" ? event.message : event.error;
|
|
95
130
|
span.setAttributes(chatResponseAttributes(message));
|
|
96
131
|
const aborted = (event.type === "error" && event.reason === "aborted") ||
|
|
@@ -100,6 +135,7 @@ function finishSpan(span, event, abortTerminationReason) {
|
|
|
100
135
|
: abortTerminationReason
|
|
101
136
|
? abortTerminationReason()
|
|
102
137
|
: "cancelled";
|
|
138
|
+
let errorType;
|
|
103
139
|
if (terminationReason !== null) {
|
|
104
140
|
// A requested cancellation is an outcome, not a failure: status stays
|
|
105
141
|
// Unset (no success assertion over a truncated generation, no error),
|
|
@@ -114,22 +150,55 @@ function finishSpan(span, event, abortTerminationReason) {
|
|
|
114
150
|
// abort (callback returned null) — fail toward a false error, never a
|
|
115
151
|
// hidden one.
|
|
116
152
|
const errorMessage = message.errorMessage ?? "Unknown error";
|
|
117
|
-
|
|
153
|
+
errorType = classifyErrorType(errorMessage, "model_error");
|
|
154
|
+
recordGenAiException(span, new Error(errorMessage), errorType);
|
|
118
155
|
span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
|
|
119
156
|
}
|
|
120
|
-
|
|
121
|
-
|
|
157
|
+
if (metrics) {
|
|
158
|
+
recordCompletionMetrics(metrics, model, message, startedAt, errorType);
|
|
122
159
|
}
|
|
123
160
|
span.end();
|
|
124
161
|
}
|
|
162
|
+
function chatMetricAttributes(model) {
|
|
163
|
+
return {
|
|
164
|
+
[GenAi.OPERATION_NAME]: "chat",
|
|
165
|
+
[GenAi.PROVIDER_NAME]: model.provider,
|
|
166
|
+
[GenAi.REQUEST_MODEL]: model.id,
|
|
167
|
+
...serverAttributes(model.baseUrl),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function recordCompletionMetrics(metrics, model, message, startedAt, errorType) {
|
|
171
|
+
const attributes = chatMetricAttributes(model);
|
|
172
|
+
if (message.model) {
|
|
173
|
+
attributes[GenAi.RESPONSE_MODEL] = message.model;
|
|
174
|
+
}
|
|
175
|
+
const durationAttributes = errorType
|
|
176
|
+
? { ...attributes, "error.type": errorType }
|
|
177
|
+
: attributes;
|
|
178
|
+
metrics.operationDuration.record((Date.now() - startedAt) / 1000, durationAttributes);
|
|
179
|
+
const inputTokens = message.usage.input + message.usage.cacheRead + message.usage.cacheWrite;
|
|
180
|
+
if (inputTokens > 0) {
|
|
181
|
+
metrics.tokenUsage.record(inputTokens, {
|
|
182
|
+
...attributes,
|
|
183
|
+
"gen_ai.token.type": "input",
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (message.usage.output > 0) {
|
|
187
|
+
metrics.tokenUsage.record(message.usage.output, {
|
|
188
|
+
...attributes,
|
|
189
|
+
"gen_ai.token.type": "output",
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
125
193
|
function recordGenAiException(span, error, errorType) {
|
|
126
194
|
const exception = error instanceof Error ? error : new Error(String(error));
|
|
127
195
|
span.setAttribute("error.type", errorType);
|
|
196
|
+
// recordException writes the standard `exception` span event
|
|
197
|
+
// (exception.type / exception.message / exception.stacktrace). The
|
|
198
|
+
// semconv `gen_ai.client.operation.exception` signal is a *log* event —
|
|
199
|
+
// duplicating it as a second span event is not part of the convention,
|
|
200
|
+
// so only the standard exception event is recorded here.
|
|
128
201
|
span.recordException(exception);
|
|
129
|
-
span.addEvent("gen_ai.client.operation.exception", {
|
|
130
|
-
"exception.type": exception.name || "Error",
|
|
131
|
-
"exception.message": exception.message,
|
|
132
|
-
});
|
|
133
202
|
}
|
|
134
203
|
function assistantErrorMessage(model, errorMessage, aborted = false) {
|
|
135
204
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-stream.js","sourceRoot":"","sources":["../src/instrument-stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,OAAO,IAAI,WAAW,EACtB,QAAQ,EACR,cAAc,EACd,KAAK,
|
|
1
|
+
{"version":3,"file":"instrument-stream.js","sourceRoot":"","sources":["../src/instrument-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GenAI client metric instruments per the OTel GenAI semconv metrics doc.
|
|
3
|
+
*
|
|
4
|
+
* Instruments are created lazily per `Meter` and cached, so repeated
|
|
5
|
+
* `instrumentStream` / `instrumentAgent` calls sharing a meter reuse the
|
|
6
|
+
* same histograms. Bucket boundaries follow the spec's
|
|
7
|
+
* ExplicitBucketBoundaries advice where one is defined.
|
|
8
|
+
*/
|
|
9
|
+
import type { Histogram, Meter } from "@opentelemetry/api";
|
|
10
|
+
export interface GenAiMetrics {
|
|
11
|
+
/** `gen_ai.client.token.usage` — record once per token type per call. */
|
|
12
|
+
tokenUsage: Histogram;
|
|
13
|
+
/** `gen_ai.client.operation.duration` — seconds per chat call. */
|
|
14
|
+
operationDuration: Histogram;
|
|
15
|
+
/** `gen_ai.client.operation.time_to_first_chunk` — streaming only. */
|
|
16
|
+
timeToFirstChunk: Histogram;
|
|
17
|
+
/** `gen_ai.client.operation.time_per_output_chunk` — per chunk after the first. */
|
|
18
|
+
timePerOutputChunk: Histogram;
|
|
19
|
+
/** `gen_ai.execute_tool.duration` — seconds per tool execution. */
|
|
20
|
+
executeToolDuration: Histogram;
|
|
21
|
+
/** `gen_ai.invoke_agent.duration` — seconds per in-process agent run. */
|
|
22
|
+
invokeAgentDuration: Histogram;
|
|
23
|
+
}
|
|
24
|
+
/** Get (or create) the GenAI instruments for a meter. */
|
|
25
|
+
export declare function genAiMetrics(meter: Meter): GenAiMetrics;
|
|
26
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAmB3D,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,UAAU,EAAE,SAAS,CAAC;IACtB,kEAAkE;IAClE,iBAAiB,EAAE,SAAS,CAAC;IAC7B,sEAAsE;IACtE,gBAAgB,EAAE,SAAS,CAAC;IAC5B,mFAAmF;IACnF,kBAAkB,EAAE,SAAS,CAAC;IAC9B,mEAAmE;IACnE,mBAAmB,EAAE,SAAS,CAAC;IAC/B,yEAAyE;IACzE,mBAAmB,EAAE,SAAS,CAAC;CAChC;AAID,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,YAAY,CAmDvD"}
|
package/dist/metrics.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GenAI client metric instruments per the OTel GenAI semconv metrics doc.
|
|
3
|
+
*
|
|
4
|
+
* Instruments are created lazily per `Meter` and cached, so repeated
|
|
5
|
+
* `instrumentStream` / `instrumentAgent` calls sharing a meter reuse the
|
|
6
|
+
* same histograms. Bucket boundaries follow the spec's
|
|
7
|
+
* ExplicitBucketBoundaries advice where one is defined.
|
|
8
|
+
*/
|
|
9
|
+
/** Spec advice for `gen_ai.client.token.usage`. */
|
|
10
|
+
const TOKEN_BUCKETS = [
|
|
11
|
+
1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304,
|
|
12
|
+
16777216, 67108864,
|
|
13
|
+
];
|
|
14
|
+
/** Spec advice for the client duration / chunk-timing histograms. */
|
|
15
|
+
const DURATION_BUCKETS = [
|
|
16
|
+
0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48,
|
|
17
|
+
40.96, 81.92,
|
|
18
|
+
];
|
|
19
|
+
/** Spec advice for in-process agent invocation durations. */
|
|
20
|
+
const AGENT_DURATION_BUCKETS = [
|
|
21
|
+
0.1, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4, 12.8, 25.6, 51.2, 102.4, 204.8, 409.6,
|
|
22
|
+
];
|
|
23
|
+
const metricsByMeter = new WeakMap();
|
|
24
|
+
/** Get (or create) the GenAI instruments for a meter. */
|
|
25
|
+
export function genAiMetrics(meter) {
|
|
26
|
+
const cached = metricsByMeter.get(meter);
|
|
27
|
+
if (cached)
|
|
28
|
+
return cached;
|
|
29
|
+
const metrics = {
|
|
30
|
+
tokenUsage: meter.createHistogram("gen_ai.client.token.usage", {
|
|
31
|
+
description: "Number of input and output tokens used.",
|
|
32
|
+
unit: "{token}",
|
|
33
|
+
advice: { explicitBucketBoundaries: TOKEN_BUCKETS },
|
|
34
|
+
}),
|
|
35
|
+
operationDuration: meter.createHistogram("gen_ai.client.operation.duration", {
|
|
36
|
+
description: "GenAI operation duration.",
|
|
37
|
+
unit: "s",
|
|
38
|
+
advice: { explicitBucketBoundaries: DURATION_BUCKETS },
|
|
39
|
+
}),
|
|
40
|
+
timeToFirstChunk: meter.createHistogram("gen_ai.client.operation.time_to_first_chunk", {
|
|
41
|
+
description: "Time to receive the first chunk of the response stream, measured from request issuance.",
|
|
42
|
+
unit: "s",
|
|
43
|
+
advice: { explicitBucketBoundaries: DURATION_BUCKETS },
|
|
44
|
+
}),
|
|
45
|
+
timePerOutputChunk: meter.createHistogram("gen_ai.client.operation.time_per_output_chunk", {
|
|
46
|
+
description: "Time per output chunk, recorded for each chunk received after the first one.",
|
|
47
|
+
unit: "s",
|
|
48
|
+
advice: { explicitBucketBoundaries: DURATION_BUCKETS },
|
|
49
|
+
}),
|
|
50
|
+
executeToolDuration: meter.createHistogram("gen_ai.execute_tool.duration", {
|
|
51
|
+
description: "The duration of a single tool execution.",
|
|
52
|
+
unit: "s",
|
|
53
|
+
advice: { explicitBucketBoundaries: DURATION_BUCKETS },
|
|
54
|
+
}),
|
|
55
|
+
invokeAgentDuration: meter.createHistogram("gen_ai.invoke_agent.duration", {
|
|
56
|
+
description: "The end-to-end duration of a single in-process agent invocation.",
|
|
57
|
+
unit: "s",
|
|
58
|
+
advice: { explicitBucketBoundaries: AGENT_DURATION_BUCKETS },
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
metricsByMeter.set(meter, metrics);
|
|
62
|
+
return metrics;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=metrics.js.map
|