@uselemma/tracing 3.0.3 → 4.0.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 +189 -45
- package/dist/client.d.ts +237 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +660 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +3 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -17
- package/dist/index.js.map +1 -1
- package/dist/vercel-ai.d.ts +117 -0
- package/dist/vercel-ai.d.ts.map +1 -0
- package/dist/vercel-ai.js +230 -0
- package/dist/vercel-ai.js.map +1 -0
- package/examples/callback-tracing.ts +55 -0
- package/examples/record-by-id.ts +47 -0
- package/examples/trace-handles.ts +59 -0
- package/examples/vercel-ai-v6.ts +27 -0
- package/examples/vercel-ai-v7.ts +27 -0
- package/package.json +5 -13
- package/dist/register.d.ts +0 -61
- package/dist/register.d.ts.map +0 -1
- package/dist/register.js +0 -76
- package/dist/register.js.map +0 -1
- package/dist/run-batch-span-processor.d.ts +0 -25
- package/dist/run-batch-span-processor.d.ts.map +0 -1
- package/dist/run-batch-span-processor.js +0 -139
- package/dist/run-batch-span-processor.js.map +0 -1
- package/dist/span-helpers.d.ts +0 -55
- package/dist/span-helpers.d.ts.map +0 -1
- package/dist/span-helpers.js +0 -103
- package/dist/span-helpers.js.map +0 -1
- package/dist/trace-wrapper.d.ts +0 -107
- package/dist/trace-wrapper.d.ts.map +0 -1
- package/dist/trace-wrapper.js +0 -133
- package/dist/trace-wrapper.js.map +0 -1
package/dist/trace-wrapper.d.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { Span } from "@opentelemetry/api";
|
|
2
|
-
export type TraceContext = {
|
|
3
|
-
/** The active OpenTelemetry span for this agent run. */
|
|
4
|
-
span: Span;
|
|
5
|
-
/** Unique identifier for this agent run. */
|
|
6
|
-
runId: string;
|
|
7
|
-
/**
|
|
8
|
-
* Override the run output and close the span immediately.
|
|
9
|
-
*
|
|
10
|
-
* In non-streaming agents, `complete()` is **optional** — the wrapper
|
|
11
|
-
* automatically captures the return value as `ai.agent.output` and closes
|
|
12
|
-
* the span when the function returns. Call it explicitly only when you need
|
|
13
|
-
* to record a different output than the return value, or close the span
|
|
14
|
-
* before the function exits.
|
|
15
|
-
*
|
|
16
|
-
* In streaming agents (`{ streaming: true }`), `complete()` is **required**
|
|
17
|
-
* — call it inside the stream's `onFinish` callback once the full output is
|
|
18
|
-
* assembled.
|
|
19
|
-
*
|
|
20
|
-
* Idempotent: the first call wins, subsequent calls are no-ops.
|
|
21
|
-
*/
|
|
22
|
-
complete: (result?: unknown) => void;
|
|
23
|
-
/**
|
|
24
|
-
* @deprecated Use {@link complete} instead.
|
|
25
|
-
*/
|
|
26
|
-
onComplete: (result: unknown) => void;
|
|
27
|
-
/**
|
|
28
|
-
* Record an error on the span and mark the run as failed.
|
|
29
|
-
* Does not close the span — the wrapper handles closing on return or error.
|
|
30
|
-
*/
|
|
31
|
-
fail: (error: unknown) => void;
|
|
32
|
-
/**
|
|
33
|
-
* @deprecated Use {@link fail} instead.
|
|
34
|
-
*/
|
|
35
|
-
recordError: (error: unknown) => void;
|
|
36
|
-
};
|
|
37
|
-
export type WrapAgentOptions = {
|
|
38
|
-
/** Mark this run as an experiment in Lemma. */
|
|
39
|
-
isExperiment?: boolean;
|
|
40
|
-
/**
|
|
41
|
-
* Set to `true` for agents that return a streaming response before the
|
|
42
|
-
* full output is known.
|
|
43
|
-
*
|
|
44
|
-
* When `true`, the wrapper does **not** auto-close the span on function
|
|
45
|
-
* return. You must call `ctx.complete(output)` inside the stream's
|
|
46
|
-
* `onFinish` callback once the full output is assembled.
|
|
47
|
-
*
|
|
48
|
-
* @default false
|
|
49
|
-
*/
|
|
50
|
-
streaming?: boolean;
|
|
51
|
-
};
|
|
52
|
-
export type WrapRunOptions = {
|
|
53
|
-
/** Optional thread identifier for this invocation. */
|
|
54
|
-
threadId?: string;
|
|
55
|
-
/** Mark this specific invocation as an experiment. */
|
|
56
|
-
isExperiment?: boolean;
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Wraps an agent function with OpenTelemetry tracing, automatically creating
|
|
60
|
-
* a span for the agent run and providing a `TraceContext` to the wrapped function.
|
|
61
|
-
*
|
|
62
|
-
* **Non-streaming (default):** simply return a value from the wrapped function.
|
|
63
|
-
* The wrapper captures it as `ai.agent.output` and closes the span automatically.
|
|
64
|
-
* No call to `ctx.complete()` is needed.
|
|
65
|
-
*
|
|
66
|
-
* **Streaming:** pass `{ streaming: true }` as the third argument. The wrapper
|
|
67
|
-
* will not auto-close the span on return; call `ctx.complete(output)` inside
|
|
68
|
-
* the stream's `onFinish` callback once the full output is assembled.
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* // Non-streaming — just return a value
|
|
72
|
-
* const myAgent = agent('my-agent', async (input: string) => {
|
|
73
|
-
* const { text } = await generateText({
|
|
74
|
-
* model: openai('gpt-4o'), prompt: input,
|
|
75
|
-
* experimental_telemetry: { isEnabled: true },
|
|
76
|
-
* });
|
|
77
|
-
* return text; // wrapper auto-captures and closes the span
|
|
78
|
-
* });
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* // Streaming — opt into manual lifecycle
|
|
82
|
-
* const streamingAgent = agent('streaming-agent', async (input: string, ctx) => {
|
|
83
|
-
* const result = await streamText({
|
|
84
|
-
* model: openai('gpt-4o'), prompt: input,
|
|
85
|
-
* experimental_telemetry: { isEnabled: true },
|
|
86
|
-
* onFinish({ text }) { ctx.complete(text); },
|
|
87
|
-
* });
|
|
88
|
-
* return result.toDataStreamResponse();
|
|
89
|
-
* }, { streaming: true });
|
|
90
|
-
*
|
|
91
|
-
* @param agentName - Human-readable agent name recorded as `ai.agent.name`.
|
|
92
|
-
* @param fn - The agent function to wrap. Receives the call-time input as its
|
|
93
|
-
* first argument and an optional {@link TraceContext} as its second.
|
|
94
|
-
* @param options - Configuration for the agent trace.
|
|
95
|
-
* @returns An async function that accepts an `input`, executes `fn` inside a
|
|
96
|
-
* traced context, and returns `{ result, runId, span }`.
|
|
97
|
-
*/
|
|
98
|
-
export declare function agent<Input = unknown>(agentName: string, fn: (input: Input, traceContext: TraceContext) => any, options?: WrapAgentOptions): (this: any, input: Input, runOptions?: WrapRunOptions) => Promise<{
|
|
99
|
-
result: any;
|
|
100
|
-
runId: string;
|
|
101
|
-
span: Span;
|
|
102
|
-
}>;
|
|
103
|
-
/**
|
|
104
|
-
* @deprecated Use {@link agent} instead. `wrapAgent` will be removed in a future major version.
|
|
105
|
-
*/
|
|
106
|
-
export declare const wrapAgent: typeof agent;
|
|
107
|
-
//# sourceMappingURL=trace-wrapper.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trace-wrapper.d.ts","sourceRoot":"","sources":["../src/trace-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAKxE,MAAM,MAAM,YAAY,GAAG;IACzB,wDAAwD;IACxD,IAAI,EAAE,IAAI,CAAC;IACX,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;OAcG;IACH,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC;;OAEG;IACH,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC;;;OAGG;IACH,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/B;;OAEG;IACH,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,+CAA+C;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAkBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,KAAK,CAAC,KAAK,GAAG,OAAO,EACnC,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,KAAK,GAAG,EACrD,OAAO,CAAC,EAAE,gBAAgB,UAKlB,GAAG,SACF,KAAK,eACC,cAAc;;;;GAmF9B;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,cAAQ,CAAC"}
|
package/dist/trace-wrapper.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.wrapAgent = void 0;
|
|
4
|
-
exports.agent = agent;
|
|
5
|
-
const api_1 = require("@opentelemetry/api");
|
|
6
|
-
const uuid_1 = require("uuid");
|
|
7
|
-
const debug_mode_1 = require("./debug-mode");
|
|
8
|
-
const experiment_mode_1 = require("./experiment-mode");
|
|
9
|
-
function resolveIsExperiment(globalEnabled, wrapperOptions, runOptions) {
|
|
10
|
-
if (globalEnabled)
|
|
11
|
-
return true;
|
|
12
|
-
if (typeof runOptions?.isExperiment === "boolean")
|
|
13
|
-
return runOptions.isExperiment;
|
|
14
|
-
return wrapperOptions?.isExperiment === true;
|
|
15
|
-
}
|
|
16
|
-
function normalizeThreadId(threadId) {
|
|
17
|
-
if (typeof threadId !== "string")
|
|
18
|
-
return undefined;
|
|
19
|
-
const trimmed = threadId.trim();
|
|
20
|
-
return trimmed.length > 0 ? trimmed : undefined;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Wraps an agent function with OpenTelemetry tracing, automatically creating
|
|
24
|
-
* a span for the agent run and providing a `TraceContext` to the wrapped function.
|
|
25
|
-
*
|
|
26
|
-
* **Non-streaming (default):** simply return a value from the wrapped function.
|
|
27
|
-
* The wrapper captures it as `ai.agent.output` and closes the span automatically.
|
|
28
|
-
* No call to `ctx.complete()` is needed.
|
|
29
|
-
*
|
|
30
|
-
* **Streaming:** pass `{ streaming: true }` as the third argument. The wrapper
|
|
31
|
-
* will not auto-close the span on return; call `ctx.complete(output)` inside
|
|
32
|
-
* the stream's `onFinish` callback once the full output is assembled.
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* // Non-streaming — just return a value
|
|
36
|
-
* const myAgent = agent('my-agent', async (input: string) => {
|
|
37
|
-
* const { text } = await generateText({
|
|
38
|
-
* model: openai('gpt-4o'), prompt: input,
|
|
39
|
-
* experimental_telemetry: { isEnabled: true },
|
|
40
|
-
* });
|
|
41
|
-
* return text; // wrapper auto-captures and closes the span
|
|
42
|
-
* });
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* // Streaming — opt into manual lifecycle
|
|
46
|
-
* const streamingAgent = agent('streaming-agent', async (input: string, ctx) => {
|
|
47
|
-
* const result = await streamText({
|
|
48
|
-
* model: openai('gpt-4o'), prompt: input,
|
|
49
|
-
* experimental_telemetry: { isEnabled: true },
|
|
50
|
-
* onFinish({ text }) { ctx.complete(text); },
|
|
51
|
-
* });
|
|
52
|
-
* return result.toDataStreamResponse();
|
|
53
|
-
* }, { streaming: true });
|
|
54
|
-
*
|
|
55
|
-
* @param agentName - Human-readable agent name recorded as `ai.agent.name`.
|
|
56
|
-
* @param fn - The agent function to wrap. Receives the call-time input as its
|
|
57
|
-
* first argument and an optional {@link TraceContext} as its second.
|
|
58
|
-
* @param options - Configuration for the agent trace.
|
|
59
|
-
* @returns An async function that accepts an `input`, executes `fn` inside a
|
|
60
|
-
* traced context, and returns `{ result, runId, span }`.
|
|
61
|
-
*/
|
|
62
|
-
function agent(agentName, fn, options) {
|
|
63
|
-
const streaming = options?.streaming ?? false;
|
|
64
|
-
const wrappedFunction = async function (input, runOptions) {
|
|
65
|
-
const tracer = api_1.trace.getTracer("lemma");
|
|
66
|
-
const runId = (0, uuid_1.v4)();
|
|
67
|
-
const isExperiment = resolveIsExperiment((0, experiment_mode_1.isExperimentModeEnabled)(), options, runOptions);
|
|
68
|
-
const threadId = normalizeThreadId(runOptions?.threadId);
|
|
69
|
-
const attributes = {
|
|
70
|
-
"ai.agent.name": agentName,
|
|
71
|
-
"lemma.run_id": runId,
|
|
72
|
-
"lemma.is_experiment": isExperiment,
|
|
73
|
-
};
|
|
74
|
-
if (threadId) {
|
|
75
|
-
attributes["lemma.thread_id"] = threadId;
|
|
76
|
-
}
|
|
77
|
-
const span = tracer.startSpan("ai.agent.run", { attributes }, api_1.ROOT_CONTEXT);
|
|
78
|
-
span.setAttribute("ai.agent.input", JSON.stringify(input) ?? "null");
|
|
79
|
-
(0, debug_mode_1.lemmaDebug)("trace-wrapper", "span started", { agentName, runId });
|
|
80
|
-
const ctx = api_1.trace.setSpan(api_1.ROOT_CONTEXT, span);
|
|
81
|
-
let outputSet = false;
|
|
82
|
-
try {
|
|
83
|
-
return await api_1.context.with(ctx, async () => {
|
|
84
|
-
const complete = (result) => {
|
|
85
|
-
if (outputSet)
|
|
86
|
-
return;
|
|
87
|
-
span.setAttribute("ai.agent.output", JSON.stringify(result) ?? "null");
|
|
88
|
-
outputSet = true;
|
|
89
|
-
span.end();
|
|
90
|
-
(0, debug_mode_1.lemmaDebug)("trace-wrapper", "complete called", { runId });
|
|
91
|
-
};
|
|
92
|
-
const fail = (error) => {
|
|
93
|
-
span.recordException(error instanceof Error ? error : new Error(String(error)));
|
|
94
|
-
span.setStatus({ code: 2 }); // SpanStatusCode.ERROR
|
|
95
|
-
};
|
|
96
|
-
const traceCtx = {
|
|
97
|
-
span,
|
|
98
|
-
runId,
|
|
99
|
-
complete,
|
|
100
|
-
onComplete: complete,
|
|
101
|
-
fail,
|
|
102
|
-
recordError: fail,
|
|
103
|
-
};
|
|
104
|
-
const result = await fn.call(this, input, traceCtx);
|
|
105
|
-
if (!streaming && !outputSet) {
|
|
106
|
-
complete(result);
|
|
107
|
-
}
|
|
108
|
-
else if (streaming && !outputSet) {
|
|
109
|
-
(0, debug_mode_1.lemmaDebug)("trace-wrapper", "streaming agent returned without complete()", { agentName, runId });
|
|
110
|
-
console.warn(`[lemma] Streaming agent "${agentName}" returned without calling ctx.complete(). ` +
|
|
111
|
-
`Call ctx.complete(output) inside the stream's onFinish callback to close the run span.`);
|
|
112
|
-
}
|
|
113
|
-
return { result, runId, span };
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
catch (err) {
|
|
117
|
-
span.recordException(err);
|
|
118
|
-
span.setStatus({ code: 2 }); // SpanStatusCode.ERROR
|
|
119
|
-
if (!outputSet) {
|
|
120
|
-
outputSet = true;
|
|
121
|
-
span.end();
|
|
122
|
-
}
|
|
123
|
-
(0, debug_mode_1.lemmaDebug)("trace-wrapper", "span ended on error", { runId, error: String(err) });
|
|
124
|
-
throw err;
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
return wrappedFunction;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* @deprecated Use {@link agent} instead. `wrapAgent` will be removed in a future major version.
|
|
131
|
-
*/
|
|
132
|
-
exports.wrapAgent = agent;
|
|
133
|
-
//# sourceMappingURL=trace-wrapper.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trace-wrapper.js","sourceRoot":"","sources":["../src/trace-wrapper.ts"],"names":[],"mappings":"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"}
|