@mastra/otel-exporter 0.0.0-cloud-deployer-for-core-0.19.1-20251001164939 → 0.0.0-cloud-storage-adapter-20251106204059
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 +263 -3
- package/README.md +12 -12
- package/dist/index.cjs +170 -157
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +170 -157
- 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 +5 -5
- 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 +12 -8
- 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 {
|
|
1
|
+
import { TracingEventType, SpanType } from '@mastra/core/observability';
|
|
2
|
+
import { BaseExporter } from '@mastra/observability';
|
|
3
3
|
import { diag, DiagConsoleLogger, DiagLogLevel, SpanKind, SpanStatusCode, TraceFlags } 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,24 +303,14 @@ var MastraReadableSpan = class {
|
|
|
294
303
|
|
|
295
304
|
// src/span-converter.ts
|
|
296
305
|
var SPAN_KIND_MAPPING = {
|
|
297
|
-
//
|
|
298
|
-
[
|
|
299
|
-
[
|
|
300
|
-
//
|
|
301
|
-
[
|
|
302
|
-
[AISpanType.MCP_TOOL_CALL]: SpanKind.CLIENT,
|
|
306
|
+
// Model operations are CLIENT spans (calling external AI services)
|
|
307
|
+
[SpanType.MODEL_GENERATION]: SpanKind.CLIENT,
|
|
308
|
+
[SpanType.MODEL_CHUNK]: SpanKind.CLIENT,
|
|
309
|
+
// MCP tool calls are CLIENT (external service calls)
|
|
310
|
+
[SpanType.MCP_TOOL_CALL]: SpanKind.CLIENT,
|
|
303
311
|
// Root spans for agent/workflow are SERVER (entry points)
|
|
304
|
-
[
|
|
305
|
-
[
|
|
306
|
-
// Internal workflow operations
|
|
307
|
-
[AISpanType.WORKFLOW_STEP]: SpanKind.INTERNAL,
|
|
308
|
-
[AISpanType.WORKFLOW_LOOP]: SpanKind.INTERNAL,
|
|
309
|
-
[AISpanType.WORKFLOW_PARALLEL]: SpanKind.INTERNAL,
|
|
310
|
-
[AISpanType.WORKFLOW_CONDITIONAL]: SpanKind.INTERNAL,
|
|
311
|
-
[AISpanType.WORKFLOW_CONDITIONAL_EVAL]: SpanKind.INTERNAL,
|
|
312
|
-
[AISpanType.WORKFLOW_SLEEP]: SpanKind.INTERNAL,
|
|
313
|
-
[AISpanType.WORKFLOW_WAIT_EVENT]: SpanKind.INTERNAL,
|
|
314
|
-
[AISpanType.GENERIC]: SpanKind.INTERNAL
|
|
312
|
+
[SpanType.AGENT_RUN]: SpanKind.SERVER,
|
|
313
|
+
[SpanType.WORKFLOW_RUN]: SpanKind.SERVER
|
|
315
314
|
};
|
|
316
315
|
var SpanConverter = class {
|
|
317
316
|
resource;
|
|
@@ -324,19 +323,19 @@ var SpanConverter = class {
|
|
|
324
323
|
};
|
|
325
324
|
}
|
|
326
325
|
/**
|
|
327
|
-
* Convert a Mastra
|
|
326
|
+
* Convert a Mastra Span to an OpenTelemetry ReadableSpan
|
|
328
327
|
* This preserves Mastra's trace and span IDs
|
|
329
328
|
*/
|
|
330
|
-
convertSpan(
|
|
331
|
-
const spanKind = this.getSpanKind(
|
|
332
|
-
const attributes = this.buildAttributes(
|
|
333
|
-
const spanName = this.buildSpanName(
|
|
334
|
-
const otelSpan = { ...
|
|
329
|
+
convertSpan(Span) {
|
|
330
|
+
const spanKind = this.getSpanKind(Span);
|
|
331
|
+
const attributes = this.buildAttributes(Span);
|
|
332
|
+
const spanName = this.buildSpanName(Span);
|
|
333
|
+
const otelSpan = { ...Span, name: spanName };
|
|
335
334
|
return new MastraReadableSpan(
|
|
336
335
|
otelSpan,
|
|
337
336
|
attributes,
|
|
338
337
|
spanKind,
|
|
339
|
-
|
|
338
|
+
Span.parentSpanId,
|
|
340
339
|
// Use the parentSpanId from the Mastra span directly
|
|
341
340
|
this.resource,
|
|
342
341
|
this.instrumentationLibrary
|
|
@@ -345,139 +344,139 @@ var SpanConverter = class {
|
|
|
345
344
|
/**
|
|
346
345
|
* Get the appropriate SpanKind based on span type and context
|
|
347
346
|
*/
|
|
348
|
-
getSpanKind(
|
|
349
|
-
if (
|
|
350
|
-
if (
|
|
347
|
+
getSpanKind(Span) {
|
|
348
|
+
if (Span.isRootSpan) {
|
|
349
|
+
if (Span.type === SpanType.AGENT_RUN || Span.type === SpanType.WORKFLOW_RUN) {
|
|
351
350
|
return SpanKind.SERVER;
|
|
352
351
|
}
|
|
353
352
|
}
|
|
354
|
-
return SPAN_KIND_MAPPING[
|
|
353
|
+
return SPAN_KIND_MAPPING[Span.type] || SpanKind.INTERNAL;
|
|
355
354
|
}
|
|
356
355
|
/**
|
|
357
356
|
* Build OTEL-compliant span name based on span type and attributes
|
|
358
357
|
*/
|
|
359
|
-
buildSpanName(
|
|
360
|
-
switch (
|
|
361
|
-
case
|
|
362
|
-
const attrs =
|
|
358
|
+
buildSpanName(Span) {
|
|
359
|
+
switch (Span.type) {
|
|
360
|
+
case SpanType.MODEL_GENERATION: {
|
|
361
|
+
const attrs = Span.attributes;
|
|
363
362
|
const operation = attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
|
|
364
363
|
const model = attrs?.model || "unknown";
|
|
365
364
|
return `${operation} ${model}`;
|
|
366
365
|
}
|
|
367
|
-
case
|
|
368
|
-
case
|
|
369
|
-
const toolAttrs =
|
|
366
|
+
case SpanType.TOOL_CALL:
|
|
367
|
+
case SpanType.MCP_TOOL_CALL: {
|
|
368
|
+
const toolAttrs = Span.attributes;
|
|
370
369
|
const toolName = toolAttrs?.toolId || "unknown";
|
|
371
370
|
return `tool.execute ${toolName}`;
|
|
372
371
|
}
|
|
373
|
-
case
|
|
374
|
-
const agentAttrs =
|
|
372
|
+
case SpanType.AGENT_RUN: {
|
|
373
|
+
const agentAttrs = Span.attributes;
|
|
375
374
|
const agentId = agentAttrs?.agentId || "unknown";
|
|
376
375
|
return `agent.${agentId}`;
|
|
377
376
|
}
|
|
378
|
-
case
|
|
379
|
-
const workflowAttrs =
|
|
377
|
+
case SpanType.WORKFLOW_RUN: {
|
|
378
|
+
const workflowAttrs = Span.attributes;
|
|
380
379
|
const workflowId = workflowAttrs?.workflowId || "unknown";
|
|
381
380
|
return `workflow.${workflowId}`;
|
|
382
381
|
}
|
|
383
|
-
case
|
|
384
|
-
return
|
|
382
|
+
case SpanType.WORKFLOW_STEP:
|
|
383
|
+
return Span.name;
|
|
385
384
|
default:
|
|
386
|
-
return
|
|
385
|
+
return Span.name;
|
|
387
386
|
}
|
|
388
387
|
}
|
|
389
388
|
/**
|
|
390
|
-
* Build OpenTelemetry attributes from Mastra
|
|
389
|
+
* Build OpenTelemetry attributes from Mastra Span
|
|
391
390
|
* Following OTEL Semantic Conventions for GenAI
|
|
392
391
|
*/
|
|
393
|
-
buildAttributes(
|
|
392
|
+
buildAttributes(Span) {
|
|
394
393
|
const attributes = {};
|
|
395
|
-
attributes["gen_ai.operation.name"] = this.getOperationName(
|
|
396
|
-
attributes["span.kind"] = this.getSpanKindString(
|
|
397
|
-
attributes["mastra.span.type"] =
|
|
398
|
-
attributes["mastra.trace_id"] =
|
|
399
|
-
attributes["mastra.span_id"] =
|
|
400
|
-
if (
|
|
401
|
-
attributes["mastra.parent_span_id"] =
|
|
394
|
+
attributes["gen_ai.operation.name"] = this.getOperationName(Span);
|
|
395
|
+
attributes["span.kind"] = this.getSpanKindString(Span);
|
|
396
|
+
attributes["mastra.span.type"] = Span.type;
|
|
397
|
+
attributes["mastra.trace_id"] = Span.traceId;
|
|
398
|
+
attributes["mastra.span_id"] = Span.id;
|
|
399
|
+
if (Span.parentSpanId) {
|
|
400
|
+
attributes["mastra.parent_span_id"] = Span.parentSpanId;
|
|
402
401
|
}
|
|
403
|
-
if (
|
|
404
|
-
const inputStr = typeof
|
|
402
|
+
if (Span.input !== void 0) {
|
|
403
|
+
const inputStr = typeof Span.input === "string" ? Span.input : JSON.stringify(Span.input);
|
|
405
404
|
attributes["input"] = inputStr;
|
|
406
|
-
if (
|
|
405
|
+
if (Span.type === SpanType.MODEL_GENERATION) {
|
|
407
406
|
attributes["gen_ai.prompt"] = inputStr;
|
|
408
|
-
} else if (
|
|
407
|
+
} else if (Span.type === SpanType.TOOL_CALL || Span.type === SpanType.MCP_TOOL_CALL) {
|
|
409
408
|
attributes["gen_ai.tool.input"] = inputStr;
|
|
410
409
|
}
|
|
411
410
|
}
|
|
412
|
-
if (
|
|
413
|
-
const outputStr = typeof
|
|
411
|
+
if (Span.output !== void 0) {
|
|
412
|
+
const outputStr = typeof Span.output === "string" ? Span.output : JSON.stringify(Span.output);
|
|
414
413
|
attributes["output"] = outputStr;
|
|
415
|
-
if (
|
|
414
|
+
if (Span.type === SpanType.MODEL_GENERATION) {
|
|
416
415
|
attributes["gen_ai.completion"] = outputStr;
|
|
417
|
-
} else if (
|
|
416
|
+
} else if (Span.type === SpanType.TOOL_CALL || Span.type === SpanType.MCP_TOOL_CALL) {
|
|
418
417
|
attributes["gen_ai.tool.output"] = outputStr;
|
|
419
418
|
}
|
|
420
419
|
}
|
|
421
|
-
if (
|
|
422
|
-
const
|
|
423
|
-
if (
|
|
424
|
-
attributes["gen_ai.request.model"] =
|
|
420
|
+
if (Span.type === SpanType.MODEL_GENERATION && Span.attributes) {
|
|
421
|
+
const modelAttrs = Span.attributes;
|
|
422
|
+
if (modelAttrs.model) {
|
|
423
|
+
attributes["gen_ai.request.model"] = modelAttrs.model;
|
|
425
424
|
}
|
|
426
|
-
if (
|
|
427
|
-
attributes["gen_ai.system"] =
|
|
425
|
+
if (modelAttrs.provider) {
|
|
426
|
+
attributes["gen_ai.system"] = modelAttrs.provider;
|
|
428
427
|
}
|
|
429
|
-
if (
|
|
430
|
-
const inputTokens =
|
|
431
|
-
const outputTokens =
|
|
428
|
+
if (modelAttrs.usage) {
|
|
429
|
+
const inputTokens = modelAttrs.usage.inputTokens ?? modelAttrs.usage.promptTokens;
|
|
430
|
+
const outputTokens = modelAttrs.usage.outputTokens ?? modelAttrs.usage.completionTokens;
|
|
432
431
|
if (inputTokens !== void 0) {
|
|
433
432
|
attributes["gen_ai.usage.input_tokens"] = inputTokens;
|
|
434
433
|
}
|
|
435
434
|
if (outputTokens !== void 0) {
|
|
436
435
|
attributes["gen_ai.usage.output_tokens"] = outputTokens;
|
|
437
436
|
}
|
|
438
|
-
if (
|
|
439
|
-
attributes["gen_ai.usage.total_tokens"] =
|
|
437
|
+
if (modelAttrs.usage.totalTokens !== void 0) {
|
|
438
|
+
attributes["gen_ai.usage.total_tokens"] = modelAttrs.usage.totalTokens;
|
|
440
439
|
}
|
|
441
|
-
if (
|
|
442
|
-
attributes["gen_ai.usage.reasoning_tokens"] =
|
|
440
|
+
if (modelAttrs.usage.reasoningTokens !== void 0) {
|
|
441
|
+
attributes["gen_ai.usage.reasoning_tokens"] = modelAttrs.usage.reasoningTokens;
|
|
443
442
|
}
|
|
444
|
-
if (
|
|
445
|
-
attributes["gen_ai.usage.cached_input_tokens"] =
|
|
443
|
+
if (modelAttrs.usage.cachedInputTokens !== void 0) {
|
|
444
|
+
attributes["gen_ai.usage.cached_input_tokens"] = modelAttrs.usage.cachedInputTokens;
|
|
446
445
|
}
|
|
447
446
|
}
|
|
448
|
-
if (
|
|
449
|
-
if (
|
|
450
|
-
attributes["gen_ai.request.temperature"] =
|
|
447
|
+
if (modelAttrs.parameters) {
|
|
448
|
+
if (modelAttrs.parameters.temperature !== void 0) {
|
|
449
|
+
attributes["gen_ai.request.temperature"] = modelAttrs.parameters.temperature;
|
|
451
450
|
}
|
|
452
|
-
if (
|
|
453
|
-
attributes["gen_ai.request.max_tokens"] =
|
|
451
|
+
if (modelAttrs.parameters.maxOutputTokens !== void 0) {
|
|
452
|
+
attributes["gen_ai.request.max_tokens"] = modelAttrs.parameters.maxOutputTokens;
|
|
454
453
|
}
|
|
455
|
-
if (
|
|
456
|
-
attributes["gen_ai.request.top_p"] =
|
|
454
|
+
if (modelAttrs.parameters.topP !== void 0) {
|
|
455
|
+
attributes["gen_ai.request.top_p"] = modelAttrs.parameters.topP;
|
|
457
456
|
}
|
|
458
|
-
if (
|
|
459
|
-
attributes["gen_ai.request.top_k"] =
|
|
457
|
+
if (modelAttrs.parameters.topK !== void 0) {
|
|
458
|
+
attributes["gen_ai.request.top_k"] = modelAttrs.parameters.topK;
|
|
460
459
|
}
|
|
461
|
-
if (
|
|
462
|
-
attributes["gen_ai.request.presence_penalty"] =
|
|
460
|
+
if (modelAttrs.parameters.presencePenalty !== void 0) {
|
|
461
|
+
attributes["gen_ai.request.presence_penalty"] = modelAttrs.parameters.presencePenalty;
|
|
463
462
|
}
|
|
464
|
-
if (
|
|
465
|
-
attributes["gen_ai.request.frequency_penalty"] =
|
|
463
|
+
if (modelAttrs.parameters.frequencyPenalty !== void 0) {
|
|
464
|
+
attributes["gen_ai.request.frequency_penalty"] = modelAttrs.parameters.frequencyPenalty;
|
|
466
465
|
}
|
|
467
|
-
if (
|
|
468
|
-
attributes["gen_ai.request.stop_sequences"] = JSON.stringify(
|
|
466
|
+
if (modelAttrs.parameters.stopSequences) {
|
|
467
|
+
attributes["gen_ai.request.stop_sequences"] = JSON.stringify(modelAttrs.parameters.stopSequences);
|
|
469
468
|
}
|
|
470
469
|
}
|
|
471
|
-
if (
|
|
472
|
-
attributes["gen_ai.response.finish_reasons"] =
|
|
470
|
+
if (modelAttrs.finishReason) {
|
|
471
|
+
attributes["gen_ai.response.finish_reasons"] = modelAttrs.finishReason;
|
|
473
472
|
}
|
|
474
473
|
}
|
|
475
|
-
if ((
|
|
476
|
-
const toolAttrs =
|
|
474
|
+
if ((Span.type === SpanType.TOOL_CALL || Span.type === SpanType.MCP_TOOL_CALL) && Span.attributes) {
|
|
475
|
+
const toolAttrs = Span.attributes;
|
|
477
476
|
if (toolAttrs.toolId) {
|
|
478
477
|
attributes["gen_ai.tool.name"] = toolAttrs.toolId;
|
|
479
478
|
}
|
|
480
|
-
if (
|
|
479
|
+
if (Span.type === SpanType.MCP_TOOL_CALL) {
|
|
481
480
|
const mcpAttrs = toolAttrs;
|
|
482
481
|
if (mcpAttrs.mcpServer) {
|
|
483
482
|
attributes["mcp.server"] = mcpAttrs.mcpServer;
|
|
@@ -494,10 +493,11 @@ var SpanConverter = class {
|
|
|
494
493
|
attributes["gen_ai.tool.success"] = toolAttrs.success;
|
|
495
494
|
}
|
|
496
495
|
}
|
|
497
|
-
if (
|
|
498
|
-
const agentAttrs =
|
|
496
|
+
if (Span.type === SpanType.AGENT_RUN && Span.attributes) {
|
|
497
|
+
const agentAttrs = Span.attributes;
|
|
499
498
|
if (agentAttrs.agentId) {
|
|
500
499
|
attributes["agent.id"] = agentAttrs.agentId;
|
|
500
|
+
attributes["gen_ai.agent.id"] = agentAttrs.agentId;
|
|
501
501
|
}
|
|
502
502
|
if (agentAttrs.maxSteps) {
|
|
503
503
|
attributes["agent.max_steps"] = agentAttrs.maxSteps;
|
|
@@ -506,8 +506,8 @@ var SpanConverter = class {
|
|
|
506
506
|
attributes["agent.available_tools"] = JSON.stringify(agentAttrs.availableTools);
|
|
507
507
|
}
|
|
508
508
|
}
|
|
509
|
-
if (
|
|
510
|
-
const workflowAttrs =
|
|
509
|
+
if (Span.type === SpanType.WORKFLOW_RUN && Span.attributes) {
|
|
510
|
+
const workflowAttrs = Span.attributes;
|
|
511
511
|
if (workflowAttrs.workflowId) {
|
|
512
512
|
attributes["workflow.id"] = workflowAttrs.workflowId;
|
|
513
513
|
}
|
|
@@ -515,19 +515,19 @@ var SpanConverter = class {
|
|
|
515
515
|
attributes["workflow.status"] = workflowAttrs.status;
|
|
516
516
|
}
|
|
517
517
|
}
|
|
518
|
-
if (
|
|
518
|
+
if (Span.errorInfo) {
|
|
519
519
|
attributes["error"] = true;
|
|
520
|
-
attributes["error.type"] =
|
|
521
|
-
attributes["error.message"] =
|
|
522
|
-
if (
|
|
523
|
-
attributes["error.domain"] =
|
|
520
|
+
attributes["error.type"] = Span.errorInfo.id || "unknown";
|
|
521
|
+
attributes["error.message"] = Span.errorInfo.message;
|
|
522
|
+
if (Span.errorInfo.domain) {
|
|
523
|
+
attributes["error.domain"] = Span.errorInfo.domain;
|
|
524
524
|
}
|
|
525
|
-
if (
|
|
526
|
-
attributes["error.category"] =
|
|
525
|
+
if (Span.errorInfo.category) {
|
|
526
|
+
attributes["error.category"] = Span.errorInfo.category;
|
|
527
527
|
}
|
|
528
528
|
}
|
|
529
|
-
if (
|
|
530
|
-
Object.entries(
|
|
529
|
+
if (Span.metadata) {
|
|
530
|
+
Object.entries(Span.metadata).forEach(([key, value]) => {
|
|
531
531
|
if (!attributes[key]) {
|
|
532
532
|
if (value === null || value === void 0) {
|
|
533
533
|
return;
|
|
@@ -540,12 +540,12 @@ var SpanConverter = class {
|
|
|
540
540
|
}
|
|
541
541
|
});
|
|
542
542
|
}
|
|
543
|
-
if (
|
|
544
|
-
attributes["mastra.start_time"] =
|
|
543
|
+
if (Span.startTime) {
|
|
544
|
+
attributes["mastra.start_time"] = Span.startTime.toISOString();
|
|
545
545
|
}
|
|
546
|
-
if (
|
|
547
|
-
attributes["mastra.end_time"] =
|
|
548
|
-
const duration =
|
|
546
|
+
if (Span.endTime) {
|
|
547
|
+
attributes["mastra.end_time"] = Span.endTime.toISOString();
|
|
548
|
+
const duration = Span.endTime.getTime() - Span.startTime.getTime();
|
|
549
549
|
attributes["mastra.duration_ms"] = duration;
|
|
550
550
|
}
|
|
551
551
|
return attributes;
|
|
@@ -553,28 +553,28 @@ var SpanConverter = class {
|
|
|
553
553
|
/**
|
|
554
554
|
* Get the operation name based on span type for gen_ai.operation.name
|
|
555
555
|
*/
|
|
556
|
-
getOperationName(
|
|
557
|
-
switch (
|
|
558
|
-
case
|
|
559
|
-
const attrs =
|
|
556
|
+
getOperationName(Span) {
|
|
557
|
+
switch (Span.type) {
|
|
558
|
+
case SpanType.MODEL_GENERATION: {
|
|
559
|
+
const attrs = Span.attributes;
|
|
560
560
|
return attrs?.resultType === "tool_selection" ? "tool_selection" : "chat";
|
|
561
561
|
}
|
|
562
|
-
case
|
|
563
|
-
case
|
|
562
|
+
case SpanType.TOOL_CALL:
|
|
563
|
+
case SpanType.MCP_TOOL_CALL:
|
|
564
564
|
return "tool.execute";
|
|
565
|
-
case
|
|
565
|
+
case SpanType.AGENT_RUN:
|
|
566
566
|
return "agent.run";
|
|
567
|
-
case
|
|
567
|
+
case SpanType.WORKFLOW_RUN:
|
|
568
568
|
return "workflow.run";
|
|
569
569
|
default:
|
|
570
|
-
return
|
|
570
|
+
return Span.type.replace(/_/g, ".");
|
|
571
571
|
}
|
|
572
572
|
}
|
|
573
573
|
/**
|
|
574
574
|
* Get span kind as string for attribute
|
|
575
575
|
*/
|
|
576
|
-
getSpanKindString(
|
|
577
|
-
const kind = this.getSpanKind(
|
|
576
|
+
getSpanKindString(Span) {
|
|
577
|
+
const kind = this.getSpanKind(Span);
|
|
578
578
|
switch (kind) {
|
|
579
579
|
case SpanKind.SERVER:
|
|
580
580
|
return "server";
|
|
@@ -592,21 +592,19 @@ var SpanConverter = class {
|
|
|
592
592
|
}
|
|
593
593
|
};
|
|
594
594
|
|
|
595
|
-
// src/
|
|
596
|
-
var OtelExporter = class {
|
|
595
|
+
// src/tracing.ts
|
|
596
|
+
var OtelExporter = class extends BaseExporter {
|
|
597
597
|
config;
|
|
598
598
|
tracingConfig;
|
|
599
599
|
spanConverter;
|
|
600
600
|
processor;
|
|
601
601
|
exporter;
|
|
602
602
|
isSetup = false;
|
|
603
|
-
isDisabled = false;
|
|
604
|
-
logger;
|
|
605
603
|
name = "opentelemetry";
|
|
606
604
|
constructor(config) {
|
|
605
|
+
super(config);
|
|
607
606
|
this.config = config;
|
|
608
607
|
this.spanConverter = new SpanConverter();
|
|
609
|
-
this.logger = new ConsoleLogger({ level: config.logLevel ?? "warn" });
|
|
610
608
|
if (config.logLevel === "debug") {
|
|
611
609
|
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);
|
|
612
610
|
}
|
|
@@ -614,11 +612,11 @@ var OtelExporter = class {
|
|
|
614
612
|
/**
|
|
615
613
|
* Initialize with tracing configuration
|
|
616
614
|
*/
|
|
617
|
-
init(
|
|
618
|
-
this.tracingConfig = config;
|
|
615
|
+
init(options) {
|
|
616
|
+
this.tracingConfig = options.config;
|
|
619
617
|
}
|
|
620
618
|
async setupExporter() {
|
|
621
|
-
if (this.isSetup) return;
|
|
619
|
+
if (this.isSetup || this.exporter) return;
|
|
622
620
|
if (!this.config.provider) {
|
|
623
621
|
this.logger.error(
|
|
624
622
|
'[OtelExporter] Provider configuration is required. Use the "custom" provider for generic endpoints.'
|
|
@@ -633,6 +631,10 @@ var OtelExporter = class {
|
|
|
633
631
|
this.isSetup = true;
|
|
634
632
|
return;
|
|
635
633
|
}
|
|
634
|
+
if (this.config.exporter) {
|
|
635
|
+
this.exporter = this.config.exporter;
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
636
638
|
const endpoint = resolved.endpoint;
|
|
637
639
|
const headers = resolved.headers;
|
|
638
640
|
const protocol = resolved.protocol;
|
|
@@ -686,7 +688,10 @@ var OtelExporter = class {
|
|
|
686
688
|
this.isSetup = true;
|
|
687
689
|
return;
|
|
688
690
|
}
|
|
689
|
-
|
|
691
|
+
}
|
|
692
|
+
async setupProcessor() {
|
|
693
|
+
if (this.processor || this.isSetup) return;
|
|
694
|
+
let resource = resourceFromAttributes({
|
|
690
695
|
[ATTR_SERVICE_NAME]: this.tracingConfig?.serviceName || "mastra-service",
|
|
691
696
|
[ATTR_SERVICE_VERSION]: "1.0.0",
|
|
692
697
|
// Add telemetry SDK information
|
|
@@ -694,6 +699,12 @@ var OtelExporter = class {
|
|
|
694
699
|
[ATTR_TELEMETRY_SDK_VERSION]: "1.0.0",
|
|
695
700
|
[ATTR_TELEMETRY_SDK_LANGUAGE]: "nodejs"
|
|
696
701
|
});
|
|
702
|
+
if (this.config.resourceAttributes) {
|
|
703
|
+
resource = resource.merge(
|
|
704
|
+
// Duplicate attributes from config will override defaults above
|
|
705
|
+
resourceFromAttributes(this.config.resourceAttributes)
|
|
706
|
+
);
|
|
707
|
+
}
|
|
697
708
|
this.spanConverter = new SpanConverter(resource);
|
|
698
709
|
this.processor = new BatchSpanProcessor(this.exporter, {
|
|
699
710
|
maxExportBatchSize: this.config.batchSize || 512,
|
|
@@ -708,13 +719,15 @@ var OtelExporter = class {
|
|
|
708
719
|
this.logger.debug(
|
|
709
720
|
`[OtelExporter] Using BatchSpanProcessor (batch size: ${this.config.batchSize || 512}, delay: 5s)`
|
|
710
721
|
);
|
|
722
|
+
}
|
|
723
|
+
async setup() {
|
|
724
|
+
if (this.isSetup) return;
|
|
725
|
+
await this.setupExporter();
|
|
726
|
+
await this.setupProcessor();
|
|
711
727
|
this.isSetup = true;
|
|
712
728
|
}
|
|
713
|
-
async
|
|
714
|
-
if (
|
|
715
|
-
return;
|
|
716
|
-
}
|
|
717
|
-
if (event.type !== AITracingEventType.SPAN_ENDED) {
|
|
729
|
+
async _exportTracingEvent(event) {
|
|
730
|
+
if (event.type !== TracingEventType.SPAN_ENDED) {
|
|
718
731
|
return;
|
|
719
732
|
}
|
|
720
733
|
const span = event.exportedSpan;
|
|
@@ -722,7 +735,7 @@ var OtelExporter = class {
|
|
|
722
735
|
}
|
|
723
736
|
async exportSpan(span) {
|
|
724
737
|
if (!this.isSetup) {
|
|
725
|
-
await this.
|
|
738
|
+
await this.setup();
|
|
726
739
|
}
|
|
727
740
|
if (this.isDisabled || !this.processor) {
|
|
728
741
|
return;
|