@mastra/otel-exporter 0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939 → 0.0.0-fix-backport-setserver-20251201144151

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$1 = require('@mastra/core/observability');
4
- var observability = 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,13 +305,13 @@ 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$1.SpanType.MODEL_GENERATION]: api.SpanKind.CLIENT,
310
- [observability$1.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$1.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$1.SpanType.AGENT_RUN]: api.SpanKind.SERVER,
315
- [observability$1.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
316
  var SpanConverter = class {
318
317
  resource;
@@ -325,19 +324,19 @@ var SpanConverter = class {
325
324
  };
326
325
  }
327
326
  /**
328
- * Convert a Mastra Span to an OpenTelemetry ReadableSpan
327
+ * Convert a Mastra AI span to an OpenTelemetry ReadableSpan
329
328
  * This preserves Mastra's trace and span IDs
330
329
  */
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 };
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 };
336
335
  return new MastraReadableSpan(
337
336
  otelSpan,
338
337
  attributes,
339
338
  spanKind,
340
- Span.parentSpanId,
339
+ aiSpan.parentSpanId,
341
340
  // Use the parentSpanId from the Mastra span directly
342
341
  this.resource,
343
342
  this.instrumentationLibrary
@@ -346,81 +345,81 @@ var SpanConverter = class {
346
345
  /**
347
346
  * Get the appropriate SpanKind based on span type and context
348
347
  */
349
- getSpanKind(Span) {
350
- if (Span.isRootSpan) {
351
- if (Span.type === observability$1.SpanType.AGENT_RUN || Span.type === observability$1.SpanType.WORKFLOW_RUN) {
348
+ getSpanKind(aiSpan) {
349
+ if (aiSpan.isRootSpan) {
350
+ if (aiSpan.type === aiTracing.AISpanType.AGENT_RUN || aiSpan.type === aiTracing.AISpanType.WORKFLOW_RUN) {
352
351
  return api.SpanKind.SERVER;
353
352
  }
354
353
  }
355
- return SPAN_KIND_MAPPING[Span.type] || api.SpanKind.INTERNAL;
354
+ return SPAN_KIND_MAPPING[aiSpan.type] || api.SpanKind.INTERNAL;
356
355
  }
357
356
  /**
358
357
  * Build OTEL-compliant span name based on span type and attributes
359
358
  */
360
- buildSpanName(Span) {
361
- switch (Span.type) {
362
- case observability$1.SpanType.MODEL_GENERATION: {
363
- const attrs = Span.attributes;
359
+ buildSpanName(aiSpan) {
360
+ switch (aiSpan.type) {
361
+ case aiTracing.AISpanType.MODEL_GENERATION: {
362
+ const attrs = aiSpan.attributes;
364
363
  const operation = attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
365
364
  const model = attrs?.model || "unknown";
366
365
  return `${operation} ${model}`;
367
366
  }
368
- case observability$1.SpanType.TOOL_CALL:
369
- case observability$1.SpanType.MCP_TOOL_CALL: {
370
- const toolAttrs = Span.attributes;
367
+ case aiTracing.AISpanType.TOOL_CALL:
368
+ case aiTracing.AISpanType.MCP_TOOL_CALL: {
369
+ const toolAttrs = aiSpan.attributes;
371
370
  const toolName = toolAttrs?.toolId || "unknown";
372
371
  return `tool.execute ${toolName}`;
373
372
  }
374
- case observability$1.SpanType.AGENT_RUN: {
375
- const agentAttrs = Span.attributes;
373
+ case aiTracing.AISpanType.AGENT_RUN: {
374
+ const agentAttrs = aiSpan.attributes;
376
375
  const agentId = agentAttrs?.agentId || "unknown";
377
376
  return `agent.${agentId}`;
378
377
  }
379
- case observability$1.SpanType.WORKFLOW_RUN: {
380
- const workflowAttrs = Span.attributes;
378
+ case aiTracing.AISpanType.WORKFLOW_RUN: {
379
+ const workflowAttrs = aiSpan.attributes;
381
380
  const workflowId = workflowAttrs?.workflowId || "unknown";
382
381
  return `workflow.${workflowId}`;
383
382
  }
384
- case observability$1.SpanType.WORKFLOW_STEP:
385
- return Span.name;
383
+ case aiTracing.AISpanType.WORKFLOW_STEP:
384
+ return aiSpan.name;
386
385
  default:
387
- return Span.name;
386
+ return aiSpan.name;
388
387
  }
389
388
  }
390
389
  /**
391
- * Build OpenTelemetry attributes from Mastra Span
390
+ * Build OpenTelemetry attributes from Mastra AI span
392
391
  * Following OTEL Semantic Conventions for GenAI
393
392
  */
394
- buildAttributes(Span) {
393
+ buildAttributes(aiSpan) {
395
394
  const attributes = {};
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;
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;
403
402
  }
404
- if (Span.input !== void 0) {
405
- 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);
406
405
  attributes["input"] = inputStr;
407
- if (Span.type === observability$1.SpanType.MODEL_GENERATION) {
406
+ if (aiSpan.type === aiTracing.AISpanType.MODEL_GENERATION) {
408
407
  attributes["gen_ai.prompt"] = inputStr;
409
- } else if (Span.type === observability$1.SpanType.TOOL_CALL || Span.type === observability$1.SpanType.MCP_TOOL_CALL) {
408
+ } else if (aiSpan.type === aiTracing.AISpanType.TOOL_CALL || aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) {
410
409
  attributes["gen_ai.tool.input"] = inputStr;
411
410
  }
412
411
  }
413
- if (Span.output !== void 0) {
414
- 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);
415
414
  attributes["output"] = outputStr;
416
- if (Span.type === observability$1.SpanType.MODEL_GENERATION) {
415
+ if (aiSpan.type === aiTracing.AISpanType.MODEL_GENERATION) {
417
416
  attributes["gen_ai.completion"] = outputStr;
418
- } else if (Span.type === observability$1.SpanType.TOOL_CALL || Span.type === observability$1.SpanType.MCP_TOOL_CALL) {
417
+ } else if (aiSpan.type === aiTracing.AISpanType.TOOL_CALL || aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) {
419
418
  attributes["gen_ai.tool.output"] = outputStr;
420
419
  }
421
420
  }
422
- if (Span.type === observability$1.SpanType.MODEL_GENERATION && Span.attributes) {
423
- const modelAttrs = Span.attributes;
421
+ if (aiSpan.type === aiTracing.AISpanType.MODEL_GENERATION && aiSpan.attributes) {
422
+ const modelAttrs = aiSpan.attributes;
424
423
  if (modelAttrs.model) {
425
424
  attributes["gen_ai.request.model"] = modelAttrs.model;
426
425
  }
@@ -473,12 +472,12 @@ var SpanConverter = class {
473
472
  attributes["gen_ai.response.finish_reasons"] = modelAttrs.finishReason;
474
473
  }
475
474
  }
476
- if ((Span.type === observability$1.SpanType.TOOL_CALL || Span.type === observability$1.SpanType.MCP_TOOL_CALL) && Span.attributes) {
477
- 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;
478
477
  if (toolAttrs.toolId) {
479
478
  attributes["gen_ai.tool.name"] = toolAttrs.toolId;
480
479
  }
481
- if (Span.type === observability$1.SpanType.MCP_TOOL_CALL) {
480
+ if (aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) {
482
481
  const mcpAttrs = toolAttrs;
483
482
  if (mcpAttrs.mcpServer) {
484
483
  attributes["mcp.server"] = mcpAttrs.mcpServer;
@@ -495,8 +494,8 @@ var SpanConverter = class {
495
494
  attributes["gen_ai.tool.success"] = toolAttrs.success;
496
495
  }
497
496
  }
498
- if (Span.type === observability$1.SpanType.AGENT_RUN && Span.attributes) {
499
- const agentAttrs = Span.attributes;
497
+ if (aiSpan.type === aiTracing.AISpanType.AGENT_RUN && aiSpan.attributes) {
498
+ const agentAttrs = aiSpan.attributes;
500
499
  if (agentAttrs.agentId) {
501
500
  attributes["agent.id"] = agentAttrs.agentId;
502
501
  attributes["gen_ai.agent.id"] = agentAttrs.agentId;
@@ -508,8 +507,8 @@ var SpanConverter = class {
508
507
  attributes["agent.available_tools"] = JSON.stringify(agentAttrs.availableTools);
509
508
  }
510
509
  }
511
- if (Span.type === observability$1.SpanType.WORKFLOW_RUN && Span.attributes) {
512
- const workflowAttrs = Span.attributes;
510
+ if (aiSpan.type === aiTracing.AISpanType.WORKFLOW_RUN && aiSpan.attributes) {
511
+ const workflowAttrs = aiSpan.attributes;
513
512
  if (workflowAttrs.workflowId) {
514
513
  attributes["workflow.id"] = workflowAttrs.workflowId;
515
514
  }
@@ -517,19 +516,19 @@ var SpanConverter = class {
517
516
  attributes["workflow.status"] = workflowAttrs.status;
518
517
  }
519
518
  }
520
- if (Span.errorInfo) {
519
+ if (aiSpan.errorInfo) {
521
520
  attributes["error"] = true;
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;
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;
526
525
  }
527
- if (Span.errorInfo.category) {
528
- attributes["error.category"] = Span.errorInfo.category;
526
+ if (aiSpan.errorInfo.category) {
527
+ attributes["error.category"] = aiSpan.errorInfo.category;
529
528
  }
530
529
  }
531
- if (Span.metadata) {
532
- Object.entries(Span.metadata).forEach(([key, value]) => {
530
+ if (aiSpan.metadata) {
531
+ Object.entries(aiSpan.metadata).forEach(([key, value]) => {
533
532
  if (!attributes[key]) {
534
533
  if (value === null || value === void 0) {
535
534
  return;
@@ -542,12 +541,12 @@ var SpanConverter = class {
542
541
  }
543
542
  });
544
543
  }
545
- if (Span.startTime) {
546
- attributes["mastra.start_time"] = Span.startTime.toISOString();
544
+ if (aiSpan.startTime) {
545
+ attributes["mastra.start_time"] = aiSpan.startTime.toISOString();
547
546
  }
548
- if (Span.endTime) {
549
- attributes["mastra.end_time"] = Span.endTime.toISOString();
550
- 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();
551
550
  attributes["mastra.duration_ms"] = duration;
552
551
  }
553
552
  return attributes;
@@ -555,28 +554,28 @@ var SpanConverter = class {
555
554
  /**
556
555
  * Get the operation name based on span type for gen_ai.operation.name
557
556
  */
558
- getOperationName(Span) {
559
- switch (Span.type) {
560
- case observability$1.SpanType.MODEL_GENERATION: {
561
- const attrs = Span.attributes;
557
+ getOperationName(aiSpan) {
558
+ switch (aiSpan.type) {
559
+ case aiTracing.AISpanType.MODEL_GENERATION: {
560
+ const attrs = aiSpan.attributes;
562
561
  return attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
563
562
  }
564
- case observability$1.SpanType.TOOL_CALL:
565
- case observability$1.SpanType.MCP_TOOL_CALL:
563
+ case aiTracing.AISpanType.TOOL_CALL:
564
+ case aiTracing.AISpanType.MCP_TOOL_CALL:
566
565
  return "tool.execute";
567
- case observability$1.SpanType.AGENT_RUN:
566
+ case aiTracing.AISpanType.AGENT_RUN:
568
567
  return "agent.run";
569
- case observability$1.SpanType.WORKFLOW_RUN:
568
+ case aiTracing.AISpanType.WORKFLOW_RUN:
570
569
  return "workflow.run";
571
570
  default:
572
- return Span.type.replace(/_/g, ".");
571
+ return aiSpan.type.replace(/_/g, ".");
573
572
  }
574
573
  }
575
574
  /**
576
575
  * Get span kind as string for attribute
577
576
  */
578
- getSpanKindString(Span) {
579
- const kind = this.getSpanKind(Span);
577
+ getSpanKindString(aiSpan) {
578
+ const kind = this.getSpanKind(aiSpan);
580
579
  switch (kind) {
581
580
  case api.SpanKind.SERVER:
582
581
  return "server";
@@ -594,8 +593,8 @@ var SpanConverter = class {
594
593
  }
595
594
  };
596
595
 
597
- // src/tracing.ts
598
- var OtelExporter = class extends observability.BaseExporter {
596
+ // src/ai-tracing.ts
597
+ var OtelExporter = class extends aiTracing.BaseExporter {
599
598
  config;
600
599
  tracingConfig;
601
600
  spanConverter;
@@ -614,8 +613,8 @@ var OtelExporter = class extends observability.BaseExporter {
614
613
  /**
615
614
  * Initialize with tracing configuration
616
615
  */
617
- init(options) {
618
- this.tracingConfig = options.config;
616
+ init(config) {
617
+ this.tracingConfig = config;
619
618
  }
620
619
  async setupExporter() {
621
620
  if (this.isSetup || this.exporter) return;
@@ -728,8 +727,8 @@ var OtelExporter = class extends observability.BaseExporter {
728
727
  await this.setupProcessor();
729
728
  this.isSetup = true;
730
729
  }
731
- async _exportTracingEvent(event) {
732
- if (event.type !== observability$1.TracingEventType.SPAN_ENDED) {
730
+ async _exportEvent(event) {
731
+ if (event.type !== aiTracing.AITracingEventType.SPAN_ENDED) {
733
732
  return;
734
733
  }
735
734
  const span = event.exportedSpan;