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