@mastra/observability 1.21.1-alpha.2 → 1.22.0-alpha.3
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/exporters/event-buffer.d.ts +5 -0
- package/dist/exporters/event-buffer.d.ts.map +1 -1
- package/dist/exporters/mastra-platform.d.ts.map +1 -1
- package/dist/exporters/mastra-storage.d.ts +14 -1
- package/dist/exporters/mastra-storage.d.ts.map +1 -1
- package/dist/exporters/span-previews.d.ts +4 -0
- package/dist/exporters/span-previews.d.ts.map +1 -0
- package/dist/index.cjs +118 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +118 -15
- package/dist/index.js.map +1 -1
- package/dist/metrics/pricing-data.json +640 -222
- package/dist/model-tracing.d.ts +5 -0
- package/dist/model-tracing.d.ts.map +1 -1
- package/dist/spans/base.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -49,12 +49,17 @@ export declare class EventBuffer {
|
|
|
49
49
|
* Builds a unique span key for tracking
|
|
50
50
|
*/
|
|
51
51
|
private buildSpanKey;
|
|
52
|
+
private exportedSpanKey;
|
|
52
53
|
/** Track successfully created spans so updates can verify span existence before flushing. */
|
|
53
54
|
addCreatedSpans(args: {
|
|
54
55
|
records: CreateSpanRecord[];
|
|
55
56
|
}): void;
|
|
57
|
+
/** Stop waiting on creates that were dropped, so their updates aren't held back for them. */
|
|
58
|
+
forgetDroppedCreates(events: BufferedEvent[]): void;
|
|
56
59
|
/** Check whether a span's create record has already been flushed to storage. */
|
|
57
60
|
spanExists(span: AnyExportedSpan): boolean;
|
|
61
|
+
/** Check whether this buffer saw the span's SPAN_STARTED but its create hasn't been confirmed yet. */
|
|
62
|
+
isAwaitingCreate(span: AnyExportedSpan): boolean;
|
|
58
63
|
/** Remove completed spans from tracking after their SPAN_ENDED updates are flushed. */
|
|
59
64
|
endFinishedSpans(args: {
|
|
60
65
|
records: UpdateSpanPartial[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-buffer.d.ts","sourceRoot":"","sources":["../../src/exporters/event-buffer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7G,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACpC;AAED,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GAAG,kBAAkB,GAAG,UAAU,CAAC;AAE5D;;;;GAIG;AACH,qBAAa,WAAW;;
|
|
1
|
+
{"version":3,"file":"event-buffer.d.ts","sourceRoot":"","sources":["../../src/exporters/event-buffer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7G,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACpC;AAED,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GAAG,kBAAkB,GAAG,UAAU,CAAC;AAE5D;;;;GAIG;AACH,qBAAa,WAAW;;IAWtB,YAAY,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,EAEvC;IAED,yEAAyE;IACzE,IAAI,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,4BAA4B,CAAA;KAAE,GAAG,IAAI,CAQ3D;IAED,qEAAqE;IACrE,KAAK,SAIJ;IAED,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,UAAU;IAKlB,gGAAgG;IAChG,QAAQ,CAAC,KAAK,EAAE,kBAAkB,QAsDjC;IAED,2FAA2F;IAC3F,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAkBrD;IAED,2FAA2F;IAC3F,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAkBrD;IAED,0CAA0C;IAC1C,IAAI,OAAO,IAAI,aAAa,EAAE,CAE7B;IAED,0CAA0C;IAC1C,IAAI,OAAO,IAAI,aAAa,EAAE,CAE7B;IAED,2DAA2D;IAC3D,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,4EAA4E;IAC5E,IAAI,OAAO,IAAI,MAAM,CAKpB;IAED;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;IAIvB,6FAA6F;IAC7F,eAAe,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,gBAAgB,EAAE,CAAA;KAAE,GAAG,IAAI,CAc3D;IAED,6FAA6F;IAC7F,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAMlD;IAED,gFAAgF;IAChF,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAEzC;IAED,sGAAsG;IACtG,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAE/C;IAED,uFAAuF;IACvF,gBAAgB,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,iBAAiB,EAAE,CAAA;KAAE,GAAG,IAAI,CAU7D;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mastra-platform.d.ts","sourceRoot":"","sources":["../../src/exporters/mastra-platform.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EAEZ,QAAQ,EACR,WAAW,EACX,UAAU,EACV,aAAa,EACd,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"mastra-platform.d.ts","sourceRoot":"","sources":["../../src/exporters/mastra-platform.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EAEZ,QAAQ,EACR,WAAW,EACX,UAAU,EACV,aAAa,EACd,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAGjD,MAAM,WAAW,4BAA6B,SAAQ,kBAAkB;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAyBD,eAAO,MAAM,iCAAiC,wCAAwC,CAAC;AACvF,eAAO,MAAM,sBAAsB,mBAAmB,CAAC;AA6MvD,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,IAAI,SAA8B;IAElC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmC;IAClE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsB;IAC1D,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,yBAAyB,CAAwC;IACzE,OAAO,CAAC,YAAY,CAAS;IAE7B,YAAY,MAAM,GAAE,4BAAiC,EAiFpD;IAED,UAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBtE;IAEK,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/C;IAEK,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAWrD;IAEK,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAWnD;IAEK,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAWzD;IAED,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,cAAc;YAMR,mBAAmB;IAYjC,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,aAAa;YAoBP,WAAW;IA4EzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,gBAAgB;YAIV,WAAW;IAoDzB;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,kBAAkB;IAkB1B;;;;;OAKG;YACW,gBAAgB;YAoDhB,gBAAgB;IAmC9B,OAAO,CAAC,WAAW;IAUnB;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAyB3B;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAqC9B;CACF"}
|
|
@@ -52,10 +52,23 @@ export declare class MastraStorageExporter extends BaseExporter {
|
|
|
52
52
|
*/
|
|
53
53
|
private flushCreates;
|
|
54
54
|
/**
|
|
55
|
-
* Flush span update/end events
|
|
55
|
+
* Flush span update/end events.
|
|
56
|
+
*
|
|
57
|
+
* When the store supports conditional updates, only spans this exporter started
|
|
58
|
+
* and hasn't confirmed the create for are deferred. Everything else, including
|
|
59
|
+
* spans another exporter instance started (such as a durable agent ending spans
|
|
60
|
+
* it rebuilt after a crash), goes straight to storage, and updates that didn't
|
|
61
|
+
* apply are counted as drops. Without conditional updates, updates for spans this
|
|
62
|
+
* exporter hasn't created are deferred until their create is flushed.
|
|
63
|
+
*
|
|
56
64
|
* When `isEnd` is true, successfully flushed spans are removed from tracking.
|
|
57
65
|
*/
|
|
58
66
|
private flushSpanUpdates;
|
|
67
|
+
/**
|
|
68
|
+
* Reports conditional span updates that storage didn't apply: the span wasn't
|
|
69
|
+
* stored, or it had already ended. Ended spans are immutable, so these are dropped.
|
|
70
|
+
*/
|
|
71
|
+
private emitNotApplied;
|
|
59
72
|
/**
|
|
60
73
|
* Runs flushBuffer() and tracks its promise so flush() can wait for writes
|
|
61
74
|
* that a timer or size trigger started on their own.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mastra-storage.d.ts","sourceRoot":"","sources":["../../src/exporters/mastra-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,QAAQ,EACR,UAAU,EACV,aAAa,EAId,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAwB,sBAAsB,EAAwB,MAAM,sBAAsB,CAAC;AAS/G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"mastra-storage.d.ts","sourceRoot":"","sources":["../../src/exporters/mastra-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,QAAQ,EACR,UAAU,EACV,aAAa,EAId,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAwB,sBAAsB,EAAwB,MAAM,sBAAsB,CAAC;AAS/G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAKtC,4FAA4F;AAC5F,MAAM,WAAW,2BAA4B,SAAQ,kBAAkB;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,QAAQ,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAAC;CAC5C;AAoCD;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,YAAY;;IACrD,IAAI,SAA6B;IAkBjC,YAAY,MAAM,GAAE,2BAAgC,EAenD;IAED;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQtD;IAED,OAAO,CAAC,eAAe;YAUT,iBAAiB;YA6CjB,iBAAiB;IAS/B;;OAEG;IACH,OAAO,CAAC,WAAW;IAyBnB;;OAEG;IACH,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,iBAAiB;IAiBzB;;;;OAIG;YACW,kBAAkB;IAQhC,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,QAAQ;IAsBhB;;;;OAIG;YACW,YAAY;IAmC1B;;;;;;;;;;;OAWG;YACW,gBAAgB;IA4E9B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAuBtB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;;;;;;OAOG;YACW,WAAW;IA+HnB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAS5D;IAED;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAMrD;IAED;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/C;IAED;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAMnD;IAED;;OAEG;IACG,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzD;IAED;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CA2B3B;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAgB9B;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"span-previews.d.ts","sourceRoot":"","sources":["../../src/exporters/span-previews.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAKlE,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,CAUvE"}
|
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ let _mastra_core_base = require("@mastra/core/base");
|
|
|
24
24
|
let _mastra_core_error = require("@mastra/core/error");
|
|
25
25
|
let _mastra_core_logger = require("@mastra/core/logger");
|
|
26
26
|
let _mastra_core_observability = require("@mastra/core/observability");
|
|
27
|
+
_mastra_core_observability = __toESM(_mastra_core_observability, 1);
|
|
27
28
|
let _mastra_core_utils = require("@mastra/core/utils");
|
|
28
29
|
let zod_v4 = require("zod/v4");
|
|
29
30
|
let fs = require("fs");
|
|
@@ -2737,8 +2738,20 @@ var ModelSpanTracker = class {
|
|
|
2737
2738
|
* feature flag, or when called without an active step span. Auto-invoked from
|
|
2738
2739
|
* chunk handlers as a safety net; explicit callers get the most accurate
|
|
2739
2740
|
* start time.
|
|
2741
|
+
*
|
|
2742
|
+
* `payload.modelId` / `payload.provider` name the model the caller is about
|
|
2743
|
+
* to invoke and are recorded on MODEL_STEP, also when a fallback attempt
|
|
2744
|
+
* reuses the step's open inference span. The safety net never records them:
|
|
2745
|
+
* a replayed step-start chunk names the model of the original call.
|
|
2740
2746
|
*/
|
|
2741
2747
|
startInference(payload) {
|
|
2748
|
+
if (payload?.modelId && payload.provider) this.#currentStepSpan?.update({ attributes: {
|
|
2749
|
+
model: payload.modelId,
|
|
2750
|
+
provider: payload.provider
|
|
2751
|
+
} });
|
|
2752
|
+
this.#openInference(payload);
|
|
2753
|
+
}
|
|
2754
|
+
#openInference(payload) {
|
|
2742
2755
|
if (!supportsModelInference()) return;
|
|
2743
2756
|
if (!this.#currentStepSpan || this.#currentInferenceSpan) return;
|
|
2744
2757
|
this.#inferenceCompletionStartTime = void 0;
|
|
@@ -2863,7 +2876,7 @@ var ModelSpanTracker = class {
|
|
|
2863
2876
|
*/
|
|
2864
2877
|
#ensureStepAndInference() {
|
|
2865
2878
|
if (!this.#currentStepSpan) this.startStep();
|
|
2866
|
-
if (!this.#currentInferenceSpan) this
|
|
2879
|
+
if (!this.#currentInferenceSpan) this.#openInference();
|
|
2867
2880
|
}
|
|
2868
2881
|
/**
|
|
2869
2882
|
* Create a new chunk span (for multi-part chunks like text-start/delta/end)
|
|
@@ -3063,7 +3076,7 @@ var ModelSpanTracker = class {
|
|
|
3063
3076
|
this.#inModelResponse = true;
|
|
3064
3077
|
if (this.#currentStepSpan) this.updateStep(chunk.payload);
|
|
3065
3078
|
else this.startStep(chunk.payload);
|
|
3066
|
-
if (!this.#currentInferenceSpan) this
|
|
3079
|
+
if (!this.#currentInferenceSpan) this.#openInference(chunk.payload);
|
|
3067
3080
|
break;
|
|
3068
3081
|
case "step-finish":
|
|
3069
3082
|
this.#inModelResponse = false;
|
|
@@ -3269,6 +3282,19 @@ function getExternalParentId(options) {
|
|
|
3269
3282
|
if (parent.isInternal || parent.isExcluded) return parent.getParentSpanId(false);
|
|
3270
3283
|
return parent.id;
|
|
3271
3284
|
}
|
|
3285
|
+
/**
|
|
3286
|
+
* Vercel AI Gateway reports which provider served a step, and any provider
|
|
3287
|
+
* attempts that failed first, only in `providerMetadata.gateway.routing`.
|
|
3288
|
+
* Read it defensively so a throwing getter never skips the strip below.
|
|
3289
|
+
*/
|
|
3290
|
+
function readGatewayRouting(providerMetadata) {
|
|
3291
|
+
try {
|
|
3292
|
+
const gateway = isPlainRecord(providerMetadata) ? providerMetadata.gateway : void 0;
|
|
3293
|
+
return isPlainRecord(gateway) ? gateway.routing : void 0;
|
|
3294
|
+
} catch {
|
|
3295
|
+
return;
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3272
3298
|
var BaseSpan = class BaseSpan {
|
|
3273
3299
|
name;
|
|
3274
3300
|
type;
|
|
@@ -3396,8 +3422,10 @@ var BaseSpan = class BaseSpan {
|
|
|
3396
3422
|
if (this.type !== _mastra_core_observability.SpanType.MODEL_STEP) return value;
|
|
3397
3423
|
try {
|
|
3398
3424
|
const prepared = { ...value };
|
|
3425
|
+
const gatewayRouting = readGatewayRouting(prepared.providerMetadata);
|
|
3399
3426
|
delete prepared.providerMetadata;
|
|
3400
3427
|
delete prepared.experimental_providerMetadata;
|
|
3428
|
+
if (gatewayRouting !== void 0) prepared.providerMetadata = { gateway: { routing: gatewayRouting } };
|
|
3401
3429
|
return prepared;
|
|
3402
3430
|
} catch {
|
|
3403
3431
|
return value;
|
|
@@ -4054,6 +4082,8 @@ var EventBuffer = class {
|
|
|
4054
4082
|
#creates = [];
|
|
4055
4083
|
#updates = [];
|
|
4056
4084
|
#allCreatedSpans = /* @__PURE__ */ new Set();
|
|
4085
|
+
/** Spans whose SPAN_STARTED this buffer has seen but whose create isn't confirmed yet */
|
|
4086
|
+
#pendingCreateSpans = /* @__PURE__ */ new Set();
|
|
4057
4087
|
#firstEventTime;
|
|
4058
4088
|
#storageStrategy;
|
|
4059
4089
|
#maxRetries;
|
|
@@ -4104,8 +4134,11 @@ var EventBuffer = class {
|
|
|
4104
4134
|
case _mastra_core_observability.TracingEventType.SPAN_STARTED:
|
|
4105
4135
|
switch (this.#storageStrategy) {
|
|
4106
4136
|
case "realtime":
|
|
4107
|
-
case "
|
|
4108
|
-
|
|
4137
|
+
case "batch-with-updates":
|
|
4138
|
+
if (!event.exportedSpan.isEvent) this.#pendingCreateSpans.add(this.exportedSpanKey(event.exportedSpan));
|
|
4139
|
+
this.pushCreate(event);
|
|
4140
|
+
break;
|
|
4141
|
+
case "event-sourced": this.pushCreate(event);
|
|
4109
4142
|
}
|
|
4110
4143
|
break;
|
|
4111
4144
|
case _mastra_core_observability.TracingEventType.SPAN_UPDATED:
|
|
@@ -4174,23 +4207,40 @@ var EventBuffer = class {
|
|
|
4174
4207
|
buildSpanKey(span) {
|
|
4175
4208
|
return `${span.traceId}:${span.spanId}`;
|
|
4176
4209
|
}
|
|
4210
|
+
exportedSpanKey(span) {
|
|
4211
|
+
return this.buildSpanKey({
|
|
4212
|
+
traceId: span.traceId,
|
|
4213
|
+
spanId: span.id
|
|
4214
|
+
});
|
|
4215
|
+
}
|
|
4177
4216
|
/** Track successfully created spans so updates can verify span existence before flushing. */
|
|
4178
4217
|
addCreatedSpans(args) {
|
|
4179
4218
|
if (this.#storageStrategy === "event-sourced" || this.#storageStrategy === "insert-only") return;
|
|
4180
|
-
for (const createRecord of args.records) if (!createRecord.isEvent)
|
|
4219
|
+
for (const createRecord of args.records) if (!createRecord.isEvent) {
|
|
4220
|
+
const key = this.buildSpanKey(createRecord);
|
|
4221
|
+
this.#pendingCreateSpans.delete(key);
|
|
4222
|
+
this.#allCreatedSpans.add(key);
|
|
4223
|
+
}
|
|
4224
|
+
}
|
|
4225
|
+
/** Stop waiting on creates that were dropped, so their updates aren't held back for them. */
|
|
4226
|
+
forgetDroppedCreates(events) {
|
|
4227
|
+
for (const event of events) if (event.type === _mastra_core_observability.TracingEventType.SPAN_STARTED) this.#pendingCreateSpans.delete(this.exportedSpanKey(event.exportedSpan));
|
|
4181
4228
|
}
|
|
4182
4229
|
/** Check whether a span's create record has already been flushed to storage. */
|
|
4183
4230
|
spanExists(span) {
|
|
4184
|
-
return this.#allCreatedSpans
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4231
|
+
return this.#allCreatedSpans.has(this.exportedSpanKey(span));
|
|
4232
|
+
}
|
|
4233
|
+
/** Check whether this buffer saw the span's SPAN_STARTED but its create hasn't been confirmed yet. */
|
|
4234
|
+
isAwaitingCreate(span) {
|
|
4235
|
+
return this.#pendingCreateSpans.has(this.exportedSpanKey(span));
|
|
4188
4236
|
}
|
|
4189
4237
|
/** Remove completed spans from tracking after their SPAN_ENDED updates are flushed. */
|
|
4190
4238
|
endFinishedSpans(args) {
|
|
4191
4239
|
if (this.#storageStrategy === "event-sourced" || this.#storageStrategy === "insert-only") return;
|
|
4192
4240
|
args.records.forEach((r) => {
|
|
4193
|
-
this
|
|
4241
|
+
const key = this.buildSpanKey(r);
|
|
4242
|
+
this.#allCreatedSpans.delete(key);
|
|
4243
|
+
this.#pendingCreateSpans.delete(key);
|
|
4194
4244
|
});
|
|
4195
4245
|
}
|
|
4196
4246
|
};
|
|
@@ -4632,6 +4682,21 @@ var DefaultExporter = class extends BaseExporter {
|
|
|
4632
4682
|
this.logger.info("DefaultExporter shutdown complete");
|
|
4633
4683
|
}
|
|
4634
4684
|
};
|
|
4685
|
+
// src/exporters/span-previews.ts
|
|
4686
|
+
const buildSpanPreviews = _mastra_core_observability.buildSpanPreviews;
|
|
4687
|
+
/** Older core versions retain their existing storage preview fallback. */
|
|
4688
|
+
function withSpanPreviews(span) {
|
|
4689
|
+
if (!_mastra_core_features.coreFeatures.has("observability-span-previews")) return span;
|
|
4690
|
+
try {
|
|
4691
|
+
const previews = buildSpanPreviews?.(span);
|
|
4692
|
+
return previews ? {
|
|
4693
|
+
...span,
|
|
4694
|
+
...previews
|
|
4695
|
+
} : span;
|
|
4696
|
+
} catch {
|
|
4697
|
+
return span;
|
|
4698
|
+
}
|
|
4699
|
+
}
|
|
4635
4700
|
// src/exporters/mastra-storage.ts
|
|
4636
4701
|
/**
|
|
4637
4702
|
* Resolves the final tracing storage strategy based on config and observability store hints
|
|
@@ -4835,6 +4900,7 @@ var MastraStorageExporter = class extends BaseExporter {
|
|
|
4835
4900
|
return { failed: true };
|
|
4836
4901
|
}
|
|
4837
4902
|
const dropped = this.#eventBuffer.reAddCreates(events);
|
|
4903
|
+
this.#eventBuffer.forgetDroppedCreates(dropped);
|
|
4838
4904
|
const retryAttempt = this.retryAttempt(events);
|
|
4839
4905
|
this.logStorageFailure(signal, events, retryAttempt, error);
|
|
4840
4906
|
this.emitDrop(signal, "retry-exhausted", dropped.length, error);
|
|
@@ -4845,7 +4911,15 @@ var MastraStorageExporter = class extends BaseExporter {
|
|
|
4845
4911
|
}
|
|
4846
4912
|
}
|
|
4847
4913
|
/**
|
|
4848
|
-
* Flush span update/end events
|
|
4914
|
+
* Flush span update/end events.
|
|
4915
|
+
*
|
|
4916
|
+
* When the store supports conditional updates, only spans this exporter started
|
|
4917
|
+
* and hasn't confirmed the create for are deferred. Everything else, including
|
|
4918
|
+
* spans another exporter instance started (such as a durable agent ending spans
|
|
4919
|
+
* it rebuilt after a crash), goes straight to storage, and updates that didn't
|
|
4920
|
+
* apply are counted as drops. Without conditional updates, updates for spans this
|
|
4921
|
+
* exporter hasn't created are deferred until their create is flushed.
|
|
4922
|
+
*
|
|
4849
4923
|
* When `isEnd` is true, successfully flushed spans are removed from tracking.
|
|
4850
4924
|
*/
|
|
4851
4925
|
async flushSpanUpdates(events, deferredUpdates, isEnd) {
|
|
@@ -4855,10 +4929,12 @@ var MastraStorageExporter = class extends BaseExporter {
|
|
|
4855
4929
|
this.emitDrop("tracing", "unsupported-storage", events.length);
|
|
4856
4930
|
return { failed: true };
|
|
4857
4931
|
}
|
|
4932
|
+
const storage = this.#observabilityStorage;
|
|
4933
|
+
const batchUpdateUnendedSpans = typeof storage.batchUpdateUnendedSpans === "function" ? storage.batchUpdateUnendedSpans.bind(storage) : void 0;
|
|
4858
4934
|
const partials = [];
|
|
4859
4935
|
for (const event of events) {
|
|
4860
4936
|
const span = event.exportedSpan;
|
|
4861
|
-
if (this.#eventBuffer.spanExists(span)) partials.push({
|
|
4937
|
+
if (batchUpdateUnendedSpans ? !this.#eventBuffer.isAwaitingCreate(span) : this.#eventBuffer.spanExists(span)) partials.push({
|
|
4862
4938
|
traceId: span.traceId,
|
|
4863
4939
|
spanId: span.id,
|
|
4864
4940
|
updates: (0, _mastra_core_storage.buildUpdateSpanRecord)(span)
|
|
@@ -4867,7 +4943,10 @@ var MastraStorageExporter = class extends BaseExporter {
|
|
|
4867
4943
|
}
|
|
4868
4944
|
if (partials.length === 0) return FLUSH_SUCCEEDED;
|
|
4869
4945
|
try {
|
|
4870
|
-
|
|
4946
|
+
if (batchUpdateUnendedSpans) {
|
|
4947
|
+
const { updated } = await batchUpdateUnendedSpans({ records: partials });
|
|
4948
|
+
this.emitNotApplied(partials, updated);
|
|
4949
|
+
} else await storage.batchUpdateSpans({ records: partials });
|
|
4871
4950
|
if (isEnd) this.#eventBuffer.endFinishedSpans({ records: partials });
|
|
4872
4951
|
return FLUSH_SUCCEEDED;
|
|
4873
4952
|
} catch (error) {
|
|
@@ -4891,6 +4970,27 @@ var MastraStorageExporter = class extends BaseExporter {
|
|
|
4891
4970
|
}
|
|
4892
4971
|
}
|
|
4893
4972
|
/**
|
|
4973
|
+
* Reports conditional span updates that storage didn't apply: the span wasn't
|
|
4974
|
+
* stored, or it had already ended. Ended spans are immutable, so these are dropped.
|
|
4975
|
+
*/
|
|
4976
|
+
emitNotApplied(partials, updated) {
|
|
4977
|
+
const appliedCounts = /* @__PURE__ */ new Map();
|
|
4978
|
+
for (const span of updated) {
|
|
4979
|
+
const key = `${span.traceId}:${span.spanId}`;
|
|
4980
|
+
appliedCounts.set(key, (appliedCounts.get(key) ?? 0) + 1);
|
|
4981
|
+
}
|
|
4982
|
+
let notApplied = 0;
|
|
4983
|
+
for (const partial of partials) {
|
|
4984
|
+
const key = `${partial.traceId}:${partial.spanId}`;
|
|
4985
|
+
const remaining = appliedCounts.get(key) ?? 0;
|
|
4986
|
+
if (remaining > 0) appliedCounts.set(key, remaining - 1);
|
|
4987
|
+
else notApplied++;
|
|
4988
|
+
}
|
|
4989
|
+
if (notApplied === 0) return;
|
|
4990
|
+
this.logger.debug("Span updates not applied: span not stored or already ended", { count: notApplied });
|
|
4991
|
+
this.emitDrop("tracing", "span-not-updatable", notApplied);
|
|
4992
|
+
}
|
|
4993
|
+
/**
|
|
4894
4994
|
* Runs flushBuffer() and tracks its promise so flush() can wait for writes
|
|
4895
4995
|
* that a timer or size trigger started on their own.
|
|
4896
4996
|
*/
|
|
@@ -5000,7 +5100,10 @@ var MastraStorageExporter = class extends BaseExporter {
|
|
|
5000
5100
|
this.logger.debug("Cannot store traces. Observability storage is not initialized");
|
|
5001
5101
|
return;
|
|
5002
5102
|
}
|
|
5003
|
-
this.#eventBuffer.addEvent(
|
|
5103
|
+
this.#eventBuffer.addEvent({
|
|
5104
|
+
...event,
|
|
5105
|
+
exportedSpan: withSpanPreviews(event.exportedSpan)
|
|
5106
|
+
});
|
|
5004
5107
|
await this.handleBatchedFlush();
|
|
5005
5108
|
}
|
|
5006
5109
|
/**
|
|
@@ -8104,7 +8207,7 @@ var MastraPlatformExporter = class extends BaseExporter {
|
|
|
8104
8207
|
}
|
|
8105
8208
|
formatSpan(span) {
|
|
8106
8209
|
return {
|
|
8107
|
-
...span,
|
|
8210
|
+
...withSpanPreviews(span),
|
|
8108
8211
|
spanId: span.id,
|
|
8109
8212
|
spanType: span.type,
|
|
8110
8213
|
startedAt: span.startTime,
|