@mastra/observability 1.5.0 → 1.5.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 +20 -0
- package/dist/index.cjs +98 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +98 -51
- package/dist/index.js.map +1 -1
- package/dist/spans/serialization.d.ts.map +1 -1
- package/dist/usage.d.ts +5 -0
- package/dist/usage.d.ts.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @mastra/observability
|
|
2
2
|
|
|
3
|
+
## 1.5.1-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix cache token extraction in multi-step agent runs. Prefer AI SDK aggregated `inputTokenDetails` over `providerMetadata` (which only reflects the last step). Also fix truthiness checks to correctly handle zero values for cache and reasoning tokens. ([#14492](https://github.com/mastra-ai/mastra/pull/14492))
|
|
8
|
+
|
|
9
|
+
Fix Datadog metric keys to match dd-trace expected format: `cacheReadTokens`, `cacheWriteTokens`, `reasoningOutputTokens`.
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`9e1a3ed`](https://github.com/mastra-ai/mastra/commit/9e1a3ed07cfafb5e8e19a796ce0bee817002d7c0), [`a579f7a`](https://github.com/mastra-ai/mastra/commit/a579f7a31e582674862b5679bc79af7ccf7429b8)]:
|
|
12
|
+
- @mastra/core@1.15.0-alpha.2
|
|
13
|
+
|
|
14
|
+
## 1.5.1-alpha.0
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Fixed span serialization to avoid incorrect [Circular] placeholders in traces. ([#14263](https://github.com/mastra-ai/mastra/pull/14263))
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [[`cb611a1`](https://github.com/mastra-ai/mastra/commit/cb611a1e89a4f4cf74c97b57e0c27bb56f2eceb5), [`62d1d3c`](https://github.com/mastra-ai/mastra/commit/62d1d3cc08fe8182e7080237fd975de862ec8c91), [`8681ecb`](https://github.com/mastra-ai/mastra/commit/8681ecb86184d5907267000e4576cc442a9a83fc), [`28d0249`](https://github.com/mastra-ai/mastra/commit/28d0249295782277040ad1e0d243e695b7ab1ce4), [`bb0f09d`](https://github.com/mastra-ai/mastra/commit/bb0f09dbac58401b36069f483acf5673202db5b5), [`5f7e9d0`](https://github.com/mastra-ai/mastra/commit/5f7e9d0db664020e1f3d97d7d18c6b0b9d4843d0)]:
|
|
21
|
+
- @mastra/core@1.15.0-alpha.0
|
|
22
|
+
|
|
3
23
|
## 1.5.0
|
|
4
24
|
|
|
5
25
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -17426,6 +17426,9 @@ var MetricsContextImpl = class {
|
|
|
17426
17426
|
};
|
|
17427
17427
|
|
|
17428
17428
|
// src/usage.ts
|
|
17429
|
+
function isDefined(value) {
|
|
17430
|
+
return value != null;
|
|
17431
|
+
}
|
|
17429
17432
|
function extractUsageMetrics(usage, providerMetadata) {
|
|
17430
17433
|
if (!usage) {
|
|
17431
17434
|
return {};
|
|
@@ -17434,31 +17437,38 @@ function extractUsageMetrics(usage, providerMetadata) {
|
|
|
17434
17437
|
const outputDetails = {};
|
|
17435
17438
|
let inputTokens = usage.inputTokens;
|
|
17436
17439
|
const outputTokens = usage.outputTokens;
|
|
17437
|
-
|
|
17440
|
+
const aiSdkDetails = usage.inputTokenDetails;
|
|
17441
|
+
if (isDefined(aiSdkDetails?.cacheReadTokens)) {
|
|
17442
|
+
inputDetails.cacheRead = aiSdkDetails.cacheReadTokens;
|
|
17443
|
+
}
|
|
17444
|
+
if (isDefined(aiSdkDetails?.cacheWriteTokens)) {
|
|
17445
|
+
inputDetails.cacheWrite = aiSdkDetails.cacheWriteTokens;
|
|
17446
|
+
}
|
|
17447
|
+
if (!isDefined(inputDetails.cacheRead) && isDefined(usage.cachedInputTokens)) {
|
|
17438
17448
|
inputDetails.cacheRead = usage.cachedInputTokens;
|
|
17439
17449
|
}
|
|
17440
|
-
if (usage.reasoningTokens) {
|
|
17450
|
+
if (isDefined(usage.reasoningTokens)) {
|
|
17441
17451
|
outputDetails.reasoning = usage.reasoningTokens;
|
|
17442
17452
|
}
|
|
17443
17453
|
const anthropic = providerMetadata?.anthropic;
|
|
17444
17454
|
if (anthropic) {
|
|
17445
|
-
if (anthropic.cacheReadInputTokens) {
|
|
17455
|
+
if (!isDefined(inputDetails.cacheRead) && isDefined(anthropic.cacheReadInputTokens)) {
|
|
17446
17456
|
inputDetails.cacheRead = anthropic.cacheReadInputTokens;
|
|
17447
17457
|
}
|
|
17448
|
-
if (anthropic.cacheCreationInputTokens) {
|
|
17458
|
+
if (!isDefined(inputDetails.cacheWrite) && isDefined(anthropic.cacheCreationInputTokens)) {
|
|
17449
17459
|
inputDetails.cacheWrite = anthropic.cacheCreationInputTokens;
|
|
17450
17460
|
}
|
|
17451
|
-
if (
|
|
17461
|
+
if (isDefined(inputDetails.cacheRead) || isDefined(inputDetails.cacheWrite)) {
|
|
17452
17462
|
inputDetails.text = usage.inputTokens;
|
|
17453
|
-
inputTokens = (usage.inputTokens ?? 0) + (
|
|
17463
|
+
inputTokens = (usage.inputTokens ?? 0) + (inputDetails.cacheRead ?? 0) + (inputDetails.cacheWrite ?? 0);
|
|
17454
17464
|
}
|
|
17455
17465
|
}
|
|
17456
17466
|
const google = providerMetadata?.google;
|
|
17457
17467
|
if (google?.usageMetadata) {
|
|
17458
|
-
if (google.usageMetadata.cachedContentTokenCount) {
|
|
17468
|
+
if (!isDefined(inputDetails.cacheRead) && isDefined(google.usageMetadata.cachedContentTokenCount)) {
|
|
17459
17469
|
inputDetails.cacheRead = google.usageMetadata.cachedContentTokenCount;
|
|
17460
17470
|
}
|
|
17461
|
-
if (google.usageMetadata.thoughtsTokenCount) {
|
|
17471
|
+
if (isDefined(google.usageMetadata.thoughtsTokenCount)) {
|
|
17462
17472
|
outputDetails.reasoning = google.usageMetadata.thoughtsTokenCount;
|
|
17463
17473
|
}
|
|
17464
17474
|
}
|
|
@@ -17950,6 +17960,17 @@ function compressJsonSchema(schema, depth = 0) {
|
|
|
17950
17960
|
if (depth > 3) {
|
|
17951
17961
|
return schema.type || "object";
|
|
17952
17962
|
}
|
|
17963
|
+
const compositionKeys = ["oneOf", "anyOf", "allOf"].filter((key) => Array.isArray(schema[key]));
|
|
17964
|
+
if (compositionKeys.length > 0) {
|
|
17965
|
+
const compressed2 = {};
|
|
17966
|
+
for (const key of compositionKeys) {
|
|
17967
|
+
compressed2[key] = schema[key].map((entry) => compressJsonSchema(entry, depth + 1));
|
|
17968
|
+
}
|
|
17969
|
+
if (typeof schema.type === "string") {
|
|
17970
|
+
compressed2.type = schema.type;
|
|
17971
|
+
}
|
|
17972
|
+
return compressed2;
|
|
17973
|
+
}
|
|
17953
17974
|
if (schema.type !== "object" || !schema.properties) {
|
|
17954
17975
|
return schema.type || schema;
|
|
17955
17976
|
}
|
|
@@ -17983,7 +18004,7 @@ function compressJsonSchema(schema, depth = 0) {
|
|
|
17983
18004
|
function deepClean(value, options = DEFAULT_DEEP_CLEAN_OPTIONS) {
|
|
17984
18005
|
const { keysToStrip, maxDepth, maxStringLength, maxArrayLength, maxObjectKeys } = options;
|
|
17985
18006
|
const stripSet = keysToStrip instanceof Set ? keysToStrip : new Set(Array.isArray(keysToStrip) ? keysToStrip : Object.keys(keysToStrip));
|
|
17986
|
-
const
|
|
18007
|
+
const ancestors = /* @__PURE__ */ new WeakSet();
|
|
17987
18008
|
function helper(val, depth) {
|
|
17988
18009
|
if (depth > maxDepth) {
|
|
17989
18010
|
return "[MaxDepth]";
|
|
@@ -18016,59 +18037,85 @@ function deepClean(value, options = DEFAULT_DEEP_CLEAN_OPTIONS) {
|
|
|
18016
18037
|
};
|
|
18017
18038
|
}
|
|
18018
18039
|
if (typeof val === "object") {
|
|
18019
|
-
if (
|
|
18040
|
+
if (ancestors.has(val)) {
|
|
18020
18041
|
return "[Circular]";
|
|
18021
18042
|
}
|
|
18022
|
-
|
|
18043
|
+
ancestors.add(val);
|
|
18023
18044
|
}
|
|
18024
|
-
|
|
18025
|
-
|
|
18026
|
-
|
|
18027
|
-
|
|
18028
|
-
|
|
18045
|
+
try {
|
|
18046
|
+
if (Array.isArray(val)) {
|
|
18047
|
+
const cleaned2 = [];
|
|
18048
|
+
for (let i = 0; i < Math.min(val.length, maxArrayLength); i++) {
|
|
18049
|
+
try {
|
|
18050
|
+
cleaned2.push(helper(val[i], depth + 1));
|
|
18051
|
+
} catch (error48) {
|
|
18052
|
+
cleaned2.push(`[${error48 instanceof Error ? truncateString(error48.message, 256) : "unknown error"}]`);
|
|
18053
|
+
}
|
|
18054
|
+
}
|
|
18055
|
+
if (val.length > maxArrayLength) {
|
|
18056
|
+
cleaned2.push(`[\u2026${val.length - maxArrayLength} more items]`);
|
|
18057
|
+
}
|
|
18058
|
+
return cleaned2;
|
|
18029
18059
|
}
|
|
18030
|
-
|
|
18031
|
-
|
|
18032
|
-
if (typeof Buffer !== "undefined" && Buffer.isBuffer(val)) {
|
|
18033
|
-
return `[Buffer length=${val.length}]`;
|
|
18034
|
-
}
|
|
18035
|
-
if (ArrayBuffer.isView(val)) {
|
|
18036
|
-
const ctor = val.constructor?.name ?? "TypedArray";
|
|
18037
|
-
const byteLength = val.byteLength ?? "?";
|
|
18038
|
-
return `[${ctor} byteLength=${byteLength}]`;
|
|
18039
|
-
}
|
|
18040
|
-
if (val instanceof ArrayBuffer) {
|
|
18041
|
-
return `[ArrayBuffer byteLength=${val.byteLength}]`;
|
|
18042
|
-
}
|
|
18043
|
-
if (typeof val.serializeForSpan === "function") {
|
|
18044
|
-
try {
|
|
18045
|
-
return helper(val.serializeForSpan(), depth);
|
|
18046
|
-
} catch {
|
|
18060
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(val)) {
|
|
18061
|
+
return `[Buffer length=${val.length}]`;
|
|
18047
18062
|
}
|
|
18048
|
-
|
|
18049
|
-
|
|
18050
|
-
|
|
18051
|
-
|
|
18052
|
-
const cleaned = {};
|
|
18053
|
-
const entries = Object.entries(val);
|
|
18054
|
-
let keyCount = 0;
|
|
18055
|
-
for (const [key, v] of entries) {
|
|
18056
|
-
if (stripSet.has(key)) {
|
|
18057
|
-
continue;
|
|
18063
|
+
if (ArrayBuffer.isView(val)) {
|
|
18064
|
+
const ctor = val.constructor?.name ?? "TypedArray";
|
|
18065
|
+
const byteLength = val.byteLength ?? "?";
|
|
18066
|
+
return `[${ctor} byteLength=${byteLength}]`;
|
|
18058
18067
|
}
|
|
18059
|
-
if (
|
|
18060
|
-
|
|
18061
|
-
break;
|
|
18068
|
+
if (val instanceof ArrayBuffer) {
|
|
18069
|
+
return `[ArrayBuffer byteLength=${val.byteLength}]`;
|
|
18062
18070
|
}
|
|
18071
|
+
let serializeForSpan;
|
|
18063
18072
|
try {
|
|
18064
|
-
|
|
18065
|
-
keyCount++;
|
|
18073
|
+
serializeForSpan = val.serializeForSpan;
|
|
18066
18074
|
} catch (error48) {
|
|
18067
|
-
|
|
18068
|
-
|
|
18075
|
+
return `[serializeForSpan failed: ${error48 instanceof Error ? truncateString(error48.message, 256) : "unknown error"}]`;
|
|
18076
|
+
}
|
|
18077
|
+
if (typeof serializeForSpan === "function") {
|
|
18078
|
+
try {
|
|
18079
|
+
return helper(serializeForSpan.call(val), depth);
|
|
18080
|
+
} catch (error48) {
|
|
18081
|
+
return `[serializeForSpan failed: ${error48 instanceof Error ? truncateString(error48.message, 256) : "unknown error"}]`;
|
|
18082
|
+
}
|
|
18083
|
+
}
|
|
18084
|
+
let looksLikeJsonSchema = false;
|
|
18085
|
+
try {
|
|
18086
|
+
looksLikeJsonSchema = isJsonSchema(val);
|
|
18087
|
+
} catch {
|
|
18088
|
+
looksLikeJsonSchema = false;
|
|
18089
|
+
}
|
|
18090
|
+
if (looksLikeJsonSchema) {
|
|
18091
|
+
try {
|
|
18092
|
+
const compressed = compressJsonSchema(val);
|
|
18093
|
+
return compressed === val ? "[JSONSchema]" : helper(compressed, depth);
|
|
18094
|
+
} catch {
|
|
18095
|
+
}
|
|
18096
|
+
}
|
|
18097
|
+
const cleaned = {};
|
|
18098
|
+
const keys = Object.keys(val).filter((key) => !stripSet.has(key));
|
|
18099
|
+
let keyCount = 0;
|
|
18100
|
+
for (const key of keys) {
|
|
18101
|
+
if (keyCount >= maxObjectKeys) {
|
|
18102
|
+
cleaned["__truncated"] = `${keys.length - keyCount} more keys omitted`;
|
|
18103
|
+
break;
|
|
18104
|
+
}
|
|
18105
|
+
try {
|
|
18106
|
+
cleaned[key] = helper(val[key], depth + 1);
|
|
18107
|
+
keyCount++;
|
|
18108
|
+
} catch (error48) {
|
|
18109
|
+
cleaned[key] = `[${error48 instanceof Error ? truncateString(error48.message, 256) : "unknown error"}]`;
|
|
18110
|
+
keyCount++;
|
|
18111
|
+
}
|
|
18112
|
+
}
|
|
18113
|
+
return cleaned;
|
|
18114
|
+
} finally {
|
|
18115
|
+
if (typeof val === "object" && val !== null) {
|
|
18116
|
+
ancestors.delete(val);
|
|
18069
18117
|
}
|
|
18070
18118
|
}
|
|
18071
|
-
return cleaned;
|
|
18072
18119
|
}
|
|
18073
18120
|
return helper(value, 0);
|
|
18074
18121
|
}
|