@mastra/otel-exporter 0.0.0-netlify-no-bundle-20251127120354 → 0.0.0-partial-response-backport-20251204204441

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,13 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var observability = require('@mastra/core/observability');
4
- var observability$1 = require('@mastra/observability');
3
+ var aiTracing = require('@mastra/core/ai-tracing');
5
4
  var api = require('@opentelemetry/api');
6
5
  var resources = require('@opentelemetry/resources');
7
6
  var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
8
7
  var semanticConventions = require('@opentelemetry/semantic-conventions');
9
8
 
10
- // src/tracing.ts
9
+ // src/ai-tracing.ts
11
10
 
12
11
  // src/loadExporter.ts
13
12
  var OTLPHttpExporter;
@@ -225,45 +224,45 @@ var MastraReadableSpan = class {
225
224
  droppedAttributesCount = 0;
226
225
  droppedEventsCount = 0;
227
226
  droppedLinksCount = 0;
228
- constructor(span, attributes, kind, parentSpanId, resource, instrumentationLibrary) {
229
- this.name = span.name;
227
+ constructor(aiSpan, attributes, kind, parentSpanId, resource, instrumentationLibrary) {
228
+ this.name = aiSpan.name;
230
229
  this.kind = kind;
231
230
  this.attributes = attributes;
232
231
  this.parentSpanId = parentSpanId;
233
232
  this.links = [];
234
233
  this.events = [];
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();
234
+ this.startTime = this.dateToHrTime(aiSpan.startTime);
235
+ this.endTime = aiSpan.endTime ? this.dateToHrTime(aiSpan.endTime) : this.startTime;
236
+ this.ended = !!aiSpan.endTime;
237
+ if (aiSpan.endTime) {
238
+ const durationMs = aiSpan.endTime.getTime() - aiSpan.startTime.getTime();
240
239
  this.duration = [Math.floor(durationMs / 1e3), durationMs % 1e3 * 1e6];
241
240
  } else {
242
241
  this.duration = [0, 0];
243
242
  }
244
- if (span.errorInfo) {
243
+ if (aiSpan.errorInfo) {
245
244
  this.status = {
246
245
  code: api.SpanStatusCode.ERROR,
247
- message: span.errorInfo.message
246
+ message: aiSpan.errorInfo.message
248
247
  };
249
248
  this.events.push({
250
249
  name: "exception",
251
250
  attributes: {
252
- "exception.message": span.errorInfo.message,
251
+ "exception.message": aiSpan.errorInfo.message,
253
252
  "exception.type": "Error",
254
- ...span.errorInfo.details?.stack && {
255
- "exception.stacktrace": span.errorInfo.details.stack
253
+ ...aiSpan.errorInfo.details?.stack && {
254
+ "exception.stacktrace": aiSpan.errorInfo.details.stack
256
255
  }
257
256
  },
258
257
  time: this.startTime,
259
258
  droppedAttributesCount: 0
260
259
  });
261
- } else if (span.endTime) {
260
+ } else if (aiSpan.endTime) {
262
261
  this.status = { code: api.SpanStatusCode.OK };
263
262
  } else {
264
263
  this.status = { code: api.SpanStatusCode.UNSET };
265
264
  }
266
- if (span.isEvent) {
265
+ if (aiSpan.isEvent) {
267
266
  this.events.push({
268
267
  name: "instant_event",
269
268
  attributes: {},
@@ -272,14 +271,14 @@ var MastraReadableSpan = class {
272
271
  });
273
272
  }
274
273
  this.spanContext = () => ({
275
- traceId: span.traceId,
276
- spanId: span.id,
274
+ traceId: aiSpan.traceId,
275
+ spanId: aiSpan.id,
277
276
  traceFlags: api.TraceFlags.SAMPLED,
278
277
  isRemote: false
279
278
  });
280
279
  if (parentSpanId) {
281
280
  this.parentSpanContext = {
282
- traceId: span.traceId,
281
+ traceId: aiSpan.traceId,
283
282
  spanId: parentSpanId,
284
283
  traceFlags: api.TraceFlags.SAMPLED,
285
284
  isRemote: false
@@ -306,118 +305,121 @@ var MastraReadableSpan = class {
306
305
  // src/span-converter.ts
307
306
  var SPAN_KIND_MAPPING = {
308
307
  // Model operations are CLIENT spans (calling external AI services)
309
- [observability.SpanType.MODEL_GENERATION]: api.SpanKind.CLIENT,
310
- [observability.SpanType.MODEL_CHUNK]: api.SpanKind.CLIENT,
308
+ [aiTracing.AISpanType.MODEL_GENERATION]: api.SpanKind.CLIENT,
309
+ [aiTracing.AISpanType.MODEL_CHUNK]: api.SpanKind.CLIENT,
311
310
  // MCP tool calls are CLIENT (external service calls)
312
- [observability.SpanType.MCP_TOOL_CALL]: api.SpanKind.CLIENT,
311
+ [aiTracing.AISpanType.MCP_TOOL_CALL]: api.SpanKind.CLIENT,
313
312
  // Root spans for agent/workflow are SERVER (entry points)
314
- [observability.SpanType.AGENT_RUN]: api.SpanKind.SERVER,
315
- [observability.SpanType.WORKFLOW_RUN]: api.SpanKind.SERVER
313
+ [aiTracing.AISpanType.AGENT_RUN]: api.SpanKind.SERVER,
314
+ [aiTracing.AISpanType.WORKFLOW_RUN]: api.SpanKind.SERVER
316
315
  };
317
- function getSpanKind(type, isRootSpan) {
318
- if (isRootSpan) {
319
- if (type === observability.SpanType.AGENT_RUN || type === observability.SpanType.WORKFLOW_RUN) {
320
- return api.SpanKind.SERVER;
321
- }
322
- }
323
- return SPAN_KIND_MAPPING[type] || api.SpanKind.INTERNAL;
324
- }
325
316
  var SpanConverter = class {
326
317
  resource;
327
318
  instrumentationLibrary;
328
319
  constructor(resource) {
329
320
  this.resource = resource;
330
321
  this.instrumentationLibrary = {
331
- name: "@mastra/otel-exporter",
322
+ name: "@mastra/otel",
332
323
  version: "1.0.0"
333
324
  };
334
325
  }
335
326
  /**
336
- * Convert a Mastra Span to an OpenTelemetry ReadableSpan
327
+ * Convert a Mastra AI span to an OpenTelemetry ReadableSpan
337
328
  * This preserves Mastra's trace and span IDs
338
329
  */
339
- convertSpan(span) {
340
- const spanKind = getSpanKind(span.type, span.isRootSpan);
341
- const attributes = this.buildAttributes(span);
342
- const spanName = this.buildSpanName(span);
343
- const otelSpan = { ...span, name: spanName };
330
+ convertSpan(aiSpan) {
331
+ const spanKind = this.getSpanKind(aiSpan);
332
+ const attributes = this.buildAttributes(aiSpan);
333
+ const spanName = this.buildSpanName(aiSpan);
334
+ const otelSpan = { ...aiSpan, name: spanName };
344
335
  return new MastraReadableSpan(
345
336
  otelSpan,
346
337
  attributes,
347
338
  spanKind,
348
- span.parentSpanId,
339
+ aiSpan.parentSpanId,
349
340
  // Use the parentSpanId from the Mastra span directly
350
341
  this.resource,
351
342
  this.instrumentationLibrary
352
343
  );
353
344
  }
345
+ /**
346
+ * Get the appropriate SpanKind based on span type and context
347
+ */
348
+ getSpanKind(aiSpan) {
349
+ if (aiSpan.isRootSpan) {
350
+ if (aiSpan.type === aiTracing.AISpanType.AGENT_RUN || aiSpan.type === aiTracing.AISpanType.WORKFLOW_RUN) {
351
+ return api.SpanKind.SERVER;
352
+ }
353
+ }
354
+ return SPAN_KIND_MAPPING[aiSpan.type] || api.SpanKind.INTERNAL;
355
+ }
354
356
  /**
355
357
  * Build OTEL-compliant span name based on span type and attributes
356
358
  */
357
- buildSpanName(Span) {
358
- switch (Span.type) {
359
- case observability.SpanType.MODEL_GENERATION: {
360
- const attrs = Span.attributes;
359
+ buildSpanName(aiSpan) {
360
+ switch (aiSpan.type) {
361
+ case aiTracing.AISpanType.MODEL_GENERATION: {
362
+ const attrs = aiSpan.attributes;
361
363
  const operation = attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
362
364
  const model = attrs?.model || "unknown";
363
365
  return `${operation} ${model}`;
364
366
  }
365
- case observability.SpanType.TOOL_CALL:
366
- case observability.SpanType.MCP_TOOL_CALL: {
367
- const toolAttrs = Span.attributes;
367
+ case aiTracing.AISpanType.TOOL_CALL:
368
+ case aiTracing.AISpanType.MCP_TOOL_CALL: {
369
+ const toolAttrs = aiSpan.attributes;
368
370
  const toolName = toolAttrs?.toolId || "unknown";
369
371
  return `tool.execute ${toolName}`;
370
372
  }
371
- case observability.SpanType.AGENT_RUN: {
372
- const agentAttrs = Span.attributes;
373
+ case aiTracing.AISpanType.AGENT_RUN: {
374
+ const agentAttrs = aiSpan.attributes;
373
375
  const agentId = agentAttrs?.agentId || "unknown";
374
376
  return `agent.${agentId}`;
375
377
  }
376
- case observability.SpanType.WORKFLOW_RUN: {
377
- const workflowAttrs = Span.attributes;
378
+ case aiTracing.AISpanType.WORKFLOW_RUN: {
379
+ const workflowAttrs = aiSpan.attributes;
378
380
  const workflowId = workflowAttrs?.workflowId || "unknown";
379
381
  return `workflow.${workflowId}`;
380
382
  }
381
- case observability.SpanType.WORKFLOW_STEP:
382
- return Span.name;
383
+ case aiTracing.AISpanType.WORKFLOW_STEP:
384
+ return aiSpan.name;
383
385
  default:
384
- return Span.name;
386
+ return aiSpan.name;
385
387
  }
386
388
  }
387
389
  /**
388
- * Build OpenTelemetry attributes from Mastra Span
390
+ * Build OpenTelemetry attributes from Mastra AI span
389
391
  * Following OTEL Semantic Conventions for GenAI
390
392
  */
391
- buildAttributes(Span) {
393
+ buildAttributes(aiSpan) {
392
394
  const attributes = {};
393
- attributes["gen_ai.operation.name"] = this.getOperationName(Span);
394
- attributes["span.kind"] = this.getSpanKindString(Span);
395
- attributes["mastra.span.type"] = Span.type;
396
- attributes["mastra.trace_id"] = Span.traceId;
397
- attributes["mastra.span_id"] = Span.id;
398
- if (Span.parentSpanId) {
399
- attributes["mastra.parent_span_id"] = Span.parentSpanId;
395
+ attributes["gen_ai.operation.name"] = this.getOperationName(aiSpan);
396
+ attributes["span.kind"] = this.getSpanKindString(aiSpan);
397
+ attributes["mastra.span.type"] = aiSpan.type;
398
+ attributes["mastra.trace_id"] = aiSpan.traceId;
399
+ attributes["mastra.span_id"] = aiSpan.id;
400
+ if (aiSpan.parentSpanId) {
401
+ attributes["mastra.parent_span_id"] = aiSpan.parentSpanId;
400
402
  }
401
- if (Span.input !== void 0) {
402
- const inputStr = typeof Span.input === "string" ? Span.input : JSON.stringify(Span.input);
403
+ if (aiSpan.input !== void 0) {
404
+ const inputStr = typeof aiSpan.input === "string" ? aiSpan.input : JSON.stringify(aiSpan.input);
403
405
  attributes["input"] = inputStr;
404
- if (Span.type === observability.SpanType.MODEL_GENERATION) {
406
+ if (aiSpan.type === aiTracing.AISpanType.MODEL_GENERATION) {
405
407
  attributes["gen_ai.prompt"] = inputStr;
406
- } else if (Span.type === observability.SpanType.TOOL_CALL || Span.type === observability.SpanType.MCP_TOOL_CALL) {
408
+ } else if (aiSpan.type === aiTracing.AISpanType.TOOL_CALL || aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) {
407
409
  attributes["gen_ai.tool.input"] = inputStr;
408
410
  }
409
411
  }
410
- if (Span.output !== void 0) {
411
- const outputStr = typeof Span.output === "string" ? Span.output : JSON.stringify(Span.output);
412
+ if (aiSpan.output !== void 0) {
413
+ const outputStr = typeof aiSpan.output === "string" ? aiSpan.output : JSON.stringify(aiSpan.output);
412
414
  attributes["output"] = outputStr;
413
- if (Span.type === observability.SpanType.MODEL_GENERATION) {
415
+ if (aiSpan.type === aiTracing.AISpanType.MODEL_GENERATION) {
414
416
  attributes["gen_ai.completion"] = outputStr;
415
- } else if (Span.type === observability.SpanType.TOOL_CALL || Span.type === observability.SpanType.MCP_TOOL_CALL) {
417
+ } else if (aiSpan.type === aiTracing.AISpanType.TOOL_CALL || aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) {
416
418
  attributes["gen_ai.tool.output"] = outputStr;
417
419
  }
418
420
  }
419
- if (Span.type === observability.SpanType.MODEL_GENERATION && Span.attributes) {
420
- const modelAttrs = Span.attributes;
421
+ if (aiSpan.type === aiTracing.AISpanType.MODEL_GENERATION && aiSpan.attributes) {
422
+ const modelAttrs = aiSpan.attributes;
421
423
  if (modelAttrs.model) {
422
424
  attributes["gen_ai.request.model"] = modelAttrs.model;
423
425
  }
@@ -470,12 +472,12 @@ var SpanConverter = class {
470
472
  attributes["gen_ai.response.finish_reasons"] = modelAttrs.finishReason;
471
473
  }
472
474
  }
473
- if ((Span.type === observability.SpanType.TOOL_CALL || Span.type === observability.SpanType.MCP_TOOL_CALL) && Span.attributes) {
474
- const toolAttrs = Span.attributes;
475
+ if ((aiSpan.type === aiTracing.AISpanType.TOOL_CALL || aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) && aiSpan.attributes) {
476
+ const toolAttrs = aiSpan.attributes;
475
477
  if (toolAttrs.toolId) {
476
478
  attributes["gen_ai.tool.name"] = toolAttrs.toolId;
477
479
  }
478
- if (Span.type === observability.SpanType.MCP_TOOL_CALL) {
480
+ if (aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) {
479
481
  const mcpAttrs = toolAttrs;
480
482
  if (mcpAttrs.mcpServer) {
481
483
  attributes["mcp.server"] = mcpAttrs.mcpServer;
@@ -492,8 +494,8 @@ var SpanConverter = class {
492
494
  attributes["gen_ai.tool.success"] = toolAttrs.success;
493
495
  }
494
496
  }
495
- if (Span.type === observability.SpanType.AGENT_RUN && Span.attributes) {
496
- const agentAttrs = Span.attributes;
497
+ if (aiSpan.type === aiTracing.AISpanType.AGENT_RUN && aiSpan.attributes) {
498
+ const agentAttrs = aiSpan.attributes;
497
499
  if (agentAttrs.agentId) {
498
500
  attributes["agent.id"] = agentAttrs.agentId;
499
501
  attributes["gen_ai.agent.id"] = agentAttrs.agentId;
@@ -505,8 +507,8 @@ var SpanConverter = class {
505
507
  attributes["agent.available_tools"] = JSON.stringify(agentAttrs.availableTools);
506
508
  }
507
509
  }
508
- if (Span.type === observability.SpanType.WORKFLOW_RUN && Span.attributes) {
509
- const workflowAttrs = Span.attributes;
510
+ if (aiSpan.type === aiTracing.AISpanType.WORKFLOW_RUN && aiSpan.attributes) {
511
+ const workflowAttrs = aiSpan.attributes;
510
512
  if (workflowAttrs.workflowId) {
511
513
  attributes["workflow.id"] = workflowAttrs.workflowId;
512
514
  }
@@ -514,19 +516,19 @@ var SpanConverter = class {
514
516
  attributes["workflow.status"] = workflowAttrs.status;
515
517
  }
516
518
  }
517
- if (Span.errorInfo) {
519
+ if (aiSpan.errorInfo) {
518
520
  attributes["error"] = true;
519
- attributes["error.type"] = Span.errorInfo.id || "unknown";
520
- attributes["error.message"] = Span.errorInfo.message;
521
- if (Span.errorInfo.domain) {
522
- attributes["error.domain"] = Span.errorInfo.domain;
521
+ attributes["error.type"] = aiSpan.errorInfo.id || "unknown";
522
+ attributes["error.message"] = aiSpan.errorInfo.message;
523
+ if (aiSpan.errorInfo.domain) {
524
+ attributes["error.domain"] = aiSpan.errorInfo.domain;
523
525
  }
524
- if (Span.errorInfo.category) {
525
- attributes["error.category"] = Span.errorInfo.category;
526
+ if (aiSpan.errorInfo.category) {
527
+ attributes["error.category"] = aiSpan.errorInfo.category;
526
528
  }
527
529
  }
528
- if (Span.metadata) {
529
- Object.entries(Span.metadata).forEach(([key, value]) => {
530
+ if (aiSpan.metadata) {
531
+ Object.entries(aiSpan.metadata).forEach(([key, value]) => {
530
532
  if (!attributes[key]) {
531
533
  if (value === null || value === void 0) {
532
534
  return;
@@ -539,12 +541,12 @@ var SpanConverter = class {
539
541
  }
540
542
  });
541
543
  }
542
- if (Span.startTime) {
543
- attributes["mastra.start_time"] = Span.startTime.toISOString();
544
+ if (aiSpan.startTime) {
545
+ attributes["mastra.start_time"] = aiSpan.startTime.toISOString();
544
546
  }
545
- if (Span.endTime) {
546
- attributes["mastra.end_time"] = Span.endTime.toISOString();
547
- const duration = Span.endTime.getTime() - Span.startTime.getTime();
547
+ if (aiSpan.endTime) {
548
+ attributes["mastra.end_time"] = aiSpan.endTime.toISOString();
549
+ const duration = aiSpan.endTime.getTime() - aiSpan.startTime.getTime();
548
550
  attributes["mastra.duration_ms"] = duration;
549
551
  }
550
552
  return attributes;
@@ -552,28 +554,28 @@ var SpanConverter = class {
552
554
  /**
553
555
  * Get the operation name based on span type for gen_ai.operation.name
554
556
  */
555
- getOperationName(Span) {
556
- switch (Span.type) {
557
- case observability.SpanType.MODEL_GENERATION: {
558
- const attrs = Span.attributes;
557
+ getOperationName(aiSpan) {
558
+ switch (aiSpan.type) {
559
+ case aiTracing.AISpanType.MODEL_GENERATION: {
560
+ const attrs = aiSpan.attributes;
559
561
  return attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
560
562
  }
561
- case observability.SpanType.TOOL_CALL:
562
- case observability.SpanType.MCP_TOOL_CALL:
563
+ case aiTracing.AISpanType.TOOL_CALL:
564
+ case aiTracing.AISpanType.MCP_TOOL_CALL:
563
565
  return "tool.execute";
564
- case observability.SpanType.AGENT_RUN:
566
+ case aiTracing.AISpanType.AGENT_RUN:
565
567
  return "agent.run";
566
- case observability.SpanType.WORKFLOW_RUN:
568
+ case aiTracing.AISpanType.WORKFLOW_RUN:
567
569
  return "workflow.run";
568
570
  default:
569
- return Span.type.replace(/_/g, ".");
571
+ return aiSpan.type.replace(/_/g, ".");
570
572
  }
571
573
  }
572
574
  /**
573
575
  * Get span kind as string for attribute
574
576
  */
575
- getSpanKindString(Span) {
576
- const kind = getSpanKind(Span.type, Span.isRootSpan);
577
+ getSpanKindString(aiSpan) {
578
+ const kind = this.getSpanKind(aiSpan);
577
579
  switch (kind) {
578
580
  case api.SpanKind.SERVER:
579
581
  return "server";
@@ -591,8 +593,8 @@ var SpanConverter = class {
591
593
  }
592
594
  };
593
595
 
594
- // src/tracing.ts
595
- var OtelExporter = class extends observability$1.BaseExporter {
596
+ // src/ai-tracing.ts
597
+ var OtelExporter = class extends aiTracing.BaseExporter {
596
598
  config;
597
599
  tracingConfig;
598
600
  spanConverter;
@@ -611,8 +613,8 @@ var OtelExporter = class extends observability$1.BaseExporter {
611
613
  /**
612
614
  * Initialize with tracing configuration
613
615
  */
614
- init(options) {
615
- this.tracingConfig = options.config;
616
+ init(config) {
617
+ this.tracingConfig = config;
616
618
  }
617
619
  async setupExporter() {
618
620
  if (this.isSetup || this.exporter) return;
@@ -725,8 +727,8 @@ var OtelExporter = class extends observability$1.BaseExporter {
725
727
  await this.setupProcessor();
726
728
  this.isSetup = true;
727
729
  }
728
- async _exportTracingEvent(event) {
729
- if (event.type !== observability.TracingEventType.SPAN_ENDED) {
730
+ async _exportEvent(event) {
731
+ if (event.type !== aiTracing.AITracingEventType.SPAN_ENDED) {
730
732
  return;
731
733
  }
732
734
  const span = event.exportedSpan;
@@ -759,9 +761,6 @@ var OtelExporter = class extends observability$1.BaseExporter {
759
761
  }
760
762
  };
761
763
 
762
- exports.MastraReadableSpan = MastraReadableSpan;
763
764
  exports.OtelExporter = OtelExporter;
764
- exports.SpanConverter = SpanConverter;
765
- exports.getSpanKind = getSpanKind;
766
765
  //# sourceMappingURL=index.cjs.map
767
766
  //# sourceMappingURL=index.cjs.map