@arizeai/openinference-instrumentation-beeai 1.5.22 → 1.5.24
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/esm/helpers/buildTraceTree.d.ts.map +1 -1
- package/dist/esm/helpers/buildTraceTree.js +10 -8
- package/dist/esm/helpers/buildTraceTree.js.map +1 -1
- package/dist/esm/helpers/getErrorSafe.d.ts.map +1 -1
- package/dist/esm/helpers/getErrorSafe.js +1 -0
- package/dist/esm/helpers/getErrorSafe.js.map +1 -1
- package/dist/esm/helpers/getSerializedObjectSafe.d.ts +46 -20
- package/dist/esm/helpers/getSerializedObjectSafe.d.ts.map +1 -1
- package/dist/esm/helpers/getSerializedObjectSafe.js +175 -154
- package/dist/esm/helpers/getSerializedObjectSafe.js.map +1 -1
- package/dist/esm/helpers/traceSerializer.js +1 -1
- package/dist/esm/helpers/traceSerializer.js.map +1 -1
- package/dist/esm/middleware.d.ts.map +1 -1
- package/dist/esm/middleware.js +68 -34
- package/dist/esm/middleware.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esnext/helpers/buildTraceTree.d.ts.map +1 -1
- package/dist/esnext/helpers/buildTraceTree.js +10 -9
- package/dist/esnext/helpers/buildTraceTree.js.map +1 -1
- package/dist/esnext/helpers/getErrorSafe.d.ts.map +1 -1
- package/dist/esnext/helpers/getErrorSafe.js +1 -0
- package/dist/esnext/helpers/getErrorSafe.js.map +1 -1
- package/dist/esnext/helpers/getSerializedObjectSafe.d.ts +46 -20
- package/dist/esnext/helpers/getSerializedObjectSafe.d.ts.map +1 -1
- package/dist/esnext/helpers/getSerializedObjectSafe.js +128 -109
- package/dist/esnext/helpers/getSerializedObjectSafe.js.map +1 -1
- package/dist/esnext/helpers/traceSerializer.js +1 -1
- package/dist/esnext/helpers/traceSerializer.js.map +1 -1
- package/dist/esnext/middleware.d.ts.map +1 -1
- package/dist/esnext/middleware.js +70 -35
- package/dist/esnext/middleware.js.map +1 -1
- package/dist/esnext/tsconfig.esnext.tsbuildinfo +1 -1
- package/dist/src/helpers/buildTraceTree.d.ts.map +1 -1
- package/dist/src/helpers/buildTraceTree.js +10 -9
- package/dist/src/helpers/buildTraceTree.js.map +1 -1
- package/dist/src/helpers/getErrorSafe.d.ts.map +1 -1
- package/dist/src/helpers/getErrorSafe.js +1 -0
- package/dist/src/helpers/getErrorSafe.js.map +1 -1
- package/dist/src/helpers/getSerializedObjectSafe.d.ts +46 -20
- package/dist/src/helpers/getSerializedObjectSafe.d.ts.map +1 -1
- package/dist/src/helpers/getSerializedObjectSafe.js +128 -109
- package/dist/src/helpers/getSerializedObjectSafe.js.map +1 -1
- package/dist/src/helpers/traceSerializer.js +1 -1
- package/dist/src/helpers/traceSerializer.js.map +1 -1
- package/dist/src/middleware.d.ts.map +1 -1
- package/dist/src/middleware.js +70 -35
- package/dist/src/middleware.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/helpers/buildTraceTree.ts +11 -12
- package/src/helpers/getErrorSafe.ts +1 -0
- package/src/helpers/getSerializedObjectSafe.ts +197 -163
- package/src/helpers/traceSerializer.ts +1 -1
- package/src/middleware.ts +95 -37
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arizeai/openinference-instrumentation-beeai",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.24",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "OpenInference Instrumentation for BeeAI framework",
|
|
6
6
|
"keywords": [
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"@opentelemetry/instrumentation": "^0.57.1",
|
|
34
34
|
"remeda": "^2.20.2",
|
|
35
35
|
"semver": "^7.7.0",
|
|
36
|
-
"@arizeai/openinference-core": "2.5.
|
|
37
|
-
"@arizeai/openinference-semantic-conventions": "2.
|
|
36
|
+
"@arizeai/openinference-core": "2.5.4",
|
|
37
|
+
"@arizeai/openinference-semantic-conventions": "2.8.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.50.0",
|
|
@@ -111,26 +111,25 @@ function buildLLMMainSpanData(data: BuiltTraceTreeProps["data"]) {
|
|
|
111
111
|
|
|
112
112
|
if (!startBeeaiSpan && !successBeeeaiSpan) return {};
|
|
113
113
|
|
|
114
|
+
const startData = startBeeaiSpan?.attributes.data;
|
|
115
|
+
const successData = successBeeeaiSpan?.attributes.data;
|
|
116
|
+
|
|
114
117
|
const provider =
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
startData?.[SemanticConventions.LLM_PROVIDER] ||
|
|
119
|
+
successData?.[SemanticConventions.LLM_PROVIDER];
|
|
117
120
|
|
|
118
121
|
const modelName =
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
startData?.[SemanticConventions.LLM_MODEL_NAME] ||
|
|
123
|
+
successData?.[SemanticConventions.LLM_MODEL_NAME];
|
|
121
124
|
|
|
122
125
|
return {
|
|
123
126
|
...(startBeeaiSpan && {
|
|
124
|
-
[SemanticConventions.INPUT_VALUE]:
|
|
125
|
-
|
|
126
|
-
[SemanticConventions.INPUT_MIME_TYPE]:
|
|
127
|
-
startBeeaiSpan?.attributes.data?.[SemanticConventions.INPUT_MIME_TYPE],
|
|
127
|
+
[SemanticConventions.INPUT_VALUE]: startData?.[SemanticConventions.INPUT_VALUE],
|
|
128
|
+
[SemanticConventions.INPUT_MIME_TYPE]: startData?.[SemanticConventions.INPUT_MIME_TYPE],
|
|
128
129
|
}),
|
|
129
130
|
...(successBeeeaiSpan && {
|
|
130
|
-
[SemanticConventions.OUTPUT_MIME_TYPE]:
|
|
131
|
-
|
|
132
|
-
[SemanticConventions.OUTPUT_VALUE]:
|
|
133
|
-
successBeeeaiSpan.attributes.data?.[SemanticConventions.OUTPUT_VALUE],
|
|
131
|
+
[SemanticConventions.OUTPUT_MIME_TYPE]: successData?.[SemanticConventions.OUTPUT_MIME_TYPE],
|
|
132
|
+
[SemanticConventions.OUTPUT_VALUE]: successData?.[SemanticConventions.OUTPUT_VALUE],
|
|
134
133
|
}),
|
|
135
134
|
...(provider && { [SemanticConventions.LLM_PROVIDER]: provider }),
|
|
136
135
|
...(modelName && { [SemanticConventions.LLM_MODEL_NAME]: modelName }),
|
|
@@ -98,6 +98,196 @@ function parseLLMOutputMessages(messages: readonly unknown[]) {
|
|
|
98
98
|
|
|
99
99
|
const matchesEvent = (name: string, events: readonly string[]): boolean => events.includes(name);
|
|
100
100
|
|
|
101
|
+
const NATIVE_TOOL_EVENT_NAMES = [
|
|
102
|
+
startToolEventName,
|
|
103
|
+
successToolEventName,
|
|
104
|
+
finishToolEventName,
|
|
105
|
+
errorToolEventName,
|
|
106
|
+
retryToolEventName,
|
|
107
|
+
] as const;
|
|
108
|
+
|
|
109
|
+
/** Maps an error onto the OpenTelemetry exception attributes. */
|
|
110
|
+
function getExceptionAttributes(error: Error | undefined) {
|
|
111
|
+
if (!error) {
|
|
112
|
+
return {};
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
"exception.message": error.message,
|
|
116
|
+
"exception.stacktrace": error.stack,
|
|
117
|
+
"exception.type": error.name,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Extracts the attributes for an agent start/success/error/retry event. */
|
|
122
|
+
function getAgentEventAttributes(dataObject: unknown) {
|
|
123
|
+
const event = isObjectWithStringKeys(dataObject) ? dataObject : {};
|
|
124
|
+
const agentMeta = isObjectWithStringKeys(event.meta) ? event.meta : undefined;
|
|
125
|
+
const tools = Array.isArray(event.tools) ? event.tools.filter(isObjectWithStringKeys) : [];
|
|
126
|
+
const memory = isObjectWithStringKeys(event.memory) ? event.memory : undefined;
|
|
127
|
+
const messages = memory && Array.isArray(memory.messages) ? memory.messages : [];
|
|
128
|
+
const error = event.error instanceof Error ? event.error : undefined;
|
|
129
|
+
const data = event.data;
|
|
130
|
+
return {
|
|
131
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.AGENT,
|
|
132
|
+
...(typeof agentMeta?.iteration === "number" && { iteration: agentMeta.iteration }),
|
|
133
|
+
...(tools?.length > 0 && {
|
|
134
|
+
[SemanticConventions.LLM_TOOLS]: tools.map((tool) => ({
|
|
135
|
+
[SemanticConventions.TOOL_NAME]: typeof tool.name === "string" ? tool.name : undefined,
|
|
136
|
+
[SemanticConventions.TOOL_DESCRIPTION]:
|
|
137
|
+
typeof tool.description === "string" ? tool.description : undefined,
|
|
138
|
+
"tool.options": tool.options,
|
|
139
|
+
})),
|
|
140
|
+
}),
|
|
141
|
+
...(messages.length > 0 && {
|
|
142
|
+
[SemanticConventions.INPUT_MIME_TYPE]: MimeType.JSON,
|
|
143
|
+
[SemanticConventions.INPUT_VALUE]: JSON.stringify(messages),
|
|
144
|
+
}),
|
|
145
|
+
...getExceptionAttributes(error),
|
|
146
|
+
...(data != null
|
|
147
|
+
? {
|
|
148
|
+
[SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
|
|
149
|
+
[SemanticConventions.OUTPUT_VALUE]: JSON.stringify(data),
|
|
150
|
+
}
|
|
151
|
+
: {}),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Extracts the attributes for an agent update/partial update event. */
|
|
156
|
+
function getUpdateEventAttributes(dataObject: unknown) {
|
|
157
|
+
const event = isObjectWithStringKeys(dataObject) ? dataObject : {};
|
|
158
|
+
const data = isObjectWithStringKeys(event.data) ? event.data : {};
|
|
159
|
+
|
|
160
|
+
const output = data.final_answer || data.tool_output;
|
|
161
|
+
return {
|
|
162
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.AGENT,
|
|
163
|
+
...(typeof data.thought === "string" && { thought: data.thought }),
|
|
164
|
+
...(typeof data.tool_name === "string" && {
|
|
165
|
+
[SemanticConventions.TOOL_NAME]: data.tool_name,
|
|
166
|
+
}),
|
|
167
|
+
...(data.tool_input != null
|
|
168
|
+
? { [SemanticConventions.TOOL_PARAMETERS]: JSON.stringify(data.tool_input) }
|
|
169
|
+
: {}),
|
|
170
|
+
...(typeof output === "string" && {
|
|
171
|
+
[SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
|
|
172
|
+
[SemanticConventions.OUTPUT_VALUE]: output,
|
|
173
|
+
}),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Extracts the attributes for a tool event emitted by an agent. */
|
|
178
|
+
function getAgentToolEventAttributes(dataObject: unknown) {
|
|
179
|
+
const event = isObjectWithStringKeys(dataObject) ? dataObject : {};
|
|
180
|
+
const data = isObjectWithStringKeys(event.data) ? event.data : {};
|
|
181
|
+
const iteration = isObjectWithStringKeys(data.iteration) ? data.iteration : undefined;
|
|
182
|
+
const tool = isObjectWithStringKeys(data.tool) ? data.tool : undefined;
|
|
183
|
+
const error = data.error instanceof Error ? data.error : undefined;
|
|
184
|
+
const output = data.result instanceof Serializable ? data.result.createSnapshot() : undefined;
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.TOOL,
|
|
188
|
+
...(typeof iteration?.thought === "string" && { thought: iteration.thought }),
|
|
189
|
+
...(data?.input
|
|
190
|
+
? {
|
|
191
|
+
[SemanticConventions.TOOL_PARAMETERS]: JSON.stringify(data.input),
|
|
192
|
+
}
|
|
193
|
+
: {}),
|
|
194
|
+
...(typeof tool?.description === "string" && {
|
|
195
|
+
[SemanticConventions.TOOL_DESCRIPTION]: tool.description,
|
|
196
|
+
}),
|
|
197
|
+
...(typeof tool?.name === "string" && {
|
|
198
|
+
[SemanticConventions.TOOL_NAME]: tool.name,
|
|
199
|
+
}),
|
|
200
|
+
...getExceptionAttributes(error),
|
|
201
|
+
...(output != null ? { [SemanticConventions.OUTPUT_VALUE]: JSON.stringify(output) } : {}),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Extracts the attributes for a tool event emitted by a Tool itself. */
|
|
206
|
+
function getNativeToolEventAttributes(dataObject: unknown) {
|
|
207
|
+
if (!dataObject) {
|
|
208
|
+
return {
|
|
209
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.TOOL,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const event = isObjectWithStringKeys(dataObject) ? dataObject : {};
|
|
213
|
+
const { input, output } = event;
|
|
214
|
+
const error = event.error instanceof Error ? event.error : undefined;
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.TOOL,
|
|
218
|
+
...(input != null ? { [SemanticConventions.TOOL_PARAMETERS]: JSON.stringify(input) } : {}),
|
|
219
|
+
...(output != null ? { [SemanticConventions.OUTPUT_VALUE]: JSON.stringify(output) } : {}),
|
|
220
|
+
...getExceptionAttributes(error),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Extracts the model/provider attributes from a ChatModel snapshot. */
|
|
225
|
+
function getChatModelCreatorAttributes(creator: ChatModel) {
|
|
226
|
+
const creatorSnapshot = creator.createSnapshot();
|
|
227
|
+
const snapshot: Record<string, unknown> = isObjectWithStringKeys(creatorSnapshot)
|
|
228
|
+
? creatorSnapshot
|
|
229
|
+
: {};
|
|
230
|
+
return {
|
|
231
|
+
...(typeof snapshot.providerId === "string" && {
|
|
232
|
+
[SemanticConventions.LLM_PROVIDER]: snapshot.providerId,
|
|
233
|
+
[`${SemanticAttributePrefixes.metadata}.${LLMAttributePostfixes.provider}`]:
|
|
234
|
+
snapshot.providerId,
|
|
235
|
+
}),
|
|
236
|
+
...(typeof snapshot.modelId === "string" && {
|
|
237
|
+
[SemanticConventions.LLM_MODEL_NAME]: snapshot.modelId,
|
|
238
|
+
[`${SemanticAttributePrefixes.metadata}.${LLMAttributePostfixes.model_name}`]:
|
|
239
|
+
snapshot.modelId,
|
|
240
|
+
}),
|
|
241
|
+
...(snapshot.parameters != null
|
|
242
|
+
? {
|
|
243
|
+
[SemanticConventions.LLM_INVOCATION_PARAMETERS]: JSON.stringify(snapshot.parameters),
|
|
244
|
+
}
|
|
245
|
+
: {}),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Extracts the attributes for an LLM start/success/error/new-token event. */
|
|
250
|
+
function getLLMEventAttributes({
|
|
251
|
+
dataObject,
|
|
252
|
+
creator,
|
|
253
|
+
}: {
|
|
254
|
+
dataObject: unknown;
|
|
255
|
+
creator: ChatModel;
|
|
256
|
+
}) {
|
|
257
|
+
const event = isObjectWithStringKeys(dataObject) ? dataObject : {};
|
|
258
|
+
const value = isObjectWithStringKeys(event.value) ? event.value : undefined;
|
|
259
|
+
const input = isObjectWithStringKeys(event.input) ? event.input : undefined;
|
|
260
|
+
const usage = value && isObjectWithStringKeys(value.usage) ? value.usage : undefined;
|
|
261
|
+
const inputMessages = input && Array.isArray(input.messages) ? input.messages : [];
|
|
262
|
+
const outputMessages = value && Array.isArray(value.messages) ? value.messages : [];
|
|
263
|
+
const error = event.error instanceof Error ? event.error : undefined;
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.LLM,
|
|
267
|
+
...(typeof usage?.completionTokens === "number" && {
|
|
268
|
+
[SemanticConventions.LLM_TOKEN_COUNT_COMPLETION]: usage.completionTokens,
|
|
269
|
+
}),
|
|
270
|
+
...(typeof usage?.promptTokens === "number" && {
|
|
271
|
+
[SemanticConventions.LLM_TOKEN_COUNT_PROMPT]: usage.promptTokens,
|
|
272
|
+
}),
|
|
273
|
+
...(typeof usage?.totalTokens === "number" && {
|
|
274
|
+
[SemanticConventions.LLM_TOKEN_COUNT_TOTAL]: usage.totalTokens,
|
|
275
|
+
}),
|
|
276
|
+
...(inputMessages.length > 0 && {
|
|
277
|
+
[SemanticConventions.INPUT_MIME_TYPE]: MimeType.JSON,
|
|
278
|
+
[SemanticConventions.INPUT_VALUE]: JSON.stringify(inputMessages),
|
|
279
|
+
...parserLLMInputMessages(inputMessages),
|
|
280
|
+
}),
|
|
281
|
+
...(outputMessages.length > 0 && {
|
|
282
|
+
[SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
|
|
283
|
+
[SemanticConventions.OUTPUT_VALUE]: JSON.stringify(outputMessages),
|
|
284
|
+
...parseLLMOutputMessages(outputMessages),
|
|
285
|
+
}),
|
|
286
|
+
...getExceptionAttributes(error),
|
|
287
|
+
...getChatModelCreatorAttributes(creator),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
101
291
|
export function getSerializedObjectSafe(dataObject: unknown, meta: EventMeta<unknown>) {
|
|
102
292
|
try {
|
|
103
293
|
// agent events
|
|
@@ -105,125 +295,22 @@ export function getSerializedObjectSafe(dataObject: unknown, meta: EventMeta<unk
|
|
|
105
295
|
matchesEvent(meta.name, [startEventName, successEventName, errorEventName, retryEventName]) &&
|
|
106
296
|
meta.creator instanceof BaseAgent
|
|
107
297
|
) {
|
|
108
|
-
|
|
109
|
-
const agentMeta = isObjectWithStringKeys(event.meta) ? event.meta : undefined;
|
|
110
|
-
const tools = Array.isArray(event.tools) ? event.tools.filter(isObjectWithStringKeys) : [];
|
|
111
|
-
const memory = isObjectWithStringKeys(event.memory) ? event.memory : undefined;
|
|
112
|
-
const messages = memory && Array.isArray(memory.messages) ? memory.messages : [];
|
|
113
|
-
const error = event.error instanceof Error ? event.error : undefined;
|
|
114
|
-
const data = event.data;
|
|
115
|
-
return {
|
|
116
|
-
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.AGENT,
|
|
117
|
-
...(typeof agentMeta?.iteration === "number" && { iteration: agentMeta.iteration }),
|
|
118
|
-
...(tools?.length > 0 && {
|
|
119
|
-
[SemanticConventions.LLM_TOOLS]: tools.map((tool) => ({
|
|
120
|
-
[SemanticConventions.TOOL_NAME]: typeof tool.name === "string" ? tool.name : undefined,
|
|
121
|
-
[SemanticConventions.TOOL_DESCRIPTION]:
|
|
122
|
-
typeof tool.description === "string" ? tool.description : undefined,
|
|
123
|
-
"tool.options": tool.options,
|
|
124
|
-
})),
|
|
125
|
-
}),
|
|
126
|
-
...(messages.length > 0 && {
|
|
127
|
-
[SemanticConventions.INPUT_MIME_TYPE]: MimeType.JSON,
|
|
128
|
-
[SemanticConventions.INPUT_VALUE]: JSON.stringify(messages),
|
|
129
|
-
}),
|
|
130
|
-
...(error && {
|
|
131
|
-
"exception.message": error.message,
|
|
132
|
-
"exception.stacktrace": error.stack,
|
|
133
|
-
"exception.type": error.name,
|
|
134
|
-
}),
|
|
135
|
-
...(data != null
|
|
136
|
-
? {
|
|
137
|
-
[SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
|
|
138
|
-
[SemanticConventions.OUTPUT_VALUE]: JSON.stringify(data),
|
|
139
|
-
}
|
|
140
|
-
: {}),
|
|
141
|
-
};
|
|
298
|
+
return getAgentEventAttributes(dataObject);
|
|
142
299
|
}
|
|
143
300
|
|
|
144
301
|
// update events
|
|
145
302
|
if (matchesEvent(meta.name, [updateEventName, partialUpdateEventName])) {
|
|
146
|
-
|
|
147
|
-
const data = isObjectWithStringKeys(event.data) ? event.data : {};
|
|
148
|
-
|
|
149
|
-
const output = data.final_answer || data.tool_output;
|
|
150
|
-
return {
|
|
151
|
-
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.AGENT,
|
|
152
|
-
...(typeof data.thought === "string" && { thought: data.thought }),
|
|
153
|
-
...(typeof data.tool_name === "string" && {
|
|
154
|
-
[SemanticConventions.TOOL_NAME]: data.tool_name,
|
|
155
|
-
}),
|
|
156
|
-
...(data.tool_input != null
|
|
157
|
-
? { [SemanticConventions.TOOL_PARAMETERS]: JSON.stringify(data.tool_input) }
|
|
158
|
-
: {}),
|
|
159
|
-
...(typeof output === "string" && {
|
|
160
|
-
[SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
|
|
161
|
-
[SemanticConventions.OUTPUT_VALUE]: output,
|
|
162
|
-
}),
|
|
163
|
-
};
|
|
303
|
+
return getUpdateEventAttributes(dataObject);
|
|
164
304
|
}
|
|
165
305
|
|
|
166
306
|
// tool events (from agent)
|
|
167
307
|
if (matchesEvent(meta.name, [toolErrorEventName, toolStartEventName, toolSuccessEventName])) {
|
|
168
|
-
|
|
169
|
-
const data = isObjectWithStringKeys(event.data) ? event.data : {};
|
|
170
|
-
const iteration = isObjectWithStringKeys(data.iteration) ? data.iteration : undefined;
|
|
171
|
-
const tool = isObjectWithStringKeys(data.tool) ? data.tool : undefined;
|
|
172
|
-
const error = data.error instanceof Error ? data.error : undefined;
|
|
173
|
-
const output = data.result instanceof Serializable ? data.result.createSnapshot() : undefined;
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.TOOL,
|
|
177
|
-
...(typeof iteration?.thought === "string" && { thought: iteration.thought }),
|
|
178
|
-
...(data?.input
|
|
179
|
-
? {
|
|
180
|
-
[SemanticConventions.TOOL_PARAMETERS]: JSON.stringify(data.input),
|
|
181
|
-
}
|
|
182
|
-
: {}),
|
|
183
|
-
...(typeof tool?.description === "string" && {
|
|
184
|
-
[SemanticConventions.TOOL_DESCRIPTION]: tool.description,
|
|
185
|
-
}),
|
|
186
|
-
...(typeof tool?.name === "string" && {
|
|
187
|
-
[SemanticConventions.TOOL_NAME]: tool.name,
|
|
188
|
-
}),
|
|
189
|
-
...(error && {
|
|
190
|
-
"exception.message": error.message,
|
|
191
|
-
"exception.stacktrace": error.stack,
|
|
192
|
-
"exception.type": error.name,
|
|
193
|
-
}),
|
|
194
|
-
...(output != null ? { [SemanticConventions.OUTPUT_VALUE]: JSON.stringify(output) } : {}),
|
|
195
|
-
};
|
|
308
|
+
return getAgentToolEventAttributes(dataObject);
|
|
196
309
|
}
|
|
197
|
-
// tool events native
|
|
198
|
-
if (
|
|
199
|
-
[
|
|
200
|
-
startToolEventName,
|
|
201
|
-
successToolEventName,
|
|
202
|
-
finishToolEventName,
|
|
203
|
-
errorToolEventName,
|
|
204
|
-
retryToolEventName,
|
|
205
|
-
].some((eventName) => eventName === meta.name) &&
|
|
206
|
-
meta.creator instanceof Tool
|
|
207
|
-
) {
|
|
208
|
-
if (!dataObject) {
|
|
209
|
-
return {
|
|
210
|
-
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.TOOL,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
const event = isObjectWithStringKeys(dataObject) ? dataObject : {};
|
|
214
|
-
const { input, output } = event;
|
|
215
|
-
const error = event.error instanceof Error ? event.error : undefined;
|
|
216
310
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
...(output != null ? { [SemanticConventions.OUTPUT_VALUE]: JSON.stringify(output) } : {}),
|
|
221
|
-
...(error && {
|
|
222
|
-
"exception.message": error.message,
|
|
223
|
-
"exception.stacktrace": error.stack,
|
|
224
|
-
"exception.type": error.name,
|
|
225
|
-
}),
|
|
226
|
-
};
|
|
311
|
+
// tool events native
|
|
312
|
+
if (matchesEvent(meta.name, NATIVE_TOOL_EVENT_NAMES) && meta.creator instanceof Tool) {
|
|
313
|
+
return getNativeToolEventAttributes(dataObject);
|
|
227
314
|
}
|
|
228
315
|
|
|
229
316
|
// llm events
|
|
@@ -236,60 +323,7 @@ export function getSerializedObjectSafe(dataObject: unknown, meta: EventMeta<unk
|
|
|
236
323
|
]) &&
|
|
237
324
|
meta.creator instanceof ChatModel
|
|
238
325
|
) {
|
|
239
|
-
|
|
240
|
-
const value = isObjectWithStringKeys(event.value) ? event.value : undefined;
|
|
241
|
-
const input = isObjectWithStringKeys(event.input) ? event.input : undefined;
|
|
242
|
-
const usage = value && isObjectWithStringKeys(value.usage) ? value.usage : undefined;
|
|
243
|
-
const inputMessages = input && Array.isArray(input.messages) ? input.messages : [];
|
|
244
|
-
const outputMessages = value && Array.isArray(value.messages) ? value.messages : [];
|
|
245
|
-
const error = event.error instanceof Error ? event.error : undefined;
|
|
246
|
-
|
|
247
|
-
const creatorSnapshot = meta.creator.createSnapshot();
|
|
248
|
-
const creator: Record<string, unknown> = isObjectWithStringKeys(creatorSnapshot)
|
|
249
|
-
? creatorSnapshot
|
|
250
|
-
: {};
|
|
251
|
-
return {
|
|
252
|
-
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.LLM,
|
|
253
|
-
...(typeof usage?.completionTokens === "number" && {
|
|
254
|
-
[SemanticConventions.LLM_TOKEN_COUNT_COMPLETION]: usage.completionTokens,
|
|
255
|
-
}),
|
|
256
|
-
...(typeof usage?.promptTokens === "number" && {
|
|
257
|
-
[SemanticConventions.LLM_TOKEN_COUNT_PROMPT]: usage.promptTokens,
|
|
258
|
-
}),
|
|
259
|
-
...(typeof usage?.totalTokens === "number" && {
|
|
260
|
-
[SemanticConventions.LLM_TOKEN_COUNT_TOTAL]: usage.totalTokens,
|
|
261
|
-
}),
|
|
262
|
-
...(inputMessages.length > 0 && {
|
|
263
|
-
[SemanticConventions.INPUT_MIME_TYPE]: MimeType.JSON,
|
|
264
|
-
[SemanticConventions.INPUT_VALUE]: JSON.stringify(inputMessages),
|
|
265
|
-
...parserLLMInputMessages(inputMessages),
|
|
266
|
-
}),
|
|
267
|
-
...(outputMessages.length > 0 && {
|
|
268
|
-
[SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
|
|
269
|
-
[SemanticConventions.OUTPUT_VALUE]: JSON.stringify(outputMessages),
|
|
270
|
-
...parseLLMOutputMessages(outputMessages),
|
|
271
|
-
}),
|
|
272
|
-
...(error && {
|
|
273
|
-
"exception.message": error.message,
|
|
274
|
-
"exception.stacktrace": error.stack,
|
|
275
|
-
"exception.type": error.name,
|
|
276
|
-
}),
|
|
277
|
-
...(typeof creator.providerId === "string" && {
|
|
278
|
-
[SemanticConventions.LLM_PROVIDER]: creator.providerId,
|
|
279
|
-
[`${SemanticAttributePrefixes.metadata}.${LLMAttributePostfixes.provider}`]:
|
|
280
|
-
creator.providerId,
|
|
281
|
-
}),
|
|
282
|
-
...(typeof creator.modelId === "string" && {
|
|
283
|
-
[SemanticConventions.LLM_MODEL_NAME]: creator.modelId,
|
|
284
|
-
[`${SemanticAttributePrefixes.metadata}.${LLMAttributePostfixes.model_name}`]:
|
|
285
|
-
creator.modelId,
|
|
286
|
-
}),
|
|
287
|
-
...(creator.parameters != null
|
|
288
|
-
? {
|
|
289
|
-
[SemanticConventions.LLM_INVOCATION_PARAMETERS]: JSON.stringify(creator.parameters),
|
|
290
|
-
}
|
|
291
|
-
: {}),
|
|
292
|
-
};
|
|
326
|
+
return getLLMEventAttributes({ dataObject, creator: meta.creator });
|
|
293
327
|
}
|
|
294
328
|
if (meta.name === finishLLMEventName && meta.creator instanceof ChatModel) {
|
|
295
329
|
return {
|
|
@@ -26,7 +26,7 @@ export function traceSerializer({ ignored_keys = [] }: { ignored_keys?: string[]
|
|
|
26
26
|
return (key, value) => {
|
|
27
27
|
// Ignore specific keys, all owned entities and keys starting with underscore
|
|
28
28
|
if (mergedIgnoreKeys.has(key) || key.startsWith("_")) {
|
|
29
|
-
return;
|
|
29
|
+
return undefined;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
return value;
|
package/src/middleware.ts
CHANGED
|
@@ -178,6 +178,90 @@ export function createTelemetryMiddleware(tracer: OITracer, mainSpanKind: OpenIn
|
|
|
178
178
|
},
|
|
179
179
|
);
|
|
180
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Creates the artificial "iteration" tree level for a top-level groupId the
|
|
183
|
+
* first time it is seen. Nested groups (like tokens) are skipped because
|
|
184
|
+
* they would introduce unuseful complexity.
|
|
185
|
+
*/
|
|
186
|
+
function createGroupSpanIfNeeded({
|
|
187
|
+
groupId,
|
|
188
|
+
parentRunId,
|
|
189
|
+
createdAt,
|
|
190
|
+
}: {
|
|
191
|
+
groupId: string | undefined;
|
|
192
|
+
parentRunId: string | undefined;
|
|
193
|
+
createdAt: Date;
|
|
194
|
+
}) {
|
|
195
|
+
if (!groupId || parentRunId || groupIterations.includes(groupId)) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
spansMap.set(
|
|
199
|
+
groupId,
|
|
200
|
+
createSpan({
|
|
201
|
+
id: groupId,
|
|
202
|
+
name: groupId,
|
|
203
|
+
target: "groupId",
|
|
204
|
+
data: {
|
|
205
|
+
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: "Chain",
|
|
206
|
+
},
|
|
207
|
+
startedAt: convertDateToPerformance(createdAt),
|
|
208
|
+
}),
|
|
209
|
+
);
|
|
210
|
+
groupIterations.push(groupId);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Drops the previous `partialUpdate` span for this iteration once a newer one
|
|
215
|
+
* arrives, unless it has nested spans, in which case it is only marked for
|
|
216
|
+
* deletion.
|
|
217
|
+
*/
|
|
218
|
+
function dropSupersededPartialUpdateSpan({
|
|
219
|
+
eventName,
|
|
220
|
+
lastIteration,
|
|
221
|
+
}: {
|
|
222
|
+
eventName: string;
|
|
223
|
+
lastIteration: string | undefined;
|
|
224
|
+
}) {
|
|
225
|
+
if (lastIteration == null || partialUpdateEventName !== eventName) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const lastIterationEventSpanId = eventsIterationsMap.get(lastIteration)?.get(eventName);
|
|
229
|
+
if (!lastIterationEventSpanId || !spansMap.has(lastIterationEventSpanId)) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const { context: spanContext } = spansMap.get(lastIterationEventSpanId)!;
|
|
233
|
+
if (parentIdsMap.has(spanContext.span_id)) {
|
|
234
|
+
spansToDeleteMap.set(lastIterationEventSpanId, undefined);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
// delete span
|
|
238
|
+
cleanSpanSources({ spanId: lastIterationEventSpanId });
|
|
239
|
+
spansMap.delete(lastIterationEventSpanId);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Saves the last event span for each iteration.
|
|
244
|
+
*/
|
|
245
|
+
function recordIterationEventSpan({
|
|
246
|
+
eventName,
|
|
247
|
+
lastIteration,
|
|
248
|
+
spanId,
|
|
249
|
+
}: {
|
|
250
|
+
eventName: string;
|
|
251
|
+
lastIteration: string | undefined;
|
|
252
|
+
spanId: string;
|
|
253
|
+
}) {
|
|
254
|
+
if (lastIteration == null) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const iterationEvents = eventsIterationsMap.get(lastIteration);
|
|
258
|
+
if (iterationEvents) {
|
|
259
|
+
iterationEvents.set(eventName, spanId);
|
|
260
|
+
} else {
|
|
261
|
+
eventsIterationsMap.set(lastIteration, new Map<string, string>([[eventName, spanId]]));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
181
265
|
/**
|
|
182
266
|
* This block collects all "not run category" events with their data and prepares spans for the OpenTelemetry.
|
|
183
267
|
* The huge number of `newToken` events are skipped and only the last one for each parent event is saved because of `generated_token_count` information
|
|
@@ -204,21 +288,11 @@ export function createTelemetryMiddleware(tracer: OITracer, mainSpanKind: OpenIn
|
|
|
204
288
|
* create groupId span level (id does not exist)
|
|
205
289
|
* I use only the top-level groups like iterations other nested groups like tokens would introduce unuseful complexity
|
|
206
290
|
*/
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
name: meta.groupId,
|
|
213
|
-
target: "groupId",
|
|
214
|
-
data: {
|
|
215
|
-
[SemanticConventions.OPENINFERENCE_SPAN_KIND]: "Chain",
|
|
216
|
-
},
|
|
217
|
-
startedAt: convertDateToPerformance(meta.createdAt),
|
|
218
|
-
}),
|
|
219
|
-
);
|
|
220
|
-
groupIterations.push(meta.groupId);
|
|
221
|
-
}
|
|
291
|
+
createGroupSpanIfNeeded({
|
|
292
|
+
groupId: meta.groupId,
|
|
293
|
+
parentRunId: meta.trace.parentRunId,
|
|
294
|
+
createdAt: meta.createdAt,
|
|
295
|
+
});
|
|
222
296
|
|
|
223
297
|
const { spanId, parentSpanId } = idNameManager.getIds({
|
|
224
298
|
path: meta.path,
|
|
@@ -252,21 +326,7 @@ export function createTelemetryMiddleware(tracer: OITracer, mainSpanKind: OpenIn
|
|
|
252
326
|
const lastIteration = groupIterations[groupIterations.length - 1];
|
|
253
327
|
|
|
254
328
|
// delete the `partialUpdate` event if does not have nested spans
|
|
255
|
-
|
|
256
|
-
if (
|
|
257
|
-
lastIterationEventSpanId &&
|
|
258
|
-
partialUpdateEventName === meta.name &&
|
|
259
|
-
spansMap.has(lastIterationEventSpanId)
|
|
260
|
-
) {
|
|
261
|
-
const { context } = spansMap.get(lastIterationEventSpanId)!;
|
|
262
|
-
if (parentIdsMap.has(context.span_id)) {
|
|
263
|
-
spansToDeleteMap.set(lastIterationEventSpanId, undefined);
|
|
264
|
-
} else {
|
|
265
|
-
// delete span
|
|
266
|
-
cleanSpanSources({ spanId: lastIterationEventSpanId });
|
|
267
|
-
spansMap.delete(lastIterationEventSpanId);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
329
|
+
dropSupersededPartialUpdateSpan({ eventName: meta.name, lastIteration });
|
|
270
330
|
|
|
271
331
|
// create new span
|
|
272
332
|
spansMap.set(span.context.span_id, span);
|
|
@@ -276,13 +336,11 @@ export function createTelemetryMiddleware(tracer: OITracer, mainSpanKind: OpenIn
|
|
|
276
336
|
}
|
|
277
337
|
|
|
278
338
|
// save the last event for each iteration
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}
|
|
285
|
-
}
|
|
339
|
+
recordIterationEventSpan({
|
|
340
|
+
eventName: meta.name,
|
|
341
|
+
lastIteration,
|
|
342
|
+
spanId: span.context.span_id,
|
|
343
|
+
});
|
|
286
344
|
} catch (e) {
|
|
287
345
|
diag.warn("Instrumentation error", e);
|
|
288
346
|
}
|