@mastra/otel-exporter 0.0.0-chore-core-swap-aiv5-ai-package-naming-20251009203931 → 0.0.0-cloud-storage-adapter-20251106204059
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/CHANGELOG.md +239 -5
- package/README.md +12 -12
- package/dist/index.cjs +170 -157
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +170 -157
- package/dist/index.js.map +1 -1
- package/dist/mastra-span.d.ts +3 -2
- package/dist/mastra-span.d.ts.map +1 -1
- package/dist/span-converter.d.ts +5 -5
- package/dist/span-converter.d.ts.map +1 -1
- package/dist/tracing.d.ts +27 -0
- package/dist/tracing.d.ts.map +1 -0
- package/dist/types.d.ts +8 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -7
- package/dist/ai-tracing.d.ts +0 -26
- package/dist/ai-tracing.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var observability$1 = require('@mastra/core/observability');
|
|
4
|
+
var observability = require('@mastra/observability');
|
|
5
5
|
var api = require('@opentelemetry/api');
|
|
6
6
|
var resources = require('@opentelemetry/resources');
|
|
7
7
|
var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
|
|
8
8
|
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
9
9
|
|
|
10
|
-
// src/
|
|
10
|
+
// src/tracing.ts
|
|
11
11
|
|
|
12
12
|
// src/loadExporter.ts
|
|
13
13
|
var OTLPHttpExporter;
|
|
@@ -209,6 +209,7 @@ var MastraReadableSpan = class {
|
|
|
209
209
|
name;
|
|
210
210
|
kind;
|
|
211
211
|
spanContext;
|
|
212
|
+
parentSpanContext;
|
|
212
213
|
parentSpanId;
|
|
213
214
|
startTime;
|
|
214
215
|
endTime;
|
|
@@ -224,45 +225,45 @@ var MastraReadableSpan = class {
|
|
|
224
225
|
droppedAttributesCount = 0;
|
|
225
226
|
droppedEventsCount = 0;
|
|
226
227
|
droppedLinksCount = 0;
|
|
227
|
-
constructor(
|
|
228
|
-
this.name =
|
|
228
|
+
constructor(span, attributes, kind, parentSpanId, resource, instrumentationLibrary) {
|
|
229
|
+
this.name = span.name;
|
|
229
230
|
this.kind = kind;
|
|
230
231
|
this.attributes = attributes;
|
|
231
232
|
this.parentSpanId = parentSpanId;
|
|
232
233
|
this.links = [];
|
|
233
234
|
this.events = [];
|
|
234
|
-
this.startTime = this.dateToHrTime(
|
|
235
|
-
this.endTime =
|
|
236
|
-
this.ended = !!
|
|
237
|
-
if (
|
|
238
|
-
const durationMs =
|
|
235
|
+
this.startTime = this.dateToHrTime(span.startTime);
|
|
236
|
+
this.endTime = span.endTime ? this.dateToHrTime(span.endTime) : this.startTime;
|
|
237
|
+
this.ended = !!span.endTime;
|
|
238
|
+
if (span.endTime) {
|
|
239
|
+
const durationMs = span.endTime.getTime() - span.startTime.getTime();
|
|
239
240
|
this.duration = [Math.floor(durationMs / 1e3), durationMs % 1e3 * 1e6];
|
|
240
241
|
} else {
|
|
241
242
|
this.duration = [0, 0];
|
|
242
243
|
}
|
|
243
|
-
if (
|
|
244
|
+
if (span.errorInfo) {
|
|
244
245
|
this.status = {
|
|
245
246
|
code: api.SpanStatusCode.ERROR,
|
|
246
|
-
message:
|
|
247
|
+
message: span.errorInfo.message
|
|
247
248
|
};
|
|
248
249
|
this.events.push({
|
|
249
250
|
name: "exception",
|
|
250
251
|
attributes: {
|
|
251
|
-
"exception.message":
|
|
252
|
+
"exception.message": span.errorInfo.message,
|
|
252
253
|
"exception.type": "Error",
|
|
253
|
-
...
|
|
254
|
-
"exception.stacktrace":
|
|
254
|
+
...span.errorInfo.details?.stack && {
|
|
255
|
+
"exception.stacktrace": span.errorInfo.details.stack
|
|
255
256
|
}
|
|
256
257
|
},
|
|
257
258
|
time: this.startTime,
|
|
258
259
|
droppedAttributesCount: 0
|
|
259
260
|
});
|
|
260
|
-
} else if (
|
|
261
|
+
} else if (span.endTime) {
|
|
261
262
|
this.status = { code: api.SpanStatusCode.OK };
|
|
262
263
|
} else {
|
|
263
264
|
this.status = { code: api.SpanStatusCode.UNSET };
|
|
264
265
|
}
|
|
265
|
-
if (
|
|
266
|
+
if (span.isEvent) {
|
|
266
267
|
this.events.push({
|
|
267
268
|
name: "instant_event",
|
|
268
269
|
attributes: {},
|
|
@@ -271,11 +272,19 @@ var MastraReadableSpan = class {
|
|
|
271
272
|
});
|
|
272
273
|
}
|
|
273
274
|
this.spanContext = () => ({
|
|
274
|
-
traceId:
|
|
275
|
-
spanId:
|
|
275
|
+
traceId: span.traceId,
|
|
276
|
+
spanId: span.id,
|
|
276
277
|
traceFlags: api.TraceFlags.SAMPLED,
|
|
277
278
|
isRemote: false
|
|
278
279
|
});
|
|
280
|
+
if (parentSpanId) {
|
|
281
|
+
this.parentSpanContext = {
|
|
282
|
+
traceId: span.traceId,
|
|
283
|
+
spanId: parentSpanId,
|
|
284
|
+
traceFlags: api.TraceFlags.SAMPLED,
|
|
285
|
+
isRemote: false
|
|
286
|
+
};
|
|
287
|
+
}
|
|
279
288
|
this.resource = resource || {};
|
|
280
289
|
this.instrumentationLibrary = instrumentationLibrary || {
|
|
281
290
|
name: "@mastra/otel",
|
|
@@ -296,24 +305,14 @@ var MastraReadableSpan = class {
|
|
|
296
305
|
|
|
297
306
|
// src/span-converter.ts
|
|
298
307
|
var SPAN_KIND_MAPPING = {
|
|
299
|
-
//
|
|
300
|
-
[
|
|
301
|
-
[
|
|
302
|
-
//
|
|
303
|
-
[
|
|
304
|
-
[aiTracing.AISpanType.MCP_TOOL_CALL]: api.SpanKind.CLIENT,
|
|
308
|
+
// Model operations are CLIENT spans (calling external AI services)
|
|
309
|
+
[observability$1.SpanType.MODEL_GENERATION]: api.SpanKind.CLIENT,
|
|
310
|
+
[observability$1.SpanType.MODEL_CHUNK]: api.SpanKind.CLIENT,
|
|
311
|
+
// MCP tool calls are CLIENT (external service calls)
|
|
312
|
+
[observability$1.SpanType.MCP_TOOL_CALL]: api.SpanKind.CLIENT,
|
|
305
313
|
// Root spans for agent/workflow are SERVER (entry points)
|
|
306
|
-
[
|
|
307
|
-
[
|
|
308
|
-
// Internal workflow operations
|
|
309
|
-
[aiTracing.AISpanType.WORKFLOW_STEP]: api.SpanKind.INTERNAL,
|
|
310
|
-
[aiTracing.AISpanType.WORKFLOW_LOOP]: api.SpanKind.INTERNAL,
|
|
311
|
-
[aiTracing.AISpanType.WORKFLOW_PARALLEL]: api.SpanKind.INTERNAL,
|
|
312
|
-
[aiTracing.AISpanType.WORKFLOW_CONDITIONAL]: api.SpanKind.INTERNAL,
|
|
313
|
-
[aiTracing.AISpanType.WORKFLOW_CONDITIONAL_EVAL]: api.SpanKind.INTERNAL,
|
|
314
|
-
[aiTracing.AISpanType.WORKFLOW_SLEEP]: api.SpanKind.INTERNAL,
|
|
315
|
-
[aiTracing.AISpanType.WORKFLOW_WAIT_EVENT]: api.SpanKind.INTERNAL,
|
|
316
|
-
[aiTracing.AISpanType.GENERIC]: api.SpanKind.INTERNAL
|
|
314
|
+
[observability$1.SpanType.AGENT_RUN]: api.SpanKind.SERVER,
|
|
315
|
+
[observability$1.SpanType.WORKFLOW_RUN]: api.SpanKind.SERVER
|
|
317
316
|
};
|
|
318
317
|
var SpanConverter = class {
|
|
319
318
|
resource;
|
|
@@ -326,19 +325,19 @@ var SpanConverter = class {
|
|
|
326
325
|
};
|
|
327
326
|
}
|
|
328
327
|
/**
|
|
329
|
-
* Convert a Mastra
|
|
328
|
+
* Convert a Mastra Span to an OpenTelemetry ReadableSpan
|
|
330
329
|
* This preserves Mastra's trace and span IDs
|
|
331
330
|
*/
|
|
332
|
-
convertSpan(
|
|
333
|
-
const spanKind = this.getSpanKind(
|
|
334
|
-
const attributes = this.buildAttributes(
|
|
335
|
-
const spanName = this.buildSpanName(
|
|
336
|
-
const otelSpan = { ...
|
|
331
|
+
convertSpan(Span) {
|
|
332
|
+
const spanKind = this.getSpanKind(Span);
|
|
333
|
+
const attributes = this.buildAttributes(Span);
|
|
334
|
+
const spanName = this.buildSpanName(Span);
|
|
335
|
+
const otelSpan = { ...Span, name: spanName };
|
|
337
336
|
return new MastraReadableSpan(
|
|
338
337
|
otelSpan,
|
|
339
338
|
attributes,
|
|
340
339
|
spanKind,
|
|
341
|
-
|
|
340
|
+
Span.parentSpanId,
|
|
342
341
|
// Use the parentSpanId from the Mastra span directly
|
|
343
342
|
this.resource,
|
|
344
343
|
this.instrumentationLibrary
|
|
@@ -347,139 +346,139 @@ var SpanConverter = class {
|
|
|
347
346
|
/**
|
|
348
347
|
* Get the appropriate SpanKind based on span type and context
|
|
349
348
|
*/
|
|
350
|
-
getSpanKind(
|
|
351
|
-
if (
|
|
352
|
-
if (
|
|
349
|
+
getSpanKind(Span) {
|
|
350
|
+
if (Span.isRootSpan) {
|
|
351
|
+
if (Span.type === observability$1.SpanType.AGENT_RUN || Span.type === observability$1.SpanType.WORKFLOW_RUN) {
|
|
353
352
|
return api.SpanKind.SERVER;
|
|
354
353
|
}
|
|
355
354
|
}
|
|
356
|
-
return SPAN_KIND_MAPPING[
|
|
355
|
+
return SPAN_KIND_MAPPING[Span.type] || api.SpanKind.INTERNAL;
|
|
357
356
|
}
|
|
358
357
|
/**
|
|
359
358
|
* Build OTEL-compliant span name based on span type and attributes
|
|
360
359
|
*/
|
|
361
|
-
buildSpanName(
|
|
362
|
-
switch (
|
|
363
|
-
case
|
|
364
|
-
const attrs =
|
|
360
|
+
buildSpanName(Span) {
|
|
361
|
+
switch (Span.type) {
|
|
362
|
+
case observability$1.SpanType.MODEL_GENERATION: {
|
|
363
|
+
const attrs = Span.attributes;
|
|
365
364
|
const operation = attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
|
|
366
365
|
const model = attrs?.model || "unknown";
|
|
367
366
|
return `${operation} ${model}`;
|
|
368
367
|
}
|
|
369
|
-
case
|
|
370
|
-
case
|
|
371
|
-
const toolAttrs =
|
|
368
|
+
case observability$1.SpanType.TOOL_CALL:
|
|
369
|
+
case observability$1.SpanType.MCP_TOOL_CALL: {
|
|
370
|
+
const toolAttrs = Span.attributes;
|
|
372
371
|
const toolName = toolAttrs?.toolId || "unknown";
|
|
373
372
|
return `tool.execute ${toolName}`;
|
|
374
373
|
}
|
|
375
|
-
case
|
|
376
|
-
const agentAttrs =
|
|
374
|
+
case observability$1.SpanType.AGENT_RUN: {
|
|
375
|
+
const agentAttrs = Span.attributes;
|
|
377
376
|
const agentId = agentAttrs?.agentId || "unknown";
|
|
378
377
|
return `agent.${agentId}`;
|
|
379
378
|
}
|
|
380
|
-
case
|
|
381
|
-
const workflowAttrs =
|
|
379
|
+
case observability$1.SpanType.WORKFLOW_RUN: {
|
|
380
|
+
const workflowAttrs = Span.attributes;
|
|
382
381
|
const workflowId = workflowAttrs?.workflowId || "unknown";
|
|
383
382
|
return `workflow.${workflowId}`;
|
|
384
383
|
}
|
|
385
|
-
case
|
|
386
|
-
return
|
|
384
|
+
case observability$1.SpanType.WORKFLOW_STEP:
|
|
385
|
+
return Span.name;
|
|
387
386
|
default:
|
|
388
|
-
return
|
|
387
|
+
return Span.name;
|
|
389
388
|
}
|
|
390
389
|
}
|
|
391
390
|
/**
|
|
392
|
-
* Build OpenTelemetry attributes from Mastra
|
|
391
|
+
* Build OpenTelemetry attributes from Mastra Span
|
|
393
392
|
* Following OTEL Semantic Conventions for GenAI
|
|
394
393
|
*/
|
|
395
|
-
buildAttributes(
|
|
394
|
+
buildAttributes(Span) {
|
|
396
395
|
const attributes = {};
|
|
397
|
-
attributes["gen_ai.operation.name"] = this.getOperationName(
|
|
398
|
-
attributes["span.kind"] = this.getSpanKindString(
|
|
399
|
-
attributes["mastra.span.type"] =
|
|
400
|
-
attributes["mastra.trace_id"] =
|
|
401
|
-
attributes["mastra.span_id"] =
|
|
402
|
-
if (
|
|
403
|
-
attributes["mastra.parent_span_id"] =
|
|
396
|
+
attributes["gen_ai.operation.name"] = this.getOperationName(Span);
|
|
397
|
+
attributes["span.kind"] = this.getSpanKindString(Span);
|
|
398
|
+
attributes["mastra.span.type"] = Span.type;
|
|
399
|
+
attributes["mastra.trace_id"] = Span.traceId;
|
|
400
|
+
attributes["mastra.span_id"] = Span.id;
|
|
401
|
+
if (Span.parentSpanId) {
|
|
402
|
+
attributes["mastra.parent_span_id"] = Span.parentSpanId;
|
|
404
403
|
}
|
|
405
|
-
if (
|
|
406
|
-
const inputStr = typeof
|
|
404
|
+
if (Span.input !== void 0) {
|
|
405
|
+
const inputStr = typeof Span.input === "string" ? Span.input : JSON.stringify(Span.input);
|
|
407
406
|
attributes["input"] = inputStr;
|
|
408
|
-
if (
|
|
407
|
+
if (Span.type === observability$1.SpanType.MODEL_GENERATION) {
|
|
409
408
|
attributes["gen_ai.prompt"] = inputStr;
|
|
410
|
-
} else if (
|
|
409
|
+
} else if (Span.type === observability$1.SpanType.TOOL_CALL || Span.type === observability$1.SpanType.MCP_TOOL_CALL) {
|
|
411
410
|
attributes["gen_ai.tool.input"] = inputStr;
|
|
412
411
|
}
|
|
413
412
|
}
|
|
414
|
-
if (
|
|
415
|
-
const outputStr = typeof
|
|
413
|
+
if (Span.output !== void 0) {
|
|
414
|
+
const outputStr = typeof Span.output === "string" ? Span.output : JSON.stringify(Span.output);
|
|
416
415
|
attributes["output"] = outputStr;
|
|
417
|
-
if (
|
|
416
|
+
if (Span.type === observability$1.SpanType.MODEL_GENERATION) {
|
|
418
417
|
attributes["gen_ai.completion"] = outputStr;
|
|
419
|
-
} else if (
|
|
418
|
+
} else if (Span.type === observability$1.SpanType.TOOL_CALL || Span.type === observability$1.SpanType.MCP_TOOL_CALL) {
|
|
420
419
|
attributes["gen_ai.tool.output"] = outputStr;
|
|
421
420
|
}
|
|
422
421
|
}
|
|
423
|
-
if (
|
|
424
|
-
const
|
|
425
|
-
if (
|
|
426
|
-
attributes["gen_ai.request.model"] =
|
|
422
|
+
if (Span.type === observability$1.SpanType.MODEL_GENERATION && Span.attributes) {
|
|
423
|
+
const modelAttrs = Span.attributes;
|
|
424
|
+
if (modelAttrs.model) {
|
|
425
|
+
attributes["gen_ai.request.model"] = modelAttrs.model;
|
|
427
426
|
}
|
|
428
|
-
if (
|
|
429
|
-
attributes["gen_ai.system"] =
|
|
427
|
+
if (modelAttrs.provider) {
|
|
428
|
+
attributes["gen_ai.system"] = modelAttrs.provider;
|
|
430
429
|
}
|
|
431
|
-
if (
|
|
432
|
-
const inputTokens =
|
|
433
|
-
const outputTokens =
|
|
430
|
+
if (modelAttrs.usage) {
|
|
431
|
+
const inputTokens = modelAttrs.usage.inputTokens ?? modelAttrs.usage.promptTokens;
|
|
432
|
+
const outputTokens = modelAttrs.usage.outputTokens ?? modelAttrs.usage.completionTokens;
|
|
434
433
|
if (inputTokens !== void 0) {
|
|
435
434
|
attributes["gen_ai.usage.input_tokens"] = inputTokens;
|
|
436
435
|
}
|
|
437
436
|
if (outputTokens !== void 0) {
|
|
438
437
|
attributes["gen_ai.usage.output_tokens"] = outputTokens;
|
|
439
438
|
}
|
|
440
|
-
if (
|
|
441
|
-
attributes["gen_ai.usage.total_tokens"] =
|
|
439
|
+
if (modelAttrs.usage.totalTokens !== void 0) {
|
|
440
|
+
attributes["gen_ai.usage.total_tokens"] = modelAttrs.usage.totalTokens;
|
|
442
441
|
}
|
|
443
|
-
if (
|
|
444
|
-
attributes["gen_ai.usage.reasoning_tokens"] =
|
|
442
|
+
if (modelAttrs.usage.reasoningTokens !== void 0) {
|
|
443
|
+
attributes["gen_ai.usage.reasoning_tokens"] = modelAttrs.usage.reasoningTokens;
|
|
445
444
|
}
|
|
446
|
-
if (
|
|
447
|
-
attributes["gen_ai.usage.cached_input_tokens"] =
|
|
445
|
+
if (modelAttrs.usage.cachedInputTokens !== void 0) {
|
|
446
|
+
attributes["gen_ai.usage.cached_input_tokens"] = modelAttrs.usage.cachedInputTokens;
|
|
448
447
|
}
|
|
449
448
|
}
|
|
450
|
-
if (
|
|
451
|
-
if (
|
|
452
|
-
attributes["gen_ai.request.temperature"] =
|
|
449
|
+
if (modelAttrs.parameters) {
|
|
450
|
+
if (modelAttrs.parameters.temperature !== void 0) {
|
|
451
|
+
attributes["gen_ai.request.temperature"] = modelAttrs.parameters.temperature;
|
|
453
452
|
}
|
|
454
|
-
if (
|
|
455
|
-
attributes["gen_ai.request.max_tokens"] =
|
|
453
|
+
if (modelAttrs.parameters.maxOutputTokens !== void 0) {
|
|
454
|
+
attributes["gen_ai.request.max_tokens"] = modelAttrs.parameters.maxOutputTokens;
|
|
456
455
|
}
|
|
457
|
-
if (
|
|
458
|
-
attributes["gen_ai.request.top_p"] =
|
|
456
|
+
if (modelAttrs.parameters.topP !== void 0) {
|
|
457
|
+
attributes["gen_ai.request.top_p"] = modelAttrs.parameters.topP;
|
|
459
458
|
}
|
|
460
|
-
if (
|
|
461
|
-
attributes["gen_ai.request.top_k"] =
|
|
459
|
+
if (modelAttrs.parameters.topK !== void 0) {
|
|
460
|
+
attributes["gen_ai.request.top_k"] = modelAttrs.parameters.topK;
|
|
462
461
|
}
|
|
463
|
-
if (
|
|
464
|
-
attributes["gen_ai.request.presence_penalty"] =
|
|
462
|
+
if (modelAttrs.parameters.presencePenalty !== void 0) {
|
|
463
|
+
attributes["gen_ai.request.presence_penalty"] = modelAttrs.parameters.presencePenalty;
|
|
465
464
|
}
|
|
466
|
-
if (
|
|
467
|
-
attributes["gen_ai.request.frequency_penalty"] =
|
|
465
|
+
if (modelAttrs.parameters.frequencyPenalty !== void 0) {
|
|
466
|
+
attributes["gen_ai.request.frequency_penalty"] = modelAttrs.parameters.frequencyPenalty;
|
|
468
467
|
}
|
|
469
|
-
if (
|
|
470
|
-
attributes["gen_ai.request.stop_sequences"] = JSON.stringify(
|
|
468
|
+
if (modelAttrs.parameters.stopSequences) {
|
|
469
|
+
attributes["gen_ai.request.stop_sequences"] = JSON.stringify(modelAttrs.parameters.stopSequences);
|
|
471
470
|
}
|
|
472
471
|
}
|
|
473
|
-
if (
|
|
474
|
-
attributes["gen_ai.response.finish_reasons"] =
|
|
472
|
+
if (modelAttrs.finishReason) {
|
|
473
|
+
attributes["gen_ai.response.finish_reasons"] = modelAttrs.finishReason;
|
|
475
474
|
}
|
|
476
475
|
}
|
|
477
|
-
if ((
|
|
478
|
-
const toolAttrs =
|
|
476
|
+
if ((Span.type === observability$1.SpanType.TOOL_CALL || Span.type === observability$1.SpanType.MCP_TOOL_CALL) && Span.attributes) {
|
|
477
|
+
const toolAttrs = Span.attributes;
|
|
479
478
|
if (toolAttrs.toolId) {
|
|
480
479
|
attributes["gen_ai.tool.name"] = toolAttrs.toolId;
|
|
481
480
|
}
|
|
482
|
-
if (
|
|
481
|
+
if (Span.type === observability$1.SpanType.MCP_TOOL_CALL) {
|
|
483
482
|
const mcpAttrs = toolAttrs;
|
|
484
483
|
if (mcpAttrs.mcpServer) {
|
|
485
484
|
attributes["mcp.server"] = mcpAttrs.mcpServer;
|
|
@@ -496,10 +495,11 @@ var SpanConverter = class {
|
|
|
496
495
|
attributes["gen_ai.tool.success"] = toolAttrs.success;
|
|
497
496
|
}
|
|
498
497
|
}
|
|
499
|
-
if (
|
|
500
|
-
const agentAttrs =
|
|
498
|
+
if (Span.type === observability$1.SpanType.AGENT_RUN && Span.attributes) {
|
|
499
|
+
const agentAttrs = Span.attributes;
|
|
501
500
|
if (agentAttrs.agentId) {
|
|
502
501
|
attributes["agent.id"] = agentAttrs.agentId;
|
|
502
|
+
attributes["gen_ai.agent.id"] = agentAttrs.agentId;
|
|
503
503
|
}
|
|
504
504
|
if (agentAttrs.maxSteps) {
|
|
505
505
|
attributes["agent.max_steps"] = agentAttrs.maxSteps;
|
|
@@ -508,8 +508,8 @@ var SpanConverter = class {
|
|
|
508
508
|
attributes["agent.available_tools"] = JSON.stringify(agentAttrs.availableTools);
|
|
509
509
|
}
|
|
510
510
|
}
|
|
511
|
-
if (
|
|
512
|
-
const workflowAttrs =
|
|
511
|
+
if (Span.type === observability$1.SpanType.WORKFLOW_RUN && Span.attributes) {
|
|
512
|
+
const workflowAttrs = Span.attributes;
|
|
513
513
|
if (workflowAttrs.workflowId) {
|
|
514
514
|
attributes["workflow.id"] = workflowAttrs.workflowId;
|
|
515
515
|
}
|
|
@@ -517,19 +517,19 @@ var SpanConverter = class {
|
|
|
517
517
|
attributes["workflow.status"] = workflowAttrs.status;
|
|
518
518
|
}
|
|
519
519
|
}
|
|
520
|
-
if (
|
|
520
|
+
if (Span.errorInfo) {
|
|
521
521
|
attributes["error"] = true;
|
|
522
|
-
attributes["error.type"] =
|
|
523
|
-
attributes["error.message"] =
|
|
524
|
-
if (
|
|
525
|
-
attributes["error.domain"] =
|
|
522
|
+
attributes["error.type"] = Span.errorInfo.id || "unknown";
|
|
523
|
+
attributes["error.message"] = Span.errorInfo.message;
|
|
524
|
+
if (Span.errorInfo.domain) {
|
|
525
|
+
attributes["error.domain"] = Span.errorInfo.domain;
|
|
526
526
|
}
|
|
527
|
-
if (
|
|
528
|
-
attributes["error.category"] =
|
|
527
|
+
if (Span.errorInfo.category) {
|
|
528
|
+
attributes["error.category"] = Span.errorInfo.category;
|
|
529
529
|
}
|
|
530
530
|
}
|
|
531
|
-
if (
|
|
532
|
-
Object.entries(
|
|
531
|
+
if (Span.metadata) {
|
|
532
|
+
Object.entries(Span.metadata).forEach(([key, value]) => {
|
|
533
533
|
if (!attributes[key]) {
|
|
534
534
|
if (value === null || value === void 0) {
|
|
535
535
|
return;
|
|
@@ -542,12 +542,12 @@ var SpanConverter = class {
|
|
|
542
542
|
}
|
|
543
543
|
});
|
|
544
544
|
}
|
|
545
|
-
if (
|
|
546
|
-
attributes["mastra.start_time"] =
|
|
545
|
+
if (Span.startTime) {
|
|
546
|
+
attributes["mastra.start_time"] = Span.startTime.toISOString();
|
|
547
547
|
}
|
|
548
|
-
if (
|
|
549
|
-
attributes["mastra.end_time"] =
|
|
550
|
-
const duration =
|
|
548
|
+
if (Span.endTime) {
|
|
549
|
+
attributes["mastra.end_time"] = Span.endTime.toISOString();
|
|
550
|
+
const duration = Span.endTime.getTime() - Span.startTime.getTime();
|
|
551
551
|
attributes["mastra.duration_ms"] = duration;
|
|
552
552
|
}
|
|
553
553
|
return attributes;
|
|
@@ -555,28 +555,28 @@ var SpanConverter = class {
|
|
|
555
555
|
/**
|
|
556
556
|
* Get the operation name based on span type for gen_ai.operation.name
|
|
557
557
|
*/
|
|
558
|
-
getOperationName(
|
|
559
|
-
switch (
|
|
560
|
-
case
|
|
561
|
-
const attrs =
|
|
558
|
+
getOperationName(Span) {
|
|
559
|
+
switch (Span.type) {
|
|
560
|
+
case observability$1.SpanType.MODEL_GENERATION: {
|
|
561
|
+
const attrs = Span.attributes;
|
|
562
562
|
return attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
|
|
563
563
|
}
|
|
564
|
-
case
|
|
565
|
-
case
|
|
564
|
+
case observability$1.SpanType.TOOL_CALL:
|
|
565
|
+
case observability$1.SpanType.MCP_TOOL_CALL:
|
|
566
566
|
return "tool.execute";
|
|
567
|
-
case
|
|
567
|
+
case observability$1.SpanType.AGENT_RUN:
|
|
568
568
|
return "agent.run";
|
|
569
|
-
case
|
|
569
|
+
case observability$1.SpanType.WORKFLOW_RUN:
|
|
570
570
|
return "workflow.run";
|
|
571
571
|
default:
|
|
572
|
-
return
|
|
572
|
+
return Span.type.replace(/_/g, ".");
|
|
573
573
|
}
|
|
574
574
|
}
|
|
575
575
|
/**
|
|
576
576
|
* Get span kind as string for attribute
|
|
577
577
|
*/
|
|
578
|
-
getSpanKindString(
|
|
579
|
-
const kind = this.getSpanKind(
|
|
578
|
+
getSpanKindString(Span) {
|
|
579
|
+
const kind = this.getSpanKind(Span);
|
|
580
580
|
switch (kind) {
|
|
581
581
|
case api.SpanKind.SERVER:
|
|
582
582
|
return "server";
|
|
@@ -594,21 +594,19 @@ var SpanConverter = class {
|
|
|
594
594
|
}
|
|
595
595
|
};
|
|
596
596
|
|
|
597
|
-
// src/
|
|
598
|
-
var OtelExporter = class {
|
|
597
|
+
// src/tracing.ts
|
|
598
|
+
var OtelExporter = class extends observability.BaseExporter {
|
|
599
599
|
config;
|
|
600
600
|
tracingConfig;
|
|
601
601
|
spanConverter;
|
|
602
602
|
processor;
|
|
603
603
|
exporter;
|
|
604
604
|
isSetup = false;
|
|
605
|
-
isDisabled = false;
|
|
606
|
-
logger;
|
|
607
605
|
name = "opentelemetry";
|
|
608
606
|
constructor(config) {
|
|
607
|
+
super(config);
|
|
609
608
|
this.config = config;
|
|
610
609
|
this.spanConverter = new SpanConverter();
|
|
611
|
-
this.logger = new logger.ConsoleLogger({ level: config.logLevel ?? "warn" });
|
|
612
610
|
if (config.logLevel === "debug") {
|
|
613
611
|
api.diag.setLogger(new api.DiagConsoleLogger(), api.DiagLogLevel.DEBUG);
|
|
614
612
|
}
|
|
@@ -616,11 +614,11 @@ var OtelExporter = class {
|
|
|
616
614
|
/**
|
|
617
615
|
* Initialize with tracing configuration
|
|
618
616
|
*/
|
|
619
|
-
init(
|
|
620
|
-
this.tracingConfig = config;
|
|
617
|
+
init(options) {
|
|
618
|
+
this.tracingConfig = options.config;
|
|
621
619
|
}
|
|
622
620
|
async setupExporter() {
|
|
623
|
-
if (this.isSetup) return;
|
|
621
|
+
if (this.isSetup || this.exporter) return;
|
|
624
622
|
if (!this.config.provider) {
|
|
625
623
|
this.logger.error(
|
|
626
624
|
'[OtelExporter] Provider configuration is required. Use the "custom" provider for generic endpoints.'
|
|
@@ -635,6 +633,10 @@ var OtelExporter = class {
|
|
|
635
633
|
this.isSetup = true;
|
|
636
634
|
return;
|
|
637
635
|
}
|
|
636
|
+
if (this.config.exporter) {
|
|
637
|
+
this.exporter = this.config.exporter;
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
638
640
|
const endpoint = resolved.endpoint;
|
|
639
641
|
const headers = resolved.headers;
|
|
640
642
|
const protocol = resolved.protocol;
|
|
@@ -688,7 +690,10 @@ var OtelExporter = class {
|
|
|
688
690
|
this.isSetup = true;
|
|
689
691
|
return;
|
|
690
692
|
}
|
|
691
|
-
|
|
693
|
+
}
|
|
694
|
+
async setupProcessor() {
|
|
695
|
+
if (this.processor || this.isSetup) return;
|
|
696
|
+
let resource = resources.resourceFromAttributes({
|
|
692
697
|
[semanticConventions.ATTR_SERVICE_NAME]: this.tracingConfig?.serviceName || "mastra-service",
|
|
693
698
|
[semanticConventions.ATTR_SERVICE_VERSION]: "1.0.0",
|
|
694
699
|
// Add telemetry SDK information
|
|
@@ -696,6 +701,12 @@ var OtelExporter = class {
|
|
|
696
701
|
[semanticConventions.ATTR_TELEMETRY_SDK_VERSION]: "1.0.0",
|
|
697
702
|
[semanticConventions.ATTR_TELEMETRY_SDK_LANGUAGE]: "nodejs"
|
|
698
703
|
});
|
|
704
|
+
if (this.config.resourceAttributes) {
|
|
705
|
+
resource = resource.merge(
|
|
706
|
+
// Duplicate attributes from config will override defaults above
|
|
707
|
+
resources.resourceFromAttributes(this.config.resourceAttributes)
|
|
708
|
+
);
|
|
709
|
+
}
|
|
699
710
|
this.spanConverter = new SpanConverter(resource);
|
|
700
711
|
this.processor = new sdkTraceBase.BatchSpanProcessor(this.exporter, {
|
|
701
712
|
maxExportBatchSize: this.config.batchSize || 512,
|
|
@@ -710,13 +721,15 @@ var OtelExporter = class {
|
|
|
710
721
|
this.logger.debug(
|
|
711
722
|
`[OtelExporter] Using BatchSpanProcessor (batch size: ${this.config.batchSize || 512}, delay: 5s)`
|
|
712
723
|
);
|
|
724
|
+
}
|
|
725
|
+
async setup() {
|
|
726
|
+
if (this.isSetup) return;
|
|
727
|
+
await this.setupExporter();
|
|
728
|
+
await this.setupProcessor();
|
|
713
729
|
this.isSetup = true;
|
|
714
730
|
}
|
|
715
|
-
async
|
|
716
|
-
if (
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
if (event.type !== aiTracing.AITracingEventType.SPAN_ENDED) {
|
|
731
|
+
async _exportTracingEvent(event) {
|
|
732
|
+
if (event.type !== observability$1.TracingEventType.SPAN_ENDED) {
|
|
720
733
|
return;
|
|
721
734
|
}
|
|
722
735
|
const span = event.exportedSpan;
|
|
@@ -724,7 +737,7 @@ var OtelExporter = class {
|
|
|
724
737
|
}
|
|
725
738
|
async exportSpan(span) {
|
|
726
739
|
if (!this.isSetup) {
|
|
727
|
-
await this.
|
|
740
|
+
await this.setup();
|
|
728
741
|
}
|
|
729
742
|
if (this.isDisabled || !this.processor) {
|
|
730
743
|
return;
|