@mastra/observability 1.16.6-alpha.0 → 1.16.6-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/CHANGELOG.md +27 -0
- package/dist/index.cjs +54 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +54 -12
- package/dist/index.js.map +1 -1
- package/dist/model-tracing.d.ts.map +1 -1
- package/dist/spans/base.d.ts +17 -7
- package/dist/spans/base.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1759,6 +1759,34 @@ function addUsageStats(a, b) {
|
|
|
1759
1759
|
function supportsModelInference() {
|
|
1760
1760
|
return coreFeatures.has("model-inference-span");
|
|
1761
1761
|
}
|
|
1762
|
+
function parseGatewayCost(providerMetadata) {
|
|
1763
|
+
const rawCost = providerMetadata?.gateway?.cost;
|
|
1764
|
+
const cost = typeof rawCost === "number" ? rawCost : typeof rawCost === "string" && rawCost.trim().length > 0 ? Number(rawCost) : void 0;
|
|
1765
|
+
return typeof cost === "number" && Number.isFinite(cost) && cost >= 0 ? cost : void 0;
|
|
1766
|
+
}
|
|
1767
|
+
function getGatewayCostContext({ stepProviderMetadata }) {
|
|
1768
|
+
if (!stepProviderMetadata) return;
|
|
1769
|
+
if (!stepProviderMetadata.some((metadata) => metadata?.gateway !== void 0)) return;
|
|
1770
|
+
const costs = [];
|
|
1771
|
+
for (const metadata of stepProviderMetadata) {
|
|
1772
|
+
const cost = parseGatewayCost(metadata);
|
|
1773
|
+
if (cost === void 0) return;
|
|
1774
|
+
costs.push(cost);
|
|
1775
|
+
}
|
|
1776
|
+
const estimatedCost = costs.reduce((total, cost) => total + cost, 0);
|
|
1777
|
+
if (!Number.isFinite(estimatedCost)) return;
|
|
1778
|
+
return {
|
|
1779
|
+
estimatedCost,
|
|
1780
|
+
costUnit: "USD",
|
|
1781
|
+
costMetadata: {
|
|
1782
|
+
source: "provider_reported",
|
|
1783
|
+
sdkProvider: "vercel_ai_gateway",
|
|
1784
|
+
sdkCostField: "gateway.cost",
|
|
1785
|
+
scope: "query_total",
|
|
1786
|
+
reportedStepCount: costs.length
|
|
1787
|
+
}
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1762
1790
|
function formatPreviewLabel(label, fallback) {
|
|
1763
1791
|
return typeof label === "string" && label.length > 0 ? label : fallback;
|
|
1764
1792
|
}
|
|
@@ -1940,10 +1968,11 @@ var ModelSpanTracker = class {
|
|
|
1940
1968
|
* If usage is provided, it will be converted to UsageStats with cache token details.
|
|
1941
1969
|
*/
|
|
1942
1970
|
endGeneration(options) {
|
|
1943
|
-
const { usage, providerMetadata, ...spanOptions } = options ?? {};
|
|
1971
|
+
const { usage, providerMetadata, stepProviderMetadata, ...spanOptions } = options ?? {};
|
|
1944
1972
|
if (spanOptions.attributes) {
|
|
1945
1973
|
spanOptions.attributes.completionStartTime = this.#completionStartTime;
|
|
1946
1974
|
spanOptions.attributes.usage = extractUsageMetrics(usage, providerMetadata);
|
|
1975
|
+
if (!spanOptions.attributes.costContext) spanOptions.attributes.costContext = getGatewayCostContext({ stepProviderMetadata });
|
|
1947
1976
|
}
|
|
1948
1977
|
this.#modelSpan?.end(spanOptions);
|
|
1949
1978
|
}
|
|
@@ -2027,13 +2056,15 @@ var ModelSpanTracker = class {
|
|
|
2027
2056
|
if (!this.#currentInferenceSpan) return;
|
|
2028
2057
|
const { usage: rawUsage, ...otherOutput } = payload.output;
|
|
2029
2058
|
const usage = extractUsageMetrics(rawUsage, payload.metadata?.providerMetadata);
|
|
2059
|
+
const responseModel = typeof payload.metadata?.modelId === "string" ? payload.metadata.modelId : void 0;
|
|
2030
2060
|
this.#currentInferenceSpan.end({
|
|
2031
2061
|
output: otherOutput,
|
|
2032
2062
|
attributes: {
|
|
2033
2063
|
usage,
|
|
2034
2064
|
finishReason: payload.stepResult.reason,
|
|
2035
2065
|
warnings: payload.stepResult.warnings,
|
|
2036
|
-
completionStartTime: this.#completionStartTime
|
|
2066
|
+
completionStartTime: this.#completionStartTime,
|
|
2067
|
+
...responseModel?.trim() ? { responseModel } : {}
|
|
2037
2068
|
}
|
|
2038
2069
|
});
|
|
2039
2070
|
this.#currentInferenceSpan = void 0;
|
|
@@ -2431,12 +2462,12 @@ function isSpanInternal(spanType, flags) {
|
|
|
2431
2462
|
/**
|
|
2432
2463
|
* Get the external parent span ID from CreateSpanOptions.
|
|
2433
2464
|
*
|
|
2434
|
-
* If the parent is internal
|
|
2435
|
-
* the
|
|
2436
|
-
* returns its ID directly.
|
|
2465
|
+
* If the parent is internal or excluded from export (`excludeSpanTypes`),
|
|
2466
|
+
* walks up the parent chain to find the closest exported ancestor.
|
|
2467
|
+
* If the parent is already exportable, returns its ID directly.
|
|
2437
2468
|
*
|
|
2438
2469
|
* This is useful when exporting spans to external observability systems
|
|
2439
|
-
* that shouldn't include internal framework spans.
|
|
2470
|
+
* that shouldn't include internal framework spans or excluded types.
|
|
2440
2471
|
*
|
|
2441
2472
|
* @param options - Span creation options
|
|
2442
2473
|
* @returns The external parent span ID, or undefined if no external parent exists
|
|
@@ -2457,8 +2488,9 @@ function isSpanInternal(spanType, flags) {
|
|
|
2457
2488
|
*/
|
|
2458
2489
|
function getExternalParentId(options) {
|
|
2459
2490
|
if (!options.parent) return;
|
|
2460
|
-
|
|
2461
|
-
|
|
2491
|
+
const parent = options.parent;
|
|
2492
|
+
if (parent.isInternal || parent.isExcluded) return parent.getParentSpanId(false);
|
|
2493
|
+
return parent.id;
|
|
2462
2494
|
}
|
|
2463
2495
|
var BaseSpan = class {
|
|
2464
2496
|
name;
|
|
@@ -2497,6 +2529,10 @@ var BaseSpan = class {
|
|
|
2497
2529
|
* when the span is internal and includeInternalSpans is false, or when
|
|
2498
2530
|
* the subclass is always excluded (e.g., NoOpSpan).
|
|
2499
2531
|
*
|
|
2532
|
+
* Public so parent-chain walks (`getParentSpan`) can skip ancestors that
|
|
2533
|
+
* exporters will never receive — otherwise descendants export a
|
|
2534
|
+
* `parentSpanId` pointing at a dropped span and become orphans.
|
|
2535
|
+
*
|
|
2500
2536
|
* Note: metadata is still attached and deepCleaned because it is read in
|
|
2501
2537
|
* process by getCorrelationContext() and by getLoggerContext() /
|
|
2502
2538
|
* getMetricsContext() (which structuredClone it).
|
|
@@ -2568,14 +2604,20 @@ var BaseSpan = class {
|
|
|
2568
2604
|
get isRootSpan() {
|
|
2569
2605
|
return !this.parent;
|
|
2570
2606
|
}
|
|
2571
|
-
/**
|
|
2607
|
+
/**
|
|
2608
|
+
* Get the closest parent span.
|
|
2609
|
+
* Always skips ancestors dropped by `excludeSpanTypes` (`isExcluded`), so
|
|
2610
|
+
* exported `parentSpanId` values never point at spans exporters omit.
|
|
2611
|
+
* When `includeInternalSpans` is false/undefined, also skips `isInternal`
|
|
2612
|
+
* ancestors.
|
|
2613
|
+
*/
|
|
2572
2614
|
getParentSpan(includeInternalSpans) {
|
|
2573
2615
|
if (!this.parent) return;
|
|
2574
|
-
|
|
2575
|
-
if (
|
|
2616
|
+
const parent = this.parent;
|
|
2617
|
+
if (parent.isExcluded || !includeInternalSpans && parent.isInternal) return parent.getParentSpan(includeInternalSpans);
|
|
2576
2618
|
return this.parent;
|
|
2577
2619
|
}
|
|
2578
|
-
/** Get the closest parent spanId that
|
|
2620
|
+
/** Get the closest parent spanId that will reach exporters (unless includeInternalSpans) */
|
|
2579
2621
|
getParentSpanId(includeInternalSpans) {
|
|
2580
2622
|
if (!this.parent) return this.parentSpanId;
|
|
2581
2623
|
const parentSpan = this.getParentSpan(includeInternalSpans);
|