@telemetry-dev/eve 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +41 -25
- package/package.json +2 -2
- package/src/client.ts +33 -22
- package/src/config.ts +2 -1
- package/src/hook.ts +33 -20
- package/src/instrumentation.ts +12 -9
package/dist/index.d.mts
CHANGED
|
@@ -5,7 +5,7 @@ import { InstrumentationDefinition, InstrumentationEvents, InstrumentationRuntim
|
|
|
5
5
|
|
|
6
6
|
//#region src/config.d.ts
|
|
7
7
|
/** Options accepted by every @telemetry-dev/eve entry point. */
|
|
8
|
-
type TelemetryDevEveOptions = Omit<TelemetryOptions, "registerGlobal">;
|
|
8
|
+
type TelemetryDevEveOptions = Omit<TelemetryOptions, "registerGlobal" | "sdkName">;
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/client.d.ts
|
|
11
11
|
interface WrapEveClientOptions extends TelemetryDevEveOptions {
|
package/dist/index.mjs
CHANGED
|
@@ -14,6 +14,7 @@ function ensureInit(options = {}, overrides) {
|
|
|
14
14
|
initialized = true;
|
|
15
15
|
init({
|
|
16
16
|
...options,
|
|
17
|
+
sdkName: "@telemetry-dev/eve",
|
|
17
18
|
registerGlobal: true,
|
|
18
19
|
spanFilter: options.spanFilter ?? ((span) => span.instrumentationScope.name !== "workflow")
|
|
19
20
|
}, overrides);
|
|
@@ -21,16 +22,16 @@ function ensureInit(options = {}, overrides) {
|
|
|
21
22
|
//#endregion
|
|
22
23
|
//#region src/client.ts
|
|
23
24
|
function asRecord$1(value) {
|
|
24
|
-
if (value === null ||
|
|
25
|
+
if (value === null || Array.isArray(value) || !(value instanceof Object)) return void 0;
|
|
25
26
|
return value;
|
|
26
27
|
}
|
|
27
28
|
function stringField$1(record, key) {
|
|
28
29
|
const value = record?.[key];
|
|
29
|
-
return
|
|
30
|
+
return value?.constructor === String && value.length > 0 ? value : void 0;
|
|
30
31
|
}
|
|
31
32
|
function numberField$1(record, key) {
|
|
32
33
|
const value = record?.[key];
|
|
33
|
-
return
|
|
34
|
+
return value?.constructor === Number ? value : void 0;
|
|
34
35
|
}
|
|
35
36
|
function eventData$1(event) {
|
|
36
37
|
if (!("data" in event)) return {};
|
|
@@ -55,8 +56,8 @@ function inputForSpan(payload) {
|
|
|
55
56
|
return payload.message ?? payload.inputResponses;
|
|
56
57
|
}
|
|
57
58
|
function bindOrReturn(target, prop) {
|
|
58
|
-
const value =
|
|
59
|
-
return
|
|
59
|
+
const value = target[prop];
|
|
60
|
+
return value instanceof Function ? value.bind(target) : value;
|
|
60
61
|
}
|
|
61
62
|
function addLifecycleEvent(span, event) {
|
|
62
63
|
const data = eventData$1(event);
|
|
@@ -105,7 +106,7 @@ async function* instrumentedStream(response, span, start, payload) {
|
|
|
105
106
|
finishReason,
|
|
106
107
|
output,
|
|
107
108
|
timeToFirstChunkMs,
|
|
108
|
-
error
|
|
109
|
+
error: error instanceof Error ? error : error === void 0 ? void 0 : /* @__PURE__ */ new Error("error")
|
|
109
110
|
});
|
|
110
111
|
};
|
|
111
112
|
try {
|
|
@@ -138,7 +139,7 @@ async function* instrumentedStream(response, span, start, payload) {
|
|
|
138
139
|
if (payload.signal?.aborted) {
|
|
139
140
|
error = failureError("cancelled", "cancelled");
|
|
140
141
|
finishReason ??= "cancelled";
|
|
141
|
-
} else error = caught;
|
|
142
|
+
} else error = caught instanceof Error ? caught : new Error(String(caught));
|
|
142
143
|
throw caught;
|
|
143
144
|
} finally {
|
|
144
145
|
finish();
|
|
@@ -148,29 +149,29 @@ function wrapSession(session, options) {
|
|
|
148
149
|
return new Proxy(session, { get(target, prop) {
|
|
149
150
|
if (prop === "send") {
|
|
150
151
|
const wrappedSend = async (input) => {
|
|
151
|
-
const
|
|
152
|
+
const turnPayload = input instanceof String || input?.constructor === String ? { message: String(input) } : input;
|
|
152
153
|
const span = startSpan(options.spanName ?? "invoke_agent", {
|
|
153
154
|
type: "agent",
|
|
154
155
|
agentName: options.agentName,
|
|
155
|
-
input: inputForSpan(
|
|
156
|
+
input: inputForSpan(turnPayload)
|
|
156
157
|
});
|
|
157
158
|
const start = performance.now();
|
|
158
159
|
let response;
|
|
159
160
|
try {
|
|
160
161
|
response = await target.send(input);
|
|
161
162
|
} catch (error) {
|
|
162
|
-
if (
|
|
163
|
+
if (turnPayload.signal?.aborted) span.end({
|
|
163
164
|
error: failureError("cancelled", "cancelled"),
|
|
164
165
|
finishReason: "cancelled"
|
|
165
166
|
});
|
|
166
|
-
else span.end({ error });
|
|
167
|
+
else span.end({ error: error instanceof Error ? error : new Error(String(error)) });
|
|
167
168
|
throw error;
|
|
168
169
|
}
|
|
169
170
|
span.span.setAttribute("gen_ai.conversation.id", response.sessionId);
|
|
170
171
|
return new MessageResponse({
|
|
171
172
|
continuationToken: response.continuationToken,
|
|
172
173
|
sessionId: response.sessionId,
|
|
173
|
-
createStream: () => instrumentedStream(response, span, start,
|
|
174
|
+
createStream: () => instrumentedStream(response, span, start, turnPayload)
|
|
174
175
|
});
|
|
175
176
|
};
|
|
176
177
|
return wrappedSend;
|
|
@@ -189,7 +190,7 @@ function wrapEveClient(client, options = {}, overrides) {
|
|
|
189
190
|
//#endregion
|
|
190
191
|
//#region src/hook.ts
|
|
191
192
|
function asRecord(value) {
|
|
192
|
-
if (value === null ||
|
|
193
|
+
if (value === null || Array.isArray(value) || !(value instanceof Object)) return void 0;
|
|
193
194
|
return value;
|
|
194
195
|
}
|
|
195
196
|
function eventData(event) {
|
|
@@ -198,11 +199,11 @@ function eventData(event) {
|
|
|
198
199
|
}
|
|
199
200
|
function stringField(record, key) {
|
|
200
201
|
const value = record?.[key];
|
|
201
|
-
return
|
|
202
|
+
return value?.constructor === String && value.length > 0 ? value : void 0;
|
|
202
203
|
}
|
|
203
204
|
function numberField(record, key) {
|
|
204
205
|
const value = record?.[key];
|
|
205
|
-
return
|
|
206
|
+
return value?.constructor === Number ? value : void 0;
|
|
206
207
|
}
|
|
207
208
|
function jsonField(record, key) {
|
|
208
209
|
const value = record?.[key];
|
|
@@ -340,7 +341,11 @@ function logEvent(event, ctx) {
|
|
|
340
341
|
...attrs,
|
|
341
342
|
"error.code": stringField(childData, "code"),
|
|
342
343
|
"eve.error.details": jsonField(childData, "details")
|
|
343
|
-
},
|
|
344
|
+
}, {
|
|
345
|
+
...child,
|
|
346
|
+
data: childData,
|
|
347
|
+
type: childType
|
|
348
|
+
});
|
|
344
349
|
return;
|
|
345
350
|
}
|
|
346
351
|
if (childType === "turn.failed") {
|
|
@@ -348,14 +353,22 @@ function logEvent(event, ctx) {
|
|
|
348
353
|
...attrs,
|
|
349
354
|
"error.code": stringField(childData, "code"),
|
|
350
355
|
"eve.error.details": jsonField(childData, "details")
|
|
351
|
-
},
|
|
356
|
+
}, {
|
|
357
|
+
...child,
|
|
358
|
+
data: childData,
|
|
359
|
+
type: childType
|
|
360
|
+
});
|
|
352
361
|
return;
|
|
353
362
|
}
|
|
354
363
|
if (childType === "session.failed") emit(event, ctx, "error", `Subagent session failed: ${stringField(childData, "message") ?? ""}`, {
|
|
355
364
|
...attrs,
|
|
356
365
|
"error.code": stringField(childData, "code"),
|
|
357
366
|
"eve.error.details": jsonField(childData, "details")
|
|
358
|
-
},
|
|
367
|
+
}, {
|
|
368
|
+
...child,
|
|
369
|
+
data: childData,
|
|
370
|
+
type: childType
|
|
371
|
+
});
|
|
359
372
|
return;
|
|
360
373
|
}
|
|
361
374
|
case "subagent.called": {
|
|
@@ -415,13 +428,13 @@ function telemetryDevHook(options = {}, overrides) {
|
|
|
415
428
|
ensureInit(options, overrides);
|
|
416
429
|
logEvent(event, ctx);
|
|
417
430
|
} catch (error) {
|
|
418
|
-
reportError$1(options.onError, error);
|
|
431
|
+
reportError$1(options.onError, error instanceof Error ? error : new Error(String(error)));
|
|
419
432
|
}
|
|
420
433
|
} } };
|
|
421
434
|
}
|
|
422
435
|
//#endregion
|
|
423
436
|
//#region src/instrumentation.ts
|
|
424
|
-
const envServiceName = () =>
|
|
437
|
+
const envServiceName = () => globalThis.process !== void 0 ? process.env.OTEL_SERVICE_NAME : void 0;
|
|
425
438
|
function reportError(onError, error) {
|
|
426
439
|
try {
|
|
427
440
|
onError?.(error);
|
|
@@ -439,20 +452,23 @@ function telemetryDevInstrumentation(options = {}, overrides) {
|
|
|
439
452
|
serviceName: sdkOptions.serviceName ?? envServiceName() ?? agentName
|
|
440
453
|
}, overrides);
|
|
441
454
|
} catch (error) {
|
|
442
|
-
reportError(sdkOptions.onError, error);
|
|
455
|
+
reportError(sdkOptions.onError, error instanceof Error ? error : new Error(String(error)));
|
|
443
456
|
}
|
|
444
457
|
},
|
|
445
458
|
events: { "step.started"(input) {
|
|
446
459
|
const ctx = { ...runtimeContext };
|
|
447
460
|
const userId = input.session.auth.initiator?.principalId ?? input.session.auth.current?.principalId;
|
|
448
|
-
|
|
461
|
+
const runtimeContextWithUser = userId ? {
|
|
462
|
+
...ctx,
|
|
463
|
+
"user.id": userId
|
|
464
|
+
} : ctx;
|
|
449
465
|
try {
|
|
450
466
|
const userResult = stepStarted?.(input);
|
|
451
|
-
if (userResult?.runtimeContext) Object.assign(
|
|
467
|
+
if (userResult?.runtimeContext) Object.assign(runtimeContextWithUser, userResult.runtimeContext);
|
|
452
468
|
} catch (error) {
|
|
453
|
-
reportError(sdkOptions.onError, error);
|
|
469
|
+
reportError(sdkOptions.onError, error instanceof Error ? error : new Error(String(error)));
|
|
454
470
|
}
|
|
455
|
-
return Object.keys(
|
|
471
|
+
return Object.keys(runtimeContextWithUser).length > 0 ? { runtimeContext: runtimeContextWithUser } : void 0;
|
|
456
472
|
} }
|
|
457
473
|
};
|
|
458
474
|
if (functionId !== void 0) return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telemetry-dev/eve",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Eve (Vercel agent framework) telemetry integration for telemetry.dev.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@opentelemetry/api": "^1.9.1",
|
|
40
|
-
"@telemetry-dev/sdk": "^0.1.
|
|
40
|
+
"@telemetry-dev/sdk": "^0.1.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@opentelemetry/sdk-logs": "^0.218.0",
|
package/src/client.ts
CHANGED
|
@@ -24,24 +24,33 @@ export interface WrapEveClientOptions extends TelemetryDevEveOptions {
|
|
|
24
24
|
spanName?: string;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
type EventRecord = { [key: string]: EventValue };
|
|
28
|
+
type EventValue =
|
|
29
|
+
| string
|
|
30
|
+
| number
|
|
31
|
+
| boolean
|
|
32
|
+
| null
|
|
33
|
+
| undefined
|
|
34
|
+
| readonly EventValue[]
|
|
35
|
+
| EventRecord;
|
|
36
|
+
function asRecord(value: EventValue): EventRecord | undefined {
|
|
37
|
+
if (value === null || Array.isArray(value) || !(value instanceof Object)) return undefined;
|
|
38
|
+
return value as EventRecord;
|
|
30
39
|
}
|
|
31
40
|
|
|
32
|
-
function stringField(record:
|
|
41
|
+
function stringField(record: EventRecord | undefined, key: string): string | undefined {
|
|
33
42
|
const value = record?.[key];
|
|
34
|
-
return
|
|
43
|
+
return value?.constructor === String && value.length > 0 ? value : undefined;
|
|
35
44
|
}
|
|
36
45
|
|
|
37
|
-
function numberField(record:
|
|
46
|
+
function numberField(record: EventRecord | undefined, key: string): number | undefined {
|
|
38
47
|
const value = record?.[key];
|
|
39
|
-
return
|
|
48
|
+
return value?.constructor === Number ? value : undefined;
|
|
40
49
|
}
|
|
41
50
|
|
|
42
|
-
function eventData(event: HandleMessageStreamEvent):
|
|
51
|
+
function eventData(event: HandleMessageStreamEvent): EventRecord {
|
|
43
52
|
if (!("data" in event)) return {};
|
|
44
|
-
return asRecord(event.data) ?? {};
|
|
53
|
+
return asRecord(event.data as EventValue) ?? {};
|
|
45
54
|
}
|
|
46
55
|
|
|
47
56
|
function eventAttributes(
|
|
@@ -66,13 +75,13 @@ function failureError(code: string | undefined, message: string | undefined): Er
|
|
|
66
75
|
return error;
|
|
67
76
|
}
|
|
68
77
|
|
|
69
|
-
function inputForSpan<TOutput>(payload: SendTurnPayload<TOutput>)
|
|
78
|
+
function inputForSpan<TOutput>(payload: SendTurnPayload<TOutput>) {
|
|
70
79
|
return payload.message ?? payload.inputResponses;
|
|
71
80
|
}
|
|
72
81
|
|
|
73
|
-
function bindOrReturn<T extends object>(target: T, prop: string | symbol)
|
|
74
|
-
const value =
|
|
75
|
-
return
|
|
82
|
+
function bindOrReturn<T extends object>(target: T, prop: string | symbol) {
|
|
83
|
+
const value = target[prop as keyof T];
|
|
84
|
+
return value instanceof Function ? value.bind(target) : value;
|
|
76
85
|
}
|
|
77
86
|
|
|
78
87
|
function addLifecycleEvent(span: SpanHandle, event: HandleMessageStreamEvent): void {
|
|
@@ -141,7 +150,7 @@ async function* instrumentedStream<TOutput>(
|
|
|
141
150
|
finishReason,
|
|
142
151
|
output,
|
|
143
152
|
timeToFirstChunkMs,
|
|
144
|
-
error,
|
|
153
|
+
error: error instanceof Error ? error : error === undefined ? undefined : new Error("error"),
|
|
145
154
|
});
|
|
146
155
|
};
|
|
147
156
|
|
|
@@ -204,7 +213,7 @@ async function* instrumentedStream<TOutput>(
|
|
|
204
213
|
error = failureError("cancelled", "cancelled");
|
|
205
214
|
finishReason ??= "cancelled";
|
|
206
215
|
} else {
|
|
207
|
-
error = caught;
|
|
216
|
+
error = caught instanceof Error ? caught : new Error(String(caught));
|
|
208
217
|
}
|
|
209
218
|
throw caught;
|
|
210
219
|
} finally {
|
|
@@ -219,25 +228,28 @@ function wrapSession(session: ClientSession, options: WrapEveClientOptions): Cli
|
|
|
219
228
|
const wrappedSend: ClientSession["send"] = async <TOutput = unknown>(
|
|
220
229
|
input: SendTurnInput<TOutput>,
|
|
221
230
|
) => {
|
|
222
|
-
const payload
|
|
223
|
-
|
|
231
|
+
const payload =
|
|
232
|
+
input instanceof String || input?.constructor === String
|
|
233
|
+
? { message: String(input) }
|
|
234
|
+
: input;
|
|
235
|
+
const turnPayload = payload as SendTurnPayload<TOutput>;
|
|
224
236
|
const span = startSpan(options.spanName ?? "invoke_agent", {
|
|
225
237
|
type: "agent",
|
|
226
238
|
agentName: options.agentName,
|
|
227
|
-
input: inputForSpan(
|
|
239
|
+
input: inputForSpan(turnPayload),
|
|
228
240
|
});
|
|
229
241
|
const start = performance.now();
|
|
230
242
|
let response: MessageResponse<TOutput>;
|
|
231
243
|
try {
|
|
232
244
|
response = await target.send(input);
|
|
233
245
|
} catch (error) {
|
|
234
|
-
if (
|
|
246
|
+
if (turnPayload.signal?.aborted) {
|
|
235
247
|
span.end({
|
|
236
248
|
error: failureError("cancelled", "cancelled"),
|
|
237
249
|
finishReason: "cancelled",
|
|
238
250
|
});
|
|
239
251
|
} else {
|
|
240
|
-
span.end({ error });
|
|
252
|
+
span.end({ error: error instanceof Error ? error : new Error(String(error)) });
|
|
241
253
|
}
|
|
242
254
|
throw error;
|
|
243
255
|
}
|
|
@@ -248,7 +260,7 @@ function wrapSession(session: ClientSession, options: WrapEveClientOptions): Cli
|
|
|
248
260
|
return new MessageResponse<TOutput>({
|
|
249
261
|
continuationToken: response.continuationToken,
|
|
250
262
|
sessionId: response.sessionId,
|
|
251
|
-
createStream: () => instrumentedStream(response, span, start,
|
|
263
|
+
createStream: () => instrumentedStream(response, span, start, turnPayload),
|
|
252
264
|
});
|
|
253
265
|
};
|
|
254
266
|
return wrappedSend;
|
|
@@ -265,7 +277,6 @@ export function wrapEveClient<C extends Client>(
|
|
|
265
277
|
): C {
|
|
266
278
|
const { agentName: _agentName, spanName: _spanName, ...sdkOptions } = options;
|
|
267
279
|
ensureInit(sdkOptions, overrides);
|
|
268
|
-
|
|
269
280
|
return new Proxy(client, {
|
|
270
281
|
get(target, prop) {
|
|
271
282
|
if (prop === "session") {
|
package/src/config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { init, shutdown, type ClientOverrides, type TelemetryOptions } from "@telemetry-dev/sdk";
|
|
2
2
|
|
|
3
3
|
/** Options accepted by every @telemetry-dev/eve entry point. */
|
|
4
|
-
export type TelemetryDevEveOptions = Omit<TelemetryOptions, "registerGlobal">;
|
|
4
|
+
export type TelemetryDevEveOptions = Omit<TelemetryOptions, "registerGlobal" | "sdkName">;
|
|
5
5
|
|
|
6
6
|
export type { ClientOverrides };
|
|
7
7
|
|
|
@@ -23,6 +23,7 @@ export function ensureInit(
|
|
|
23
23
|
init(
|
|
24
24
|
{
|
|
25
25
|
...options,
|
|
26
|
+
sdkName: "@telemetry-dev/eve",
|
|
26
27
|
registerGlobal: true,
|
|
27
28
|
spanFilter: options.spanFilter ?? ((span) => span.instrumentationScope.name !== "workflow"),
|
|
28
29
|
},
|
package/src/hook.ts
CHANGED
|
@@ -4,29 +4,30 @@ import type { HookContext, HookDefinition } from "eve/hooks";
|
|
|
4
4
|
|
|
5
5
|
import { ensureInit, type ClientOverrides, type TelemetryDevEveOptions } from "./config.ts";
|
|
6
6
|
|
|
7
|
-
type Attrs =
|
|
7
|
+
type Attrs = { [key: string]: Value };
|
|
8
|
+
type Value = string | number | boolean | null | undefined | readonly Value[] | Attrs;
|
|
8
9
|
|
|
9
|
-
function asRecord(value:
|
|
10
|
-
if (value === null ||
|
|
11
|
-
return value as
|
|
10
|
+
function asRecord(value: Value): Attrs | undefined {
|
|
11
|
+
if (value === null || Array.isArray(value) || !(value instanceof Object)) return undefined;
|
|
12
|
+
return value as Attrs;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
function eventData(event: HandleMessageStreamEvent):
|
|
15
|
+
function eventData(event: HandleMessageStreamEvent): Attrs {
|
|
15
16
|
if (!("data" in event)) return {};
|
|
16
|
-
return asRecord(event.data) ?? {};
|
|
17
|
+
return asRecord(event.data as Value) ?? {};
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
function stringField(record:
|
|
20
|
+
function stringField(record: Attrs | undefined, key: string): string | undefined {
|
|
20
21
|
const value = record?.[key];
|
|
21
|
-
return
|
|
22
|
+
return value?.constructor === String && value.length > 0 ? value : undefined;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
function numberField(record:
|
|
25
|
+
function numberField(record: Attrs | undefined, key: string): number | undefined {
|
|
25
26
|
const value = record?.[key];
|
|
26
|
-
return
|
|
27
|
+
return value?.constructor === Number ? value : undefined;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
function jsonField(record:
|
|
30
|
+
function jsonField(record: Attrs | undefined, key: string): string | undefined {
|
|
30
31
|
const value = record?.[key];
|
|
31
32
|
if (value === undefined) return undefined;
|
|
32
33
|
try {
|
|
@@ -36,7 +37,7 @@ function jsonField(record: Record<string, unknown> | undefined, key: string): st
|
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
function baseAttributes(event: HandleMessageStreamEvent, ctx: HookContext)
|
|
40
|
+
function baseAttributes(event: HandleMessageStreamEvent, ctx: HookContext) {
|
|
40
41
|
const data = eventData(event);
|
|
41
42
|
return {
|
|
42
43
|
"gen_ai.conversation.id": ctx.session.id,
|
|
@@ -48,7 +49,7 @@ function baseAttributes(event: HandleMessageStreamEvent, ctx: HookContext): Attr
|
|
|
48
49
|
};
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
function toolAttrs(result:
|
|
52
|
+
function toolAttrs(result: Value) {
|
|
52
53
|
const record = asRecord(result);
|
|
53
54
|
const subagentName = stringField(record, "subagentName");
|
|
54
55
|
return {
|
|
@@ -59,7 +60,7 @@ function toolAttrs(result: unknown): Attrs {
|
|
|
59
60
|
"eve.subagent.name": subagentName,
|
|
60
61
|
};
|
|
61
62
|
}
|
|
62
|
-
function reportError(onError: ((error:
|
|
63
|
+
function reportError(onError: ((error: Error) => void) | undefined, error: Error): void {
|
|
63
64
|
try {
|
|
64
65
|
onError?.(error);
|
|
65
66
|
} catch {
|
|
@@ -84,7 +85,7 @@ function emit(
|
|
|
84
85
|
});
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
function stepCompletedMessage(data:
|
|
88
|
+
function stepCompletedMessage(data: Attrs): string {
|
|
88
89
|
const finishReason = stringField(data, "finishReason") ?? "unknown";
|
|
89
90
|
const usage = asRecord(data.usage);
|
|
90
91
|
const inputTokens = numberField(usage, "inputTokens");
|
|
@@ -186,7 +187,7 @@ function logEvent(event: HandleMessageStreamEvent, ctx: HookContext): void {
|
|
|
186
187
|
});
|
|
187
188
|
return;
|
|
188
189
|
case "subagent.event": {
|
|
189
|
-
const child = asRecord(data.event);
|
|
190
|
+
const child = asRecord(data.event as Value);
|
|
190
191
|
const childData = asRecord(child?.data);
|
|
191
192
|
const childType = stringField(child, "type");
|
|
192
193
|
const attrs = {
|
|
@@ -204,7 +205,11 @@ function logEvent(event: HandleMessageStreamEvent, ctx: HookContext): void {
|
|
|
204
205
|
"error.code": stringField(childData, "code"),
|
|
205
206
|
"eve.error.details": jsonField(childData, "details"),
|
|
206
207
|
},
|
|
207
|
-
|
|
208
|
+
{
|
|
209
|
+
...child,
|
|
210
|
+
data: childData,
|
|
211
|
+
type: childType,
|
|
212
|
+
} as HandleMessageStreamEvent,
|
|
208
213
|
);
|
|
209
214
|
return;
|
|
210
215
|
}
|
|
@@ -219,7 +224,11 @@ function logEvent(event: HandleMessageStreamEvent, ctx: HookContext): void {
|
|
|
219
224
|
"error.code": stringField(childData, "code"),
|
|
220
225
|
"eve.error.details": jsonField(childData, "details"),
|
|
221
226
|
},
|
|
222
|
-
|
|
227
|
+
{
|
|
228
|
+
...child,
|
|
229
|
+
data: childData,
|
|
230
|
+
type: childType,
|
|
231
|
+
} as HandleMessageStreamEvent,
|
|
223
232
|
);
|
|
224
233
|
return;
|
|
225
234
|
}
|
|
@@ -234,7 +243,11 @@ function logEvent(event: HandleMessageStreamEvent, ctx: HookContext): void {
|
|
|
234
243
|
"error.code": stringField(childData, "code"),
|
|
235
244
|
"eve.error.details": jsonField(childData, "details"),
|
|
236
245
|
},
|
|
237
|
-
|
|
246
|
+
{
|
|
247
|
+
...child,
|
|
248
|
+
data: childData,
|
|
249
|
+
type: childType,
|
|
250
|
+
} as HandleMessageStreamEvent,
|
|
238
251
|
);
|
|
239
252
|
}
|
|
240
253
|
return;
|
|
@@ -305,7 +318,7 @@ export function telemetryDevHook(
|
|
|
305
318
|
ensureInit(options, overrides);
|
|
306
319
|
logEvent(event, ctx);
|
|
307
320
|
} catch (error) {
|
|
308
|
-
reportError(options.onError, error);
|
|
321
|
+
reportError(options.onError, error instanceof Error ? error : new Error(String(error)));
|
|
309
322
|
}
|
|
310
323
|
},
|
|
311
324
|
},
|
package/src/instrumentation.ts
CHANGED
|
@@ -20,8 +20,8 @@ export interface TelemetryDevInstrumentationOptions extends TelemetryDevEveOptio
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const envServiceName = (): string | undefined =>
|
|
23
|
-
|
|
24
|
-
function reportError(onError: ((error:
|
|
23
|
+
globalThis.process !== undefined ? process.env.OTEL_SERVICE_NAME : undefined;
|
|
24
|
+
function reportError(onError: ((error: Error) => void) | undefined, error: Error): void {
|
|
25
25
|
try {
|
|
26
26
|
onError?.(error);
|
|
27
27
|
} catch {
|
|
@@ -49,27 +49,30 @@ export function telemetryDevInstrumentation(
|
|
|
49
49
|
overrides,
|
|
50
50
|
);
|
|
51
51
|
} catch (error) {
|
|
52
|
-
reportError(sdkOptions.onError, error);
|
|
52
|
+
reportError(sdkOptions.onError, error instanceof Error ? error : new Error(String(error)));
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
events: {
|
|
56
56
|
"step.started"(input) {
|
|
57
|
-
const ctx
|
|
57
|
+
const ctx = { ...runtimeContext } satisfies InstrumentationRuntimeContext;
|
|
58
58
|
const userId =
|
|
59
59
|
input.session.auth.initiator?.principalId ?? input.session.auth.current?.principalId;
|
|
60
|
-
|
|
60
|
+
const runtimeContextWithUser = userId ? { ...ctx, "user.id": userId } : ctx;
|
|
61
61
|
|
|
62
62
|
try {
|
|
63
63
|
const userResult = stepStarted?.(input);
|
|
64
64
|
if (userResult?.runtimeContext) {
|
|
65
|
-
Object.assign(
|
|
65
|
+
Object.assign(runtimeContextWithUser, userResult.runtimeContext);
|
|
66
66
|
}
|
|
67
67
|
} catch (error) {
|
|
68
|
-
reportError(
|
|
68
|
+
reportError(
|
|
69
|
+
sdkOptions.onError,
|
|
70
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
71
|
+
);
|
|
69
72
|
}
|
|
70
73
|
|
|
71
|
-
return Object.keys(
|
|
72
|
-
? { runtimeContext:
|
|
74
|
+
return Object.keys(runtimeContextWithUser).length > 0
|
|
75
|
+
? { runtimeContext: runtimeContextWithUser }
|
|
73
76
|
: undefined;
|
|
74
77
|
},
|
|
75
78
|
},
|