@mastra/observability 1.20.1 → 1.21.0-alpha.1
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 +66 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +66 -18
- package/dist/index.js.map +1 -1
- package/dist/metrics/auto-extract.d.ts +1 -1
- package/dist/metrics/auto-extract.d.ts.map +1 -1
- package/dist/metrics/pricing-data.json +598 -464
- package/dist/model-tracing.d.ts +3 -2
- package/dist/model-tracing.d.ts.map +1 -1
- package/dist/spans/base.d.ts +2 -2
- package/dist/spans/base.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1969,12 +1969,20 @@ function emitDurationMetrics(span, metrics) {
|
|
|
1969
1969
|
const durationMs = span.endTime.getTime() - span.startTime.getTime();
|
|
1970
1970
|
metrics.emit(durationMetricName, durationMs, { status: span.errorInfo ? "error" : "ok" });
|
|
1971
1971
|
}
|
|
1972
|
-
/** Emit token usage metrics for a model-generation span. */
|
|
1972
|
+
/** Emit token usage metrics for a model-generation or classifier-evaluation span. */
|
|
1973
1973
|
function emitTokenMetrics(span, metrics) {
|
|
1974
|
-
if (span.type
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1974
|
+
if (span.type === _mastra_core_observability.SpanType.MODEL_GENERATION) {
|
|
1975
|
+
const attrs = span.attributes;
|
|
1976
|
+
if (attrs?.usage) emitUsageMetrics(attrs, attrs.usage, metrics);
|
|
1977
|
+
return;
|
|
1978
|
+
}
|
|
1979
|
+
if (span.type === _mastra_core_observability.SpanType.CLASSIFIER_EVALUATION) {
|
|
1980
|
+
const attrs = span.attributes;
|
|
1981
|
+
if (attrs?.usage) emitUsageMetrics({
|
|
1982
|
+
provider: attrs.provider,
|
|
1983
|
+
model: attrs.modelId
|
|
1984
|
+
}, attrs.usage, metrics);
|
|
1985
|
+
}
|
|
1978
1986
|
}
|
|
1979
1987
|
/**
|
|
1980
1988
|
* Emit token usage metrics from an explicit usage payload, using the supplied
|
|
@@ -2506,6 +2514,26 @@ function extractStepInput(payload) {
|
|
|
2506
2514
|
}
|
|
2507
2515
|
}
|
|
2508
2516
|
/**
|
|
2517
|
+
* Chunks that come from the model provider. The first one marks the response's
|
|
2518
|
+
* first chunk, matching OTel's `gen_ai.response.time_to_first_chunk`. Everything
|
|
2519
|
+
* else, such as lifecycle markers or `data-*` parts a processor writes before the
|
|
2520
|
+
* model call, is Mastra's own and does not count.
|
|
2521
|
+
*/
|
|
2522
|
+
const MODEL_RESPONSE_CHUNK_TYPES = /* @__PURE__ */ new Set([
|
|
2523
|
+
"response-metadata",
|
|
2524
|
+
"raw",
|
|
2525
|
+
"text-start",
|
|
2526
|
+
"text-delta",
|
|
2527
|
+
"reasoning-start",
|
|
2528
|
+
"reasoning-delta",
|
|
2529
|
+
"reasoning-file",
|
|
2530
|
+
"tool-call-input-streaming-start",
|
|
2531
|
+
"tool-call-delta",
|
|
2532
|
+
"tool-call",
|
|
2533
|
+
"source",
|
|
2534
|
+
"file"
|
|
2535
|
+
]);
|
|
2536
|
+
/**
|
|
2509
2537
|
* Manages MODEL_STEP and MODEL_CHUNK span tracking for streaming Model responses.
|
|
2510
2538
|
*
|
|
2511
2539
|
* Should be instantiated once per MODEL_GENERATION span and shared across
|
|
@@ -2522,6 +2550,15 @@ var ModelSpanTracker = class {
|
|
|
2522
2550
|
#chunkSequence = 0;
|
|
2523
2551
|
#completionStartTime;
|
|
2524
2552
|
#inferenceCompletionStartTime;
|
|
2553
|
+
/**
|
|
2554
|
+
* True between a step's `step-start` and `step-finish` chunks, the window in which
|
|
2555
|
+
* the provider responds. Chunks outside it, such as a `tool-call` replayed for a
|
|
2556
|
+
* finished background task on resume, are Mastra's own and never start the clock.
|
|
2557
|
+
* Durable runs wrap one step's provider stream at a time, so every chunk there counts.
|
|
2558
|
+
*/
|
|
2559
|
+
#inModelResponse = false;
|
|
2560
|
+
/** Set only by the agent's main loop; receives the first chunk's completionStartTime. */
|
|
2561
|
+
#agentRunSpan;
|
|
2525
2562
|
#currentStepInputIsFinal = false;
|
|
2526
2563
|
/** When true, step-finish chunks don't auto-close the step span (for durable execution) */
|
|
2527
2564
|
#deferStepClose = false;
|
|
@@ -2529,8 +2566,9 @@ var ModelSpanTracker = class {
|
|
|
2529
2566
|
#pendingStepFinishPayload;
|
|
2530
2567
|
/** Static request-side context applied to every MODEL_INFERENCE span */
|
|
2531
2568
|
#inferenceContext;
|
|
2532
|
-
constructor(modelSpan) {
|
|
2569
|
+
constructor(modelSpan, options) {
|
|
2533
2570
|
this.#modelSpan = modelSpan;
|
|
2571
|
+
this.#agentRunSpan = options?.agentRunSpan;
|
|
2534
2572
|
}
|
|
2535
2573
|
/**
|
|
2536
2574
|
* Set request-side context applied to subsequent MODEL_INFERENCE spans.
|
|
@@ -2540,12 +2578,22 @@ var ModelSpanTracker = class {
|
|
|
2540
2578
|
this.#inferenceContext = context;
|
|
2541
2579
|
}
|
|
2542
2580
|
/**
|
|
2543
|
-
*
|
|
2581
|
+
* Record when the provider's first chunk arrived and copy that clock up the
|
|
2582
|
+
* agent's own chain (inference → step → generation → agent run), first write
|
|
2583
|
+
* wins at each level. Time to first chunk is derived later as
|
|
2584
|
+
* `completionStartTime - startTime` on whichever span is being read.
|
|
2544
2585
|
*/
|
|
2545
2586
|
#captureCompletionStartTime() {
|
|
2587
|
+
this.#ensureStepAndInference();
|
|
2588
|
+
if (this.#inferenceCompletionStartTime) return;
|
|
2546
2589
|
const now = /* @__PURE__ */ new Date();
|
|
2590
|
+
this.#inferenceCompletionStartTime = now;
|
|
2547
2591
|
this.#completionStartTime ??= now;
|
|
2548
|
-
|
|
2592
|
+
for (const span of [
|
|
2593
|
+
this.#currentStepSpan,
|
|
2594
|
+
this.#modelSpan,
|
|
2595
|
+
this.#agentRunSpan
|
|
2596
|
+
]) if (span && !span.attributes?.completionStartTime) span.update({ attributes: { completionStartTime: now } });
|
|
2549
2597
|
}
|
|
2550
2598
|
/**
|
|
2551
2599
|
* Get the tracing context for creating child spans.
|
|
@@ -2589,13 +2637,16 @@ var ModelSpanTracker = class {
|
|
|
2589
2637
|
}, model);
|
|
2590
2638
|
if (providerCostContext && !spanOptions.attributes) spanOptions.attributes = {};
|
|
2591
2639
|
if (spanOptions.attributes) {
|
|
2592
|
-
spanOptions.attributes.completionStartTime = this.#completionStartTime;
|
|
2640
|
+
spanOptions.attributes.completionStartTime = this.#completionStartTime ?? spanOptions.attributes.completionStartTime;
|
|
2593
2641
|
spanOptions.attributes.usage = extractUsageMetrics(usage, providerMetadata);
|
|
2594
2642
|
spanOptions.attributes.costContext = providerCostContext ?? spanOptions.attributes.costContext;
|
|
2595
2643
|
if (!spanOptions.attributes.costContext) spanOptions.attributes.costContext = getGatewayCostContext({ stepProviderMetadata });
|
|
2596
2644
|
}
|
|
2597
2645
|
this.#modelSpan?.end(spanOptions);
|
|
2598
2646
|
}
|
|
2647
|
+
getCompletionStartTime() {
|
|
2648
|
+
return this.#completionStartTime;
|
|
2649
|
+
}
|
|
2599
2650
|
/**
|
|
2600
2651
|
* Update the generation span
|
|
2601
2652
|
*/
|
|
@@ -2663,6 +2714,7 @@ var ModelSpanTracker = class {
|
|
|
2663
2714
|
});
|
|
2664
2715
|
this.#currentStepInputIsFinal = Array.isArray(payload?.inputMessages);
|
|
2665
2716
|
this.#chunkSequence = 0;
|
|
2717
|
+
this.#inferenceCompletionStartTime = void 0;
|
|
2666
2718
|
}
|
|
2667
2719
|
/**
|
|
2668
2720
|
* End the current MODEL_INFERENCE span when the provider stream finishes.
|
|
@@ -2984,13 +3036,7 @@ var ModelSpanTracker = class {
|
|
|
2984
3036
|
*/
|
|
2985
3037
|
wrapStream(stream) {
|
|
2986
3038
|
return stream.pipeThrough(new stream_web.TransformStream({ transform: (chunk, controller) => {
|
|
2987
|
-
|
|
2988
|
-
case "text-delta":
|
|
2989
|
-
case "tool-call-delta":
|
|
2990
|
-
case "reasoning-delta":
|
|
2991
|
-
this.#captureCompletionStartTime();
|
|
2992
|
-
break;
|
|
2993
|
-
}
|
|
3039
|
+
if ((this.#inModelResponse || this.#deferStepClose) && MODEL_RESPONSE_CHUNK_TYPES.has(chunk.type)) this.#captureCompletionStartTime();
|
|
2994
3040
|
controller.enqueue(chunk);
|
|
2995
3041
|
switch (chunk.type) {
|
|
2996
3042
|
case "text-start":
|
|
@@ -3014,11 +3060,13 @@ var ModelSpanTracker = class {
|
|
|
3014
3060
|
this.#handleObjectChunk(chunk);
|
|
3015
3061
|
break;
|
|
3016
3062
|
case "step-start":
|
|
3063
|
+
this.#inModelResponse = true;
|
|
3017
3064
|
if (this.#currentStepSpan) this.updateStep(chunk.payload);
|
|
3018
3065
|
else this.startStep(chunk.payload);
|
|
3019
3066
|
if (!this.#currentInferenceSpan) this.startInference(chunk.payload);
|
|
3020
3067
|
break;
|
|
3021
3068
|
case "step-finish":
|
|
3069
|
+
this.#inModelResponse = false;
|
|
3022
3070
|
if (this.#deferStepClose) {
|
|
3023
3071
|
this.#pendingStepFinishPayload = chunk.payload;
|
|
3024
3072
|
this.#endChunkSpan();
|
|
@@ -3376,9 +3424,9 @@ var BaseSpan = class BaseSpan {
|
|
|
3376
3424
|
* Create a ModelSpanTracker for this span (only works if this is a MODEL_GENERATION span)
|
|
3377
3425
|
* Returns undefined for non-MODEL_GENERATION spans
|
|
3378
3426
|
*/
|
|
3379
|
-
createTracker() {
|
|
3427
|
+
createTracker(options) {
|
|
3380
3428
|
if (this.type !== _mastra_core_observability.SpanType.MODEL_GENERATION) return;
|
|
3381
|
-
return new ModelSpanTracker(this);
|
|
3429
|
+
return new ModelSpanTracker(this, options);
|
|
3382
3430
|
}
|
|
3383
3431
|
/** Returns `TRUE` if the span is the root span of a trace */
|
|
3384
3432
|
get isRootSpan() {
|