@mastra/otel-exporter 0.0.0-model-router-unknown-provider-20251017212006 → 0.0.0-netlify-no-bundle-20251127120354

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,13 @@
1
1
  'use strict';
2
2
 
3
- var aiTracing = require('@mastra/core/ai-tracing');
4
- var logger = require('@mastra/core/logger');
3
+ var observability = require('@mastra/core/observability');
4
+ var observability$1 = 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/ai-tracing.ts
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(aiSpan, attributes, kind, parentSpanId, resource, instrumentationLibrary) {
228
- this.name = aiSpan.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(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();
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 (aiSpan.errorInfo) {
244
+ if (span.errorInfo) {
244
245
  this.status = {
245
246
  code: api.SpanStatusCode.ERROR,
246
- message: aiSpan.errorInfo.message
247
+ message: span.errorInfo.message
247
248
  };
248
249
  this.events.push({
249
250
  name: "exception",
250
251
  attributes: {
251
- "exception.message": aiSpan.errorInfo.message,
252
+ "exception.message": span.errorInfo.message,
252
253
  "exception.type": "Error",
253
- ...aiSpan.errorInfo.details?.stack && {
254
- "exception.stacktrace": aiSpan.errorInfo.details.stack
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 (aiSpan.endTime) {
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 (aiSpan.isEvent) {
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: aiSpan.traceId,
275
- spanId: aiSpan.id,
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,180 +305,177 @@ var MastraReadableSpan = class {
296
305
 
297
306
  // src/span-converter.ts
298
307
  var SPAN_KIND_MAPPING = {
299
- // LLM operations are CLIENT spans (calling external AI services)
300
- [aiTracing.AISpanType.LLM_GENERATION]: api.SpanKind.CLIENT,
301
- [aiTracing.AISpanType.LLM_CHUNK]: api.SpanKind.CLIENT,
308
+ // 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,
302
311
  // MCP tool calls are CLIENT (external service calls)
303
- [aiTracing.AISpanType.MCP_TOOL_CALL]: api.SpanKind.CLIENT,
312
+ [observability.SpanType.MCP_TOOL_CALL]: api.SpanKind.CLIENT,
304
313
  // Root spans for agent/workflow are SERVER (entry points)
305
- [aiTracing.AISpanType.AGENT_RUN]: api.SpanKind.SERVER,
306
- [aiTracing.AISpanType.WORKFLOW_RUN]: api.SpanKind.SERVER
314
+ [observability.SpanType.AGENT_RUN]: api.SpanKind.SERVER,
315
+ [observability.SpanType.WORKFLOW_RUN]: api.SpanKind.SERVER
307
316
  };
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
+ }
308
325
  var SpanConverter = class {
309
326
  resource;
310
327
  instrumentationLibrary;
311
328
  constructor(resource) {
312
329
  this.resource = resource;
313
330
  this.instrumentationLibrary = {
314
- name: "@mastra/otel",
331
+ name: "@mastra/otel-exporter",
315
332
  version: "1.0.0"
316
333
  };
317
334
  }
318
335
  /**
319
- * Convert a Mastra AI span to an OpenTelemetry ReadableSpan
336
+ * Convert a Mastra Span to an OpenTelemetry ReadableSpan
320
337
  * This preserves Mastra's trace and span IDs
321
338
  */
322
- convertSpan(aiSpan) {
323
- const spanKind = this.getSpanKind(aiSpan);
324
- const attributes = this.buildAttributes(aiSpan);
325
- const spanName = this.buildSpanName(aiSpan);
326
- const otelSpan = { ...aiSpan, name: spanName };
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 };
327
344
  return new MastraReadableSpan(
328
345
  otelSpan,
329
346
  attributes,
330
347
  spanKind,
331
- aiSpan.parentSpanId,
348
+ span.parentSpanId,
332
349
  // Use the parentSpanId from the Mastra span directly
333
350
  this.resource,
334
351
  this.instrumentationLibrary
335
352
  );
336
353
  }
337
- /**
338
- * Get the appropriate SpanKind based on span type and context
339
- */
340
- getSpanKind(aiSpan) {
341
- if (aiSpan.isRootSpan) {
342
- if (aiSpan.type === aiTracing.AISpanType.AGENT_RUN || aiSpan.type === aiTracing.AISpanType.WORKFLOW_RUN) {
343
- return api.SpanKind.SERVER;
344
- }
345
- }
346
- return SPAN_KIND_MAPPING[aiSpan.type] || api.SpanKind.INTERNAL;
347
- }
348
354
  /**
349
355
  * Build OTEL-compliant span name based on span type and attributes
350
356
  */
351
- buildSpanName(aiSpan) {
352
- switch (aiSpan.type) {
353
- case aiTracing.AISpanType.LLM_GENERATION: {
354
- const attrs = aiSpan.attributes;
357
+ buildSpanName(Span) {
358
+ switch (Span.type) {
359
+ case observability.SpanType.MODEL_GENERATION: {
360
+ const attrs = Span.attributes;
355
361
  const operation = attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
356
362
  const model = attrs?.model || "unknown";
357
363
  return `${operation} ${model}`;
358
364
  }
359
- case aiTracing.AISpanType.TOOL_CALL:
360
- case aiTracing.AISpanType.MCP_TOOL_CALL: {
361
- const toolAttrs = aiSpan.attributes;
365
+ case observability.SpanType.TOOL_CALL:
366
+ case observability.SpanType.MCP_TOOL_CALL: {
367
+ const toolAttrs = Span.attributes;
362
368
  const toolName = toolAttrs?.toolId || "unknown";
363
369
  return `tool.execute ${toolName}`;
364
370
  }
365
- case aiTracing.AISpanType.AGENT_RUN: {
366
- const agentAttrs = aiSpan.attributes;
371
+ case observability.SpanType.AGENT_RUN: {
372
+ const agentAttrs = Span.attributes;
367
373
  const agentId = agentAttrs?.agentId || "unknown";
368
374
  return `agent.${agentId}`;
369
375
  }
370
- case aiTracing.AISpanType.WORKFLOW_RUN: {
371
- const workflowAttrs = aiSpan.attributes;
376
+ case observability.SpanType.WORKFLOW_RUN: {
377
+ const workflowAttrs = Span.attributes;
372
378
  const workflowId = workflowAttrs?.workflowId || "unknown";
373
379
  return `workflow.${workflowId}`;
374
380
  }
375
- case aiTracing.AISpanType.WORKFLOW_STEP:
376
- return aiSpan.name;
381
+ case observability.SpanType.WORKFLOW_STEP:
382
+ return Span.name;
377
383
  default:
378
- return aiSpan.name;
384
+ return Span.name;
379
385
  }
380
386
  }
381
387
  /**
382
- * Build OpenTelemetry attributes from Mastra AI span
388
+ * Build OpenTelemetry attributes from Mastra Span
383
389
  * Following OTEL Semantic Conventions for GenAI
384
390
  */
385
- buildAttributes(aiSpan) {
391
+ buildAttributes(Span) {
386
392
  const attributes = {};
387
- attributes["gen_ai.operation.name"] = this.getOperationName(aiSpan);
388
- attributes["span.kind"] = this.getSpanKindString(aiSpan);
389
- attributes["mastra.span.type"] = aiSpan.type;
390
- attributes["mastra.trace_id"] = aiSpan.traceId;
391
- attributes["mastra.span_id"] = aiSpan.id;
392
- if (aiSpan.parentSpanId) {
393
- attributes["mastra.parent_span_id"] = aiSpan.parentSpanId;
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;
394
400
  }
395
- if (aiSpan.input !== void 0) {
396
- const inputStr = typeof aiSpan.input === "string" ? aiSpan.input : JSON.stringify(aiSpan.input);
401
+ if (Span.input !== void 0) {
402
+ const inputStr = typeof Span.input === "string" ? Span.input : JSON.stringify(Span.input);
397
403
  attributes["input"] = inputStr;
398
- if (aiSpan.type === aiTracing.AISpanType.LLM_GENERATION) {
404
+ if (Span.type === observability.SpanType.MODEL_GENERATION) {
399
405
  attributes["gen_ai.prompt"] = inputStr;
400
- } else if (aiSpan.type === aiTracing.AISpanType.TOOL_CALL || aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) {
406
+ } else if (Span.type === observability.SpanType.TOOL_CALL || Span.type === observability.SpanType.MCP_TOOL_CALL) {
401
407
  attributes["gen_ai.tool.input"] = inputStr;
402
408
  }
403
409
  }
404
- if (aiSpan.output !== void 0) {
405
- const outputStr = typeof aiSpan.output === "string" ? aiSpan.output : JSON.stringify(aiSpan.output);
410
+ if (Span.output !== void 0) {
411
+ const outputStr = typeof Span.output === "string" ? Span.output : JSON.stringify(Span.output);
406
412
  attributes["output"] = outputStr;
407
- if (aiSpan.type === aiTracing.AISpanType.LLM_GENERATION) {
413
+ if (Span.type === observability.SpanType.MODEL_GENERATION) {
408
414
  attributes["gen_ai.completion"] = outputStr;
409
- } else if (aiSpan.type === aiTracing.AISpanType.TOOL_CALL || aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) {
415
+ } else if (Span.type === observability.SpanType.TOOL_CALL || Span.type === observability.SpanType.MCP_TOOL_CALL) {
410
416
  attributes["gen_ai.tool.output"] = outputStr;
411
417
  }
412
418
  }
413
- if (aiSpan.type === aiTracing.AISpanType.LLM_GENERATION && aiSpan.attributes) {
414
- const llmAttrs = aiSpan.attributes;
415
- if (llmAttrs.model) {
416
- attributes["gen_ai.request.model"] = llmAttrs.model;
419
+ if (Span.type === observability.SpanType.MODEL_GENERATION && Span.attributes) {
420
+ const modelAttrs = Span.attributes;
421
+ if (modelAttrs.model) {
422
+ attributes["gen_ai.request.model"] = modelAttrs.model;
417
423
  }
418
- if (llmAttrs.provider) {
419
- attributes["gen_ai.system"] = llmAttrs.provider;
424
+ if (modelAttrs.provider) {
425
+ attributes["gen_ai.system"] = modelAttrs.provider;
420
426
  }
421
- if (llmAttrs.usage) {
422
- const inputTokens = llmAttrs.usage.inputTokens ?? llmAttrs.usage.promptTokens;
423
- const outputTokens = llmAttrs.usage.outputTokens ?? llmAttrs.usage.completionTokens;
427
+ if (modelAttrs.usage) {
428
+ const inputTokens = modelAttrs.usage.inputTokens ?? modelAttrs.usage.promptTokens;
429
+ const outputTokens = modelAttrs.usage.outputTokens ?? modelAttrs.usage.completionTokens;
424
430
  if (inputTokens !== void 0) {
425
431
  attributes["gen_ai.usage.input_tokens"] = inputTokens;
426
432
  }
427
433
  if (outputTokens !== void 0) {
428
434
  attributes["gen_ai.usage.output_tokens"] = outputTokens;
429
435
  }
430
- if (llmAttrs.usage.totalTokens !== void 0) {
431
- attributes["gen_ai.usage.total_tokens"] = llmAttrs.usage.totalTokens;
436
+ if (modelAttrs.usage.totalTokens !== void 0) {
437
+ attributes["gen_ai.usage.total_tokens"] = modelAttrs.usage.totalTokens;
432
438
  }
433
- if (llmAttrs.usage.reasoningTokens !== void 0) {
434
- attributes["gen_ai.usage.reasoning_tokens"] = llmAttrs.usage.reasoningTokens;
439
+ if (modelAttrs.usage.reasoningTokens !== void 0) {
440
+ attributes["gen_ai.usage.reasoning_tokens"] = modelAttrs.usage.reasoningTokens;
435
441
  }
436
- if (llmAttrs.usage.cachedInputTokens !== void 0) {
437
- attributes["gen_ai.usage.cached_input_tokens"] = llmAttrs.usage.cachedInputTokens;
442
+ if (modelAttrs.usage.cachedInputTokens !== void 0) {
443
+ attributes["gen_ai.usage.cached_input_tokens"] = modelAttrs.usage.cachedInputTokens;
438
444
  }
439
445
  }
440
- if (llmAttrs.parameters) {
441
- if (llmAttrs.parameters.temperature !== void 0) {
442
- attributes["gen_ai.request.temperature"] = llmAttrs.parameters.temperature;
446
+ if (modelAttrs.parameters) {
447
+ if (modelAttrs.parameters.temperature !== void 0) {
448
+ attributes["gen_ai.request.temperature"] = modelAttrs.parameters.temperature;
443
449
  }
444
- if (llmAttrs.parameters.maxOutputTokens !== void 0) {
445
- attributes["gen_ai.request.max_tokens"] = llmAttrs.parameters.maxOutputTokens;
450
+ if (modelAttrs.parameters.maxOutputTokens !== void 0) {
451
+ attributes["gen_ai.request.max_tokens"] = modelAttrs.parameters.maxOutputTokens;
446
452
  }
447
- if (llmAttrs.parameters.topP !== void 0) {
448
- attributes["gen_ai.request.top_p"] = llmAttrs.parameters.topP;
453
+ if (modelAttrs.parameters.topP !== void 0) {
454
+ attributes["gen_ai.request.top_p"] = modelAttrs.parameters.topP;
449
455
  }
450
- if (llmAttrs.parameters.topK !== void 0) {
451
- attributes["gen_ai.request.top_k"] = llmAttrs.parameters.topK;
456
+ if (modelAttrs.parameters.topK !== void 0) {
457
+ attributes["gen_ai.request.top_k"] = modelAttrs.parameters.topK;
452
458
  }
453
- if (llmAttrs.parameters.presencePenalty !== void 0) {
454
- attributes["gen_ai.request.presence_penalty"] = llmAttrs.parameters.presencePenalty;
459
+ if (modelAttrs.parameters.presencePenalty !== void 0) {
460
+ attributes["gen_ai.request.presence_penalty"] = modelAttrs.parameters.presencePenalty;
455
461
  }
456
- if (llmAttrs.parameters.frequencyPenalty !== void 0) {
457
- attributes["gen_ai.request.frequency_penalty"] = llmAttrs.parameters.frequencyPenalty;
462
+ if (modelAttrs.parameters.frequencyPenalty !== void 0) {
463
+ attributes["gen_ai.request.frequency_penalty"] = modelAttrs.parameters.frequencyPenalty;
458
464
  }
459
- if (llmAttrs.parameters.stopSequences) {
460
- attributes["gen_ai.request.stop_sequences"] = JSON.stringify(llmAttrs.parameters.stopSequences);
465
+ if (modelAttrs.parameters.stopSequences) {
466
+ attributes["gen_ai.request.stop_sequences"] = JSON.stringify(modelAttrs.parameters.stopSequences);
461
467
  }
462
468
  }
463
- if (llmAttrs.finishReason) {
464
- attributes["gen_ai.response.finish_reasons"] = llmAttrs.finishReason;
469
+ if (modelAttrs.finishReason) {
470
+ attributes["gen_ai.response.finish_reasons"] = modelAttrs.finishReason;
465
471
  }
466
472
  }
467
- if ((aiSpan.type === aiTracing.AISpanType.TOOL_CALL || aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) && aiSpan.attributes) {
468
- const toolAttrs = aiSpan.attributes;
473
+ if ((Span.type === observability.SpanType.TOOL_CALL || Span.type === observability.SpanType.MCP_TOOL_CALL) && Span.attributes) {
474
+ const toolAttrs = Span.attributes;
469
475
  if (toolAttrs.toolId) {
470
476
  attributes["gen_ai.tool.name"] = toolAttrs.toolId;
471
477
  }
472
- if (aiSpan.type === aiTracing.AISpanType.MCP_TOOL_CALL) {
478
+ if (Span.type === observability.SpanType.MCP_TOOL_CALL) {
473
479
  const mcpAttrs = toolAttrs;
474
480
  if (mcpAttrs.mcpServer) {
475
481
  attributes["mcp.server"] = mcpAttrs.mcpServer;
@@ -486,10 +492,11 @@ var SpanConverter = class {
486
492
  attributes["gen_ai.tool.success"] = toolAttrs.success;
487
493
  }
488
494
  }
489
- if (aiSpan.type === aiTracing.AISpanType.AGENT_RUN && aiSpan.attributes) {
490
- const agentAttrs = aiSpan.attributes;
495
+ if (Span.type === observability.SpanType.AGENT_RUN && Span.attributes) {
496
+ const agentAttrs = Span.attributes;
491
497
  if (agentAttrs.agentId) {
492
498
  attributes["agent.id"] = agentAttrs.agentId;
499
+ attributes["gen_ai.agent.id"] = agentAttrs.agentId;
493
500
  }
494
501
  if (agentAttrs.maxSteps) {
495
502
  attributes["agent.max_steps"] = agentAttrs.maxSteps;
@@ -498,8 +505,8 @@ var SpanConverter = class {
498
505
  attributes["agent.available_tools"] = JSON.stringify(agentAttrs.availableTools);
499
506
  }
500
507
  }
501
- if (aiSpan.type === aiTracing.AISpanType.WORKFLOW_RUN && aiSpan.attributes) {
502
- const workflowAttrs = aiSpan.attributes;
508
+ if (Span.type === observability.SpanType.WORKFLOW_RUN && Span.attributes) {
509
+ const workflowAttrs = Span.attributes;
503
510
  if (workflowAttrs.workflowId) {
504
511
  attributes["workflow.id"] = workflowAttrs.workflowId;
505
512
  }
@@ -507,19 +514,19 @@ var SpanConverter = class {
507
514
  attributes["workflow.status"] = workflowAttrs.status;
508
515
  }
509
516
  }
510
- if (aiSpan.errorInfo) {
517
+ if (Span.errorInfo) {
511
518
  attributes["error"] = true;
512
- attributes["error.type"] = aiSpan.errorInfo.id || "unknown";
513
- attributes["error.message"] = aiSpan.errorInfo.message;
514
- if (aiSpan.errorInfo.domain) {
515
- attributes["error.domain"] = aiSpan.errorInfo.domain;
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;
516
523
  }
517
- if (aiSpan.errorInfo.category) {
518
- attributes["error.category"] = aiSpan.errorInfo.category;
524
+ if (Span.errorInfo.category) {
525
+ attributes["error.category"] = Span.errorInfo.category;
519
526
  }
520
527
  }
521
- if (aiSpan.metadata) {
522
- Object.entries(aiSpan.metadata).forEach(([key, value]) => {
528
+ if (Span.metadata) {
529
+ Object.entries(Span.metadata).forEach(([key, value]) => {
523
530
  if (!attributes[key]) {
524
531
  if (value === null || value === void 0) {
525
532
  return;
@@ -532,12 +539,12 @@ var SpanConverter = class {
532
539
  }
533
540
  });
534
541
  }
535
- if (aiSpan.startTime) {
536
- attributes["mastra.start_time"] = aiSpan.startTime.toISOString();
542
+ if (Span.startTime) {
543
+ attributes["mastra.start_time"] = Span.startTime.toISOString();
537
544
  }
538
- if (aiSpan.endTime) {
539
- attributes["mastra.end_time"] = aiSpan.endTime.toISOString();
540
- const duration = aiSpan.endTime.getTime() - aiSpan.startTime.getTime();
545
+ if (Span.endTime) {
546
+ attributes["mastra.end_time"] = Span.endTime.toISOString();
547
+ const duration = Span.endTime.getTime() - Span.startTime.getTime();
541
548
  attributes["mastra.duration_ms"] = duration;
542
549
  }
543
550
  return attributes;
@@ -545,28 +552,28 @@ var SpanConverter = class {
545
552
  /**
546
553
  * Get the operation name based on span type for gen_ai.operation.name
547
554
  */
548
- getOperationName(aiSpan) {
549
- switch (aiSpan.type) {
550
- case aiTracing.AISpanType.LLM_GENERATION: {
551
- const attrs = aiSpan.attributes;
555
+ getOperationName(Span) {
556
+ switch (Span.type) {
557
+ case observability.SpanType.MODEL_GENERATION: {
558
+ const attrs = Span.attributes;
552
559
  return attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
553
560
  }
554
- case aiTracing.AISpanType.TOOL_CALL:
555
- case aiTracing.AISpanType.MCP_TOOL_CALL:
561
+ case observability.SpanType.TOOL_CALL:
562
+ case observability.SpanType.MCP_TOOL_CALL:
556
563
  return "tool.execute";
557
- case aiTracing.AISpanType.AGENT_RUN:
564
+ case observability.SpanType.AGENT_RUN:
558
565
  return "agent.run";
559
- case aiTracing.AISpanType.WORKFLOW_RUN:
566
+ case observability.SpanType.WORKFLOW_RUN:
560
567
  return "workflow.run";
561
568
  default:
562
- return aiSpan.type.replace(/_/g, ".");
569
+ return Span.type.replace(/_/g, ".");
563
570
  }
564
571
  }
565
572
  /**
566
573
  * Get span kind as string for attribute
567
574
  */
568
- getSpanKindString(aiSpan) {
569
- const kind = this.getSpanKind(aiSpan);
575
+ getSpanKindString(Span) {
576
+ const kind = getSpanKind(Span.type, Span.isRootSpan);
570
577
  switch (kind) {
571
578
  case api.SpanKind.SERVER:
572
579
  return "server";
@@ -584,21 +591,19 @@ var SpanConverter = class {
584
591
  }
585
592
  };
586
593
 
587
- // src/ai-tracing.ts
588
- var OtelExporter = class {
594
+ // src/tracing.ts
595
+ var OtelExporter = class extends observability$1.BaseExporter {
589
596
  config;
590
597
  tracingConfig;
591
598
  spanConverter;
592
599
  processor;
593
600
  exporter;
594
601
  isSetup = false;
595
- isDisabled = false;
596
- logger;
597
602
  name = "opentelemetry";
598
603
  constructor(config) {
604
+ super(config);
599
605
  this.config = config;
600
606
  this.spanConverter = new SpanConverter();
601
- this.logger = new logger.ConsoleLogger({ level: config.logLevel ?? "warn" });
602
607
  if (config.logLevel === "debug") {
603
608
  api.diag.setLogger(new api.DiagConsoleLogger(), api.DiagLogLevel.DEBUG);
604
609
  }
@@ -606,11 +611,11 @@ var OtelExporter = class {
606
611
  /**
607
612
  * Initialize with tracing configuration
608
613
  */
609
- init(config) {
610
- this.tracingConfig = config;
614
+ init(options) {
615
+ this.tracingConfig = options.config;
611
616
  }
612
617
  async setupExporter() {
613
- if (this.isSetup) return;
618
+ if (this.isSetup || this.exporter) return;
614
619
  if (!this.config.provider) {
615
620
  this.logger.error(
616
621
  '[OtelExporter] Provider configuration is required. Use the "custom" provider for generic endpoints.'
@@ -625,6 +630,10 @@ var OtelExporter = class {
625
630
  this.isSetup = true;
626
631
  return;
627
632
  }
633
+ if (this.config.exporter) {
634
+ this.exporter = this.config.exporter;
635
+ return;
636
+ }
628
637
  const endpoint = resolved.endpoint;
629
638
  const headers = resolved.headers;
630
639
  const protocol = resolved.protocol;
@@ -678,6 +687,9 @@ var OtelExporter = class {
678
687
  this.isSetup = true;
679
688
  return;
680
689
  }
690
+ }
691
+ async setupProcessor() {
692
+ if (this.processor || this.isSetup) return;
681
693
  let resource = resources.resourceFromAttributes({
682
694
  [semanticConventions.ATTR_SERVICE_NAME]: this.tracingConfig?.serviceName || "mastra-service",
683
695
  [semanticConventions.ATTR_SERVICE_VERSION]: "1.0.0",
@@ -706,13 +718,15 @@ var OtelExporter = class {
706
718
  this.logger.debug(
707
719
  `[OtelExporter] Using BatchSpanProcessor (batch size: ${this.config.batchSize || 512}, delay: 5s)`
708
720
  );
721
+ }
722
+ async setup() {
723
+ if (this.isSetup) return;
724
+ await this.setupExporter();
725
+ await this.setupProcessor();
709
726
  this.isSetup = true;
710
727
  }
711
- async exportEvent(event) {
712
- if (this.isDisabled) {
713
- return;
714
- }
715
- if (event.type !== aiTracing.AITracingEventType.SPAN_ENDED) {
728
+ async _exportTracingEvent(event) {
729
+ if (event.type !== observability.TracingEventType.SPAN_ENDED) {
716
730
  return;
717
731
  }
718
732
  const span = event.exportedSpan;
@@ -720,7 +734,7 @@ var OtelExporter = class {
720
734
  }
721
735
  async exportSpan(span) {
722
736
  if (!this.isSetup) {
723
- await this.setupExporter();
737
+ await this.setup();
724
738
  }
725
739
  if (this.isDisabled || !this.processor) {
726
740
  return;
@@ -745,6 +759,9 @@ var OtelExporter = class {
745
759
  }
746
760
  };
747
761
 
762
+ exports.MastraReadableSpan = MastraReadableSpan;
748
763
  exports.OtelExporter = OtelExporter;
764
+ exports.SpanConverter = SpanConverter;
765
+ exports.getSpanKind = getSpanKind;
749
766
  //# sourceMappingURL=index.cjs.map
750
767
  //# sourceMappingURL=index.cjs.map