@mastra/otel-exporter 0.0.0-just-snapshot-20251014192224 → 0.0.0-main-test-20251105183450

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