@brizz/sdk 0.1.2-rc.1 → 0.1.3-rc.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 +97 -90
- package/dist/index.cjs +144 -1039
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -42
- package/dist/index.d.ts +1 -42
- package/dist/index.js +139 -1034
- package/dist/index.js.map +1 -1
- package/dist/loader.mjs +11 -0
- package/dist/preload.cjs +147 -956
- package/dist/preload.cjs.map +1 -1
- package/dist/preload.js +145 -957
- package/dist/preload.js.map +1 -1
- package/package.json +29 -25
package/dist/index.cjs
CHANGED
|
@@ -33,8 +33,7 @@ __export(src_exports, {
|
|
|
33
33
|
Brizz: () => Brizz,
|
|
34
34
|
DEFAULT_PII_PATTERNS: () => DEFAULT_PII_PATTERNS,
|
|
35
35
|
LogLevel: () => LogLevel,
|
|
36
|
-
SeverityNumber: () =>
|
|
37
|
-
VercelAIInstrumentation: () => VercelAIInstrumentation,
|
|
36
|
+
SeverityNumber: () => import_api_logs2.SeverityNumber,
|
|
38
37
|
WithSessionId: () => WithSessionId,
|
|
39
38
|
detectRuntime: () => detectRuntime,
|
|
40
39
|
emitEvent: () => emitEvent,
|
|
@@ -47,14 +46,13 @@ __export(src_exports, {
|
|
|
47
46
|
logger: () => logger,
|
|
48
47
|
maskAttributes: () => maskAttributes,
|
|
49
48
|
maskValue: () => maskValue,
|
|
50
|
-
maybeRegisterESMLoader: () => maybeRegisterESMLoader,
|
|
51
49
|
setLogLevel: () => setLogLevel
|
|
52
50
|
});
|
|
53
51
|
module.exports = __toCommonJS(src_exports);
|
|
54
52
|
|
|
55
53
|
// src/internal/instrumentation/auto-init.ts
|
|
56
54
|
var import_auto_instrumentations_node = require("@opentelemetry/auto-instrumentations-node");
|
|
57
|
-
var
|
|
55
|
+
var import_instrumentation = require("@opentelemetry/instrumentation");
|
|
58
56
|
var import_instrumentation_anthropic = require("@traceloop/instrumentation-anthropic");
|
|
59
57
|
var import_instrumentation_bedrock = require("@traceloop/instrumentation-bedrock");
|
|
60
58
|
var import_instrumentation_chromadb = require("@traceloop/instrumentation-chromadb");
|
|
@@ -211,936 +209,6 @@ function getLogLevel() {
|
|
|
211
209
|
return logger.getLevel();
|
|
212
210
|
}
|
|
213
211
|
|
|
214
|
-
// src/internal/instrumentation/vercel-ai/instrumentation.ts
|
|
215
|
-
var import_instrumentation = require("@opentelemetry/instrumentation");
|
|
216
|
-
|
|
217
|
-
// src/internal/instrumentation/vercel-ai/patchers/base-patcher.ts
|
|
218
|
-
var import_api2 = require("@opentelemetry/api");
|
|
219
|
-
|
|
220
|
-
// src/internal/instrumentation/vercel-ai/semconv.ts
|
|
221
|
-
var ATTR_GEN_AI_SYSTEM = "gen_ai.system";
|
|
222
|
-
var ATTR_GEN_AI_OPERATION_NAME = "gen_ai.operation.name";
|
|
223
|
-
var ATTR_GEN_AI_REQUEST_MODEL = "gen_ai.request.model";
|
|
224
|
-
var ATTR_GEN_AI_REQUEST_MAX_TOKENS = "gen_ai.request.max_tokens";
|
|
225
|
-
var ATTR_GEN_AI_REQUEST_TEMPERATURE = "gen_ai.request.temperature";
|
|
226
|
-
var ATTR_GEN_AI_REQUEST_TOP_P = "gen_ai.request.top_p";
|
|
227
|
-
var ATTR_GEN_AI_REQUEST_TOP_K = "gen_ai.request.top_k";
|
|
228
|
-
var ATTR_GEN_AI_REQUEST_STOP_SEQUENCES = "gen_ai.request.stop_sequences";
|
|
229
|
-
var ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY = "gen_ai.request.frequency_penalty";
|
|
230
|
-
var ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY = "gen_ai.request.presence_penalty";
|
|
231
|
-
var ATTR_GEN_AI_RESPONSE_ID = "gen_ai.response.id";
|
|
232
|
-
var ATTR_GEN_AI_RESPONSE_MODEL = "gen_ai.response.model";
|
|
233
|
-
var ATTR_GEN_AI_RESPONSE_FINISH_REASONS = "gen_ai.response.finish_reasons";
|
|
234
|
-
var ATTR_GEN_AI_TOKEN_TYPE = "gen_ai.token.type";
|
|
235
|
-
var ATTR_GEN_AI_PROMPT = "gen_ai.prompt";
|
|
236
|
-
var ATTR_GEN_AI_COMPLETION = "gen_ai.completion";
|
|
237
|
-
var ATTR_GEN_AI_OPENAI_API_BASE = "gen_ai.openai.api_base";
|
|
238
|
-
var ATTR_EVENT_NAME = "event.name";
|
|
239
|
-
var EVENT_GEN_AI_USER_MESSAGE = "gen_ai.user.message";
|
|
240
|
-
var EVENT_GEN_AI_ASSISTANT_MESSAGE = "gen_ai.assistant.message";
|
|
241
|
-
var EVENT_GEN_AI_SYSTEM_MESSAGE = "gen_ai.system.message";
|
|
242
|
-
var EVENT_GEN_AI_TOOL_MESSAGE = "gen_ai.tool.message";
|
|
243
|
-
var METRIC_GEN_AI_CLIENT_OPERATION_DURATION = "gen_ai.client.operation.duration";
|
|
244
|
-
var METRIC_GEN_AI_CLIENT_TOKEN_USAGE = "gen_ai.client.token.usage";
|
|
245
|
-
var OPERATION_NAME_CHAT = "chat";
|
|
246
|
-
var OPERATION_NAME_EMBEDDINGS = "embeddings";
|
|
247
|
-
var TOKEN_TYPE_INPUT = "input";
|
|
248
|
-
var TOKEN_TYPE_OUTPUT = "output";
|
|
249
|
-
var PROVIDER_OPENAI = "openai";
|
|
250
|
-
var PROVIDER_ANTHROPIC = "anthropic";
|
|
251
|
-
var PROVIDER_GOOGLE = "google";
|
|
252
|
-
var PROVIDER_AMAZON = "amazon";
|
|
253
|
-
var PROVIDER_AZURE = "azure";
|
|
254
|
-
var PROVIDER_VERCEL = "vercel";
|
|
255
|
-
var PROVIDER_UNKNOWN = "unknown";
|
|
256
|
-
var SPAN_NAME_GEN_AI_CHAT = "gen_ai.chat";
|
|
257
|
-
var SPAN_NAME_GEN_AI_EMBEDDINGS = "gen_ai.embeddings";
|
|
258
|
-
|
|
259
|
-
// src/internal/instrumentation/vercel-ai/utils.ts
|
|
260
|
-
function detectProvider(model) {
|
|
261
|
-
if (typeof model === "object" && model !== null) {
|
|
262
|
-
const modelObj = model;
|
|
263
|
-
if (modelObj.provider) {
|
|
264
|
-
return {
|
|
265
|
-
system: normalizeProviderName(modelObj.provider),
|
|
266
|
-
apiBase: extractApiBase(modelObj)
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
if (modelObj.modelId) {
|
|
270
|
-
return detectProviderFromModelId(modelObj.modelId);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
if (typeof model === "string") {
|
|
274
|
-
return detectProviderFromModelId(model);
|
|
275
|
-
}
|
|
276
|
-
return { system: PROVIDER_UNKNOWN };
|
|
277
|
-
}
|
|
278
|
-
function detectProviderFromModelId(modelId) {
|
|
279
|
-
const lowerModel = modelId.toLowerCase();
|
|
280
|
-
if (lowerModel.startsWith("gpt-") || lowerModel.startsWith("text-davinci-") || lowerModel.startsWith("text-embedding-") || lowerModel.startsWith("dall-e") || lowerModel.startsWith("whisper-") || lowerModel.startsWith("tts-")) {
|
|
281
|
-
return { system: PROVIDER_OPENAI };
|
|
282
|
-
}
|
|
283
|
-
if (lowerModel.startsWith("claude-")) {
|
|
284
|
-
return { system: PROVIDER_ANTHROPIC };
|
|
285
|
-
}
|
|
286
|
-
if (lowerModel.startsWith("gemini-") || lowerModel.startsWith("palm-") || lowerModel.includes("bison") || lowerModel.includes("gecko")) {
|
|
287
|
-
return { system: PROVIDER_GOOGLE };
|
|
288
|
-
}
|
|
289
|
-
if (lowerModel.startsWith("amazon.") || lowerModel.startsWith("anthropic.claude-") || lowerModel.startsWith("ai21.") || lowerModel.startsWith("cohere.") || lowerModel.startsWith("meta.llama")) {
|
|
290
|
-
return { system: PROVIDER_AMAZON };
|
|
291
|
-
}
|
|
292
|
-
if (lowerModel.includes("azure") || lowerModel.includes(".openai.azure.com")) {
|
|
293
|
-
return { system: PROVIDER_AZURE };
|
|
294
|
-
}
|
|
295
|
-
const parts = modelId.split(/[-._/]/);
|
|
296
|
-
if (parts.length > 0 && parts[0]) {
|
|
297
|
-
return { system: normalizeProviderName(parts[0]) };
|
|
298
|
-
}
|
|
299
|
-
return { system: PROVIDER_UNKNOWN };
|
|
300
|
-
}
|
|
301
|
-
function normalizeProviderName(provider) {
|
|
302
|
-
const normalized = provider.toLowerCase().trim();
|
|
303
|
-
switch (normalized) {
|
|
304
|
-
case "openai":
|
|
305
|
-
case "open-ai":
|
|
306
|
-
case "open_ai": {
|
|
307
|
-
return PROVIDER_OPENAI;
|
|
308
|
-
}
|
|
309
|
-
case "anthropic":
|
|
310
|
-
case "claude": {
|
|
311
|
-
return PROVIDER_ANTHROPIC;
|
|
312
|
-
}
|
|
313
|
-
case "google":
|
|
314
|
-
case "vertex":
|
|
315
|
-
case "vertexai":
|
|
316
|
-
case "vertex-ai":
|
|
317
|
-
case "gemini": {
|
|
318
|
-
return PROVIDER_GOOGLE;
|
|
319
|
-
}
|
|
320
|
-
case "amazon":
|
|
321
|
-
case "aws":
|
|
322
|
-
case "bedrock":
|
|
323
|
-
case "amazon-bedrock": {
|
|
324
|
-
return PROVIDER_AMAZON;
|
|
325
|
-
}
|
|
326
|
-
case "azure":
|
|
327
|
-
case "azure-openai":
|
|
328
|
-
case "microsoft": {
|
|
329
|
-
return PROVIDER_AZURE;
|
|
330
|
-
}
|
|
331
|
-
case "vercel":
|
|
332
|
-
case "vercel-ai": {
|
|
333
|
-
return PROVIDER_VERCEL;
|
|
334
|
-
}
|
|
335
|
-
default: {
|
|
336
|
-
return normalized;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
function extractApiBase(model) {
|
|
341
|
-
if (typeof model === "object" && model !== null) {
|
|
342
|
-
const anyModel = model;
|
|
343
|
-
return anyModel.apiBase || anyModel.baseURL || anyModel.endpoint || void 0;
|
|
344
|
-
}
|
|
345
|
-
return void 0;
|
|
346
|
-
}
|
|
347
|
-
function extractModelId(model) {
|
|
348
|
-
if (typeof model === "string") {
|
|
349
|
-
return model;
|
|
350
|
-
}
|
|
351
|
-
if (typeof model === "object" && model !== null) {
|
|
352
|
-
return model.modelId || "unknown";
|
|
353
|
-
}
|
|
354
|
-
return "unknown";
|
|
355
|
-
}
|
|
356
|
-
function messagesToAttributes(messages, prefix, captureContent) {
|
|
357
|
-
const attributes = {};
|
|
358
|
-
for (const [index, msg] of messages.entries()) {
|
|
359
|
-
const baseKey = `${prefix}.${index}`;
|
|
360
|
-
attributes[`${baseKey}.role`] = msg.role;
|
|
361
|
-
if (captureContent && msg.content) {
|
|
362
|
-
if (typeof msg.content === "string") {
|
|
363
|
-
attributes[`${baseKey}.content`] = msg.content;
|
|
364
|
-
} else if (Array.isArray(msg.content)) {
|
|
365
|
-
const textParts = msg.content.filter((part) => part.type === "text" && part.text).map((part) => part.text).join(" ");
|
|
366
|
-
if (textParts) {
|
|
367
|
-
attributes[`${baseKey}.content`] = textParts;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
if (msg.toolInvocations && msg.toolInvocations.length > 0) {
|
|
372
|
-
attributes[`${baseKey}.tool_calls`] = msg.toolInvocations.length;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
return attributes;
|
|
376
|
-
}
|
|
377
|
-
function promptToAttributes(prompt, captureContent) {
|
|
378
|
-
const attributes = {};
|
|
379
|
-
attributes[`${ATTR_GEN_AI_PROMPT}.0.role`] = "user";
|
|
380
|
-
if (captureContent) {
|
|
381
|
-
attributes[`${ATTR_GEN_AI_PROMPT}.0.content`] = prompt;
|
|
382
|
-
}
|
|
383
|
-
return attributes;
|
|
384
|
-
}
|
|
385
|
-
function completionToAttributes(text, finishReason, captureContent) {
|
|
386
|
-
const attributes = {};
|
|
387
|
-
attributes[`${ATTR_GEN_AI_COMPLETION}.0.role`] = "assistant";
|
|
388
|
-
if (captureContent) {
|
|
389
|
-
attributes[`${ATTR_GEN_AI_COMPLETION}.0.content`] = text;
|
|
390
|
-
}
|
|
391
|
-
if (finishReason) {
|
|
392
|
-
attributes[`${ATTR_GEN_AI_COMPLETION}.0.finish_reason`] = finishReason;
|
|
393
|
-
}
|
|
394
|
-
return attributes;
|
|
395
|
-
}
|
|
396
|
-
function tokenUsageToAttributes(usage) {
|
|
397
|
-
if (!usage) {
|
|
398
|
-
return {};
|
|
399
|
-
}
|
|
400
|
-
const attributes = {};
|
|
401
|
-
if (usage.inputTokens !== void 0) {
|
|
402
|
-
attributes["gen_ai.usage.prompt_tokens"] = usage.inputTokens;
|
|
403
|
-
attributes["gen_ai.usage.input_tokens"] = usage.inputTokens;
|
|
404
|
-
attributes["llm.usage.prompt_tokens"] = usage.inputTokens;
|
|
405
|
-
} else if (usage.promptTokens !== void 0) {
|
|
406
|
-
attributes["gen_ai.usage.prompt_tokens"] = usage.promptTokens;
|
|
407
|
-
attributes["gen_ai.usage.input_tokens"] = usage.promptTokens;
|
|
408
|
-
attributes["llm.usage.prompt_tokens"] = usage.promptTokens;
|
|
409
|
-
}
|
|
410
|
-
if (usage.outputTokens !== void 0) {
|
|
411
|
-
attributes["gen_ai.usage.completion_tokens"] = usage.outputTokens;
|
|
412
|
-
attributes["gen_ai.usage.output_tokens"] = usage.outputTokens;
|
|
413
|
-
attributes["llm.usage.completion_tokens"] = usage.outputTokens;
|
|
414
|
-
} else if (usage.completionTokens !== void 0) {
|
|
415
|
-
attributes["gen_ai.usage.completion_tokens"] = usage.completionTokens;
|
|
416
|
-
attributes["gen_ai.usage.output_tokens"] = usage.completionTokens;
|
|
417
|
-
attributes["llm.usage.completion_tokens"] = usage.completionTokens;
|
|
418
|
-
}
|
|
419
|
-
if (usage.totalTokens === void 0) {
|
|
420
|
-
const inputTokens = usage.inputTokens || usage.promptTokens;
|
|
421
|
-
const outputTokens = usage.outputTokens || usage.completionTokens;
|
|
422
|
-
if (inputTokens !== void 0 && outputTokens !== void 0) {
|
|
423
|
-
const totalTokens = inputTokens + outputTokens;
|
|
424
|
-
attributes["gen_ai.usage.total_tokens"] = totalTokens;
|
|
425
|
-
attributes["llm.usage.total_tokens"] = totalTokens;
|
|
426
|
-
}
|
|
427
|
-
} else {
|
|
428
|
-
attributes["gen_ai.usage.total_tokens"] = usage.totalTokens;
|
|
429
|
-
attributes["llm.usage.total_tokens"] = usage.totalTokens;
|
|
430
|
-
}
|
|
431
|
-
return attributes;
|
|
432
|
-
}
|
|
433
|
-
function shouldRecordError(error) {
|
|
434
|
-
if (error instanceof Error) {
|
|
435
|
-
const message = error.message.toLowerCase();
|
|
436
|
-
if (message.includes("abort") || message.includes("cancel")) {
|
|
437
|
-
return false;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
return true;
|
|
441
|
-
}
|
|
442
|
-
function getEnvBool(name) {
|
|
443
|
-
const value = process.env[name];
|
|
444
|
-
if (value === void 0) {
|
|
445
|
-
return void 0;
|
|
446
|
-
}
|
|
447
|
-
return value.toLowerCase() === "true" || value === "1";
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// src/internal/instrumentation/vercel-ai/patchers/base-patcher.ts
|
|
451
|
-
var BasePatcher = class {
|
|
452
|
-
constructor(context8) {
|
|
453
|
-
this.context = context8;
|
|
454
|
-
}
|
|
455
|
-
createSpan(spanName, params, operationName, additionalAttributes) {
|
|
456
|
-
const provider = detectProvider(params.model);
|
|
457
|
-
const modelId = extractModelId(params.model);
|
|
458
|
-
const span = this.context.tracer.startSpan(spanName, {
|
|
459
|
-
kind: import_api2.SpanKind.CLIENT,
|
|
460
|
-
attributes: {
|
|
461
|
-
[ATTR_GEN_AI_SYSTEM]: provider.system,
|
|
462
|
-
[ATTR_GEN_AI_OPERATION_NAME]: operationName,
|
|
463
|
-
[ATTR_GEN_AI_REQUEST_MODEL]: modelId,
|
|
464
|
-
...params.maxTokens && { [ATTR_GEN_AI_REQUEST_MAX_TOKENS]: params.maxTokens },
|
|
465
|
-
...params.temperature !== void 0 && {
|
|
466
|
-
[ATTR_GEN_AI_REQUEST_TEMPERATURE]: params.temperature
|
|
467
|
-
},
|
|
468
|
-
...params.topP !== void 0 && { [ATTR_GEN_AI_REQUEST_TOP_P]: params.topP },
|
|
469
|
-
...params.topK !== void 0 && { [ATTR_GEN_AI_REQUEST_TOP_K]: params.topK },
|
|
470
|
-
...params.frequencyPenalty !== void 0 && {
|
|
471
|
-
[ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY]: params.frequencyPenalty
|
|
472
|
-
},
|
|
473
|
-
...params.presencePenalty !== void 0 && {
|
|
474
|
-
[ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY]: params.presencePenalty
|
|
475
|
-
},
|
|
476
|
-
...params.stopSequences && {
|
|
477
|
-
[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES]: params.stopSequences
|
|
478
|
-
},
|
|
479
|
-
...provider.apiBase && { [ATTR_GEN_AI_OPENAI_API_BASE]: provider.apiBase },
|
|
480
|
-
...additionalAttributes
|
|
481
|
-
}
|
|
482
|
-
});
|
|
483
|
-
return { span, provider, modelId };
|
|
484
|
-
}
|
|
485
|
-
handleError(error, span) {
|
|
486
|
-
if (shouldRecordError(error)) {
|
|
487
|
-
span.recordException(error);
|
|
488
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR, message: error.message });
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
finalizeDuration(span, startTime, config, provider, modelId, operationName) {
|
|
492
|
-
if (config.enableMetrics) {
|
|
493
|
-
const duration = (globalThis.performance.now() - startTime) / 1e3;
|
|
494
|
-
this.context.recordDurationMetric(duration, provider.system, modelId, operationName);
|
|
495
|
-
}
|
|
496
|
-
span.end();
|
|
497
|
-
}
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
// src/internal/instrumentation/vercel-ai/patchers/generate-text-patcher.ts
|
|
501
|
-
var import_api3 = require("@opentelemetry/api");
|
|
502
|
-
var GenerateTextPatcher = class extends BasePatcher {
|
|
503
|
-
patch(original) {
|
|
504
|
-
return async (params) => {
|
|
505
|
-
const config = this.context.getConfig();
|
|
506
|
-
const startTime = globalThis.performance.now();
|
|
507
|
-
const { span, provider, modelId } = this.createSpan(
|
|
508
|
-
SPAN_NAME_GEN_AI_CHAT,
|
|
509
|
-
params,
|
|
510
|
-
OPERATION_NAME_CHAT
|
|
511
|
-
);
|
|
512
|
-
if (params.prompt) {
|
|
513
|
-
span.setAttributes(
|
|
514
|
-
promptToAttributes(params.prompt, config.captureMessageContent || false)
|
|
515
|
-
);
|
|
516
|
-
} else if (params.messages) {
|
|
517
|
-
span.setAttributes(
|
|
518
|
-
messagesToAttributes(
|
|
519
|
-
params.messages,
|
|
520
|
-
"gen_ai.prompt",
|
|
521
|
-
config.captureMessageContent || false
|
|
522
|
-
)
|
|
523
|
-
);
|
|
524
|
-
if (config.emitEvents) {
|
|
525
|
-
this.context.emitMessageEvents(params.messages, provider.system, span);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
try {
|
|
529
|
-
const result = await import_api3.context.with(
|
|
530
|
-
import_api3.trace.setSpan(import_api3.context.active(), span),
|
|
531
|
-
() => original(params)
|
|
532
|
-
);
|
|
533
|
-
if (result.response) {
|
|
534
|
-
span.setAttributes({
|
|
535
|
-
...result.response.id && { [ATTR_GEN_AI_RESPONSE_ID]: result.response.id },
|
|
536
|
-
...result.response.model && { [ATTR_GEN_AI_RESPONSE_MODEL]: result.response.model }
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
|
-
if (result.finishReason) {
|
|
540
|
-
span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, [result.finishReason]);
|
|
541
|
-
}
|
|
542
|
-
span.setAttributes(
|
|
543
|
-
completionToAttributes(
|
|
544
|
-
result.text,
|
|
545
|
-
result.finishReason,
|
|
546
|
-
config.captureMessageContent || false
|
|
547
|
-
)
|
|
548
|
-
);
|
|
549
|
-
const usage = result.usage || result.totalUsage || result.steps?.[0]?.usage;
|
|
550
|
-
if (usage) {
|
|
551
|
-
span.setAttributes(tokenUsageToAttributes(usage));
|
|
552
|
-
if (config.enableMetrics) {
|
|
553
|
-
this.context.recordTokenMetrics(usage, provider.system, modelId);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
if (config.emitEvents) {
|
|
557
|
-
this.context.emitAssistantMessageEvent(result.text, provider.system, span);
|
|
558
|
-
}
|
|
559
|
-
span.setStatus({ code: import_api3.SpanStatusCode.OK });
|
|
560
|
-
return result;
|
|
561
|
-
} catch (error) {
|
|
562
|
-
this.handleError(error, span);
|
|
563
|
-
throw error;
|
|
564
|
-
} finally {
|
|
565
|
-
this.finalizeDuration(span, startTime, config, provider, modelId, OPERATION_NAME_CHAT);
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
};
|
|
570
|
-
|
|
571
|
-
// src/internal/instrumentation/vercel-ai/patchers/stream-text-patcher.ts
|
|
572
|
-
var import_api4 = require("@opentelemetry/api");
|
|
573
|
-
var StreamTextPatcher = class extends BasePatcher {
|
|
574
|
-
constructor(context8, streamHandler) {
|
|
575
|
-
super(context8);
|
|
576
|
-
this.streamHandler = streamHandler;
|
|
577
|
-
}
|
|
578
|
-
patch(original) {
|
|
579
|
-
return async (params) => {
|
|
580
|
-
const config = this.context.getConfig();
|
|
581
|
-
const startTime = globalThis.performance.now();
|
|
582
|
-
const { span, provider, modelId } = this.createSpan(
|
|
583
|
-
SPAN_NAME_GEN_AI_CHAT,
|
|
584
|
-
params,
|
|
585
|
-
OPERATION_NAME_CHAT,
|
|
586
|
-
{ "gen_ai.streaming": true }
|
|
587
|
-
);
|
|
588
|
-
if (params.prompt) {
|
|
589
|
-
span.setAttributes(
|
|
590
|
-
promptToAttributes(params.prompt, config.captureMessageContent || false)
|
|
591
|
-
);
|
|
592
|
-
} else if (params.messages) {
|
|
593
|
-
span.setAttributes(
|
|
594
|
-
messagesToAttributes(
|
|
595
|
-
params.messages,
|
|
596
|
-
"gen_ai.prompt",
|
|
597
|
-
config.captureMessageContent || false
|
|
598
|
-
)
|
|
599
|
-
);
|
|
600
|
-
if (config.emitEvents) {
|
|
601
|
-
this.context.emitMessageEvents(params.messages, provider.system, span);
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
try {
|
|
605
|
-
const stream = await import_api4.context.with(
|
|
606
|
-
import_api4.trace.setSpan(import_api4.context.active(), span),
|
|
607
|
-
() => original(params)
|
|
608
|
-
);
|
|
609
|
-
return this.streamHandler.wrapStream(stream, span, config, provider, modelId, startTime);
|
|
610
|
-
} catch (error) {
|
|
611
|
-
this.handleError(error, span);
|
|
612
|
-
span.end();
|
|
613
|
-
throw error;
|
|
614
|
-
}
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
};
|
|
618
|
-
|
|
619
|
-
// src/internal/instrumentation/vercel-ai/patchers/embeddings-patcher.ts
|
|
620
|
-
var import_api5 = require("@opentelemetry/api");
|
|
621
|
-
var EmbeddingsPatcher = class extends BasePatcher {
|
|
622
|
-
patch(original, isMany = false) {
|
|
623
|
-
return async (params) => {
|
|
624
|
-
const config = this.context.getConfig();
|
|
625
|
-
const startTime = globalThis.performance.now();
|
|
626
|
-
const additionalAttributes = isMany ? { "gen_ai.embeddings.count": params.values ? params.values.length : 0 } : {};
|
|
627
|
-
const { span, provider, modelId } = this.createSpan(
|
|
628
|
-
SPAN_NAME_GEN_AI_EMBEDDINGS,
|
|
629
|
-
params,
|
|
630
|
-
OPERATION_NAME_EMBEDDINGS,
|
|
631
|
-
additionalAttributes
|
|
632
|
-
);
|
|
633
|
-
if (!isMany && config.captureMessageContent && params.value) {
|
|
634
|
-
span.setAttribute("gen_ai.prompt.0.content", params.value);
|
|
635
|
-
}
|
|
636
|
-
try {
|
|
637
|
-
const result = await import_api5.context.with(
|
|
638
|
-
import_api5.trace.setSpan(import_api5.context.active(), span),
|
|
639
|
-
() => original(params)
|
|
640
|
-
);
|
|
641
|
-
if (result.response) {
|
|
642
|
-
span.setAttributes({
|
|
643
|
-
...result.response.id && { [ATTR_GEN_AI_RESPONSE_ID]: result.response.id },
|
|
644
|
-
...result.response.model && { [ATTR_GEN_AI_RESPONSE_MODEL]: result.response.model }
|
|
645
|
-
});
|
|
646
|
-
}
|
|
647
|
-
if (isMany) {
|
|
648
|
-
if (result.embeddings && result.embeddings.length > 0 && result.embeddings[0]) {
|
|
649
|
-
span.setAttribute("gen_ai.response.embedding_dimensions", result.embeddings[0].length);
|
|
650
|
-
}
|
|
651
|
-
} else {
|
|
652
|
-
if (result.embedding) {
|
|
653
|
-
span.setAttribute("gen_ai.response.embedding_dimensions", result.embedding.length);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
if (result.usage) {
|
|
657
|
-
span.setAttributes(tokenUsageToAttributes(result.usage));
|
|
658
|
-
if (config.enableMetrics) {
|
|
659
|
-
this.context.recordTokenMetrics(result.usage, provider.system, modelId);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
span.setStatus({ code: import_api5.SpanStatusCode.OK });
|
|
663
|
-
return result;
|
|
664
|
-
} catch (error) {
|
|
665
|
-
this.handleError(error, span);
|
|
666
|
-
throw error;
|
|
667
|
-
} finally {
|
|
668
|
-
this.finalizeDuration(span, startTime, config, provider, modelId, OPERATION_NAME_EMBEDDINGS);
|
|
669
|
-
}
|
|
670
|
-
};
|
|
671
|
-
}
|
|
672
|
-
};
|
|
673
|
-
|
|
674
|
-
// src/internal/instrumentation/vercel-ai/stream-handler.ts
|
|
675
|
-
var import_api6 = require("@opentelemetry/api");
|
|
676
|
-
var StreamHandler = class {
|
|
677
|
-
constructor(context8) {
|
|
678
|
-
this.context = context8;
|
|
679
|
-
}
|
|
680
|
-
wrapStream(stream, span, config, provider, modelId, startTime) {
|
|
681
|
-
const self = this;
|
|
682
|
-
let fullText = "";
|
|
683
|
-
let finishReason;
|
|
684
|
-
let usage;
|
|
685
|
-
let response;
|
|
686
|
-
const wrappedStream = new Proxy(stream, {
|
|
687
|
-
get(target, prop) {
|
|
688
|
-
if (prop === Symbol.asyncIterator) {
|
|
689
|
-
return async function* () {
|
|
690
|
-
try {
|
|
691
|
-
for await (const chunk of target) {
|
|
692
|
-
if (chunk.type === "text-delta" && chunk.textDelta) {
|
|
693
|
-
fullText += chunk.textDelta;
|
|
694
|
-
} else if (chunk.type === "finish") {
|
|
695
|
-
finishReason = chunk.finishReason;
|
|
696
|
-
usage = chunk.usage;
|
|
697
|
-
} else if (chunk.type === "response-metadata") {
|
|
698
|
-
response = chunk.response;
|
|
699
|
-
}
|
|
700
|
-
yield chunk;
|
|
701
|
-
}
|
|
702
|
-
} finally {
|
|
703
|
-
self.finalizeStream(
|
|
704
|
-
span,
|
|
705
|
-
config,
|
|
706
|
-
provider,
|
|
707
|
-
modelId,
|
|
708
|
-
startTime,
|
|
709
|
-
fullText,
|
|
710
|
-
finishReason,
|
|
711
|
-
usage,
|
|
712
|
-
response
|
|
713
|
-
);
|
|
714
|
-
}
|
|
715
|
-
};
|
|
716
|
-
}
|
|
717
|
-
if (prop === "textStream" || prop === "fullStream") {
|
|
718
|
-
const originalStream = target[prop];
|
|
719
|
-
return {
|
|
720
|
-
[Symbol.asyncIterator]: async function* () {
|
|
721
|
-
try {
|
|
722
|
-
for await (const chunk of originalStream) {
|
|
723
|
-
if (prop === "textStream") {
|
|
724
|
-
fullText += chunk;
|
|
725
|
-
}
|
|
726
|
-
yield chunk;
|
|
727
|
-
}
|
|
728
|
-
} finally {
|
|
729
|
-
const streamUsage = await target.usage.catch(() => null);
|
|
730
|
-
if (streamUsage) {
|
|
731
|
-
usage = streamUsage;
|
|
732
|
-
}
|
|
733
|
-
self.finalizeStream(
|
|
734
|
-
span,
|
|
735
|
-
config,
|
|
736
|
-
provider,
|
|
737
|
-
modelId,
|
|
738
|
-
startTime,
|
|
739
|
-
fullText,
|
|
740
|
-
finishReason,
|
|
741
|
-
usage,
|
|
742
|
-
response
|
|
743
|
-
);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
|
-
const value = target[prop];
|
|
749
|
-
if (typeof value === "function") {
|
|
750
|
-
return value.bind(target);
|
|
751
|
-
}
|
|
752
|
-
return value;
|
|
753
|
-
}
|
|
754
|
-
});
|
|
755
|
-
return wrappedStream;
|
|
756
|
-
}
|
|
757
|
-
finalizeStream(span, config, provider, modelId, startTime, fullText, finishReason, usage, response) {
|
|
758
|
-
if (response) {
|
|
759
|
-
span.setAttributes({
|
|
760
|
-
...response.id && { [ATTR_GEN_AI_RESPONSE_ID]: response.id },
|
|
761
|
-
...response.model && { [ATTR_GEN_AI_RESPONSE_MODEL]: response.model }
|
|
762
|
-
});
|
|
763
|
-
}
|
|
764
|
-
if (finishReason) {
|
|
765
|
-
span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, [finishReason]);
|
|
766
|
-
}
|
|
767
|
-
if (fullText) {
|
|
768
|
-
span.setAttributes(
|
|
769
|
-
completionToAttributes(
|
|
770
|
-
fullText,
|
|
771
|
-
finishReason,
|
|
772
|
-
config.captureMessageContent || false
|
|
773
|
-
)
|
|
774
|
-
);
|
|
775
|
-
}
|
|
776
|
-
if (usage) {
|
|
777
|
-
span.setAttributes(tokenUsageToAttributes(usage));
|
|
778
|
-
if (config.enableMetrics) {
|
|
779
|
-
this.context.recordTokenMetrics(usage, provider.system, modelId);
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
if (config.enableMetrics) {
|
|
783
|
-
const duration = (performance.now() - startTime) / 1e3;
|
|
784
|
-
this.context.recordDurationMetric(duration, provider.system, modelId, OPERATION_NAME_CHAT);
|
|
785
|
-
}
|
|
786
|
-
span.setStatus({ code: import_api6.SpanStatusCode.OK });
|
|
787
|
-
span.end();
|
|
788
|
-
}
|
|
789
|
-
};
|
|
790
|
-
|
|
791
|
-
// src/internal/instrumentation/vercel-ai/telemetry-recorder.ts
|
|
792
|
-
var import_api7 = require("@opentelemetry/api");
|
|
793
|
-
var import_api_logs = require("@opentelemetry/api-logs");
|
|
794
|
-
var TelemetryRecorder = class {
|
|
795
|
-
constructor(genaiClientOperationDuration, genaiClientTokenUsage, logger2) {
|
|
796
|
-
this.genaiClientOperationDuration = genaiClientOperationDuration;
|
|
797
|
-
this.genaiClientTokenUsage = genaiClientTokenUsage;
|
|
798
|
-
this.logger = logger2;
|
|
799
|
-
}
|
|
800
|
-
/**
|
|
801
|
-
* Record token usage metrics
|
|
802
|
-
*/
|
|
803
|
-
recordTokenMetrics(usage, system, model) {
|
|
804
|
-
if (!this.genaiClientTokenUsage) {
|
|
805
|
-
return;
|
|
806
|
-
}
|
|
807
|
-
const commonAttrs = {
|
|
808
|
-
[ATTR_GEN_AI_SYSTEM]: system,
|
|
809
|
-
[ATTR_GEN_AI_REQUEST_MODEL]: model
|
|
810
|
-
};
|
|
811
|
-
const inputTokens = usage.inputTokens || usage.promptTokens;
|
|
812
|
-
const outputTokens = usage.outputTokens || usage.completionTokens;
|
|
813
|
-
if (inputTokens !== void 0) {
|
|
814
|
-
this.genaiClientTokenUsage.record(inputTokens, {
|
|
815
|
-
...commonAttrs,
|
|
816
|
-
[ATTR_GEN_AI_TOKEN_TYPE]: TOKEN_TYPE_INPUT
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
if (outputTokens !== void 0) {
|
|
820
|
-
this.genaiClientTokenUsage.record(outputTokens, {
|
|
821
|
-
...commonAttrs,
|
|
822
|
-
[ATTR_GEN_AI_TOKEN_TYPE]: TOKEN_TYPE_OUTPUT
|
|
823
|
-
});
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
/**
|
|
827
|
-
* Record operation duration metric
|
|
828
|
-
*/
|
|
829
|
-
recordDurationMetric(duration, system, model, operation) {
|
|
830
|
-
if (!this.genaiClientOperationDuration) {
|
|
831
|
-
return;
|
|
832
|
-
}
|
|
833
|
-
this.genaiClientOperationDuration.record(duration, {
|
|
834
|
-
[ATTR_GEN_AI_SYSTEM]: system,
|
|
835
|
-
[ATTR_GEN_AI_REQUEST_MODEL]: model,
|
|
836
|
-
[ATTR_GEN_AI_OPERATION_NAME]: operation
|
|
837
|
-
});
|
|
838
|
-
}
|
|
839
|
-
/**
|
|
840
|
-
* Emit message events
|
|
841
|
-
*/
|
|
842
|
-
emitMessageEvents(messages, system, span) {
|
|
843
|
-
if (!this.logger) {
|
|
844
|
-
return;
|
|
845
|
-
}
|
|
846
|
-
const ctx = import_api7.trace.setSpan(import_api7.context.active(), span);
|
|
847
|
-
for (const msg of messages) {
|
|
848
|
-
let eventName;
|
|
849
|
-
switch (msg.role) {
|
|
850
|
-
case "system": {
|
|
851
|
-
eventName = EVENT_GEN_AI_SYSTEM_MESSAGE;
|
|
852
|
-
break;
|
|
853
|
-
}
|
|
854
|
-
case "user": {
|
|
855
|
-
eventName = EVENT_GEN_AI_USER_MESSAGE;
|
|
856
|
-
break;
|
|
857
|
-
}
|
|
858
|
-
case "assistant": {
|
|
859
|
-
eventName = EVENT_GEN_AI_ASSISTANT_MESSAGE;
|
|
860
|
-
break;
|
|
861
|
-
}
|
|
862
|
-
case "tool":
|
|
863
|
-
case "function": {
|
|
864
|
-
eventName = EVENT_GEN_AI_TOOL_MESSAGE;
|
|
865
|
-
break;
|
|
866
|
-
}
|
|
867
|
-
default: {
|
|
868
|
-
continue;
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
this.logger.emit({
|
|
872
|
-
timestamp: Date.now(),
|
|
873
|
-
context: ctx,
|
|
874
|
-
severityNumber: import_api_logs.SeverityNumber.INFO,
|
|
875
|
-
attributes: {
|
|
876
|
-
[ATTR_EVENT_NAME]: eventName,
|
|
877
|
-
[ATTR_GEN_AI_SYSTEM]: system
|
|
878
|
-
},
|
|
879
|
-
body: {
|
|
880
|
-
role: msg.role,
|
|
881
|
-
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
|
|
882
|
-
name: msg.name
|
|
883
|
-
}
|
|
884
|
-
});
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
/**
|
|
888
|
-
* Emit assistant message event
|
|
889
|
-
*/
|
|
890
|
-
emitAssistantMessageEvent(text, system, span) {
|
|
891
|
-
if (!this.logger) {
|
|
892
|
-
return;
|
|
893
|
-
}
|
|
894
|
-
const ctx = import_api7.trace.setSpan(import_api7.context.active(), span);
|
|
895
|
-
this.logger.emit({
|
|
896
|
-
timestamp: Date.now(),
|
|
897
|
-
context: ctx,
|
|
898
|
-
severityNumber: import_api_logs.SeverityNumber.INFO,
|
|
899
|
-
attributes: {
|
|
900
|
-
[ATTR_EVENT_NAME]: EVENT_GEN_AI_ASSISTANT_MESSAGE,
|
|
901
|
-
[ATTR_GEN_AI_SYSTEM]: system
|
|
902
|
-
},
|
|
903
|
-
body: {
|
|
904
|
-
role: "assistant",
|
|
905
|
-
content: text
|
|
906
|
-
}
|
|
907
|
-
});
|
|
908
|
-
}
|
|
909
|
-
};
|
|
910
|
-
|
|
911
|
-
// src/internal/instrumentation/vercel-ai/instrumentation.ts
|
|
912
|
-
var PACKAGE_NAME = "@brizz/vercel-ai-instrumentation";
|
|
913
|
-
var PACKAGE_VERSION = "0.1.0";
|
|
914
|
-
var VercelAIInstrumentation = class _VercelAIInstrumentation extends import_instrumentation.InstrumentationBase {
|
|
915
|
-
_genaiClientOperationDuration;
|
|
916
|
-
_genaiClientTokenUsage;
|
|
917
|
-
_telemetryRecorder;
|
|
918
|
-
_streamHandler;
|
|
919
|
-
_patchers = /* @__PURE__ */ new Map();
|
|
920
|
-
// Holds last patched namespace when available (reserved for future factory wrapping)
|
|
921
|
-
_vercelAiNamespace = null;
|
|
922
|
-
static _WRAPPED_SYMBOL = Symbol.for("brizz.vercel-ai.patched");
|
|
923
|
-
constructor(config = {}) {
|
|
924
|
-
super(PACKAGE_NAME, PACKAGE_VERSION, config);
|
|
925
|
-
const cfg = this.getConfig();
|
|
926
|
-
const envCC = getEnvBool("OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT");
|
|
927
|
-
if (envCC !== void 0) {
|
|
928
|
-
cfg.captureMessageContent = envCC;
|
|
929
|
-
}
|
|
930
|
-
this._initializeComponents();
|
|
931
|
-
}
|
|
932
|
-
setConfig(config = {}) {
|
|
933
|
-
const {
|
|
934
|
-
captureMessageContent = true,
|
|
935
|
-
enableMetrics = true,
|
|
936
|
-
emitEvents = true,
|
|
937
|
-
...validConfig
|
|
938
|
-
} = config;
|
|
939
|
-
const fullConfig = {
|
|
940
|
-
...validConfig,
|
|
941
|
-
captureMessageContent,
|
|
942
|
-
enableMetrics,
|
|
943
|
-
emitEvents
|
|
944
|
-
};
|
|
945
|
-
super.setConfig(fullConfig);
|
|
946
|
-
}
|
|
947
|
-
_initializeComponents() {
|
|
948
|
-
this._telemetryRecorder = new TelemetryRecorder(
|
|
949
|
-
this._genaiClientOperationDuration,
|
|
950
|
-
this._genaiClientTokenUsage,
|
|
951
|
-
this.logger
|
|
952
|
-
);
|
|
953
|
-
this._streamHandler = new StreamHandler({
|
|
954
|
-
recordTokenMetrics: this._telemetryRecorder.recordTokenMetrics.bind(this._telemetryRecorder),
|
|
955
|
-
recordDurationMetric: this._telemetryRecorder.recordDurationMetric.bind(
|
|
956
|
-
this._telemetryRecorder
|
|
957
|
-
)
|
|
958
|
-
});
|
|
959
|
-
const patcherContext = {
|
|
960
|
-
tracer: this.tracer,
|
|
961
|
-
getConfig: this.getConfig.bind(this),
|
|
962
|
-
recordTokenMetrics: this._telemetryRecorder.recordTokenMetrics.bind(this._telemetryRecorder),
|
|
963
|
-
recordDurationMetric: this._telemetryRecorder.recordDurationMetric.bind(
|
|
964
|
-
this._telemetryRecorder
|
|
965
|
-
),
|
|
966
|
-
emitMessageEvents: this._telemetryRecorder.emitMessageEvents.bind(this._telemetryRecorder),
|
|
967
|
-
emitAssistantMessageEvent: this._telemetryRecorder.emitAssistantMessageEvent.bind(
|
|
968
|
-
this._telemetryRecorder
|
|
969
|
-
)
|
|
970
|
-
};
|
|
971
|
-
this._patchers.set("generateText", new GenerateTextPatcher(patcherContext));
|
|
972
|
-
this._patchers.set("streamText", new StreamTextPatcher(patcherContext, this._streamHandler));
|
|
973
|
-
this._patchers.set("embed", new EmbeddingsPatcher(patcherContext));
|
|
974
|
-
this._patchers.set("embedMany", new EmbeddingsPatcher(patcherContext));
|
|
975
|
-
}
|
|
976
|
-
init() {
|
|
977
|
-
return [
|
|
978
|
-
new import_instrumentation.InstrumentationNodeModuleDefinition(
|
|
979
|
-
"ai",
|
|
980
|
-
[">=4.0.0 <6"],
|
|
981
|
-
(moduleExports) => {
|
|
982
|
-
logger.info("Starting instrumentation of Vercel AI SDK module");
|
|
983
|
-
this._vercelAiNamespace = moduleExports;
|
|
984
|
-
const patched = this._patchModuleExports(moduleExports);
|
|
985
|
-
return patched ?? moduleExports;
|
|
986
|
-
},
|
|
987
|
-
(moduleExports) => {
|
|
988
|
-
logger.debug("Uninstrumenting @vercel/ai module");
|
|
989
|
-
return moduleExports;
|
|
990
|
-
}
|
|
991
|
-
)
|
|
992
|
-
];
|
|
993
|
-
}
|
|
994
|
-
_updateMetricInstruments() {
|
|
995
|
-
const config = this.getConfig();
|
|
996
|
-
if (!config.enableMetrics) {
|
|
997
|
-
return;
|
|
998
|
-
}
|
|
999
|
-
this._genaiClientOperationDuration = this.meter.createHistogram(
|
|
1000
|
-
METRIC_GEN_AI_CLIENT_OPERATION_DURATION,
|
|
1001
|
-
{
|
|
1002
|
-
description: "GenAI operation duration",
|
|
1003
|
-
unit: "s",
|
|
1004
|
-
advice: {
|
|
1005
|
-
explicitBucketBoundaries: [
|
|
1006
|
-
0.01,
|
|
1007
|
-
0.02,
|
|
1008
|
-
0.04,
|
|
1009
|
-
0.08,
|
|
1010
|
-
0.16,
|
|
1011
|
-
0.32,
|
|
1012
|
-
0.64,
|
|
1013
|
-
1.28,
|
|
1014
|
-
2.56,
|
|
1015
|
-
5.12,
|
|
1016
|
-
10.24,
|
|
1017
|
-
20.48,
|
|
1018
|
-
40.96,
|
|
1019
|
-
81.92
|
|
1020
|
-
]
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
);
|
|
1024
|
-
this._genaiClientTokenUsage = this.meter.createHistogram(METRIC_GEN_AI_CLIENT_TOKEN_USAGE, {
|
|
1025
|
-
description: "Measures number of input and output tokens used",
|
|
1026
|
-
unit: "{token}",
|
|
1027
|
-
advice: {
|
|
1028
|
-
explicitBucketBoundaries: [
|
|
1029
|
-
1,
|
|
1030
|
-
4,
|
|
1031
|
-
16,
|
|
1032
|
-
64,
|
|
1033
|
-
256,
|
|
1034
|
-
1024,
|
|
1035
|
-
4096,
|
|
1036
|
-
16384,
|
|
1037
|
-
65536,
|
|
1038
|
-
262144,
|
|
1039
|
-
1048576,
|
|
1040
|
-
4194304,
|
|
1041
|
-
16777216,
|
|
1042
|
-
67108864
|
|
1043
|
-
]
|
|
1044
|
-
}
|
|
1045
|
-
});
|
|
1046
|
-
this._telemetryRecorder = new TelemetryRecorder(
|
|
1047
|
-
this._genaiClientOperationDuration,
|
|
1048
|
-
this._genaiClientTokenUsage,
|
|
1049
|
-
this.logger
|
|
1050
|
-
);
|
|
1051
|
-
}
|
|
1052
|
-
/**
|
|
1053
|
-
* Patch known AI SDK functions in-place on the provided module exports object.
|
|
1054
|
-
* This approach is compatible with both CJS and ESM module loaders.
|
|
1055
|
-
*/
|
|
1056
|
-
_patchModuleExports(moduleExports) {
|
|
1057
|
-
if (!moduleExports || typeof moduleExports !== "object") {
|
|
1058
|
-
return null;
|
|
1059
|
-
}
|
|
1060
|
-
let inPlacePatched = true;
|
|
1061
|
-
const wrapFunction = (name, isEmbedMany = false) => {
|
|
1062
|
-
const current = moduleExports[name];
|
|
1063
|
-
if (typeof current !== "function") {
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
const currentFn = current;
|
|
1067
|
-
if (currentFn[_VercelAIInstrumentation._WRAPPED_SYMBOL]) {
|
|
1068
|
-
return;
|
|
1069
|
-
}
|
|
1070
|
-
const descriptor = Object.getOwnPropertyDescriptor(moduleExports, name);
|
|
1071
|
-
if (descriptor && (!descriptor.writable || !descriptor.configurable) && !descriptor.set) {
|
|
1072
|
-
inPlacePatched = false;
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
1075
|
-
const patcher = this._patchers.get(name);
|
|
1076
|
-
if (!patcher) {
|
|
1077
|
-
return;
|
|
1078
|
-
}
|
|
1079
|
-
const patched = isEmbedMany ? patcher.patch(currentFn, true) : patcher.patch(currentFn);
|
|
1080
|
-
try {
|
|
1081
|
-
Object.defineProperty(patched, _VercelAIInstrumentation._WRAPPED_SYMBOL, {
|
|
1082
|
-
value: true,
|
|
1083
|
-
enumerable: false,
|
|
1084
|
-
configurable: false
|
|
1085
|
-
});
|
|
1086
|
-
} catch {
|
|
1087
|
-
}
|
|
1088
|
-
try {
|
|
1089
|
-
moduleExports[name] = patched;
|
|
1090
|
-
} catch {
|
|
1091
|
-
inPlacePatched = false;
|
|
1092
|
-
}
|
|
1093
|
-
};
|
|
1094
|
-
wrapFunction("generateText");
|
|
1095
|
-
wrapFunction("streamText");
|
|
1096
|
-
wrapFunction("embed");
|
|
1097
|
-
wrapFunction("embedMany", true);
|
|
1098
|
-
if (!inPlacePatched) {
|
|
1099
|
-
const proxiedModule = new Proxy(moduleExports, {
|
|
1100
|
-
get: (target, prop, receiver) => {
|
|
1101
|
-
const originalValue = Reflect.get(target, prop, receiver);
|
|
1102
|
-
if (typeof originalValue === "function" && typeof prop === "string" && this._patchers.has(prop)) {
|
|
1103
|
-
const patcher = this._patchers.get(prop);
|
|
1104
|
-
const isEmbedMany = prop === "embedMany";
|
|
1105
|
-
const wrapped = isEmbedMany ? patcher.patch(originalValue, true) : patcher.patch(originalValue);
|
|
1106
|
-
return wrapped;
|
|
1107
|
-
}
|
|
1108
|
-
return originalValue;
|
|
1109
|
-
}
|
|
1110
|
-
});
|
|
1111
|
-
return proxiedModule;
|
|
1112
|
-
}
|
|
1113
|
-
return moduleExports;
|
|
1114
|
-
}
|
|
1115
|
-
/**
|
|
1116
|
-
* Manual instrumentation hook for bundlers/Next.js. Applies in-place wrapping
|
|
1117
|
-
* on the provided module namespace.
|
|
1118
|
-
*/
|
|
1119
|
-
manuallyInstrument(module3) {
|
|
1120
|
-
try {
|
|
1121
|
-
const result = this._patchModuleExports(module3);
|
|
1122
|
-
if (result !== null) {
|
|
1123
|
-
logger.debug("Applied manual Vercel AI instrumentation");
|
|
1124
|
-
this._vercelAiNamespace = result;
|
|
1125
|
-
return result;
|
|
1126
|
-
}
|
|
1127
|
-
logger.warn("Manual Vercel AI instrumentation received invalid module");
|
|
1128
|
-
return module3;
|
|
1129
|
-
} catch (error) {
|
|
1130
|
-
logger.error(`Failed manual Vercel AI instrumentation: ${String(error)}`);
|
|
1131
|
-
return this._vercelAiNamespace || module3;
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
/**
|
|
1135
|
-
* Wrap a created provider/client instance (factory return) when possible.
|
|
1136
|
-
* Call this from wrappers that construct provider clients (e.g., OpenAI SDK).
|
|
1137
|
-
*/
|
|
1138
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1139
|
-
wrapFactoryReturn(instance) {
|
|
1140
|
-
return instance;
|
|
1141
|
-
}
|
|
1142
|
-
};
|
|
1143
|
-
|
|
1144
212
|
// src/internal/instrumentation/auto-init.ts
|
|
1145
213
|
var autoInstrumentationsLoaded = false;
|
|
1146
214
|
var exceptionLogger = (error) => {
|
|
@@ -1149,7 +217,7 @@ var exceptionLogger = (error) => {
|
|
|
1149
217
|
function loadNodeAutoInstrumentations() {
|
|
1150
218
|
try {
|
|
1151
219
|
const nodeInstrumentations = (0, import_auto_instrumentations_node.getNodeAutoInstrumentations)();
|
|
1152
|
-
(0,
|
|
220
|
+
(0, import_instrumentation.registerInstrumentations)({ instrumentations: nodeInstrumentations });
|
|
1153
221
|
return nodeInstrumentations;
|
|
1154
222
|
} catch (error) {
|
|
1155
223
|
logger.error(`Failed to load Node.js auto-instrumentations: ${String(error)}`);
|
|
@@ -1159,8 +227,6 @@ function loadNodeAutoInstrumentations() {
|
|
|
1159
227
|
function loadGenAIInstrumentations() {
|
|
1160
228
|
const instrumentations = [];
|
|
1161
229
|
const genAIInstrumentationClasses = [
|
|
1162
|
-
{ class: VercelAIInstrumentation, name: "Vercel AI" },
|
|
1163
|
-
// Load first to avoid conflicts
|
|
1164
230
|
{ class: import_instrumentation_openai.OpenAIInstrumentation, name: "OpenAI" },
|
|
1165
231
|
{ class: import_instrumentation_anthropic.AnthropicInstrumentation, name: "Anthropic" },
|
|
1166
232
|
{ class: import_instrumentation_cohere.CohereInstrumentation, name: "Cohere" },
|
|
@@ -1183,7 +249,7 @@ function loadGenAIInstrumentations() {
|
|
|
1183
249
|
}
|
|
1184
250
|
}
|
|
1185
251
|
try {
|
|
1186
|
-
(0,
|
|
252
|
+
(0, import_instrumentation.registerInstrumentations)({ instrumentations });
|
|
1187
253
|
logger.info(`Auto-registered ${instrumentations.length} GenAI instrumentations`);
|
|
1188
254
|
} catch (error) {
|
|
1189
255
|
logger.error(`Failed to register GenAI instrumentations: ${String(error)}`);
|
|
@@ -1379,8 +445,7 @@ var InstrumentationRegistry = class _InstrumentationRegistry {
|
|
|
1379
445
|
},
|
|
1380
446
|
{ class: import_instrumentation_chromadb2.ChromaDBInstrumentation, name: "ChromaDB", module: this.manualModules?.chromadb },
|
|
1381
447
|
{ class: import_instrumentation_qdrant2.QdrantInstrumentation, name: "Qdrant", module: this.manualModules?.qdrant },
|
|
1382
|
-
{ class: import_instrumentation_together2.TogetherInstrumentation, name: "Together", module: this.manualModules?.together }
|
|
1383
|
-
{ class: VercelAIInstrumentation, name: "Vercel AI", module: this.manualModules?.vercelAI }
|
|
448
|
+
{ class: import_instrumentation_together2.TogetherInstrumentation, name: "Together", module: this.manualModules?.together }
|
|
1384
449
|
];
|
|
1385
450
|
for (const config of instrumentationConfigs) {
|
|
1386
451
|
if (config.module) {
|
|
@@ -1399,13 +464,13 @@ var InstrumentationRegistry = class _InstrumentationRegistry {
|
|
|
1399
464
|
};
|
|
1400
465
|
|
|
1401
466
|
// src/internal/log/logging.ts
|
|
1402
|
-
var
|
|
467
|
+
var import_api_logs = require("@opentelemetry/api-logs");
|
|
1403
468
|
var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-http");
|
|
1404
469
|
var import_resources = require("@opentelemetry/resources");
|
|
1405
470
|
var import_sdk_logs2 = require("@opentelemetry/sdk-logs");
|
|
1406
471
|
|
|
1407
472
|
// src/internal/log/processors/log-processor.ts
|
|
1408
|
-
var
|
|
473
|
+
var import_api3 = require("@opentelemetry/api");
|
|
1409
474
|
var import_sdk_logs = require("@opentelemetry/sdk-logs");
|
|
1410
475
|
|
|
1411
476
|
// src/internal/masking/patterns.ts
|
|
@@ -2031,11 +1096,11 @@ function maskAttributes(attributes, rules, outputOriginalValue = false) {
|
|
|
2031
1096
|
}
|
|
2032
1097
|
|
|
2033
1098
|
// src/internal/semantic-conventions.ts
|
|
2034
|
-
var
|
|
1099
|
+
var import_api2 = require("@opentelemetry/api");
|
|
2035
1100
|
var BRIZZ = "brizz";
|
|
2036
1101
|
var PROPERTIES = "properties";
|
|
2037
1102
|
var SESSION_ID = "session.id";
|
|
2038
|
-
var PROPERTIES_CONTEXT_KEY = (0,
|
|
1103
|
+
var PROPERTIES_CONTEXT_KEY = (0, import_api2.createContextKey)(PROPERTIES);
|
|
2039
1104
|
|
|
2040
1105
|
// src/internal/log/processors/log-processor.ts
|
|
2041
1106
|
var DEFAULT_LOG_MASKING_RULES = [
|
|
@@ -2056,7 +1121,7 @@ var BrizzSimpleLogRecordProcessor = class extends import_sdk_logs.SimpleLogRecor
|
|
|
2056
1121
|
if (maskingConfig) {
|
|
2057
1122
|
maskLog(logRecord, maskingConfig);
|
|
2058
1123
|
}
|
|
2059
|
-
const associationProperties =
|
|
1124
|
+
const associationProperties = import_api3.context.active().getValue(PROPERTIES_CONTEXT_KEY);
|
|
2060
1125
|
if (associationProperties) {
|
|
2061
1126
|
for (const [key, value] of Object.entries(associationProperties)) {
|
|
2062
1127
|
logRecord.setAttribute(`${BRIZZ}.${key}`, value);
|
|
@@ -2076,7 +1141,7 @@ var BrizzBatchLogRecordProcessor = class extends import_sdk_logs.BatchLogRecordP
|
|
|
2076
1141
|
if (maskingConfig) {
|
|
2077
1142
|
maskLog(logRecord, maskingConfig);
|
|
2078
1143
|
}
|
|
2079
|
-
const associationProperties =
|
|
1144
|
+
const associationProperties = import_api3.context.active().getValue(PROPERTIES_CONTEXT_KEY);
|
|
2080
1145
|
if (associationProperties) {
|
|
2081
1146
|
for (const [key, value] of Object.entries(associationProperties)) {
|
|
2082
1147
|
logRecord.setAttribute(`${BRIZZ}.${key}`, value);
|
|
@@ -2213,7 +1278,7 @@ var LoggingModule = class _LoggingModule {
|
|
|
2213
1278
|
/**
|
|
2214
1279
|
* Emit a custom event to the telemetry pipeline
|
|
2215
1280
|
*/
|
|
2216
|
-
emitEvent(name, attributes, body, severityNumber =
|
|
1281
|
+
emitEvent(name, attributes, body, severityNumber = import_api_logs.SeverityNumber.INFO) {
|
|
2217
1282
|
logger.debug("Attempting to emit event", {
|
|
2218
1283
|
name,
|
|
2219
1284
|
hasAttributes: !!attributes,
|
|
@@ -2281,7 +1346,7 @@ var LoggingModule = class _LoggingModule {
|
|
|
2281
1346
|
logger.debug("Logging module shutdown completed");
|
|
2282
1347
|
}
|
|
2283
1348
|
};
|
|
2284
|
-
function emitEvent(name, attributes, body, severityNumber =
|
|
1349
|
+
function emitEvent(name, attributes, body, severityNumber = import_api_logs.SeverityNumber.INFO) {
|
|
2285
1350
|
return LoggingModule.getInstance().emitEvent(name, attributes, body, severityNumber);
|
|
2286
1351
|
}
|
|
2287
1352
|
|
|
@@ -2391,8 +1456,122 @@ function getMetricsReader() {
|
|
|
2391
1456
|
var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
|
|
2392
1457
|
|
|
2393
1458
|
// src/internal/trace/processors/span-processor.ts
|
|
2394
|
-
var
|
|
1459
|
+
var import_api4 = require("@opentelemetry/api");
|
|
2395
1460
|
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
1461
|
+
|
|
1462
|
+
// src/internal/trace/transformations/vercel-ai.ts
|
|
1463
|
+
var import_ai_semantic_conventions = require("@traceloop/ai-semantic-conventions");
|
|
1464
|
+
var AI_GENERATE_TEXT_DO_GENERATE = "ai.generateText.doGenerate";
|
|
1465
|
+
var AI_STREAM_TEXT_DO_STREAM = "ai.streamText.doStream";
|
|
1466
|
+
var HANDLED_SPAN_NAMES = {
|
|
1467
|
+
[AI_GENERATE_TEXT_DO_GENERATE]: "gen_ai.chat",
|
|
1468
|
+
[AI_STREAM_TEXT_DO_STREAM]: "gen_ai.chat",
|
|
1469
|
+
"ai.streamText": "ai.streamText",
|
|
1470
|
+
"ai.toolCall": (span) => {
|
|
1471
|
+
const toolName = span.attributes["ai.toolCall.name"];
|
|
1472
|
+
return `${toolName}.tool`;
|
|
1473
|
+
}
|
|
1474
|
+
};
|
|
1475
|
+
var AI_RESPONSE_TEXT = "ai.response.text";
|
|
1476
|
+
var AI_PROMPT_MESSAGES = "ai.prompt.messages";
|
|
1477
|
+
var AI_USAGE_PROMPT_TOKENS = "ai.usage.promptTokens";
|
|
1478
|
+
var AI_USAGE_COMPLETION_TOKENS = "ai.usage.completionTokens";
|
|
1479
|
+
var AI_MODEL_PROVIDER = "ai.model.provider";
|
|
1480
|
+
var transformAiSdkSpanName = (span) => {
|
|
1481
|
+
if (span.name in HANDLED_SPAN_NAMES) {
|
|
1482
|
+
if (typeof HANDLED_SPAN_NAMES[span.name] === "function") {
|
|
1483
|
+
span.name = HANDLED_SPAN_NAMES[span.name](span);
|
|
1484
|
+
} else {
|
|
1485
|
+
span.name = HANDLED_SPAN_NAMES[span.name];
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
};
|
|
1489
|
+
var transformResponseText = (attributes) => {
|
|
1490
|
+
if (AI_RESPONSE_TEXT in attributes) {
|
|
1491
|
+
attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_COMPLETIONS}.0.content`] = attributes[AI_RESPONSE_TEXT];
|
|
1492
|
+
attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_COMPLETIONS}.0.role`] = "assistant";
|
|
1493
|
+
delete attributes[AI_RESPONSE_TEXT];
|
|
1494
|
+
}
|
|
1495
|
+
};
|
|
1496
|
+
var transformPromptMessages = (attributes) => {
|
|
1497
|
+
if (AI_PROMPT_MESSAGES in attributes) {
|
|
1498
|
+
try {
|
|
1499
|
+
const messages = JSON.parse(attributes[AI_PROMPT_MESSAGES]);
|
|
1500
|
+
messages.forEach((msg, index) => {
|
|
1501
|
+
logger.debug("Transforming prompt message", { msg, type: typeof msg.content });
|
|
1502
|
+
if (typeof msg.content === "string") {
|
|
1503
|
+
attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = msg.content;
|
|
1504
|
+
} else {
|
|
1505
|
+
if (Array.isArray(msg.content) && msg.content.length > 0) {
|
|
1506
|
+
const lastContent = msg.content[msg.content.length - 1];
|
|
1507
|
+
if (lastContent.text) {
|
|
1508
|
+
attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = lastContent.text;
|
|
1509
|
+
}
|
|
1510
|
+
} else {
|
|
1511
|
+
attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = JSON.stringify(
|
|
1512
|
+
msg.content
|
|
1513
|
+
);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.role`] = msg.role;
|
|
1517
|
+
});
|
|
1518
|
+
delete attributes[AI_PROMPT_MESSAGES];
|
|
1519
|
+
} catch {
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
};
|
|
1523
|
+
var transformPromptTokens = (attributes) => {
|
|
1524
|
+
if (AI_USAGE_PROMPT_TOKENS in attributes) {
|
|
1525
|
+
attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_PROMPT_TOKENS}`] = attributes[AI_USAGE_PROMPT_TOKENS];
|
|
1526
|
+
delete attributes[AI_USAGE_PROMPT_TOKENS];
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
var transformCompletionTokens = (attributes) => {
|
|
1530
|
+
if (AI_USAGE_COMPLETION_TOKENS in attributes) {
|
|
1531
|
+
attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_COMPLETION_TOKENS}`] = attributes[AI_USAGE_COMPLETION_TOKENS];
|
|
1532
|
+
delete attributes[AI_USAGE_COMPLETION_TOKENS];
|
|
1533
|
+
}
|
|
1534
|
+
};
|
|
1535
|
+
var calculateTotalTokens = (attributes) => {
|
|
1536
|
+
const promptTokens = attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_PROMPT_TOKENS}`];
|
|
1537
|
+
const completionTokens = attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_COMPLETION_TOKENS}`];
|
|
1538
|
+
if (promptTokens && completionTokens) {
|
|
1539
|
+
attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_TOTAL_TOKENS}`] = Number(promptTokens) + Number(completionTokens);
|
|
1540
|
+
}
|
|
1541
|
+
};
|
|
1542
|
+
var transformVendor = (attributes) => {
|
|
1543
|
+
if (AI_MODEL_PROVIDER in attributes) {
|
|
1544
|
+
const vendor = attributes[AI_MODEL_PROVIDER];
|
|
1545
|
+
if (vendor && vendor.startsWith("openai")) {
|
|
1546
|
+
attributes[import_ai_semantic_conventions.SpanAttributes.LLM_SYSTEM] = "OpenAI";
|
|
1547
|
+
} else {
|
|
1548
|
+
attributes[import_ai_semantic_conventions.SpanAttributes.LLM_SYSTEM] = vendor;
|
|
1549
|
+
}
|
|
1550
|
+
delete attributes[AI_MODEL_PROVIDER];
|
|
1551
|
+
}
|
|
1552
|
+
};
|
|
1553
|
+
var transformAiSdkAttributes = (attributes) => {
|
|
1554
|
+
transformResponseText(attributes);
|
|
1555
|
+
transformPromptMessages(attributes);
|
|
1556
|
+
transformPromptTokens(attributes);
|
|
1557
|
+
transformCompletionTokens(attributes);
|
|
1558
|
+
calculateTotalTokens(attributes);
|
|
1559
|
+
transformVendor(attributes);
|
|
1560
|
+
};
|
|
1561
|
+
var shouldHandleSpan = (span) => {
|
|
1562
|
+
return span.name in HANDLED_SPAN_NAMES;
|
|
1563
|
+
};
|
|
1564
|
+
var transformAiSdkSpan = (span) => {
|
|
1565
|
+
logger.debug("Transforming AI SDK span", { spanName: span.name });
|
|
1566
|
+
if (!shouldHandleSpan(span)) {
|
|
1567
|
+
logger.debug("Skipping span transformation", { spanName: span.name });
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
transformAiSdkSpanName(span);
|
|
1571
|
+
transformAiSdkAttributes(span.attributes);
|
|
1572
|
+
};
|
|
1573
|
+
|
|
1574
|
+
// src/internal/trace/processors/span-processor.ts
|
|
2396
1575
|
var DEFAULT_MASKING_RULES = [
|
|
2397
1576
|
{
|
|
2398
1577
|
mode: "partial",
|
|
@@ -2403,16 +1582,6 @@ var DEFAULT_MASKING_RULES = [
|
|
|
2403
1582
|
mode: "partial",
|
|
2404
1583
|
attributePattern: "gen_ai.completion",
|
|
2405
1584
|
patterns: DEFAULT_PII_PATTERNS
|
|
2406
|
-
},
|
|
2407
|
-
{
|
|
2408
|
-
mode: "partial",
|
|
2409
|
-
attributePattern: "traceloop.entity.input",
|
|
2410
|
-
patterns: DEFAULT_PII_PATTERNS
|
|
2411
|
-
},
|
|
2412
|
-
{
|
|
2413
|
-
mode: "partial",
|
|
2414
|
-
attributePattern: "traceloop.entity.output",
|
|
2415
|
-
patterns: DEFAULT_PII_PATTERNS
|
|
2416
1585
|
}
|
|
2417
1586
|
];
|
|
2418
1587
|
var BrizzSimpleSpanProcessor = class extends import_sdk_trace_base.SimpleSpanProcessor {
|
|
@@ -2437,7 +1606,7 @@ var BrizzSimpleSpanProcessor = class extends import_sdk_trace_base.SimpleSpanPro
|
|
|
2437
1606
|
if (maskingConfig) {
|
|
2438
1607
|
maskSpan(span, maskingConfig);
|
|
2439
1608
|
}
|
|
2440
|
-
const associationProperties =
|
|
1609
|
+
const associationProperties = import_api4.context.active().getValue(PROPERTIES_CONTEXT_KEY);
|
|
2441
1610
|
if (associationProperties) {
|
|
2442
1611
|
for (const [key, value] of Object.entries(associationProperties)) {
|
|
2443
1612
|
span.setAttribute(`${BRIZZ}.${key}`, value);
|
|
@@ -2445,6 +1614,10 @@ var BrizzSimpleSpanProcessor = class extends import_sdk_trace_base.SimpleSpanPro
|
|
|
2445
1614
|
}
|
|
2446
1615
|
super.onStart(span, parentContext);
|
|
2447
1616
|
}
|
|
1617
|
+
onEnd(span) {
|
|
1618
|
+
transformAiSdkSpan(span);
|
|
1619
|
+
super.onEnd(span);
|
|
1620
|
+
}
|
|
2448
1621
|
};
|
|
2449
1622
|
var BrizzBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProcessor {
|
|
2450
1623
|
config;
|
|
@@ -2457,7 +1630,7 @@ var BrizzBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProce
|
|
|
2457
1630
|
if (maskingConfig) {
|
|
2458
1631
|
maskSpan(span, maskingConfig);
|
|
2459
1632
|
}
|
|
2460
|
-
const associationProperties =
|
|
1633
|
+
const associationProperties = import_api4.context.active().getValue(PROPERTIES_CONTEXT_KEY);
|
|
2461
1634
|
if (associationProperties) {
|
|
2462
1635
|
for (const [key, value] of Object.entries(associationProperties)) {
|
|
2463
1636
|
span.setAttribute(`${BRIZZ}.${key}`, value);
|
|
@@ -2465,6 +1638,10 @@ var BrizzBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProce
|
|
|
2465
1638
|
}
|
|
2466
1639
|
super.onStart(span, parentContext);
|
|
2467
1640
|
}
|
|
1641
|
+
onEnd(span) {
|
|
1642
|
+
transformAiSdkSpan(span);
|
|
1643
|
+
super.onEnd(span);
|
|
1644
|
+
}
|
|
2468
1645
|
};
|
|
2469
1646
|
function maskSpan(span, config) {
|
|
2470
1647
|
if (!span.attributes || Object.keys(span.attributes).length === 0) {
|
|
@@ -2552,8 +1729,9 @@ var TracingModule = class _TracingModule {
|
|
|
2552
1729
|
disableBatch: config.disableBatch,
|
|
2553
1730
|
hasMasking: !!config.masking?.spanMasking
|
|
2554
1731
|
});
|
|
2555
|
-
|
|
1732
|
+
const spanProcessor = config.disableBatch ? new BrizzSimpleSpanProcessor(this.spanExporter, config) : new BrizzBatchSpanProcessor(this.spanExporter, config);
|
|
2556
1733
|
logger.debug("Span processor initialized successfully");
|
|
1734
|
+
this.spanProcessor = spanProcessor;
|
|
2557
1735
|
}
|
|
2558
1736
|
/**
|
|
2559
1737
|
* Get the span exporter
|
|
@@ -2595,13 +1773,13 @@ function getSpanProcessor() {
|
|
|
2595
1773
|
}
|
|
2596
1774
|
|
|
2597
1775
|
// src/internal/trace/session.ts
|
|
2598
|
-
var
|
|
1776
|
+
var import_api5 = require("@opentelemetry/api");
|
|
2599
1777
|
function withProperties(properties, fn, thisArg, ...args) {
|
|
2600
1778
|
if (Object.keys(properties).length === 0) {
|
|
2601
1779
|
return fn.apply(thisArg, args);
|
|
2602
1780
|
}
|
|
2603
|
-
const newContext =
|
|
2604
|
-
return
|
|
1781
|
+
const newContext = import_api5.context.active().setValue(PROPERTIES_CONTEXT_KEY, properties);
|
|
1782
|
+
return import_api5.context.with(newContext, fn, thisArg, ...args);
|
|
2605
1783
|
}
|
|
2606
1784
|
function WithSessionId(sessionId, fn, thisArg, ...args) {
|
|
2607
1785
|
return withProperties({ [SESSION_ID]: sessionId }, fn, thisArg, ...args);
|
|
@@ -2795,7 +1973,7 @@ var _Brizz = class __Brizz {
|
|
|
2795
1973
|
var Brizz = new _Brizz();
|
|
2796
1974
|
|
|
2797
1975
|
// src/index.ts
|
|
2798
|
-
var
|
|
1976
|
+
var import_api_logs2 = require("@opentelemetry/api-logs");
|
|
2799
1977
|
|
|
2800
1978
|
// src/node/runtime.ts
|
|
2801
1979
|
function detectRuntime() {
|
|
@@ -2839,77 +2017,6 @@ function detectRuntime() {
|
|
|
2839
2017
|
};
|
|
2840
2018
|
}
|
|
2841
2019
|
|
|
2842
|
-
// src/node/loader.ts
|
|
2843
|
-
var import_node_module = __toESM(require("module"), 1);
|
|
2844
|
-
var import_import_in_the_middle = require("import-in-the-middle");
|
|
2845
|
-
var import_meta = {};
|
|
2846
|
-
var loaderDebug = (() => {
|
|
2847
|
-
const isDebug = process.env["BRIZZ_ESM_DEBUG"] === "true" || process.env["BRIZZ_LOG_LEVEL"] === "debug";
|
|
2848
|
-
return {
|
|
2849
|
-
log: (msg, data) => {
|
|
2850
|
-
if (!isDebug) {
|
|
2851
|
-
return;
|
|
2852
|
-
}
|
|
2853
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2854
|
-
const dataStr = data ? ` ${JSON.stringify(data)}` : "";
|
|
2855
|
-
console.log(`[${timestamp}] [ESM-LOADER] ${msg}${dataStr}`);
|
|
2856
|
-
},
|
|
2857
|
-
error: (msg, error) => {
|
|
2858
|
-
if (!isDebug) {
|
|
2859
|
-
return;
|
|
2860
|
-
}
|
|
2861
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2862
|
-
const errorStr = error instanceof Error ? ` ${error.message}` : error ? ` ${JSON.stringify(error)}` : "";
|
|
2863
|
-
console.error(`[${timestamp}] [ESM-LOADER] ERROR: ${msg}${errorStr}`);
|
|
2864
|
-
}
|
|
2865
|
-
};
|
|
2866
|
-
})();
|
|
2867
|
-
var LOADER_REGISTERED_KEY = Symbol.for("__brizz_esm_loader_registered__");
|
|
2868
|
-
function checkLoaderAPISupport() {
|
|
2869
|
-
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
2870
|
-
if (major === void 0 || minor === void 0) {
|
|
2871
|
-
loaderDebug.log("Failed to detect Node version, assuming loader API is supported");
|
|
2872
|
-
return true;
|
|
2873
|
-
}
|
|
2874
|
-
const supported = major >= 21 || major === 20 && minor >= 6 || major === 18 && minor >= 19;
|
|
2875
|
-
loaderDebug.log("Loader API support check:", {
|
|
2876
|
-
nodeVersion: `${major}.${minor}`,
|
|
2877
|
-
supportsLoaderAPI: supported
|
|
2878
|
-
});
|
|
2879
|
-
return supported;
|
|
2880
|
-
}
|
|
2881
|
-
function maybeRegisterESMLoader() {
|
|
2882
|
-
if (globalThis[LOADER_REGISTERED_KEY] === true) {
|
|
2883
|
-
loaderDebug.log("ESM loader already registered, skipping");
|
|
2884
|
-
return false;
|
|
2885
|
-
}
|
|
2886
|
-
globalThis[LOADER_REGISTERED_KEY] = true;
|
|
2887
|
-
loaderDebug.log("Starting ESM loader registration...");
|
|
2888
|
-
if (!checkLoaderAPISupport()) {
|
|
2889
|
-
loaderDebug.log("Node.js version does not support loader API, skipping");
|
|
2890
|
-
return false;
|
|
2891
|
-
}
|
|
2892
|
-
try {
|
|
2893
|
-
loaderDebug.log("Creating MessageChannel for import-in-the-middle...");
|
|
2894
|
-
const { addHookMessagePort } = (0, import_import_in_the_middle.createAddHookMessageChannel)();
|
|
2895
|
-
loaderDebug.log("Registering import-in-the-middle/hook.mjs...");
|
|
2896
|
-
import_node_module.default.register("import-in-the-middle/hook.mjs", import_meta.url, {
|
|
2897
|
-
data: { addHookMessagePort },
|
|
2898
|
-
transferList: [addHookMessagePort]
|
|
2899
|
-
});
|
|
2900
|
-
loaderDebug.log("ESM loader successfully registered!");
|
|
2901
|
-
return true;
|
|
2902
|
-
} catch (error) {
|
|
2903
|
-
loaderDebug.error("Failed to register ESM loader:", error);
|
|
2904
|
-
globalThis[LOADER_REGISTERED_KEY] = false;
|
|
2905
|
-
return false;
|
|
2906
|
-
}
|
|
2907
|
-
}
|
|
2908
|
-
if (globalThis[LOADER_REGISTERED_KEY] !== true) {
|
|
2909
|
-
loaderDebug.log("Loader module imported, attempting to register...");
|
|
2910
|
-
maybeRegisterESMLoader();
|
|
2911
|
-
}
|
|
2912
|
-
|
|
2913
2020
|
// src/init.ts
|
|
2914
2021
|
var init_exports = {};
|
|
2915
2022
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -2918,7 +2025,6 @@ var init_exports = {};
|
|
|
2918
2025
|
DEFAULT_PII_PATTERNS,
|
|
2919
2026
|
LogLevel,
|
|
2920
2027
|
SeverityNumber,
|
|
2921
|
-
VercelAIInstrumentation,
|
|
2922
2028
|
WithSessionId,
|
|
2923
2029
|
detectRuntime,
|
|
2924
2030
|
emitEvent,
|
|
@@ -2931,7 +2037,6 @@ var init_exports = {};
|
|
|
2931
2037
|
logger,
|
|
2932
2038
|
maskAttributes,
|
|
2933
2039
|
maskValue,
|
|
2934
|
-
maybeRegisterESMLoader,
|
|
2935
2040
|
setLogLevel
|
|
2936
2041
|
});
|
|
2937
2042
|
//# sourceMappingURL=index.cjs.map
|