@respan/instrumentation-vercel 1.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/dist/_translator.d.ts +39 -0
- package/dist/_translator.js +706 -0
- package/dist/_translator.js.map +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.js +2 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/constants/logs.d.ts +17 -0
- package/dist/constants/logs.js +45 -0
- package/dist/constants/logs.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate Vercel AI SDK spans → Traceloop/OpenLLMetry format.
|
|
3
|
+
*
|
|
4
|
+
* The Vercel AI SDK emits OTEL spans with its own attribute schema (ai.model.id,
|
|
5
|
+
* ai.prompt.messages, ai.response.text, etc.). This SpanProcessor enriches those
|
|
6
|
+
* spans with the Traceloop/GenAI semantic conventions the Respan backend expects.
|
|
7
|
+
*
|
|
8
|
+
* Two-phase enrichment:
|
|
9
|
+
* - onStart(): Sets RESPAN_LOG_TYPE so the span passes CompositeProcessor filtering
|
|
10
|
+
* - onEnd(): Full attribute translation (model, messages, tokens, metadata, etc.)
|
|
11
|
+
*
|
|
12
|
+
* Vercel attrs are preserved (additive enrichment via setDefault, not destructive).
|
|
13
|
+
*
|
|
14
|
+
* Ported from @respan/exporter-vercel — all exporter features are replicated:
|
|
15
|
+
* - Model normalization (Gemini, Claude, DeepSeek, O3-mini)
|
|
16
|
+
* - Prompt message parsing (ai.prompt.messages + ai.prompt fallback)
|
|
17
|
+
* - Completion message building (ai.response.text, ai.response.object, tool calls)
|
|
18
|
+
* - Token count normalization (input/output → prompt/completion)
|
|
19
|
+
* - Tool definitions (ai.prompt.tools) and tool choice (gen_ai.usage.tool_choice)
|
|
20
|
+
* - Customer params (ai.telemetry.metadata.customer_* + customer_params JSON)
|
|
21
|
+
* - General metadata (ai.telemetry.metadata.* → respan.metadata.*)
|
|
22
|
+
* - Stream detection, environment, cost, TTFT, generation time, unit prices
|
|
23
|
+
* - Log type detection with operationId + attribute-based fallbacks
|
|
24
|
+
*/
|
|
25
|
+
import type { Context } from "@opentelemetry/api";
|
|
26
|
+
import type { SpanProcessor, ReadableSpan, Span } from "@opentelemetry/sdk-trace-base";
|
|
27
|
+
/**
|
|
28
|
+
* SpanProcessor that translates Vercel AI SDK attributes to Traceloop/OpenLLMetry.
|
|
29
|
+
*
|
|
30
|
+
* Phase 1 (onStart): Sets RESPAN_LOG_TYPE so CompositeProcessor lets the span through.
|
|
31
|
+
* Phase 2 (onEnd): Full attribute enrichment — model, messages, tokens, metadata,
|
|
32
|
+
* tools, performance metrics, environment, etc.
|
|
33
|
+
*/
|
|
34
|
+
export declare class VercelAITranslator implements SpanProcessor {
|
|
35
|
+
onStart(span: Span, _parentContext: Context): void;
|
|
36
|
+
onEnd(span: ReadableSpan): void;
|
|
37
|
+
shutdown(): Promise<void>;
|
|
38
|
+
forceFlush(): Promise<void>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate Vercel AI SDK spans → Traceloop/OpenLLMetry format.
|
|
3
|
+
*
|
|
4
|
+
* The Vercel AI SDK emits OTEL spans with its own attribute schema (ai.model.id,
|
|
5
|
+
* ai.prompt.messages, ai.response.text, etc.). This SpanProcessor enriches those
|
|
6
|
+
* spans with the Traceloop/GenAI semantic conventions the Respan backend expects.
|
|
7
|
+
*
|
|
8
|
+
* Two-phase enrichment:
|
|
9
|
+
* - onStart(): Sets RESPAN_LOG_TYPE so the span passes CompositeProcessor filtering
|
|
10
|
+
* - onEnd(): Full attribute translation (model, messages, tokens, metadata, etc.)
|
|
11
|
+
*
|
|
12
|
+
* Vercel attrs are preserved (additive enrichment via setDefault, not destructive).
|
|
13
|
+
*
|
|
14
|
+
* Ported from @respan/exporter-vercel — all exporter features are replicated:
|
|
15
|
+
* - Model normalization (Gemini, Claude, DeepSeek, O3-mini)
|
|
16
|
+
* - Prompt message parsing (ai.prompt.messages + ai.prompt fallback)
|
|
17
|
+
* - Completion message building (ai.response.text, ai.response.object, tool calls)
|
|
18
|
+
* - Token count normalization (input/output → prompt/completion)
|
|
19
|
+
* - Tool definitions (ai.prompt.tools) and tool choice (gen_ai.usage.tool_choice)
|
|
20
|
+
* - Customer params (ai.telemetry.metadata.customer_* + customer_params JSON)
|
|
21
|
+
* - General metadata (ai.telemetry.metadata.* → respan.metadata.*)
|
|
22
|
+
* - Stream detection, environment, cost, TTFT, generation time, unit prices
|
|
23
|
+
* - Log type detection with operationId + attribute-based fallbacks
|
|
24
|
+
*/
|
|
25
|
+
import { RespanSpanAttributes, RespanLogType } from "@respan/respan-sdk";
|
|
26
|
+
import { VERCEL_SPAN_CONFIG, VERCEL_PARENT_SPANS } from "./constants/index.js";
|
|
27
|
+
// ── Attribute keys (single source of truth from SDK) ─────────────────────────
|
|
28
|
+
const RESPAN_LOG_TYPE = RespanSpanAttributes.RESPAN_LOG_TYPE;
|
|
29
|
+
const GEN_AI_REQUEST_MODEL = RespanSpanAttributes.GEN_AI_REQUEST_MODEL;
|
|
30
|
+
const GEN_AI_USAGE_PROMPT_TOKENS = RespanSpanAttributes.GEN_AI_USAGE_PROMPT_TOKENS;
|
|
31
|
+
const GEN_AI_USAGE_COMPLETION_TOKENS = RespanSpanAttributes.GEN_AI_USAGE_COMPLETION_TOKENS;
|
|
32
|
+
const LLM_REQUEST_TYPE = RespanSpanAttributes.LLM_REQUEST_TYPE;
|
|
33
|
+
const CUSTOMER_ID = RespanSpanAttributes.RESPAN_CUSTOMER_PARAMS_ID;
|
|
34
|
+
const CUSTOMER_EMAIL = RespanSpanAttributes.RESPAN_CUSTOMER_PARAMS_EMAIL;
|
|
35
|
+
const CUSTOMER_NAME = RespanSpanAttributes.RESPAN_CUSTOMER_PARAMS_NAME;
|
|
36
|
+
const THREAD_ID = RespanSpanAttributes.RESPAN_THREADS_ID;
|
|
37
|
+
const TRACE_GROUP_ID = RespanSpanAttributes.RESPAN_TRACE_GROUP_ID;
|
|
38
|
+
const RESPAN_SPAN_TOOLS = RespanSpanAttributes.RESPAN_SPAN_TOOLS;
|
|
39
|
+
const RESPAN_METADATA_AGENT_NAME = RespanSpanAttributes.RESPAN_METADATA_AGENT_NAME;
|
|
40
|
+
const RESPAN_METADATA_PREFIX = RespanSpanAttributes.RESPAN_METADATA; // "respan.metadata"
|
|
41
|
+
/** Build a respan.metadata.<key> attribute name. */
|
|
42
|
+
function metadataKey(key) {
|
|
43
|
+
return `${RESPAN_METADATA_PREFIX}.${key}`;
|
|
44
|
+
}
|
|
45
|
+
// Traceloop wire-format keys
|
|
46
|
+
const TL_SPAN_KIND = "traceloop.span.kind";
|
|
47
|
+
const TL_ENTITY_NAME = "traceloop.entity.name";
|
|
48
|
+
const TL_ENTITY_INPUT = "traceloop.entity.input";
|
|
49
|
+
const TL_ENTITY_OUTPUT = "traceloop.entity.output";
|
|
50
|
+
const TL_ENTITY_PATH = "traceloop.entity.path";
|
|
51
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
52
|
+
function setDefault(attrs, key, value) {
|
|
53
|
+
if (attrs[key] === undefined && value !== undefined && value !== null) {
|
|
54
|
+
attrs[key] = value;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function safeJsonStr(value) {
|
|
58
|
+
if (value === undefined || value === null)
|
|
59
|
+
return "";
|
|
60
|
+
if (typeof value === "string")
|
|
61
|
+
return value;
|
|
62
|
+
try {
|
|
63
|
+
return JSON.stringify(value);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return String(value);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function safeJsonParse(value) {
|
|
70
|
+
if (typeof value !== "string")
|
|
71
|
+
return value;
|
|
72
|
+
try {
|
|
73
|
+
return JSON.parse(value);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Detect whether a span is from the Vercel AI SDK.
|
|
81
|
+
*
|
|
82
|
+
* Primary check: instrumentation scope name === "ai" (set by the Vercel AI SDK).
|
|
83
|
+
* Fallback: ai.sdk attribute or ai.* span name.
|
|
84
|
+
*
|
|
85
|
+
* Does NOT match on gen_ai.* attributes alone — those may come from other
|
|
86
|
+
* instrumentations (OpenInference, Traceloop) and must not be stripped.
|
|
87
|
+
*/
|
|
88
|
+
function isVercelAISpan(span) {
|
|
89
|
+
// Primary: check OTEL instrumentation scope (most reliable, no false positives)
|
|
90
|
+
if (span.instrumentationLibrary?.name === "ai")
|
|
91
|
+
return true;
|
|
92
|
+
// Fallback: explicit Vercel marker or span name convention
|
|
93
|
+
if (span.attributes["ai.sdk"] !== undefined)
|
|
94
|
+
return true;
|
|
95
|
+
if (span.name.startsWith("ai."))
|
|
96
|
+
return true;
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
// ── Log type detection (with operationId + attribute fallbacks) ──────────────
|
|
100
|
+
/**
|
|
101
|
+
* Resolve the Respan log type for a Vercel AI SDK span.
|
|
102
|
+
* Replicates the full fallback chain from the exporter's parseLogType().
|
|
103
|
+
*/
|
|
104
|
+
function resolveLogType(name, attrs) {
|
|
105
|
+
// 1. Direct span name match
|
|
106
|
+
const config = VERCEL_SPAN_CONFIG[name];
|
|
107
|
+
if (config)
|
|
108
|
+
return config.logType;
|
|
109
|
+
const parentType = VERCEL_PARENT_SPANS[name];
|
|
110
|
+
if (parentType)
|
|
111
|
+
return parentType;
|
|
112
|
+
// 2. operationId attribute fallback
|
|
113
|
+
const operationId = attrs["ai.operationId"]?.toString();
|
|
114
|
+
if (operationId) {
|
|
115
|
+
const opConfig = VERCEL_SPAN_CONFIG[operationId];
|
|
116
|
+
if (opConfig)
|
|
117
|
+
return opConfig.logType;
|
|
118
|
+
const opParent = VERCEL_PARENT_SPANS[operationId];
|
|
119
|
+
if (opParent)
|
|
120
|
+
return opParent;
|
|
121
|
+
}
|
|
122
|
+
// 3. Attribute-based fallback detection (same heuristics as exporter)
|
|
123
|
+
if (attrs["ai.embedding"] || attrs["ai.embeddings"] ||
|
|
124
|
+
name.includes("embed") || operationId?.includes("embed")) {
|
|
125
|
+
return RespanLogType.EMBEDDING;
|
|
126
|
+
}
|
|
127
|
+
if (attrs["ai.toolCall.id"] || attrs["ai.toolCall.name"] ||
|
|
128
|
+
attrs["ai.toolCall.args"] || attrs["ai.toolCall.result"] ||
|
|
129
|
+
attrs["ai.response.toolCalls"] ||
|
|
130
|
+
name.includes("tool") || operationId?.includes("tool")) {
|
|
131
|
+
return RespanLogType.TOOL;
|
|
132
|
+
}
|
|
133
|
+
if (attrs["ai.agent.id"] ||
|
|
134
|
+
name.includes("agent") || operationId?.includes("agent")) {
|
|
135
|
+
return RespanLogType.AGENT;
|
|
136
|
+
}
|
|
137
|
+
if (attrs["ai.workflow.id"] ||
|
|
138
|
+
name.includes("workflow") || operationId?.includes("workflow")) {
|
|
139
|
+
return RespanLogType.WORKFLOW;
|
|
140
|
+
}
|
|
141
|
+
if (attrs["ai.transcript"] ||
|
|
142
|
+
name.includes("transcript") || operationId?.includes("transcript")) {
|
|
143
|
+
return RespanLogType.TRANSCRIPTION;
|
|
144
|
+
}
|
|
145
|
+
if (attrs["ai.speech"] ||
|
|
146
|
+
name.includes("speech") || operationId?.includes("speech")) {
|
|
147
|
+
return RespanLogType.SPEECH;
|
|
148
|
+
}
|
|
149
|
+
// 4. Generation span fallback (doGenerate/doStream)
|
|
150
|
+
if (name.includes("doGenerate") || name.includes("doStream")) {
|
|
151
|
+
return RespanLogType.TEXT;
|
|
152
|
+
}
|
|
153
|
+
return RespanLogType.UNKNOWN;
|
|
154
|
+
}
|
|
155
|
+
// ── Model normalization ──────────────────────────────────────────────────────
|
|
156
|
+
/**
|
|
157
|
+
* Normalize the model ID from Vercel's ai.model.id to a standard model name.
|
|
158
|
+
* Replicates the logic from the existing exporter.
|
|
159
|
+
*/
|
|
160
|
+
function normalizeModel(modelId) {
|
|
161
|
+
const model = modelId.toLowerCase();
|
|
162
|
+
if (model.includes("gemini-2.0-flash-001"))
|
|
163
|
+
return "gemini/gemini-2.0-flash";
|
|
164
|
+
if (model.includes("gemini-2.0-pro"))
|
|
165
|
+
return "gemini/gemini-2.0-pro-exp-02-05";
|
|
166
|
+
if (model.includes("claude-3-5-sonnet"))
|
|
167
|
+
return "claude-3-5-sonnet-20241022";
|
|
168
|
+
if (model.includes("deepseek"))
|
|
169
|
+
return "deepseek/" + model;
|
|
170
|
+
if (model.includes("o3-mini"))
|
|
171
|
+
return "o3-mini";
|
|
172
|
+
return model;
|
|
173
|
+
}
|
|
174
|
+
// ── Prompt/completion message formatting ─────────────────────────────────────
|
|
175
|
+
/**
|
|
176
|
+
* Parse ai.prompt.messages into a JSON string suitable for traceloop.entity.input.
|
|
177
|
+
* Falls back to ai.prompt as a single user message.
|
|
178
|
+
*/
|
|
179
|
+
function formatPromptInput(attrs) {
|
|
180
|
+
const messages = attrs["ai.prompt.messages"];
|
|
181
|
+
if (messages) {
|
|
182
|
+
try {
|
|
183
|
+
const parsed = typeof messages === "string" ? JSON.parse(messages) : messages;
|
|
184
|
+
return safeJsonStr(parsed);
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// fall through
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const prompt = attrs["ai.prompt"];
|
|
191
|
+
if (prompt) {
|
|
192
|
+
return safeJsonStr([{ role: "user", content: String(prompt) }]);
|
|
193
|
+
}
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Build completion output from ai.response.text, ai.response.object, and tool calls.
|
|
198
|
+
* Also includes tool result messages when present (for tool call spans).
|
|
199
|
+
*/
|
|
200
|
+
function formatCompletionOutput(attrs) {
|
|
201
|
+
let content = "";
|
|
202
|
+
if (attrs["ai.response.object"]) {
|
|
203
|
+
try {
|
|
204
|
+
const rawObject = attrs["ai.response.object"];
|
|
205
|
+
const parsed = typeof rawObject === "string" ? JSON.parse(rawObject) : rawObject;
|
|
206
|
+
// generateObject returns the object directly (no `response` wrapper).
|
|
207
|
+
// Prefer known wrappers when present, otherwise serialize the object itself.
|
|
208
|
+
const normalized = parsed?.response ?? parsed?.object ?? parsed?.output ?? parsed?.result ?? parsed;
|
|
209
|
+
content = safeJsonStr(normalized);
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
content = String(attrs["ai.response.text"] ?? "");
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
content = String(attrs["ai.response.text"] ?? "");
|
|
217
|
+
}
|
|
218
|
+
if (!content)
|
|
219
|
+
return undefined;
|
|
220
|
+
// Build assistant message with optional tool calls
|
|
221
|
+
const message = { role: "assistant", content };
|
|
222
|
+
const toolCalls = parseToolCalls(attrs);
|
|
223
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
224
|
+
message.tool_calls = toolCalls;
|
|
225
|
+
}
|
|
226
|
+
// Include tool result as a separate message if present
|
|
227
|
+
const messages = [message];
|
|
228
|
+
if (attrs["ai.toolCall.result"]) {
|
|
229
|
+
messages.push({
|
|
230
|
+
role: "tool",
|
|
231
|
+
tool_call_id: String(attrs["ai.toolCall.id"] || ""),
|
|
232
|
+
content: String(attrs["ai.toolCall.result"] || ""),
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
return safeJsonStr(messages.length === 1 ? message : messages);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Parse tool call data from various Vercel AI SDK attribute formats.
|
|
239
|
+
*/
|
|
240
|
+
function parseToolCalls(attrs) {
|
|
241
|
+
// Try array formats first
|
|
242
|
+
for (const key of ["ai.response.toolCalls", "ai.toolCall", "ai.toolCalls"]) {
|
|
243
|
+
if (!attrs[key])
|
|
244
|
+
continue;
|
|
245
|
+
try {
|
|
246
|
+
const parsed = typeof attrs[key] === "string" ? JSON.parse(attrs[key]) : attrs[key];
|
|
247
|
+
const calls = Array.isArray(parsed) ? parsed : [parsed];
|
|
248
|
+
return calls.map((call) => {
|
|
249
|
+
if (!call || typeof call !== "object")
|
|
250
|
+
return { type: "function" };
|
|
251
|
+
const result = { ...call };
|
|
252
|
+
if (!result.type)
|
|
253
|
+
result.type = "function";
|
|
254
|
+
if (!result.id && (result.toolCallId || result.tool_call_id)) {
|
|
255
|
+
result.id = result.toolCallId || result.tool_call_id;
|
|
256
|
+
}
|
|
257
|
+
return result;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Try individual tool call attributes
|
|
265
|
+
if (attrs["ai.toolCall.id"] || attrs["ai.toolCall.name"] || attrs["ai.toolCall.args"]) {
|
|
266
|
+
const toolCall = { type: "function" };
|
|
267
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
268
|
+
if (key.startsWith("ai.toolCall.")) {
|
|
269
|
+
toolCall[key.replace("ai.toolCall.", "")] = value;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return [toolCall];
|
|
273
|
+
}
|
|
274
|
+
return undefined;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Format tool call span input/output for traceloop.entity.input/output.
|
|
278
|
+
*/
|
|
279
|
+
function formatToolInput(attrs) {
|
|
280
|
+
const name = attrs["ai.toolCall.name"];
|
|
281
|
+
const args = attrs["ai.toolCall.args"];
|
|
282
|
+
if (!name && !args)
|
|
283
|
+
return undefined;
|
|
284
|
+
const input = {};
|
|
285
|
+
if (name)
|
|
286
|
+
input.name = name;
|
|
287
|
+
if (args) {
|
|
288
|
+
input.args = typeof args === "string" ? safeJsonParse(args) : args;
|
|
289
|
+
}
|
|
290
|
+
return safeJsonStr(input);
|
|
291
|
+
}
|
|
292
|
+
function formatToolOutput(attrs) {
|
|
293
|
+
const result = attrs["ai.toolCall.result"];
|
|
294
|
+
if (result === undefined)
|
|
295
|
+
return undefined;
|
|
296
|
+
return safeJsonStr(typeof result === "string" ? safeJsonParse(result) : result);
|
|
297
|
+
}
|
|
298
|
+
// ── Tools & tool choice (from exporter's parseTools / parseToolChoice) ───────
|
|
299
|
+
/**
|
|
300
|
+
* Parse ai.prompt.tools into a normalized tool definition array.
|
|
301
|
+
* Accepts both nested ({type:"function",function:{...}}) and flat shapes.
|
|
302
|
+
*/
|
|
303
|
+
function parseTools(attrs) {
|
|
304
|
+
try {
|
|
305
|
+
const tools = attrs["ai.prompt.tools"];
|
|
306
|
+
if (!tools)
|
|
307
|
+
return undefined;
|
|
308
|
+
const raw = Array.isArray(tools) ? tools : [tools];
|
|
309
|
+
const parsed = raw
|
|
310
|
+
.map((tool) => {
|
|
311
|
+
try {
|
|
312
|
+
return typeof tool === "string" ? JSON.parse(tool) : tool;
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
return undefined;
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
.filter(Boolean)
|
|
319
|
+
.map((tool) => {
|
|
320
|
+
// Accept both nested and flat shapes; normalize to nested
|
|
321
|
+
if (tool && tool.type === "function") {
|
|
322
|
+
if (tool.function && typeof tool.function === "object")
|
|
323
|
+
return tool;
|
|
324
|
+
const { name, description, parameters, ...rest } = tool;
|
|
325
|
+
return {
|
|
326
|
+
...rest,
|
|
327
|
+
type: "function",
|
|
328
|
+
function: {
|
|
329
|
+
name,
|
|
330
|
+
...(description ? { description } : {}),
|
|
331
|
+
...(parameters ? { parameters } : {}),
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
return tool;
|
|
336
|
+
});
|
|
337
|
+
if (parsed.length === 0)
|
|
338
|
+
return undefined;
|
|
339
|
+
return safeJsonStr(parsed);
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
return undefined;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Parse gen_ai.usage.tool_choice into a normalized structure.
|
|
347
|
+
*/
|
|
348
|
+
function parseToolChoice(attrs) {
|
|
349
|
+
try {
|
|
350
|
+
const toolChoice = attrs["gen_ai.usage.tool_choice"];
|
|
351
|
+
if (!toolChoice)
|
|
352
|
+
return undefined;
|
|
353
|
+
const parsed = typeof toolChoice === "string" ? JSON.parse(toolChoice) : toolChoice;
|
|
354
|
+
return safeJsonStr({
|
|
355
|
+
type: String(parsed.type),
|
|
356
|
+
function: { name: String(parsed.function.name) },
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// ── Metadata / customer params ───────────────────────────────────────────────
|
|
364
|
+
/**
|
|
365
|
+
* Extract ai.telemetry.metadata.* and map customer/thread params to Respan attrs.
|
|
366
|
+
* Also handles prompt_unit_price, completion_unit_price, and span_type metadata.
|
|
367
|
+
*/
|
|
368
|
+
function enrichMetadata(attrs, spanName) {
|
|
369
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
370
|
+
if (!key.startsWith("ai.telemetry.metadata."))
|
|
371
|
+
continue;
|
|
372
|
+
const cleanKey = key.slice("ai.telemetry.metadata.".length);
|
|
373
|
+
// Map well-known keys to Respan span attributes
|
|
374
|
+
switch (cleanKey) {
|
|
375
|
+
case "customer_identifier":
|
|
376
|
+
setDefault(attrs, CUSTOMER_ID, String(value));
|
|
377
|
+
break;
|
|
378
|
+
case "customer_email":
|
|
379
|
+
setDefault(attrs, CUSTOMER_EMAIL, String(value));
|
|
380
|
+
break;
|
|
381
|
+
case "customer_name":
|
|
382
|
+
setDefault(attrs, CUSTOMER_NAME, String(value));
|
|
383
|
+
break;
|
|
384
|
+
case "thread_identifier":
|
|
385
|
+
setDefault(attrs, THREAD_ID, String(value));
|
|
386
|
+
break;
|
|
387
|
+
case "trace_group_identifier":
|
|
388
|
+
setDefault(attrs, TRACE_GROUP_ID, String(value));
|
|
389
|
+
break;
|
|
390
|
+
case "customer_params": {
|
|
391
|
+
// customer_params can be a JSON object with all three fields
|
|
392
|
+
try {
|
|
393
|
+
const parsed = typeof value === "string" ? JSON.parse(value) : value;
|
|
394
|
+
if (parsed?.customer_identifier)
|
|
395
|
+
setDefault(attrs, CUSTOMER_ID, parsed.customer_identifier);
|
|
396
|
+
if (parsed?.customer_email)
|
|
397
|
+
setDefault(attrs, CUSTOMER_EMAIL, parsed.customer_email);
|
|
398
|
+
if (parsed?.customer_name)
|
|
399
|
+
setDefault(attrs, CUSTOMER_NAME, parsed.customer_name);
|
|
400
|
+
}
|
|
401
|
+
catch {
|
|
402
|
+
// ignore
|
|
403
|
+
}
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
case "prompt_unit_price":
|
|
407
|
+
setDefault(attrs, metadataKey("prompt_unit_price"), String(value));
|
|
408
|
+
break;
|
|
409
|
+
case "completion_unit_price":
|
|
410
|
+
setDefault(attrs, metadataKey("completion_unit_price"), String(value));
|
|
411
|
+
break;
|
|
412
|
+
case "userId":
|
|
413
|
+
// userId is a fallback for customer_identifier (backward compat with exporter)
|
|
414
|
+
setDefault(attrs, CUSTOMER_ID, String(value));
|
|
415
|
+
setDefault(attrs, metadataKey(cleanKey), String(value ?? ""));
|
|
416
|
+
break;
|
|
417
|
+
default:
|
|
418
|
+
// All other metadata → respan.metadata.<key>
|
|
419
|
+
setDefault(attrs, metadataKey(cleanKey), String(value ?? ""));
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
// ── Token count normalization ────────────────────────────────────────────────
|
|
425
|
+
function enrichTokens(attrs) {
|
|
426
|
+
// Vercel AI SDK may use gen_ai.usage.input_tokens / gen_ai.usage.output_tokens
|
|
427
|
+
// Respan backend expects gen_ai.usage.prompt_tokens / gen_ai.usage.completion_tokens
|
|
428
|
+
const inputTokens = attrs["gen_ai.usage.input_tokens"] ??
|
|
429
|
+
attrs["gen_ai.usage.prompt_tokens"];
|
|
430
|
+
const outputTokens = attrs["gen_ai.usage.output_tokens"] ??
|
|
431
|
+
attrs["gen_ai.usage.completion_tokens"];
|
|
432
|
+
if (inputTokens !== undefined) {
|
|
433
|
+
setDefault(attrs, GEN_AI_USAGE_PROMPT_TOKENS, Number(inputTokens));
|
|
434
|
+
}
|
|
435
|
+
if (outputTokens !== undefined) {
|
|
436
|
+
setDefault(attrs, GEN_AI_USAGE_COMPLETION_TOKENS, Number(outputTokens));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
// ── Performance / cost metrics ───────────────────────────────────────────────
|
|
440
|
+
/**
|
|
441
|
+
* Enrich performance and cost attributes that the exporter handled explicitly.
|
|
442
|
+
* These are Vercel-specific attrs that the backend needs in standard locations.
|
|
443
|
+
*/
|
|
444
|
+
function enrichPerformanceMetrics(attrs, spanName) {
|
|
445
|
+
// Stream detection from span name
|
|
446
|
+
setDefault(attrs, metadataKey("stream"), String(spanName.includes("doStream")));
|
|
447
|
+
// Time to first token from ai.response.msToFinish (Vercel-specific)
|
|
448
|
+
const msToFinish = attrs["ai.response.msToFinish"];
|
|
449
|
+
if (msToFinish !== undefined) {
|
|
450
|
+
setDefault(attrs, metadataKey("time_to_first_token"), String(Number(msToFinish) / 1000));
|
|
451
|
+
}
|
|
452
|
+
// Cost (gen_ai.usage.cost is standard but ensure it's present)
|
|
453
|
+
const cost = attrs["gen_ai.usage.cost"];
|
|
454
|
+
if (cost !== undefined) {
|
|
455
|
+
setDefault(attrs, metadataKey("cost"), String(cost));
|
|
456
|
+
}
|
|
457
|
+
// TTFT (gen_ai.usage.ttft)
|
|
458
|
+
const ttft = attrs["gen_ai.usage.ttft"];
|
|
459
|
+
if (ttft !== undefined) {
|
|
460
|
+
setDefault(attrs, metadataKey("ttft"), String(ttft));
|
|
461
|
+
}
|
|
462
|
+
// Generation time
|
|
463
|
+
const genTime = attrs["gen_ai.usage.generation_time"];
|
|
464
|
+
if (genTime !== undefined) {
|
|
465
|
+
setDefault(attrs, metadataKey("generation_time"), String(genTime));
|
|
466
|
+
}
|
|
467
|
+
// Warnings
|
|
468
|
+
const warnings = attrs["gen_ai.usage.warnings"];
|
|
469
|
+
if (warnings !== undefined) {
|
|
470
|
+
setDefault(attrs, metadataKey("warnings"), String(warnings));
|
|
471
|
+
}
|
|
472
|
+
// Response type (text/json_schema/json_object)
|
|
473
|
+
const type = attrs["gen_ai.usage.type"];
|
|
474
|
+
if (type !== undefined) {
|
|
475
|
+
setDefault(attrs, metadataKey("type"), String(type));
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
// ── Cleanup: strip redundant Vercel attrs after translation ──────────────────
|
|
479
|
+
/**
|
|
480
|
+
* Vercel AI SDK attributes that have been translated to Traceloop/GenAI/Respan
|
|
481
|
+
* equivalents. These are deleted after translation to keep spans clean.
|
|
482
|
+
*/
|
|
483
|
+
const VERCEL_ATTRS_TO_STRIP = [
|
|
484
|
+
// ── Vercel AI SDK attrs (translated to Traceloop/GenAI equivalents) ────
|
|
485
|
+
// Model (translated to gen_ai.request.model)
|
|
486
|
+
"ai.model.id",
|
|
487
|
+
"ai.model.provider",
|
|
488
|
+
"ai.response.model",
|
|
489
|
+
// Prompt/completion (translated to traceloop.entity.input/output)
|
|
490
|
+
"ai.prompt",
|
|
491
|
+
"ai.prompt.messages",
|
|
492
|
+
"ai.prompt.format",
|
|
493
|
+
"ai.response.text",
|
|
494
|
+
"ai.response.object",
|
|
495
|
+
// Tokens (translated to gen_ai.usage.prompt_tokens/completion_tokens)
|
|
496
|
+
"ai.usage.promptTokens",
|
|
497
|
+
"ai.usage.completionTokens",
|
|
498
|
+
// Response metadata (redundant with standard OTEL/GenAI attrs)
|
|
499
|
+
"ai.response.finishReason",
|
|
500
|
+
"ai.response.id",
|
|
501
|
+
"ai.response.timestamp",
|
|
502
|
+
"ai.response.providerMetadata",
|
|
503
|
+
"ai.response.msToFinish",
|
|
504
|
+
// SDK internals (no user value)
|
|
505
|
+
"ai.operationId",
|
|
506
|
+
"ai.settings.maxRetries",
|
|
507
|
+
"ai.settings.maxSteps",
|
|
508
|
+
"ai.sdk",
|
|
509
|
+
"operation.name",
|
|
510
|
+
// Tool calls (translated to traceloop.entity.input/output for tool spans)
|
|
511
|
+
"ai.toolCall.id",
|
|
512
|
+
"ai.toolCall.name",
|
|
513
|
+
"ai.toolCall.args",
|
|
514
|
+
"ai.toolCall.result",
|
|
515
|
+
"ai.response.toolCalls",
|
|
516
|
+
// GenAI duplicates (already consumed by backend as top-level fields)
|
|
517
|
+
"gen_ai.response.finish_reasons",
|
|
518
|
+
"gen_ai.response.id",
|
|
519
|
+
"gen_ai.usage.input_tokens",
|
|
520
|
+
"gen_ai.usage.output_tokens",
|
|
521
|
+
"gen_ai.system",
|
|
522
|
+
// ── Traceloop routing attrs (Vercel-specific, not user-facing) ──────────
|
|
523
|
+
// Keep traceloop.span.kind and respan.entity.log_type — backend needs them.
|
|
524
|
+
// Keep respan.environment — may be set by user via propagateAttributes().
|
|
525
|
+
"traceloop.entity.name",
|
|
526
|
+
"traceloop.entity.path",
|
|
527
|
+
// ── OTEL resource / process noise (no user value in metadata) ──────────
|
|
528
|
+
"service.name",
|
|
529
|
+
"telemetry.sdk.language",
|
|
530
|
+
"telemetry.sdk.name",
|
|
531
|
+
"telemetry.sdk.version",
|
|
532
|
+
"process.pid",
|
|
533
|
+
"process.executable.name",
|
|
534
|
+
"process.executable.path",
|
|
535
|
+
"process.command_args",
|
|
536
|
+
"process.runtime.version",
|
|
537
|
+
"process.runtime.name",
|
|
538
|
+
"process.runtime.description",
|
|
539
|
+
"process.command",
|
|
540
|
+
"process.owner",
|
|
541
|
+
"host.name",
|
|
542
|
+
"host.arch",
|
|
543
|
+
"host.id",
|
|
544
|
+
"otel.scope.name",
|
|
545
|
+
"otel.scope.version",
|
|
546
|
+
// ── Next.js auto-instrumentation noise ─────────────────────────────────
|
|
547
|
+
"next.span_name",
|
|
548
|
+
"next.span_type",
|
|
549
|
+
"http.url",
|
|
550
|
+
"http.method",
|
|
551
|
+
"net.peer.name",
|
|
552
|
+
];
|
|
553
|
+
/**
|
|
554
|
+
* Remove redundant Vercel AI SDK attributes after translation.
|
|
555
|
+
* Also strips ai.telemetry.metadata.* keys that have been mapped to respan.* attrs.
|
|
556
|
+
*/
|
|
557
|
+
function stripRedundantAttrs(attrs) {
|
|
558
|
+
for (const key of VERCEL_ATTRS_TO_STRIP) {
|
|
559
|
+
delete attrs[key];
|
|
560
|
+
}
|
|
561
|
+
// Strip ai.telemetry.metadata.* (already mapped to respan.metadata.* / respan.customer_params.*)
|
|
562
|
+
for (const key of Object.keys(attrs)) {
|
|
563
|
+
if (key.startsWith("ai.telemetry.metadata.")) {
|
|
564
|
+
delete attrs[key];
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
// Strip ai.prompt.tools (translated to respan.span.tools)
|
|
568
|
+
if (attrs["ai.prompt.tools"] !== undefined) {
|
|
569
|
+
delete attrs["ai.prompt.tools"];
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
// ── Main processor ───────────────────────────────────────────────────────────
|
|
573
|
+
/**
|
|
574
|
+
* SpanProcessor that translates Vercel AI SDK attributes to Traceloop/OpenLLMetry.
|
|
575
|
+
*
|
|
576
|
+
* Phase 1 (onStart): Sets RESPAN_LOG_TYPE so CompositeProcessor lets the span through.
|
|
577
|
+
* Phase 2 (onEnd): Full attribute enrichment — model, messages, tokens, metadata,
|
|
578
|
+
* tools, performance metrics, environment, etc.
|
|
579
|
+
*/
|
|
580
|
+
export class VercelAITranslator {
|
|
581
|
+
onStart(span, _parentContext) {
|
|
582
|
+
// Cast to access attributes (Span interface doesn't expose them, but the impl does)
|
|
583
|
+
const s = span;
|
|
584
|
+
const name = s.name ?? "";
|
|
585
|
+
if (!name.startsWith("ai."))
|
|
586
|
+
return;
|
|
587
|
+
// Set RESPAN_LOG_TYPE early so CompositeProcessor accepts this span
|
|
588
|
+
const config = VERCEL_SPAN_CONFIG[name];
|
|
589
|
+
if (config) {
|
|
590
|
+
s.setAttribute(RESPAN_LOG_TYPE, config.logType);
|
|
591
|
+
}
|
|
592
|
+
else if (VERCEL_PARENT_SPANS[name] !== undefined) {
|
|
593
|
+
s.setAttribute(RESPAN_LOG_TYPE, VERCEL_PARENT_SPANS[name]);
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
// Unknown ai.* span — use full fallback detection
|
|
597
|
+
// At onStart, attributes may be sparse, so set a generic type.
|
|
598
|
+
// The precise type will be resolved in onEnd() with full attributes.
|
|
599
|
+
s.setAttribute(RESPAN_LOG_TYPE, RespanLogType.TASK);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
onEnd(span) {
|
|
603
|
+
const attrs = span.attributes;
|
|
604
|
+
if (!attrs)
|
|
605
|
+
return;
|
|
606
|
+
if (!isVercelAISpan(span))
|
|
607
|
+
return;
|
|
608
|
+
const name = span.name;
|
|
609
|
+
const config = VERCEL_SPAN_CONFIG[name];
|
|
610
|
+
const parentLogType = VERCEL_PARENT_SPANS[name];
|
|
611
|
+
// Resolve the log type using full fallback chain (name → operationId → attributes)
|
|
612
|
+
const logType = resolveLogType(name, attrs);
|
|
613
|
+
// ── Always: metadata, customer params, environment ────────────────────
|
|
614
|
+
enrichMetadata(attrs, name);
|
|
615
|
+
// ── Parent wrapper spans: minimal enrichment only ─────────────────────
|
|
616
|
+
if (parentLogType !== undefined && !config) {
|
|
617
|
+
setDefault(attrs, RESPAN_LOG_TYPE, logType);
|
|
618
|
+
stripRedundantAttrs(attrs);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
// ── Detailed / leaf spans: full enrichment ────────────────────────────
|
|
622
|
+
// Update RESPAN_LOG_TYPE with the resolved type (may be more accurate than onStart)
|
|
623
|
+
attrs[RESPAN_LOG_TYPE] = logType;
|
|
624
|
+
if (config) {
|
|
625
|
+
setDefault(attrs, TL_SPAN_KIND, config.kind);
|
|
626
|
+
// LLM-specific enrichment
|
|
627
|
+
if (config.isLLM) {
|
|
628
|
+
setDefault(attrs, LLM_REQUEST_TYPE, RespanLogType.CHAT);
|
|
629
|
+
// Model
|
|
630
|
+
const modelId = attrs["ai.model.id"];
|
|
631
|
+
if (modelId) {
|
|
632
|
+
setDefault(attrs, GEN_AI_REQUEST_MODEL, normalizeModel(String(modelId)));
|
|
633
|
+
}
|
|
634
|
+
// Prompt messages → entity input
|
|
635
|
+
const input = formatPromptInput(attrs);
|
|
636
|
+
if (input)
|
|
637
|
+
setDefault(attrs, TL_ENTITY_INPUT, input);
|
|
638
|
+
// Completion → entity output
|
|
639
|
+
const output = formatCompletionOutput(attrs);
|
|
640
|
+
if (output)
|
|
641
|
+
setDefault(attrs, TL_ENTITY_OUTPUT, output);
|
|
642
|
+
// Token counts
|
|
643
|
+
enrichTokens(attrs);
|
|
644
|
+
// Tool definitions
|
|
645
|
+
const tools = parseTools(attrs);
|
|
646
|
+
if (tools)
|
|
647
|
+
setDefault(attrs, RESPAN_SPAN_TOOLS, tools);
|
|
648
|
+
// Tool choice
|
|
649
|
+
const toolChoice = parseToolChoice(attrs);
|
|
650
|
+
if (toolChoice)
|
|
651
|
+
setDefault(attrs, metadataKey("tool_choice"), toolChoice);
|
|
652
|
+
// Performance metrics (stream, TTFT, cost, etc.)
|
|
653
|
+
enrichPerformanceMetrics(attrs, name);
|
|
654
|
+
}
|
|
655
|
+
// Tool call spans
|
|
656
|
+
if (config.logType === RespanLogType.TOOL || logType === RespanLogType.TOOL) {
|
|
657
|
+
const toolInput = formatToolInput(attrs);
|
|
658
|
+
if (toolInput)
|
|
659
|
+
setDefault(attrs, TL_ENTITY_INPUT, toolInput);
|
|
660
|
+
const toolOutput = formatToolOutput(attrs);
|
|
661
|
+
if (toolOutput)
|
|
662
|
+
setDefault(attrs, TL_ENTITY_OUTPUT, toolOutput);
|
|
663
|
+
}
|
|
664
|
+
// Agent spans
|
|
665
|
+
if (config.logType === RespanLogType.AGENT || logType === RespanLogType.AGENT) {
|
|
666
|
+
const agentName = attrs["ai.agent.name"] ?? attrs["ai.agent.id"] ?? name;
|
|
667
|
+
setDefault(attrs, RESPAN_METADATA_AGENT_NAME, String(agentName));
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
else {
|
|
671
|
+
// Unknown ai.* span — enrich with fallback-resolved type
|
|
672
|
+
// If fallback detected it as an LLM span, add model + tokens
|
|
673
|
+
if (logType === RespanLogType.TEXT || logType === RespanLogType.EMBEDDING) {
|
|
674
|
+
const modelId = attrs["ai.model.id"];
|
|
675
|
+
if (modelId) {
|
|
676
|
+
setDefault(attrs, GEN_AI_REQUEST_MODEL, normalizeModel(String(modelId)));
|
|
677
|
+
}
|
|
678
|
+
enrichTokens(attrs);
|
|
679
|
+
if (logType === RespanLogType.TEXT) {
|
|
680
|
+
setDefault(attrs, LLM_REQUEST_TYPE, RespanLogType.CHAT);
|
|
681
|
+
const input = formatPromptInput(attrs);
|
|
682
|
+
if (input)
|
|
683
|
+
setDefault(attrs, TL_ENTITY_INPUT, input);
|
|
684
|
+
const output = formatCompletionOutput(attrs);
|
|
685
|
+
if (output)
|
|
686
|
+
setDefault(attrs, TL_ENTITY_OUTPUT, output);
|
|
687
|
+
enrichPerformanceMetrics(attrs, name);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
// If fallback detected tool, add tool input/output
|
|
691
|
+
if (logType === RespanLogType.TOOL) {
|
|
692
|
+
const toolInput = formatToolInput(attrs);
|
|
693
|
+
if (toolInput)
|
|
694
|
+
setDefault(attrs, TL_ENTITY_INPUT, toolInput);
|
|
695
|
+
const toolOutput = formatToolOutput(attrs);
|
|
696
|
+
if (toolOutput)
|
|
697
|
+
setDefault(attrs, TL_ENTITY_OUTPUT, toolOutput);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
// ── Cleanup: remove redundant Vercel attrs that have been translated ──
|
|
701
|
+
stripRedundantAttrs(attrs);
|
|
702
|
+
}
|
|
703
|
+
async shutdown() { }
|
|
704
|
+
async forceFlush() { }
|
|
705
|
+
}
|
|
706
|
+
//# sourceMappingURL=_translator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_translator.js","sourceRoot":"","sources":["../src/_translator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { VERCEL_SPAN_CONFIG, VERCEL_PARENT_SPANS, type VercelSpanConfig, } from "./logs.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GAEpB,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mappings from Vercel AI SDK span names to Respan/Traceloop conventions.
|
|
3
|
+
*
|
|
4
|
+
* The Vercel AI SDK emits OTEL spans with names like "ai.generateText.doGenerate".
|
|
5
|
+
* These mappings tell the translator which traceloop.span.kind, respan log type,
|
|
6
|
+
* and whether to apply full LLM attribute enrichment.
|
|
7
|
+
*/
|
|
8
|
+
export interface VercelSpanConfig {
|
|
9
|
+
/** Traceloop span kind (workflow, agent, task, tool) */
|
|
10
|
+
kind: string;
|
|
11
|
+
/** Respan log type for backend categorization */
|
|
12
|
+
logType: string;
|
|
13
|
+
/** Whether this span represents an LLM call (triggers prompt/completion enrichment) */
|
|
14
|
+
isLLM: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare const VERCEL_SPAN_CONFIG: Record<string, VercelSpanConfig>;
|
|
17
|
+
export declare const VERCEL_PARENT_SPANS: Record<string, string>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mappings from Vercel AI SDK span names to Respan/Traceloop conventions.
|
|
3
|
+
*
|
|
4
|
+
* The Vercel AI SDK emits OTEL spans with names like "ai.generateText.doGenerate".
|
|
5
|
+
* These mappings tell the translator which traceloop.span.kind, respan log type,
|
|
6
|
+
* and whether to apply full LLM attribute enrichment.
|
|
7
|
+
*/
|
|
8
|
+
import { RespanLogType } from "@respan/respan-sdk";
|
|
9
|
+
// ── Detailed spans (leaf nodes with actual LLM/embedding/tool data) ─────────
|
|
10
|
+
export const VERCEL_SPAN_CONFIG = {
|
|
11
|
+
// LLM generation (detailed spans carry response data)
|
|
12
|
+
"ai.generateText.doGenerate": { kind: RespanLogType.TASK, logType: RespanLogType.TEXT, isLLM: true },
|
|
13
|
+
"ai.streamText.doStream": { kind: RespanLogType.TASK, logType: RespanLogType.TEXT, isLLM: true },
|
|
14
|
+
"ai.generateObject.doGenerate": { kind: RespanLogType.TASK, logType: RespanLogType.TEXT, isLLM: true },
|
|
15
|
+
"ai.streamObject.doStream": { kind: RespanLogType.TASK, logType: RespanLogType.TEXT, isLLM: true },
|
|
16
|
+
// Embeddings
|
|
17
|
+
"ai.embed.doEmbed": { kind: RespanLogType.TASK, logType: RespanLogType.EMBEDDING, isLLM: false },
|
|
18
|
+
"ai.embedMany.doEmbed": { kind: RespanLogType.TASK, logType: RespanLogType.EMBEDDING, isLLM: false },
|
|
19
|
+
// Tool calls
|
|
20
|
+
"ai.toolCall": { kind: RespanLogType.TOOL, logType: RespanLogType.TOOL, isLLM: false },
|
|
21
|
+
// Agent / workflow
|
|
22
|
+
"ai.agent": { kind: RespanLogType.AGENT, logType: RespanLogType.AGENT, isLLM: false },
|
|
23
|
+
"ai.agent.run": { kind: RespanLogType.AGENT, logType: RespanLogType.AGENT, isLLM: false },
|
|
24
|
+
"ai.agent.step": { kind: RespanLogType.TASK, logType: RespanLogType.TASK, isLLM: false },
|
|
25
|
+
"ai.workflow": { kind: RespanLogType.WORKFLOW, logType: RespanLogType.WORKFLOW, isLLM: false },
|
|
26
|
+
// Function / handoff
|
|
27
|
+
"ai.function": { kind: RespanLogType.TOOL, logType: RespanLogType.FUNCTION, isLLM: false },
|
|
28
|
+
"ai.handoff": { kind: RespanLogType.TASK, logType: RespanLogType.HANDOFF, isLLM: false },
|
|
29
|
+
// Media
|
|
30
|
+
"ai.transcript": { kind: RespanLogType.TASK, logType: RespanLogType.TRANSCRIPTION, isLLM: false },
|
|
31
|
+
"ai.speech": { kind: RespanLogType.TASK, logType: RespanLogType.SPEECH, isLLM: false },
|
|
32
|
+
// Other
|
|
33
|
+
"ai.response": { kind: RespanLogType.TASK, logType: RespanLogType.RESPONSE, isLLM: false },
|
|
34
|
+
"ai.stream.firstChunk": { kind: RespanLogType.TASK, logType: RespanLogType.TEXT, isLLM: false },
|
|
35
|
+
};
|
|
36
|
+
// ── Parent wrapper spans (structural only, no LLM data) ─────────────────────
|
|
37
|
+
export const VERCEL_PARENT_SPANS = {
|
|
38
|
+
"ai.generateText": RespanLogType.TEXT,
|
|
39
|
+
"ai.streamText": RespanLogType.TEXT,
|
|
40
|
+
"ai.generateObject": RespanLogType.TEXT,
|
|
41
|
+
"ai.streamObject": RespanLogType.TEXT,
|
|
42
|
+
"ai.embed": RespanLogType.EMBEDDING,
|
|
43
|
+
"ai.embedMany": RespanLogType.EMBEDDING,
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/constants/logs.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Respan instrumentation plugin for the Vercel AI SDK.
|
|
3
|
+
*
|
|
4
|
+
* Registers a {@link VercelAITranslator} SpanProcessor that enriches Vercel AI SDK
|
|
5
|
+
* OTEL spans with Traceloop/GenAI semantic conventions so they flow through the
|
|
6
|
+
* unified Respan OTEL pipeline.
|
|
7
|
+
*
|
|
8
|
+
* The Vercel AI SDK already emits OTEL spans natively. This instrumentation
|
|
9
|
+
* translates its attribute schema (ai.model.id, ai.prompt.messages, ai.response.text)
|
|
10
|
+
* into the Traceloop format the Respan backend expects (gen_ai.request.model,
|
|
11
|
+
* traceloop.entity.input, traceloop.entity.output, etc.).
|
|
12
|
+
*
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { Respan } from "@respan/respan";
|
|
15
|
+
* import { VercelAIInstrumentor } from "@respan/instrumentation-vercel";
|
|
16
|
+
*
|
|
17
|
+
* const respan = new Respan({
|
|
18
|
+
* instrumentations: [new VercelAIInstrumentor()],
|
|
19
|
+
* });
|
|
20
|
+
* await respan.initialize();
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export { VercelAITranslator } from "./_translator.js";
|
|
24
|
+
export { VERCEL_SPAN_CONFIG, VERCEL_PARENT_SPANS } from "./constants/index.js";
|
|
25
|
+
export declare class VercelAIInstrumentor {
|
|
26
|
+
readonly name = "vercel-ai";
|
|
27
|
+
/** Class-level flag: only register the translator once across all instances */
|
|
28
|
+
private static _translatorRegistered;
|
|
29
|
+
activate(): void;
|
|
30
|
+
deactivate(): void;
|
|
31
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Respan instrumentation plugin for the Vercel AI SDK.
|
|
3
|
+
*
|
|
4
|
+
* Registers a {@link VercelAITranslator} SpanProcessor that enriches Vercel AI SDK
|
|
5
|
+
* OTEL spans with Traceloop/GenAI semantic conventions so they flow through the
|
|
6
|
+
* unified Respan OTEL pipeline.
|
|
7
|
+
*
|
|
8
|
+
* The Vercel AI SDK already emits OTEL spans natively. This instrumentation
|
|
9
|
+
* translates its attribute schema (ai.model.id, ai.prompt.messages, ai.response.text)
|
|
10
|
+
* into the Traceloop format the Respan backend expects (gen_ai.request.model,
|
|
11
|
+
* traceloop.entity.input, traceloop.entity.output, etc.).
|
|
12
|
+
*
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { Respan } from "@respan/respan";
|
|
15
|
+
* import { VercelAIInstrumentor } from "@respan/instrumentation-vercel";
|
|
16
|
+
*
|
|
17
|
+
* const respan = new Respan({
|
|
18
|
+
* instrumentations: [new VercelAIInstrumentor()],
|
|
19
|
+
* });
|
|
20
|
+
* await respan.initialize();
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import { trace } from "@opentelemetry/api";
|
|
24
|
+
import { VercelAITranslator } from "./_translator.js";
|
|
25
|
+
export { VercelAITranslator } from "./_translator.js";
|
|
26
|
+
export { VERCEL_SPAN_CONFIG, VERCEL_PARENT_SPANS } from "./constants/index.js";
|
|
27
|
+
export class VercelAIInstrumentor {
|
|
28
|
+
name = "vercel-ai";
|
|
29
|
+
/** Class-level flag: only register the translator once across all instances */
|
|
30
|
+
static _translatorRegistered = false;
|
|
31
|
+
activate() {
|
|
32
|
+
if (VercelAIInstrumentor._translatorRegistered)
|
|
33
|
+
return;
|
|
34
|
+
// Walk the TracerProvider chain to find one that supports addSpanProcessor.
|
|
35
|
+
// trace.getTracerProvider() returns a ProxyTracerProvider; the real
|
|
36
|
+
// NodeTracerProvider lives at ._delegate (or ._delegate._tracerProvider).
|
|
37
|
+
const tp = trace.getTracerProvider();
|
|
38
|
+
const provider = (typeof tp?.addSpanProcessor === "function" && tp) ||
|
|
39
|
+
(typeof tp?._delegate?.addSpanProcessor === "function" && tp._delegate) ||
|
|
40
|
+
(typeof tp?._delegate?._tracerProvider?.addSpanProcessor === "function" && tp._delegate._tracerProvider) ||
|
|
41
|
+
null;
|
|
42
|
+
if (provider) {
|
|
43
|
+
// NOTE: The translator is registered AFTER CompositeProcessor (which was
|
|
44
|
+
// added during startTracing). This means CompositeProcessor.onEnd routes
|
|
45
|
+
// spans to BatchSpanProcessor before our onEnd enriches them. This works
|
|
46
|
+
// because BatchSpanProcessor holds span references and exports async —
|
|
47
|
+
// our enrichment completes before the next batch flush. If SimpleSpanProcessor
|
|
48
|
+
// is ever used, the translator would need to be registered first.
|
|
49
|
+
provider.addSpanProcessor(new VercelAITranslator());
|
|
50
|
+
VercelAIInstrumentor._translatorRegistered = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
deactivate() {
|
|
54
|
+
// Reset static flag so a subsequent initialize() can re-register.
|
|
55
|
+
// The old translator processor is torn down with the TracerProvider.
|
|
56
|
+
VercelAIInstrumentor._translatorRegistered = false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,MAAM,OAAO,oBAAoB;IACf,IAAI,GAAG,WAAW,CAAC;IAEnC,+EAA+E;IACvE,MAAM,CAAC,qBAAqB,GAAG,KAAK,CAAC;IAE7C,QAAQ;QACN,IAAI,oBAAoB,CAAC,qBAAqB;YAAE,OAAO;QAEvD,4EAA4E;QAC5E,oEAAoE;QACpE,0EAA0E;QAC1E,MAAM,EAAE,GAAG,KAAK,CAAC,iBAAiB,EAAS,CAAC;QAC5C,MAAM,QAAQ,GACZ,CAAC,OAAO,EAAE,EAAE,gBAAgB,KAAK,UAAU,IAAI,EAAE,CAAC;YAClD,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,gBAAgB,KAAK,UAAU,IAAI,EAAE,CAAC,SAAS,CAAC;YACvE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,KAAK,UAAU,IAAI,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC;YACxG,IAAI,CAAC;QAEP,IAAI,QAAQ,EAAE,CAAC;YACb,yEAAyE;YACzE,yEAAyE;YACzE,yEAAyE;YACzE,uEAAuE;YACvE,+EAA+E;YAC/E,kEAAkE;YAClE,QAAQ,CAAC,gBAAgB,CAAC,IAAI,kBAAkB,EAAE,CAAC,CAAC;YACpD,oBAAoB,CAAC,qBAAqB,GAAG,IAAI,CAAC;QACpD,CAAC;IACH,CAAC;IAED,UAAU;QACR,kEAAkE;QAClE,qEAAqE;QACrE,oBAAoB,CAAC,qBAAqB,GAAG,KAAK,CAAC;IACrD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@respan/instrumentation-vercel",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Respan instrumentation plugin for Vercel AI SDK",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"author": "Respan <team@respan.ai>",
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"publish": "yarn npm publish",
|
|
21
|
+
"release": "yarn build && yarn version patch && yarn publish"
|
|
22
|
+
},
|
|
23
|
+
"packageManager": "yarn@4.6.0",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@opentelemetry/api": "^1.9.0",
|
|
26
|
+
"@opentelemetry/sdk-trace-base": "^1.29.0",
|
|
27
|
+
"@respan/respan-sdk": "^1.0.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^22.15.29",
|
|
31
|
+
"typescript": "^5.7.3"
|
|
32
|
+
}
|
|
33
|
+
}
|