@mastra/observability 1.17.0 → 1.17.1-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/CHANGELOG.md +28 -0
- package/README.md +3 -1
- package/dist/exporters/mastra-platform.d.ts +2 -0
- package/dist/exporters/mastra-platform.d.ts.map +1 -1
- package/dist/index.cjs +241 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +240 -49
- package/dist/index.js.map +1 -1
- package/dist/instances/base.d.ts.map +1 -1
- package/dist/metrics/estimator.d.ts.map +1 -1
- package/dist/metrics/pricing-registry.d.ts.map +1 -1
- package/dist/metrics/types.d.ts +4 -0
- package/dist/metrics/types.d.ts.map +1 -1
- package/dist/metrics/usage-metrics.d.ts.map +1 -1
- package/dist/spans/base.d.ts +2 -0
- package/dist/spans/base.d.ts.map +1 -1
- package/dist/spans/default.d.ts.map +1 -1
- package/dist/spans/metadata.d.ts +22 -0
- package/dist/spans/metadata.d.ts.map +1 -0
- package/dist/spans/serialization.d.ts +0 -5
- package/dist/spans/serialization.d.ts.map +1 -1
- package/dist/usage.d.ts.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @mastra/observability
|
|
2
2
|
|
|
3
|
+
## 1.17.1-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed Anthropic cache-write cost estimates by applying TTL-specific rates without double counting aggregate tokens. ([#21563](https://github.com/mastra-ai/mastra/pull/21563))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`d7e6745`](https://github.com/mastra-ai/mastra/commit/d7e67456954863c55440ea9c49bc6ceb9949972d), [`9acb50f`](https://github.com/mastra-ai/mastra/commit/9acb50f71cec9c362f06820033f90ae6b1f8282f), [`46e9e3f`](https://github.com/mastra-ai/mastra/commit/46e9e3f73babe1bc70080a596cf2ac0b9da48519), [`3f9a190`](https://github.com/mastra-ai/mastra/commit/3f9a19057c027155867b9317294ee4ca7bd0581a), [`e8808e3`](https://github.com/mastra-ai/mastra/commit/e8808e3d8eb585a2565be53e56a7e0e1477352a4), [`d4be8c1`](https://github.com/mastra-ai/mastra/commit/d4be8c1739d22d621e3f78790e1dd5eb5ecc3589), [`a5d2eb1`](https://github.com/mastra-ai/mastra/commit/a5d2eb10347eade1ae2816d88f466c25186c54a5), [`e81744c`](https://github.com/mastra-ai/mastra/commit/e81744cd13c46619c142dc521dc0baac47607a84)]:
|
|
10
|
+
- @mastra/core@1.60.0-alpha.4
|
|
11
|
+
|
|
12
|
+
## 1.17.1-alpha.0
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Fixed span serialization so internal tracing fields are removed only from framework-owned payloads while preserving user data with the same key names. ([#21332](https://github.com/mastra-ai/mastra/pull/21332))
|
|
17
|
+
|
|
18
|
+
- Advertise quota-pause support to the Mastra platform. `MastraPlatformExporter` now sends `x-mastra-observability-capabilities: quota-pause-v1` on every request (batch uploads for all five signal types, plus the traces recovery probe), letting the platform respond with `402 Payment Required` to clients that understand the quota-pause contract while shielding legacy clients from retry loops. No configuration change is required: ([#21447](https://github.com/mastra-ai/mastra/pull/21447))
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { MastraPlatformExporter } from '@mastra/observability';
|
|
22
|
+
|
|
23
|
+
const exporter = new MastraPlatformExporter({
|
|
24
|
+
accessToken: process.env.MASTRA_PLATFORM_ACCESS_TOKEN,
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- Updated dependencies [[`15101bb`](https://github.com/mastra-ai/mastra/commit/15101bb53c0d934f31af6b8813b88191e382a5e5), [`c2c3deb`](https://github.com/mastra-ai/mastra/commit/c2c3debcf670c7082d0a5e553aa99818a864698c), [`33374ba`](https://github.com/mastra-ai/mastra/commit/33374ba359e4fb13eaa918ae925fe167a3c55414), [`c5f964d`](https://github.com/mastra-ai/mastra/commit/c5f964d3f77064e978f8066ec506eed77ba5c63c), [`f8f653f`](https://github.com/mastra-ai/mastra/commit/f8f653f10980d01a73706cc3c8689ca5e40ce808)]:
|
|
29
|
+
- @mastra/core@1.60.0-alpha.1
|
|
30
|
+
|
|
3
31
|
## 1.17.0
|
|
4
32
|
|
|
5
33
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -56,9 +56,11 @@ Metrics are automatically extracted from span lifecycle events by `AutoExtracted
|
|
|
56
56
|
- `mastra_workflow_duration_ms`
|
|
57
57
|
- `mastra_model_duration_ms`
|
|
58
58
|
- `mastra_model_total_input_tokens` / `mastra_model_total_output_tokens`
|
|
59
|
-
- `mastra_model_input_text_tokens` / `mastra_model_input_cache_read_tokens` / `mastra_model_input_cache_write_tokens` / `mastra_model_input_audio_tokens` / `mastra_model_input_image_tokens`
|
|
59
|
+
- `mastra_model_input_text_tokens` / `mastra_model_input_cache_read_tokens` / `mastra_model_input_cache_write_tokens` / `mastra_model_input_cache_write_5m_tokens` / `mastra_model_input_cache_write_1h_tokens` / `mastra_model_input_audio_tokens` / `mastra_model_input_image_tokens`
|
|
60
60
|
- `mastra_model_output_text_tokens` / `mastra_model_output_reasoning_tokens` / `mastra_model_output_audio_tokens` / `mastra_model_output_image_tokens`
|
|
61
61
|
|
|
62
|
+
For Anthropic models, the aggregate cache-write metric remains available while the 5-minute and 1-hour metrics preserve the provider's TTL-specific token counts and pricing.
|
|
63
|
+
|
|
62
64
|
Auto-extracted metrics carry labels: `entity_type`, `entity_name`, `status`, plus `model` and `provider` on model generation spans.
|
|
63
65
|
|
|
64
66
|
### Structured logging
|
|
@@ -14,6 +14,8 @@ export interface MastraPlatformExporterConfig extends BaseExporterConfig {
|
|
|
14
14
|
scoresEndpoint?: string;
|
|
15
15
|
feedbackEndpoint?: string;
|
|
16
16
|
}
|
|
17
|
+
export declare const OBSERVABILITY_CAPABILITIES_HEADER = "x-mastra-observability-capabilities";
|
|
18
|
+
export declare const QUOTA_PAUSE_CAPABILITY = "quota-pause-v1";
|
|
17
19
|
export declare class MastraPlatformExporter extends BaseExporter {
|
|
18
20
|
name: string;
|
|
19
21
|
private readonly platformConfig;
|
|
@@ -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;AAEjD,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,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;
|
|
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;AAEjD,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,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;gBAEjB,MAAM,GAAE,4BAAiC;cAyErC,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBjE,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1C,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAahD,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9C,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1D,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;IA2BtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAsChC"}
|
package/dist/index.cjs
CHANGED
|
@@ -210,21 +210,15 @@ var BaseObservabilityEventBus = class BaseObservabilityEventBus extends _mastra_
|
|
|
210
210
|
* }
|
|
211
211
|
* ```
|
|
212
212
|
*/
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
"
|
|
219
|
-
|
|
220
|
-
"providerMetadata",
|
|
221
|
-
"steps",
|
|
222
|
-
"tracingContext",
|
|
223
|
-
"execute",
|
|
224
|
-
"validate"
|
|
225
|
-
]);
|
|
213
|
+
const FUNCTION_KEYS_TO_STRIP = /* @__PURE__ */ new Set(["execute", "validate"]);
|
|
214
|
+
const LOGGER_METHODS = [
|
|
215
|
+
"debug",
|
|
216
|
+
"info",
|
|
217
|
+
"warn",
|
|
218
|
+
"error"
|
|
219
|
+
];
|
|
226
220
|
const DEFAULT_DEEP_CLEAN_OPTIONS = Object.freeze({
|
|
227
|
-
keysToStrip:
|
|
221
|
+
keysToStrip: [],
|
|
228
222
|
maxDepth: 8,
|
|
229
223
|
maxStringLength: 128 * 1024,
|
|
230
224
|
maxArrayLength: 50,
|
|
@@ -237,7 +231,7 @@ const DEFAULT_DEEP_CLEAN_OPTIONS = Object.freeze({
|
|
|
237
231
|
function mergeSerializationOptions(userOptions) {
|
|
238
232
|
if (!userOptions) return DEFAULT_DEEP_CLEAN_OPTIONS;
|
|
239
233
|
return {
|
|
240
|
-
keysToStrip:
|
|
234
|
+
keysToStrip: DEFAULT_DEEP_CLEAN_OPTIONS.keysToStrip,
|
|
241
235
|
maxDepth: userOptions.maxDepth ?? DEFAULT_DEEP_CLEAN_OPTIONS.maxDepth,
|
|
242
236
|
maxStringLength: userOptions.maxStringLength ?? DEFAULT_DEEP_CLEAN_OPTIONS.maxStringLength,
|
|
243
237
|
maxArrayLength: userOptions.maxArrayLength ?? DEFAULT_DEEP_CLEAN_OPTIONS.maxArrayLength,
|
|
@@ -263,6 +257,47 @@ function getMapKeyType(key) {
|
|
|
263
257
|
if (key instanceof Error) return "error";
|
|
264
258
|
return typeof key;
|
|
265
259
|
}
|
|
260
|
+
function hasOnlyKnownKeys(value, keys) {
|
|
261
|
+
try {
|
|
262
|
+
return Object.keys(value).every((key) => keys.includes(key));
|
|
263
|
+
} catch {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function isSpanLike(value) {
|
|
268
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
269
|
+
const span = value;
|
|
270
|
+
try {
|
|
271
|
+
return typeof span.id === "string" && typeof span.traceId === "string" && typeof span.type === "string" && typeof span.name === "string";
|
|
272
|
+
} catch {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
function isTracingContextLike(value) {
|
|
277
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
278
|
+
const context = value;
|
|
279
|
+
if (!hasOnlyKnownKeys(context, ["currentSpan"])) return false;
|
|
280
|
+
try {
|
|
281
|
+
return context.currentSpan === void 0 || isSpanLike(context.currentSpan);
|
|
282
|
+
} catch {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function isLoggerLike(value) {
|
|
287
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
288
|
+
const logger = value;
|
|
289
|
+
try {
|
|
290
|
+
return LOGGER_METHODS.some((method) => typeof logger[method] === "function");
|
|
291
|
+
} catch {
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function shouldStripEntry(key, value, stripSet) {
|
|
296
|
+
if (stripSet.has(key)) return true;
|
|
297
|
+
if (key === "tracingContext" && isTracingContextLike(value)) return true;
|
|
298
|
+
if (key === "logger") return typeof value === "function" || isLoggerLike(value);
|
|
299
|
+
return FUNCTION_KEYS_TO_STRIP.has(key) && typeof value === "function";
|
|
300
|
+
}
|
|
266
301
|
function restoreSerializedMapKey(keyType, key) {
|
|
267
302
|
switch (keyType) {
|
|
268
303
|
case "undefined": return;
|
|
@@ -365,7 +400,7 @@ function deepClean(value, options = DEFAULT_DEEP_CLEAN_OPTIONS) {
|
|
|
365
400
|
let mapKeyCount = 0;
|
|
366
401
|
let omittedMapEntries = 0;
|
|
367
402
|
for (const [mapKey, mapVal] of val) {
|
|
368
|
-
if (typeof mapKey === "string" &&
|
|
403
|
+
if (typeof mapKey === "string" && shouldStripEntry(mapKey, mapVal, stripSet)) continue;
|
|
369
404
|
if (mapKeyCount >= maxObjectKeys) {
|
|
370
405
|
omittedMapEntries++;
|
|
371
406
|
continue;
|
|
@@ -441,15 +476,34 @@ function deepClean(value, options = DEFAULT_DEEP_CLEAN_OPTIONS) {
|
|
|
441
476
|
}
|
|
442
477
|
if (looksLikeJsonSchema) return val;
|
|
443
478
|
const cleaned = {};
|
|
444
|
-
|
|
479
|
+
let keys;
|
|
480
|
+
try {
|
|
481
|
+
keys = Object.keys(val);
|
|
482
|
+
} catch (error) {
|
|
483
|
+
return formatSerializationError(error);
|
|
484
|
+
}
|
|
445
485
|
let keyCount = 0;
|
|
446
486
|
for (const key of keys) {
|
|
487
|
+
if (stripSet.has(key)) continue;
|
|
488
|
+
let rawValue;
|
|
489
|
+
try {
|
|
490
|
+
rawValue = val[key];
|
|
491
|
+
} catch (error) {
|
|
492
|
+
if (keyCount >= maxObjectKeys) {
|
|
493
|
+
cleaned["__truncated"] = `${keys.length - keyCount} more keys omitted`;
|
|
494
|
+
break;
|
|
495
|
+
}
|
|
496
|
+
cleaned[key] = formatSerializationError(error);
|
|
497
|
+
keyCount++;
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
if (shouldStripEntry(key, rawValue, stripSet)) continue;
|
|
447
501
|
if (keyCount >= maxObjectKeys) {
|
|
448
502
|
cleaned["__truncated"] = `${keys.length - keyCount} more keys omitted`;
|
|
449
503
|
break;
|
|
450
504
|
}
|
|
451
505
|
try {
|
|
452
|
-
cleaned[key] = helper(
|
|
506
|
+
cleaned[key] = helper(rawValue, depth + 1);
|
|
453
507
|
keyCount++;
|
|
454
508
|
} catch (error) {
|
|
455
509
|
cleaned[key] = formatSerializationError(error);
|
|
@@ -1048,6 +1102,8 @@ const MINIFIED_METER_TO_CANONICAL = {
|
|
|
1048
1102
|
ot: "output_tokens",
|
|
1049
1103
|
icrt: "input_cache_read_tokens",
|
|
1050
1104
|
icwt: "input_cache_write_tokens",
|
|
1105
|
+
icwt5m: "input_cache_write_5m_tokens",
|
|
1106
|
+
icwt1h: "input_cache_write_1h_tokens",
|
|
1051
1107
|
iat: "input_audio_tokens",
|
|
1052
1108
|
oat: "output_audio_tokens",
|
|
1053
1109
|
ort: "output_reasoning_tokens"
|
|
@@ -1104,6 +1160,15 @@ function parsePricingModelText(content) {
|
|
|
1104
1160
|
}
|
|
1105
1161
|
return pricingModels;
|
|
1106
1162
|
}
|
|
1163
|
+
function expandRates(row, tier) {
|
|
1164
|
+
const rates = Object.fromEntries(Object.entries(tier.r).map(([meter, value]) => [MINIFIED_METER_TO_CANONICAL[meter], value.c]));
|
|
1165
|
+
const cacheWriteRate = rates.input_cache_write_tokens;
|
|
1166
|
+
if (row.m.includes("claude") && typeof cacheWriteRate === "number") {
|
|
1167
|
+
rates.input_cache_write_5m_tokens ??= cacheWriteRate;
|
|
1168
|
+
rates.input_cache_write_1h_tokens ??= cacheWriteRate * 1.6;
|
|
1169
|
+
}
|
|
1170
|
+
return rates;
|
|
1171
|
+
}
|
|
1107
1172
|
function expandPricingModelRow(row) {
|
|
1108
1173
|
return new PricingModel({
|
|
1109
1174
|
id: row.i,
|
|
@@ -1118,7 +1183,7 @@ function expandPricingModelRow(row) {
|
|
|
1118
1183
|
op: condition.op,
|
|
1119
1184
|
value: condition.value
|
|
1120
1185
|
})),
|
|
1121
|
-
rates:
|
|
1186
|
+
rates: expandRates(row, tier)
|
|
1122
1187
|
}))
|
|
1123
1188
|
});
|
|
1124
1189
|
}
|
|
@@ -1249,6 +1314,8 @@ const PricingMeter = {
|
|
|
1249
1314
|
INPUT_AUDIO_TOKENS: "input_audio_tokens",
|
|
1250
1315
|
INPUT_CACHE_READ_TOKENS: "input_cache_read_tokens",
|
|
1251
1316
|
INPUT_CACHE_WRITE_TOKENS: "input_cache_write_tokens",
|
|
1317
|
+
INPUT_CACHE_WRITE_5M_TOKENS: "input_cache_write_5m_tokens",
|
|
1318
|
+
INPUT_CACHE_WRITE_1H_TOKENS: "input_cache_write_1h_tokens",
|
|
1252
1319
|
INPUT_IMAGE_TOKENS: "input_image_tokens",
|
|
1253
1320
|
OUTPUT_TOKENS: "output_tokens",
|
|
1254
1321
|
OUTPUT_AUDIO_TOKENS: "output_audio_tokens",
|
|
@@ -1261,6 +1328,8 @@ const TokenMetrics = {
|
|
|
1261
1328
|
INPUT_TEXT: "mastra_model_input_text_tokens",
|
|
1262
1329
|
INPUT_CACHE_READ: "mastra_model_input_cache_read_tokens",
|
|
1263
1330
|
INPUT_CACHE_WRITE: "mastra_model_input_cache_write_tokens",
|
|
1331
|
+
INPUT_CACHE_WRITE_5M: "mastra_model_input_cache_write_5m_tokens",
|
|
1332
|
+
INPUT_CACHE_WRITE_1H: "mastra_model_input_cache_write_1h_tokens",
|
|
1264
1333
|
INPUT_AUDIO: "mastra_model_input_audio_tokens",
|
|
1265
1334
|
INPUT_IMAGE: "mastra_model_input_image_tokens",
|
|
1266
1335
|
OUTPUT_TEXT: "mastra_model_output_text_tokens",
|
|
@@ -1290,6 +1359,8 @@ function getTokenMetricSamples(usage) {
|
|
|
1290
1359
|
pushIfPositive(TokenMetrics.INPUT_TEXT, usage.inputDetails.text);
|
|
1291
1360
|
pushIfPositive(TokenMetrics.INPUT_CACHE_READ, usage.inputDetails.cacheRead);
|
|
1292
1361
|
pushIfPositive(TokenMetrics.INPUT_CACHE_WRITE, usage.inputDetails.cacheWrite);
|
|
1362
|
+
pushIfPositive(TokenMetrics.INPUT_CACHE_WRITE_5M, usage.inputDetails.cacheWrite5m);
|
|
1363
|
+
pushIfPositive(TokenMetrics.INPUT_CACHE_WRITE_1H, usage.inputDetails.cacheWrite1h);
|
|
1293
1364
|
pushIfPositive(TokenMetrics.INPUT_AUDIO, usage.inputDetails.audio);
|
|
1294
1365
|
pushIfPositive(TokenMetrics.INPUT_IMAGE, usage.inputDetails.image);
|
|
1295
1366
|
}
|
|
@@ -1356,15 +1427,40 @@ function estimateCosts(args, pricingRegistry = PricingRegistry.getGlobal()) {
|
|
|
1356
1427
|
results.set(TokenMetrics.INPUT_CACHE_READ, result.costContext);
|
|
1357
1428
|
inputDetailResults.push(result);
|
|
1358
1429
|
}
|
|
1359
|
-
|
|
1430
|
+
const cacheWriteDetailResults = [];
|
|
1431
|
+
const cacheWrite5m = usage.inputDetails?.cacheWrite5m ?? 0;
|
|
1432
|
+
const cacheWrite1h = usage.inputDetails?.cacheWrite1h ?? 0;
|
|
1433
|
+
if (cacheWrite5m > 0) {
|
|
1434
|
+
const result = estimateCostForMeter({
|
|
1435
|
+
meter: PricingMeter.INPUT_CACHE_WRITE_5M_TOKENS,
|
|
1436
|
+
tokenCount: cacheWrite5m,
|
|
1437
|
+
...estimateFields
|
|
1438
|
+
});
|
|
1439
|
+
results.set(TokenMetrics.INPUT_CACHE_WRITE_5M, result.costContext);
|
|
1440
|
+
cacheWriteDetailResults.push(result);
|
|
1441
|
+
inputDetailResults.push(result);
|
|
1442
|
+
}
|
|
1443
|
+
if (cacheWrite1h > 0) {
|
|
1444
|
+
const result = estimateCostForMeter({
|
|
1445
|
+
meter: PricingMeter.INPUT_CACHE_WRITE_1H_TOKENS,
|
|
1446
|
+
tokenCount: cacheWrite1h,
|
|
1447
|
+
...estimateFields
|
|
1448
|
+
});
|
|
1449
|
+
results.set(TokenMetrics.INPUT_CACHE_WRITE_1H, result.costContext);
|
|
1450
|
+
cacheWriteDetailResults.push(result);
|
|
1451
|
+
inputDetailResults.push(result);
|
|
1452
|
+
}
|
|
1453
|
+
const unclassifiedCacheWrite = Math.max(0, (usage.inputDetails?.cacheWrite ?? 0) - cacheWrite5m - cacheWrite1h);
|
|
1454
|
+
if (unclassifiedCacheWrite > 0) {
|
|
1360
1455
|
const result = estimateCostForMeter({
|
|
1361
1456
|
meter: PricingMeter.INPUT_CACHE_WRITE_TOKENS,
|
|
1362
|
-
tokenCount:
|
|
1457
|
+
tokenCount: unclassifiedCacheWrite,
|
|
1363
1458
|
...estimateFields
|
|
1364
1459
|
});
|
|
1365
|
-
|
|
1460
|
+
cacheWriteDetailResults.push(result);
|
|
1366
1461
|
inputDetailResults.push(result);
|
|
1367
1462
|
}
|
|
1463
|
+
if (cacheWriteDetailResults.length > 0) setCombinedCostContext(results, TokenMetrics.INPUT_CACHE_WRITE, cacheWriteDetailResults, pricingModel, costMetadata);
|
|
1368
1464
|
if (usage.inputDetails?.image) {
|
|
1369
1465
|
const result = estimateCostForMeter({
|
|
1370
1466
|
meter: PricingMeter.INPUT_IMAGE_TOKENS,
|
|
@@ -1441,6 +1537,20 @@ function estimateCosts(args, pricingRegistry = PricingRegistry.getGlobal()) {
|
|
|
1441
1537
|
function applyErrorContextForUsage(results, usage, errorContext) {
|
|
1442
1538
|
for (const sample of getTokenMetricSamples(usage)) results.set(sample.name, errorContext);
|
|
1443
1539
|
}
|
|
1540
|
+
function setCombinedCostContext(results, metric, detailResults, pricingModel, costMetadata) {
|
|
1541
|
+
const estimatedCosts = detailResults.map((result) => result.costContext.estimatedCost).filter((value) => typeof value === "number");
|
|
1542
|
+
const hasFailedCost = detailResults.some((result) => !result.success);
|
|
1543
|
+
results.set(metric, {
|
|
1544
|
+
provider: pricingModel.provider,
|
|
1545
|
+
model: pricingModel.model,
|
|
1546
|
+
...estimatedCosts.length > 0 && { estimatedCost: estimatedCosts.reduce((sum, value) => sum + value, 0) },
|
|
1547
|
+
...estimatedCosts.length > 0 && { costUnit: pricingModel.currency },
|
|
1548
|
+
costMetadata: hasFailedCost ? {
|
|
1549
|
+
...costMetadata,
|
|
1550
|
+
error: "partial_cost"
|
|
1551
|
+
} : { ...costMetadata }
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1444
1554
|
function setAggregateCostContext(args) {
|
|
1445
1555
|
const { results, totalMetric, fallbackMeter, totalTokenCount, detailResults, pricingModel, pricingTier, costMetadata } = args;
|
|
1446
1556
|
if (totalTokenCount == null) return;
|
|
@@ -1681,14 +1791,24 @@ function extractUsageMetrics(usage, providerMetadata) {
|
|
|
1681
1791
|
if (isDefined(aiSdkDetails?.cacheReadTokens)) inputDetails.cacheRead = aiSdkDetails.cacheReadTokens;
|
|
1682
1792
|
if (isDefined(aiSdkDetails?.cacheWriteTokens)) inputDetails.cacheWrite = aiSdkDetails.cacheWriteTokens;
|
|
1683
1793
|
if (!isDefined(inputDetails.cacheRead) && isDefined(usage.cachedInputTokens)) inputDetails.cacheRead = usage.cachedInputTokens;
|
|
1794
|
+
if (isDefined(usage.cacheCreationInputTokens5m)) inputDetails.cacheWrite5m = usage.cacheCreationInputTokens5m;
|
|
1795
|
+
if (isDefined(usage.cacheCreationInputTokens1h)) inputDetails.cacheWrite1h = usage.cacheCreationInputTokens1h;
|
|
1684
1796
|
if (!isDefined(inputDetails.cacheWrite) && isDefined(usage.cacheCreationInputTokens)) inputDetails.cacheWrite = usage.cacheCreationInputTokens;
|
|
1797
|
+
if (!isDefined(inputDetails.cacheWrite) && (isDefined(inputDetails.cacheWrite5m) || isDefined(inputDetails.cacheWrite1h))) inputDetails.cacheWrite = (inputDetails.cacheWrite5m ?? 0) + (inputDetails.cacheWrite1h ?? 0);
|
|
1685
1798
|
if (isDefined(usage.reasoningTokens)) outputDetails.reasoning = usage.reasoningTokens;
|
|
1686
1799
|
const anthropic = providerMetadata?.anthropic;
|
|
1687
1800
|
if (anthropic) {
|
|
1688
1801
|
const rawV3InputUsage = isV3RawUsage(usage.raw) ? usage.raw.inputTokens : void 0;
|
|
1689
1802
|
const hasV3CachedTotals = rawV3InputUsage?.total !== void 0 && (rawV3InputUsage.cacheRead !== void 0 || rawV3InputUsage.cacheWrite !== void 0);
|
|
1690
1803
|
if (!isDefined(inputDetails.cacheRead) && isDefined(anthropic.cacheReadInputTokens)) inputDetails.cacheRead = anthropic.cacheReadInputTokens;
|
|
1691
|
-
|
|
1804
|
+
const cacheWrite5m = anthropic.cacheCreation?.ephemeral_5m_input_tokens ?? anthropic.cacheCreation?.ephemeral5mInputTokens;
|
|
1805
|
+
const cacheWrite1h = anthropic.cacheCreation?.ephemeral_1h_input_tokens ?? anthropic.cacheCreation?.ephemeral1hInputTokens;
|
|
1806
|
+
if (!isDefined(inputDetails.cacheWrite5m) && isDefined(cacheWrite5m)) inputDetails.cacheWrite5m = cacheWrite5m;
|
|
1807
|
+
if (!isDefined(inputDetails.cacheWrite1h) && isDefined(cacheWrite1h)) inputDetails.cacheWrite1h = cacheWrite1h;
|
|
1808
|
+
if (!isDefined(inputDetails.cacheWrite)) {
|
|
1809
|
+
if (isDefined(anthropic.cacheCreationInputTokens)) inputDetails.cacheWrite = anthropic.cacheCreationInputTokens;
|
|
1810
|
+
else if (isDefined(cacheWrite5m) || isDefined(cacheWrite1h)) inputDetails.cacheWrite = (cacheWrite5m ?? 0) + (cacheWrite1h ?? 0);
|
|
1811
|
+
}
|
|
1692
1812
|
if (!(hasV3CachedTotals || isDefined(usage.cachedInputTokens) && usage.cachedInputTokens > 0 || isDefined(usage.cacheCreationInputTokens) && usage.cacheCreationInputTokens > 0) && (isDefined(inputDetails.cacheRead) || isDefined(inputDetails.cacheWrite))) inputTokens = (usage.inputTokens ?? 0) + (inputDetails.cacheRead ?? 0) + (inputDetails.cacheWrite ?? 0);
|
|
1693
1813
|
}
|
|
1694
1814
|
const google = providerMetadata?.google;
|
|
@@ -1729,6 +1849,8 @@ function mergeInputDetails(a, b) {
|
|
|
1729
1849
|
text: addOptional(a.text, b.text),
|
|
1730
1850
|
cacheRead: addOptional(a.cacheRead, b.cacheRead),
|
|
1731
1851
|
cacheWrite: addOptional(a.cacheWrite, b.cacheWrite),
|
|
1852
|
+
cacheWrite5m: addOptional(a.cacheWrite5m, b.cacheWrite5m),
|
|
1853
|
+
cacheWrite1h: addOptional(a.cacheWrite1h, b.cacheWrite1h),
|
|
1732
1854
|
audio: addOptional(a.audio, b.audio),
|
|
1733
1855
|
image: addOptional(a.image, b.image)
|
|
1734
1856
|
};
|
|
@@ -2462,6 +2584,49 @@ var ModelSpanTracker = class {
|
|
|
2462
2584
|
}
|
|
2463
2585
|
};
|
|
2464
2586
|
//#endregion
|
|
2587
|
+
//#region src/spans/metadata.ts
|
|
2588
|
+
/**
|
|
2589
|
+
* Shared span-metadata helpers.
|
|
2590
|
+
*
|
|
2591
|
+
* Used by both the observability instance (`instances/base.ts`) and the span
|
|
2592
|
+
* base class (`spans/base.ts`) so the plain-record check and the
|
|
2593
|
+
* descriptor-preserving merge stay in a single place. Both feed the same span
|
|
2594
|
+
* metadata pipeline, so keeping one implementation avoids divergence.
|
|
2595
|
+
*/
|
|
2596
|
+
/**
|
|
2597
|
+
* Returns true only for plain object records (prototype is `Object.prototype`
|
|
2598
|
+
* or `null`). Maps, Dates, class instances, and arrays return false so callers
|
|
2599
|
+
* can preserve their original shape instead of shallow-copying them into `{}`.
|
|
2600
|
+
*/
|
|
2601
|
+
function isPlainRecord(value) {
|
|
2602
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2603
|
+
try {
|
|
2604
|
+
const prototype = Object.getPrototypeOf(value);
|
|
2605
|
+
return prototype === Object.prototype || prototype === null;
|
|
2606
|
+
} catch {
|
|
2607
|
+
return false;
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
/**
|
|
2611
|
+
* Merges two metadata values while preserving property descriptors (so getters
|
|
2612
|
+
* are copied as accessors rather than eagerly invoked). Only plain records are
|
|
2613
|
+
* merged; if either side is non-plain the second argument is returned as-is,
|
|
2614
|
+
* matching the previous per-module behavior.
|
|
2615
|
+
*/
|
|
2616
|
+
function mergeMetadata$1(parentMetadata, metadata) {
|
|
2617
|
+
if (!parentMetadata) return metadata;
|
|
2618
|
+
if (!metadata) return parentMetadata;
|
|
2619
|
+
if (!isPlainRecord(parentMetadata) || !isPlainRecord(metadata)) return metadata;
|
|
2620
|
+
try {
|
|
2621
|
+
const merged = {};
|
|
2622
|
+
Object.defineProperties(merged, Object.getOwnPropertyDescriptors(parentMetadata));
|
|
2623
|
+
Object.defineProperties(merged, Object.getOwnPropertyDescriptors(metadata));
|
|
2624
|
+
return merged;
|
|
2625
|
+
} catch {
|
|
2626
|
+
return metadata;
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
//#endregion
|
|
2465
2630
|
//#region src/spans/base.ts
|
|
2466
2631
|
/**
|
|
2467
2632
|
* Determines if a span type should be considered internal based on flags.
|
|
@@ -2586,10 +2751,7 @@ var BaseSpan = class {
|
|
|
2586
2751
|
this.type = options.type;
|
|
2587
2752
|
this.isInternal = isSpanInternal(this.type, options.tracingPolicy?.internal);
|
|
2588
2753
|
this.isExcluded = this.alwaysExcluded || observabilityConfig.excludeSpanTypes?.includes(this.type) === true || this.isInternal && !observabilityConfig.includeInternalSpans;
|
|
2589
|
-
this.metadata = deepClean(options.parent?.metadata
|
|
2590
|
-
...options.parent?.metadata,
|
|
2591
|
-
...options.metadata
|
|
2592
|
-
} : void 0, this.deepCleanOptions);
|
|
2754
|
+
this.metadata = deepClean(this.prepareSpanMetadata(mergeMetadata$1(options.parent?.metadata, options.metadata)), this.deepCleanOptions);
|
|
2593
2755
|
this.parent = options.parent;
|
|
2594
2756
|
this.startTime = options.startTime ?? /* @__PURE__ */ new Date();
|
|
2595
2757
|
this.observabilityInstance = observabilityInstance;
|
|
@@ -2607,9 +2769,32 @@ var BaseSpan = class {
|
|
|
2607
2769
|
}
|
|
2608
2770
|
this.attributes = deepClean(options.attributes, this.deepCleanOptions) || {};
|
|
2609
2771
|
if (options.requestContext && options.requestContext.size() > 0) this.requestContext = deepClean(options.requestContext, this.deepCleanOptions);
|
|
2610
|
-
if (this.isEvent) this.output = deepClean(options.output, this.deepCleanOptions);
|
|
2772
|
+
if (this.isEvent) this.output = deepClean(this.prepareSpanOutput(options.output), this.deepCleanOptions);
|
|
2611
2773
|
else this.input = deepClean(options.input, this.deepCleanOptions);
|
|
2612
2774
|
}
|
|
2775
|
+
prepareSpanOutput(value) {
|
|
2776
|
+
if (!isPlainRecord(value)) return value;
|
|
2777
|
+
if (this.type !== _mastra_core_observability.SpanType.MODEL_STEP && this.type !== _mastra_core_observability.SpanType.MODEL_INFERENCE) return value;
|
|
2778
|
+
try {
|
|
2779
|
+
const prepared = { ...value };
|
|
2780
|
+
delete prepared.steps;
|
|
2781
|
+
return prepared;
|
|
2782
|
+
} catch {
|
|
2783
|
+
return value;
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
prepareSpanMetadata(value) {
|
|
2787
|
+
if (!isPlainRecord(value)) return value;
|
|
2788
|
+
if (this.type !== _mastra_core_observability.SpanType.MODEL_STEP) return value;
|
|
2789
|
+
try {
|
|
2790
|
+
const prepared = { ...value };
|
|
2791
|
+
delete prepared.providerMetadata;
|
|
2792
|
+
delete prepared.experimental_providerMetadata;
|
|
2793
|
+
return prepared;
|
|
2794
|
+
} catch {
|
|
2795
|
+
return value;
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2613
2798
|
createChildSpan(options) {
|
|
2614
2799
|
return this.observabilityInstance.startSpan({
|
|
2615
2800
|
...options,
|
|
@@ -2816,10 +3001,10 @@ var DefaultSpan = class extends BaseSpan {
|
|
|
2816
3001
|
this.endTime = /* @__PURE__ */ new Date();
|
|
2817
3002
|
if (options?.metadata) this.metadata = {
|
|
2818
3003
|
...this.metadata,
|
|
2819
|
-
...deepClean(options.metadata, this.deepCleanOptions)
|
|
3004
|
+
...deepClean(this.prepareSpanMetadata(options.metadata), this.deepCleanOptions)
|
|
2820
3005
|
};
|
|
2821
3006
|
if (this.isExcluded) return;
|
|
2822
|
-
if (options?.output !== void 0) this.output = deepClean(options.output, this.deepCleanOptions);
|
|
3007
|
+
if (options?.output !== void 0) this.output = deepClean(this.prepareSpanOutput(options.output), this.deepCleanOptions);
|
|
2823
3008
|
if (options?.attributes) this.attributes = {
|
|
2824
3009
|
...this.attributes,
|
|
2825
3010
|
...deepClean(options.attributes, this.deepCleanOptions)
|
|
@@ -2830,7 +3015,7 @@ var DefaultSpan = class extends BaseSpan {
|
|
|
2830
3015
|
const { error, endSpan = true, attributes, metadata } = options;
|
|
2831
3016
|
if (metadata) this.metadata = {
|
|
2832
3017
|
...this.metadata,
|
|
2833
|
-
...deepClean(metadata, this.deepCleanOptions)
|
|
3018
|
+
...deepClean(this.prepareSpanMetadata(metadata), this.deepCleanOptions)
|
|
2834
3019
|
};
|
|
2835
3020
|
if (!this.isExcluded) {
|
|
2836
3021
|
this.errorInfo = deepClean(error instanceof _mastra_core_error.MastraError ? {
|
|
@@ -2859,11 +3044,11 @@ var DefaultSpan = class extends BaseSpan {
|
|
|
2859
3044
|
if (options.name !== void 0) this.name = options.name;
|
|
2860
3045
|
if (options.metadata) this.metadata = {
|
|
2861
3046
|
...this.metadata,
|
|
2862
|
-
...deepClean(options.metadata, this.deepCleanOptions)
|
|
3047
|
+
...deepClean(this.prepareSpanMetadata(options.metadata), this.deepCleanOptions)
|
|
2863
3048
|
};
|
|
2864
3049
|
if (this.isExcluded) return;
|
|
2865
3050
|
if (options.input !== void 0) this.input = deepClean(options.input, this.deepCleanOptions);
|
|
2866
|
-
if (options.output !== void 0) this.output = deepClean(options.output, this.deepCleanOptions);
|
|
3051
|
+
if (options.output !== void 0) this.output = deepClean(this.prepareSpanOutput(options.output), this.deepCleanOptions);
|
|
2867
3052
|
if (options.attributes) this.attributes = {
|
|
2868
3053
|
...this.attributes,
|
|
2869
3054
|
...deepClean(options.attributes, this.deepCleanOptions)
|
|
@@ -2951,6 +3136,19 @@ var NoOpSpan = class extends BaseSpan {
|
|
|
2951
3136
|
/**
|
|
2952
3137
|
* BaseObservability - Abstract base class for Observability implementations
|
|
2953
3138
|
*/
|
|
3139
|
+
function hasMetadataKey(metadata, key) {
|
|
3140
|
+
if (!metadata || typeof metadata !== "object") return false;
|
|
3141
|
+
try {
|
|
3142
|
+
return Object.prototype.hasOwnProperty.call(Object.getOwnPropertyDescriptors(metadata), key);
|
|
3143
|
+
} catch {
|
|
3144
|
+
return true;
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
function injectEnvironmentMetadata(metadata, environment) {
|
|
3148
|
+
if (environment === void 0 || hasMetadataKey(metadata, "environment")) return metadata;
|
|
3149
|
+
if (metadata && !isPlainRecord(metadata)) return metadata;
|
|
3150
|
+
return mergeMetadata$1(metadata, { environment });
|
|
3151
|
+
}
|
|
2954
3152
|
/**
|
|
2955
3153
|
* Abstract base class for all Observability implementations in Mastra.
|
|
2956
3154
|
*/
|
|
@@ -3046,16 +3244,9 @@ var BaseObservabilityInstance = class extends _mastra_core_base.MastraBase {
|
|
|
3046
3244
|
let traceState;
|
|
3047
3245
|
if (options.parent) traceState = options.parent.traceState;
|
|
3048
3246
|
else traceState = this.computeTraceState(tracingOptions);
|
|
3049
|
-
const
|
|
3050
|
-
const mergedMetadata = metadata || tracingMetadata ? {
|
|
3051
|
-
...metadata,
|
|
3052
|
-
...tracingMetadata
|
|
3053
|
-
} : void 0;
|
|
3247
|
+
const mergedMetadata = mergeMetadata$1(metadata, !options.parent ? tracingOptions?.metadata : void 0);
|
|
3054
3248
|
const enrichedMetadata = this.extractMetadataFromRequestContext(requestContext, mergedMetadata, traceState);
|
|
3055
|
-
const finalMetadata = !options.parent
|
|
3056
|
-
...enrichedMetadata ?? {},
|
|
3057
|
-
environment: this.#mastraEnvironment
|
|
3058
|
-
} : enrichedMetadata;
|
|
3249
|
+
const finalMetadata = !options.parent ? injectEnvironmentMetadata(enrichedMetadata, this.#mastraEnvironment) : enrichedMetadata;
|
|
3059
3250
|
const tags = !options.parent ? tracingOptions?.tags : void 0;
|
|
3060
3251
|
const traceId = !options.parent ? options.traceId ?? tracingOptions?.traceId : options.traceId;
|
|
3061
3252
|
const parentSpanId = options.parentSpanId;
|
|
@@ -3320,10 +3511,7 @@ var BaseObservabilityInstance = class extends _mastra_core_base.MastraBase {
|
|
|
3320
3511
|
if (!requestContext || !traceState || traceState.requestContextKeys.length === 0) return explicitMetadata;
|
|
3321
3512
|
const extracted = this.extractKeys(requestContext, traceState.requestContextKeys);
|
|
3322
3513
|
if (Object.keys(extracted).length === 0 && !explicitMetadata) return;
|
|
3323
|
-
return
|
|
3324
|
-
...extracted,
|
|
3325
|
-
...explicitMetadata
|
|
3326
|
-
};
|
|
3514
|
+
return mergeMetadata$1(extracted, explicitMetadata);
|
|
3327
3515
|
}
|
|
3328
3516
|
/**
|
|
3329
3517
|
* Extract specific keys from RequestContext
|
|
@@ -6370,6 +6558,8 @@ const QUOTA_EXCEEDED_STATUS = 402;
|
|
|
6370
6558
|
const OBSERVABILITY_STATUS_HEADER = "x-mastra-observability";
|
|
6371
6559
|
const OBSERVABILITY_DISABLED_VALUE = "disabled";
|
|
6372
6560
|
const OBSERVABILITY_RETRY_AFTER_HEADER = "x-mastra-observability-retry-after";
|
|
6561
|
+
const OBSERVABILITY_CAPABILITIES_HEADER = "x-mastra-observability-capabilities";
|
|
6562
|
+
const QUOTA_PAUSE_CAPABILITY = "quota-pause-v1";
|
|
6373
6563
|
const DEFAULT_QUOTA_PROBE_INTERVAL_SECONDS = 300;
|
|
6374
6564
|
const MAX_QUOTA_PROBE_INTERVAL_SECONDS = Math.floor(2147483647 / 1e3);
|
|
6375
6565
|
function isObservabilityDisabled(response) {
|
|
@@ -6696,7 +6886,8 @@ var MastraPlatformExporter = class extends BaseExporter {
|
|
|
6696
6886
|
buildPublishHeaders() {
|
|
6697
6887
|
return {
|
|
6698
6888
|
Authorization: `Bearer ${this.platformConfig.accessToken}`,
|
|
6699
|
-
"Content-Type": "application/json"
|
|
6889
|
+
"Content-Type": "application/json",
|
|
6890
|
+
[OBSERVABILITY_CAPABILITIES_HEADER]: QUOTA_PAUSE_CAPABILITY
|
|
6700
6891
|
};
|
|
6701
6892
|
}
|
|
6702
6893
|
buildPublishBody(signal, records) {
|
|
@@ -6749,7 +6940,7 @@ var MastraPlatformExporter = class extends BaseExporter {
|
|
|
6749
6940
|
this.flushTimer = null;
|
|
6750
6941
|
}
|
|
6751
6942
|
this.resetBuffer();
|
|
6752
|
-
this.logger.warn(`Mastra observability paused: quota exhausted
|
|
6943
|
+
this.logger.warn(`Mastra observability export paused: platform quota exhausted (OBSERVABILITY_QUOTA_EXCEEDED). Dropping telemetry and retrying in ${retryAfterSeconds} seconds. Check Platform billing/usage to restore telemetry.`);
|
|
6753
6944
|
this.scheduleQuotaProbe();
|
|
6754
6945
|
}
|
|
6755
6946
|
scheduleQuotaProbe() {
|
|
@@ -9332,7 +9523,6 @@ exports.CardinalityFilter = CardinalityFilter;
|
|
|
9332
9523
|
exports.CloudExporter = CloudExporter;
|
|
9333
9524
|
exports.ConsoleExporter = ConsoleExporter;
|
|
9334
9525
|
exports.DEFAULT_DEEP_CLEAN_OPTIONS = DEFAULT_DEEP_CLEAN_OPTIONS;
|
|
9335
|
-
exports.DEFAULT_KEYS_TO_STRIP = DEFAULT_KEYS_TO_STRIP;
|
|
9336
9526
|
exports.DEFAULT_LIMITS = DEFAULT_LIMITS;
|
|
9337
9527
|
exports.DefaultExporter = DefaultExporter;
|
|
9338
9528
|
exports.DefaultObservabilityInstance = DefaultObservabilityInstance;
|
|
@@ -9344,8 +9534,10 @@ exports.MastraStorageExporter = MastraStorageExporter;
|
|
|
9344
9534
|
exports.MetricsContextImpl = MetricsContextImpl;
|
|
9345
9535
|
exports.ModelSpanTracker = ModelSpanTracker;
|
|
9346
9536
|
exports.NoOpSpan = NoOpSpan;
|
|
9537
|
+
exports.OBSERVABILITY_CAPABILITIES_HEADER = OBSERVABILITY_CAPABILITIES_HEADER;
|
|
9347
9538
|
exports.Observability = Observability;
|
|
9348
9539
|
exports.ObservabilityBus = ObservabilityBus;
|
|
9540
|
+
exports.QUOTA_PAUSE_CAPABILITY = QUOTA_PAUSE_CAPABILITY;
|
|
9349
9541
|
exports.SamplingStrategyType = SamplingStrategyType;
|
|
9350
9542
|
exports.SensitiveDataFilter = SensitiveDataFilter;
|
|
9351
9543
|
exports.TestExporter = TestExporter;
|