@mastra/observability 1.9.1-alpha.0 → 1.9.1-alpha.2
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 +31 -0
- package/dist/index.cjs +169 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +169 -11
- package/dist/index.js.map +1 -1
- package/dist/metrics/pricing-data.jsonl +450 -166
- package/dist/metrics/pricing-registry.d.ts.map +1 -1
- package/dist/model-tracing.d.ts.map +1 -1
- package/dist/spans/base.d.ts.map +1 -1
- package/dist/spans/default.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,36 @@
|
|
|
1
1
|
# @mastra/observability
|
|
2
2
|
|
|
3
|
+
## 1.9.1-alpha.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Cost estimates now use the latest model pricing rates for more accurate calculations ([#15362](https://github.com/mastra-ai/mastra/pull/15362))
|
|
8
|
+
|
|
9
|
+
- Reduced observability overhead for `MODEL_STEP` spans by storing a lightweight message preview of request bodies. ([#15249](https://github.com/mastra-ai/mastra/pull/15249))
|
|
10
|
+
|
|
11
|
+
This keeps span previews readable and avoids pulling large payloads into exporter input.
|
|
12
|
+
|
|
13
|
+
- Fixed cost lookup for models with date suffixes. Providers like OpenAI often return model names with date suffixes (e.g., `gpt-5.4-mini-2026-03-17`) that don't exactly match pricing data entries. The lookup now tries multiple variants including stripping date suffixes and converting dots to dashes. ([#15349](https://github.com/mastra-ai/mastra/pull/15349))
|
|
14
|
+
|
|
15
|
+
- Added `entityVersionId`, `parentEntityVersionId`, and `rootEntityVersionId` to span correlation context, enabling version information to propagate to scores, metrics, logs, and feedback emitted during traced execution. ([#15317](https://github.com/mastra-ai/mastra/pull/15317))
|
|
16
|
+
|
|
17
|
+
- Fixed stack traces for errors reported to Sentry. Exceptions now point to the code that threw the error instead of `SentryExporter.handleSpanEnded` inside the exporter, so issues in Sentry are actually debuggable. ([#15343](https://github.com/mastra-ai/mastra/pull/15343))
|
|
18
|
+
|
|
19
|
+
This was caused by two issues, both fixed:
|
|
20
|
+
- `@mastra/sentry` passed the error message as a string to `Sentry.captureException`, which made Sentry synthesize a stack trace from the exporter's call site. It now passes an `Error` instance with the captured stack attached.
|
|
21
|
+
- `@mastra/observability` stored the wrapping `MastraError`'s stack on the span, hiding the original error's location. When the `MastraError` has a cause, the cause's stack is now preserved.
|
|
22
|
+
|
|
23
|
+
Fixes [#15337](https://github.com/mastra-ai/mastra/issues/15337).
|
|
24
|
+
|
|
25
|
+
- Updated dependencies [[`cbdf3e1`](https://github.com/mastra-ai/mastra/commit/cbdf3e12b3d0c30a6e5347be658e2009648c130a), [`8fe46d3`](https://github.com/mastra-ai/mastra/commit/8fe46d354027f3f0f0846e64219772348de106dd), [`18c67db`](https://github.com/mastra-ai/mastra/commit/18c67dbb9c9ebc26f26f65f7d3ff836e5691ef46), [`8dcc77e`](https://github.com/mastra-ai/mastra/commit/8dcc77e78a5340f5848f74b9e9f1b3da3513c1f5), [`aa67fc5`](https://github.com/mastra-ai/mastra/commit/aa67fc59ee8a5eeff1f23eb05970b8d7a536c8ff), [`fa8140b`](https://github.com/mastra-ai/mastra/commit/fa8140bcd4251d2e3ac85fdc5547dfc4f372b5be), [`190f452`](https://github.com/mastra-ai/mastra/commit/190f45258b0640e2adfc8219fa3258cdc5b8f071), [`7e7bf60`](https://github.com/mastra-ai/mastra/commit/7e7bf606886bf374a6f9d4ca9b09dd83d0533372), [`184907d`](https://github.com/mastra-ai/mastra/commit/184907d775d8609c03c26e78ccaf37315f3aa287), [`0c4cd13`](https://github.com/mastra-ai/mastra/commit/0c4cd131931c04ac5405373c932a242dbe88edd6), [`b16a753`](https://github.com/mastra-ai/mastra/commit/b16a753d5748440248d7df82e29bb987a9c8386c)]:
|
|
26
|
+
- @mastra/core@1.25.0-alpha.3
|
|
27
|
+
|
|
28
|
+
## 1.9.1-alpha.1
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Fixed double-counting of Anthropic cache tokens in usage metrics ([#15316](https://github.com/mastra-ai/mastra/pull/15316))
|
|
33
|
+
|
|
3
34
|
## 1.9.1-alpha.0
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -18093,6 +18093,7 @@ var PricingRegistry = class _PricingRegistry {
|
|
|
18093
18093
|
constructor(pricingModels) {
|
|
18094
18094
|
this.pricingModels = pricingModels;
|
|
18095
18095
|
}
|
|
18096
|
+
pricingModels;
|
|
18096
18097
|
static globalRegistry = null;
|
|
18097
18098
|
static fromText(pricingModelText) {
|
|
18098
18099
|
return new _PricingRegistry(parsePricingModelText(pricingModelText));
|
|
@@ -18109,12 +18110,11 @@ var PricingRegistry = class _PricingRegistry {
|
|
|
18109
18110
|
return _PricingRegistry.globalRegistry;
|
|
18110
18111
|
}
|
|
18111
18112
|
get(args) {
|
|
18112
|
-
const
|
|
18113
|
-
const
|
|
18114
|
-
|
|
18115
|
-
|
|
18116
|
-
|
|
18117
|
-
return this.pricingModels.get(dashedKey) ?? null;
|
|
18113
|
+
const variants = getModelVariants(args.model);
|
|
18114
|
+
for (const variant of variants) {
|
|
18115
|
+
const key = makePricingKey({ provider: args.provider, model: variant });
|
|
18116
|
+
const match = this.pricingModels.get(key);
|
|
18117
|
+
if (match) return match;
|
|
18118
18118
|
}
|
|
18119
18119
|
return null;
|
|
18120
18120
|
}
|
|
@@ -18204,6 +18204,18 @@ function normalizeProvider(provider) {
|
|
|
18204
18204
|
const dotIndex = normalized.indexOf(".");
|
|
18205
18205
|
return dotIndex !== -1 ? normalized.substring(0, dotIndex) : normalized;
|
|
18206
18206
|
}
|
|
18207
|
+
function getModelVariants(model) {
|
|
18208
|
+
const dashed = model.replace(/\./g, "-");
|
|
18209
|
+
return [model, dashed, stripDateSuffix(model), stripDateSuffix(dashed)];
|
|
18210
|
+
}
|
|
18211
|
+
function stripDateSuffix(model) {
|
|
18212
|
+
let stripped = model.replace(/-20\d{2}-\d{2}-\d{2}$/, "");
|
|
18213
|
+
if (stripped !== model) return stripped;
|
|
18214
|
+
stripped = model.replace(/-20\d{6}(-[a-z]+)?$/, "$1");
|
|
18215
|
+
if (stripped !== model) return stripped;
|
|
18216
|
+
stripped = model.replace(/-\d{2}-20\d{2}$/, "");
|
|
18217
|
+
return stripped;
|
|
18218
|
+
}
|
|
18207
18219
|
|
|
18208
18220
|
// src/metrics/types.ts
|
|
18209
18221
|
var PricingMeter = {
|
|
@@ -18594,7 +18606,8 @@ function extractUsageMetrics(usage, providerMetadata) {
|
|
|
18594
18606
|
if (!isDefined(inputDetails.cacheWrite) && isDefined(anthropic.cacheCreationInputTokens)) {
|
|
18595
18607
|
inputDetails.cacheWrite = anthropic.cacheCreationInputTokens;
|
|
18596
18608
|
}
|
|
18597
|
-
|
|
18609
|
+
const inputAlreadyIncludesCache = hasV3CachedTotals || isDefined(usage.cachedInputTokens) && usage.cachedInputTokens > 0;
|
|
18610
|
+
if (!inputAlreadyIncludesCache && (isDefined(inputDetails.cacheRead) || isDefined(inputDetails.cacheWrite))) {
|
|
18598
18611
|
inputTokens = (usage.inputTokens ?? 0) + (inputDetails.cacheRead ?? 0) + (inputDetails.cacheWrite ?? 0);
|
|
18599
18612
|
}
|
|
18600
18613
|
}
|
|
@@ -18633,15 +18646,150 @@ function sumDefinedValues(obj, keys) {
|
|
|
18633
18646
|
}
|
|
18634
18647
|
|
|
18635
18648
|
// src/model-tracing.ts
|
|
18649
|
+
function formatPreviewLabel(label, fallback) {
|
|
18650
|
+
return typeof label === "string" && label.length > 0 ? label : fallback;
|
|
18651
|
+
}
|
|
18652
|
+
function summarizePart(part) {
|
|
18653
|
+
if (typeof part === "string") {
|
|
18654
|
+
return part;
|
|
18655
|
+
}
|
|
18656
|
+
if (!part || typeof part !== "object") {
|
|
18657
|
+
return "";
|
|
18658
|
+
}
|
|
18659
|
+
if ("text" in part && typeof part.text === "string") {
|
|
18660
|
+
return part.text;
|
|
18661
|
+
}
|
|
18662
|
+
if ("parts" in part && Array.isArray(part.parts)) {
|
|
18663
|
+
return part.parts.map(summarizePart).filter(Boolean).join("");
|
|
18664
|
+
}
|
|
18665
|
+
if ("inlineData" in part && part.inlineData && typeof part.inlineData === "object") {
|
|
18666
|
+
return `[${formatPreviewLabel(part.inlineData.mimeType, "binary")}]`;
|
|
18667
|
+
}
|
|
18668
|
+
if ("image_url" in part) {
|
|
18669
|
+
return "[image]";
|
|
18670
|
+
}
|
|
18671
|
+
if ("functionCall" in part && part.functionCall && typeof part.functionCall === "object") {
|
|
18672
|
+
return `[tool: ${formatPreviewLabel(part.functionCall.name, "unknown")}]`;
|
|
18673
|
+
}
|
|
18674
|
+
if ("function_call" in part && part.function_call && typeof part.function_call === "object") {
|
|
18675
|
+
return `[tool: ${formatPreviewLabel(part.function_call.name, "unknown")}]`;
|
|
18676
|
+
}
|
|
18677
|
+
if ("function" in part && part.function && typeof part.function === "object") {
|
|
18678
|
+
return `[tool: ${formatPreviewLabel(part.function.name, "unknown")}]`;
|
|
18679
|
+
}
|
|
18680
|
+
if ("toolName" in part) {
|
|
18681
|
+
return `[tool: ${formatPreviewLabel(part.toolName, "unknown")}]`;
|
|
18682
|
+
}
|
|
18683
|
+
if ("type" in part && typeof part.type === "string") {
|
|
18684
|
+
switch (part.type) {
|
|
18685
|
+
case "image":
|
|
18686
|
+
return "[image]";
|
|
18687
|
+
case "file":
|
|
18688
|
+
return "[file]";
|
|
18689
|
+
case "reasoning":
|
|
18690
|
+
return "[reasoning]";
|
|
18691
|
+
case "tool-call":
|
|
18692
|
+
return `[tool: ${formatPreviewLabel(part.toolName, "unknown")}]`;
|
|
18693
|
+
case "tool-result":
|
|
18694
|
+
return "[tool-result]";
|
|
18695
|
+
default:
|
|
18696
|
+
return `[${part.type}]`;
|
|
18697
|
+
}
|
|
18698
|
+
}
|
|
18699
|
+
if ("content" in part && typeof part.content === "string") {
|
|
18700
|
+
return part.content;
|
|
18701
|
+
}
|
|
18702
|
+
return "[object]";
|
|
18703
|
+
}
|
|
18704
|
+
function summarizeMessageContent(content) {
|
|
18705
|
+
if (typeof content === "string") {
|
|
18706
|
+
return content;
|
|
18707
|
+
}
|
|
18708
|
+
if (Array.isArray(content)) {
|
|
18709
|
+
return content.map(summarizePart).filter(Boolean).join("");
|
|
18710
|
+
}
|
|
18711
|
+
if (content && typeof content === "object") {
|
|
18712
|
+
if ("parts" in content && Array.isArray(content.parts)) {
|
|
18713
|
+
return content.parts.map(summarizePart).filter(Boolean).join("");
|
|
18714
|
+
}
|
|
18715
|
+
return summarizePart(content);
|
|
18716
|
+
}
|
|
18717
|
+
if (content == null) {
|
|
18718
|
+
return "";
|
|
18719
|
+
}
|
|
18720
|
+
return String(content);
|
|
18721
|
+
}
|
|
18722
|
+
function appendToolPreview(preview, toolCalls) {
|
|
18723
|
+
if (!Array.isArray(toolCalls) || toolCalls.length === 0) {
|
|
18724
|
+
return preview;
|
|
18725
|
+
}
|
|
18726
|
+
const toolPreview = toolCalls.map((toolCall) => summarizePart(toolCall)).filter(Boolean).join(" ");
|
|
18727
|
+
if (!toolPreview) {
|
|
18728
|
+
return preview;
|
|
18729
|
+
}
|
|
18730
|
+
return preview ? `${preview} ${toolPreview}` : toolPreview;
|
|
18731
|
+
}
|
|
18732
|
+
function appendPreview(preview, addition) {
|
|
18733
|
+
if (!addition) {
|
|
18734
|
+
return preview;
|
|
18735
|
+
}
|
|
18736
|
+
return preview ? `${preview} ${addition}` : addition;
|
|
18737
|
+
}
|
|
18738
|
+
function normalizeMessages(messages) {
|
|
18739
|
+
return messages.map((message) => {
|
|
18740
|
+
if (!message || typeof message !== "object") {
|
|
18741
|
+
return { role: "user", content: summarizeMessageContent(message) };
|
|
18742
|
+
}
|
|
18743
|
+
const role = typeof message.role === "string" ? message.role : "user";
|
|
18744
|
+
const baseContent = summarizeMessageContent(message.content);
|
|
18745
|
+
const contentWithToolArrays = appendToolPreview(
|
|
18746
|
+
appendToolPreview(baseContent, message.toolCalls),
|
|
18747
|
+
message.tool_calls
|
|
18748
|
+
);
|
|
18749
|
+
const functionCall = message.functionCall;
|
|
18750
|
+
const functionCallPreview = functionCall === void 0 ? "" : summarizePart({ functionCall });
|
|
18751
|
+
const functionCallSnakeCase = message.function_call;
|
|
18752
|
+
const functionCallSnakeCasePreview = functionCallSnakeCase === void 0 ? "" : summarizePart({ function_call: functionCallSnakeCase });
|
|
18753
|
+
const contentWithFunctionCall = appendPreview(
|
|
18754
|
+
appendPreview(contentWithToolArrays, functionCallPreview),
|
|
18755
|
+
functionCallSnakeCasePreview
|
|
18756
|
+
);
|
|
18757
|
+
return { role, content: contentWithFunctionCall };
|
|
18758
|
+
});
|
|
18759
|
+
}
|
|
18760
|
+
function summarizeRequestBody(body) {
|
|
18761
|
+
if (body == null) {
|
|
18762
|
+
return void 0;
|
|
18763
|
+
}
|
|
18764
|
+
if (typeof body !== "object") {
|
|
18765
|
+
return typeof body === "string" ? body : String(body);
|
|
18766
|
+
}
|
|
18767
|
+
if (Array.isArray(body.messages)) {
|
|
18768
|
+
return normalizeMessages(body.messages);
|
|
18769
|
+
}
|
|
18770
|
+
if (Array.isArray(body.contents)) {
|
|
18771
|
+
return body.contents.map((item) => ({
|
|
18772
|
+
role: typeof item?.role === "string" ? item.role : "user",
|
|
18773
|
+
content: Array.isArray(item?.parts) ? item.parts.map(summarizePart).filter(Boolean).join("") : ""
|
|
18774
|
+
}));
|
|
18775
|
+
}
|
|
18776
|
+
const summary = {};
|
|
18777
|
+
if (typeof body.model === "string") {
|
|
18778
|
+
summary.model = body.model;
|
|
18779
|
+
}
|
|
18780
|
+
const bodyKeys = Object.keys(body).filter((key) => key !== "body");
|
|
18781
|
+
if (bodyKeys.length > 0) {
|
|
18782
|
+
summary.keys = bodyKeys;
|
|
18783
|
+
}
|
|
18784
|
+
return Object.keys(summary).length > 0 ? summary : "[request body]";
|
|
18785
|
+
}
|
|
18636
18786
|
function extractStepInput(request) {
|
|
18637
18787
|
if (!request) return void 0;
|
|
18638
18788
|
const { body } = request;
|
|
18639
18789
|
if (body == null) return request;
|
|
18640
18790
|
try {
|
|
18641
18791
|
const parsed = typeof body === "string" ? JSON.parse(body) : body;
|
|
18642
|
-
|
|
18643
|
-
if (Array.isArray(parsed?.contents)) return parsed.contents;
|
|
18644
|
-
return parsed;
|
|
18792
|
+
return summarizeRequestBody(parsed);
|
|
18645
18793
|
} catch {
|
|
18646
18794
|
return request;
|
|
18647
18795
|
}
|
|
@@ -19228,6 +19376,10 @@ var BaseSpan = class {
|
|
|
19228
19376
|
}
|
|
19229
19377
|
const metadata = this.metadata ?? {};
|
|
19230
19378
|
const getMetadataString = (key) => typeof metadata[key] === "string" ? metadata[key] : void 0;
|
|
19379
|
+
const getSpanMetadataString = (span, key) => {
|
|
19380
|
+
const m = span?.metadata;
|
|
19381
|
+
return m && typeof m[key] === "string" ? m[key] : void 0;
|
|
19382
|
+
};
|
|
19231
19383
|
const parentSpan = this.getParentSpan(false);
|
|
19232
19384
|
let rootSpan = this;
|
|
19233
19385
|
while (rootSpan.parent) {
|
|
@@ -19241,12 +19393,15 @@ var BaseSpan = class {
|
|
|
19241
19393
|
entityType: this.entityType,
|
|
19242
19394
|
entityId: this.entityId,
|
|
19243
19395
|
entityName: this.entityName,
|
|
19396
|
+
entityVersionId: getMetadataString("entityVersionId"),
|
|
19244
19397
|
parentEntityType: parentSpan?.entityType,
|
|
19245
19398
|
parentEntityId: parentSpan?.entityId,
|
|
19246
19399
|
parentEntityName: parentSpan?.entityName,
|
|
19400
|
+
parentEntityVersionId: getSpanMetadataString(parentSpan, "entityVersionId"),
|
|
19247
19401
|
rootEntityType: rootSpan.entityType,
|
|
19248
19402
|
rootEntityId: rootSpan.entityId,
|
|
19249
19403
|
rootEntityName: rootSpan.entityName,
|
|
19404
|
+
rootEntityVersionId: getSpanMetadataString(rootSpan, "entityVersionId"),
|
|
19250
19405
|
userId: getMetadataString("userId"),
|
|
19251
19406
|
organizationId: getMetadataString("organizationId"),
|
|
19252
19407
|
resourceId: getMetadataString("resourceId"),
|
|
@@ -19383,7 +19538,10 @@ var DefaultSpan = class extends BaseSpan {
|
|
|
19383
19538
|
domain: error48.domain,
|
|
19384
19539
|
message: error48.message,
|
|
19385
19540
|
name: error48.name,
|
|
19386
|
-
stack
|
|
19541
|
+
// Prefer the original cause's stack when available. MastraError wraps
|
|
19542
|
+
// thrown errors, so its own stack points to the wrapping site rather
|
|
19543
|
+
// than where the underlying error was thrown.
|
|
19544
|
+
stack: error48.cause instanceof Error && error48.cause.stack || error48.stack
|
|
19387
19545
|
} : {
|
|
19388
19546
|
message: error48.message,
|
|
19389
19547
|
name: error48.name,
|