@mastra/pg 1.30.0-alpha.2 → 1.30.0-alpha.4
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/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +91 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +91 -9
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-aggregate.d.ts.map +1 -1
- package/dist/vector/sql-builder.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/docs/SKILL.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -341,13 +341,9 @@ const FILTER_OPERATORS = {
|
|
|
341
341
|
};
|
|
342
342
|
},
|
|
343
343
|
$exists: (key, paramIndex, value) => {
|
|
344
|
-
const
|
|
345
|
-
if (value === false) return {
|
|
346
|
-
sql: `NOT (metadata ? '${jsonPathKey}')`,
|
|
347
|
-
needsValue: false
|
|
348
|
-
};
|
|
344
|
+
const existsSql = key.includes(".") ? `${getJsonExtractExpr(key)} IS NOT NULL` : `metadata ? '${parseJsonPathKey(key)}'`;
|
|
349
345
|
return {
|
|
350
|
-
sql:
|
|
346
|
+
sql: value === false ? `NOT (${existsSql})` : existsSql,
|
|
351
347
|
needsValue: false
|
|
352
348
|
};
|
|
353
349
|
},
|
|
@@ -18508,13 +18504,32 @@ function compilePostgresTraceAggregate(schema, plan) {
|
|
|
18508
18504
|
if (intervalMs === void 0) throw new Error(`Unsupported trusted trace-aggregate interval: ${plan.interval}`);
|
|
18509
18505
|
factColumns.push(`to_timestamp(floor(EXTRACT(EPOCH FROM r."startedAt") * 1000 / ${intervalMs}) * ${intervalMs} / 1000.0) AS "bucket"`);
|
|
18510
18506
|
}
|
|
18507
|
+
const measureKinds = new Set(plan.measures.map((measure) => measureRule(measure.name)?.kind));
|
|
18508
|
+
const hasCost = measureKinds.has("cost");
|
|
18509
|
+
let usageJoin = "";
|
|
18510
|
+
if (hasCost || measureKinds.has("tokens")) {
|
|
18511
|
+
ctes.push(...compileUsageCtes(schema, plan, param));
|
|
18512
|
+
usageJoin = "\n LEFT JOIN usage u ON u.\"traceId\" = r.\"traceId\"";
|
|
18513
|
+
USAGE_METRIC_NAMES.forEach((_, index) => factColumns.push(`CASE WHEN u."traceId" IS NOT NULL THEN COALESCE(u."t${index}", 0) END AS "t${index}"`));
|
|
18514
|
+
factColumns.push(`u."traceId" IS NOT NULL AS "usageBearing"`, `CASE WHEN u."priced" THEN u."cost" END AS "traceCost"`, `COALESCE(u."priced" AND NOT u."pricingFailure", FALSE) AS "covered"`, `u."unitMin"`, `u."unitMax"`);
|
|
18515
|
+
}
|
|
18511
18516
|
ctes.push(`facts AS (
|
|
18512
18517
|
SELECT ${factColumns.join(",\n ")}
|
|
18513
|
-
FROM candidates r
|
|
18518
|
+
FROM candidates r${usageJoin}
|
|
18514
18519
|
)`);
|
|
18520
|
+
const mixedUnitsSql = (alias) => `MIN(${alias}"unitMin" COLLATE "C") <> MAX(${alias}"unitMax" COLLATE "C")`;
|
|
18515
18521
|
const measureSql = (name, alias = "") => {
|
|
18516
18522
|
const column = (name) => `${alias}"${name}"`;
|
|
18517
18523
|
if (name === "count") return "COUNT(*)::float8";
|
|
18524
|
+
const rule = measureRule(name);
|
|
18525
|
+
if (rule?.kind === "tokens" && rule.metricNames) {
|
|
18526
|
+
const value = rule.metricNames.map((metricName) => column(`t${usageMetricIndex(metricName)}`)).join(" + ");
|
|
18527
|
+
return `(${rule.statistic === "avg" ? "AVG" : "SUM"}(${value}))::float8`;
|
|
18528
|
+
}
|
|
18529
|
+
if (rule?.kind === "cost") {
|
|
18530
|
+
const aggregate = rule.statistic === "avg" ? "AVG" : "SUM";
|
|
18531
|
+
return `(CASE WHEN ${mixedUnitsSql(alias)} THEN NULL ELSE ${aggregate}(${column("traceCost")}) END)::float8`;
|
|
18532
|
+
}
|
|
18518
18533
|
if (name === "errorCount") return `(COUNT(*) FILTER (WHERE ${column("isError")}))::float8`;
|
|
18519
18534
|
if (name === "errorRate") return `(COUNT(*) FILTER (WHERE ${column("isError")}))::float8 / COUNT(*)`;
|
|
18520
18535
|
if (name === "duration.avg") return `AVG(${column("durationMs")})`;
|
|
@@ -18552,8 +18567,17 @@ function compilePostgresTraceAggregate(schema, plan) {
|
|
|
18552
18567
|
const orderSql = [`${orderTarget} ${direction} NULLS LAST`, ...dimensionColumns.map((column) => `${column} COLLATE "C" ASC NULLS LAST`)].join(", ");
|
|
18553
18568
|
const groupSql = dimensionColumns.length > 0 ? dimensionColumns.join(", ") : "()";
|
|
18554
18569
|
const limitParameter = param(plan.limit + 1);
|
|
18570
|
+
const costColumns = (alias) => {
|
|
18571
|
+
if (!hasCost) return [];
|
|
18572
|
+
const mixedUnit = param(_mastra_core_storage.TRACE_AGGREGATE_MIXED_COST_UNIT);
|
|
18573
|
+
return [`(COUNT(*) FILTER (WHERE ${alias}"covered"))::float8 / NULLIF(COUNT(*) FILTER (WHERE ${alias}"usageBearing"), 0) AS "costCoverage"`, `CASE WHEN ${mixedUnitsSql(alias)} THEN ${mixedUnit}::text ELSE MIN(${alias}"unitMin" COLLATE "C") END AS "costUnit"`];
|
|
18574
|
+
};
|
|
18555
18575
|
if (plan.interval === void 0) {
|
|
18556
|
-
const projected = [
|
|
18576
|
+
const projected = [
|
|
18577
|
+
...dimensionColumns,
|
|
18578
|
+
...plan.measures.map((measure, index) => `${measureSql(measure.name)} AS "m${index}"`),
|
|
18579
|
+
...costColumns("")
|
|
18580
|
+
];
|
|
18557
18581
|
return {
|
|
18558
18582
|
text: `WITH ${ctes.join(",\n")}
|
|
18559
18583
|
SELECT ${projected.join(", ")}
|
|
@@ -18579,6 +18603,7 @@ LIMIT ${limitParameter}`,
|
|
|
18579
18603
|
...dimensionColumns.map((column) => `f.${column}`),
|
|
18580
18604
|
"f.\"bucket\"",
|
|
18581
18605
|
...plan.measures.map((measure, index) => `${measureSql(measure.name, "f.")} AS "m${index}"`),
|
|
18606
|
+
...costColumns("f."),
|
|
18582
18607
|
`(SELECT COUNT(*) FROM ranked) > ${maxRankParameter} AS "truncated"`
|
|
18583
18608
|
];
|
|
18584
18609
|
return {
|
|
@@ -18596,6 +18621,59 @@ ORDER BY g."rank" ASC, f."bucket" ASC`,
|
|
|
18596
18621
|
values
|
|
18597
18622
|
};
|
|
18598
18623
|
}
|
|
18624
|
+
const USAGE_METRIC_NAMES = _mastra_core_storage.TRACE_AGGREGATE_USAGE_METRIC_NAMES;
|
|
18625
|
+
function measureRule(name) {
|
|
18626
|
+
return _mastra_core_storage.isTraceAggregateCanonicalMeasure(name) ? _mastra_core_storage.TRACE_AGGREGATE_MEASURE_REGISTRY[name] : void 0;
|
|
18627
|
+
}
|
|
18628
|
+
function usageMetricIndex(name) {
|
|
18629
|
+
const index = USAGE_METRIC_NAMES.indexOf(name);
|
|
18630
|
+
if (index === -1) throw new Error(`Unsupported trusted trace-aggregate token metric: ${name}`);
|
|
18631
|
+
return index;
|
|
18632
|
+
}
|
|
18633
|
+
/**
|
|
18634
|
+
* Builds `usage`: one row per candidate trace that has at least one token metric row, holding
|
|
18635
|
+
* per-name token sums (`t<i>`, indexed by `TRACE_AGGREGATE_USAGE_METRIC_NAMES`) and the trace's
|
|
18636
|
+
* pricing state. Metric rows are matched by traceId, usage metric name, tenant scope, and
|
|
18637
|
+
* `timestamp >= from` only: a trace that starts in the window can emit metrics after `to`, and
|
|
18638
|
+
* the candidates semi-join already bounds the scan.
|
|
18639
|
+
*
|
|
18640
|
+
* Rows are deduplicated on `metricId` alone. The primary key is (`metricId`, `timestamp`)
|
|
18641
|
+
* because the table is partitioned by timestamp, so retried copies with different timestamps
|
|
18642
|
+
* are both stored.
|
|
18643
|
+
*/
|
|
18644
|
+
function compileUsageCtes(schema, plan, param) {
|
|
18645
|
+
const scopeConditions = plan.scope ? [`m."organizationId" = ${param(plan.scope.organizationId)}`, ...plan.scope.resourceId === void 0 ? [] : [`m."resourceId" = ${param(plan.scope.resourceId)}`]] : [];
|
|
18646
|
+
const rowConditions = [
|
|
18647
|
+
`m."traceId" IN (SELECT "traceId" FROM candidates)`,
|
|
18648
|
+
`m."name" = ANY(${param(USAGE_METRIC_NAMES)}::text[])`,
|
|
18649
|
+
`m."timestamp" >= ${param(plan.timeRange.from)}::timestamptz`,
|
|
18650
|
+
...scopeConditions
|
|
18651
|
+
];
|
|
18652
|
+
const costRow = `"name" = ANY(${param(_mastra_core_storage.TRACE_AGGREGATE_COST_METRIC_NAMES)}::text[])`;
|
|
18653
|
+
const priced = `${costRow} AND "estimatedCost" IS NOT NULL AND "costUnit" IS NOT NULL AND NOT "hasError"`;
|
|
18654
|
+
const failed = `${costRow} AND ("hasError" OR ("estimatedCost" IS NOT NULL AND "costUnit" IS NULL))`;
|
|
18655
|
+
const tokenColumns = USAGE_METRIC_NAMES.map((name, index) => `SUM("value") FILTER (WHERE "name" = ${param(name)}) AS "t${index}"`);
|
|
18656
|
+
return [`usage_rows AS (
|
|
18657
|
+
SELECT DISTINCT ON (m."metricId") m."traceId", m."name", m."value", m."estimatedCost", m."costUnit",
|
|
18658
|
+
COALESCE(jsonb_typeof(m."costMetadata" -> 'error'), 'null') <> 'null' AS "hasError"
|
|
18659
|
+
FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)} m
|
|
18660
|
+
WHERE ${rowConditions.join("\n AND ")}
|
|
18661
|
+
ORDER BY m."metricId", m."timestamp"
|
|
18662
|
+
)`, `usage AS (
|
|
18663
|
+
SELECT "traceId",
|
|
18664
|
+
${tokenColumns.join(",\n ")},
|
|
18665
|
+
SUM("estimatedCost") FILTER (WHERE ${priced}) AS "cost",
|
|
18666
|
+
bool_or(${priced}) AS "priced",
|
|
18667
|
+
bool_or(${failed}) AS "pricingFailure",
|
|
18668
|
+
MIN("costUnit" COLLATE "C") FILTER (WHERE ${priced}) AS "unitMin",
|
|
18669
|
+
MAX("costUnit" COLLATE "C") FILTER (WHERE ${priced}) AS "unitMax"
|
|
18670
|
+
FROM usage_rows
|
|
18671
|
+
GROUP BY "traceId"
|
|
18672
|
+
)`];
|
|
18673
|
+
}
|
|
18674
|
+
function nullableNumber(value) {
|
|
18675
|
+
return value === null || value === void 0 ? null : Number(value);
|
|
18676
|
+
}
|
|
18599
18677
|
function toIsoTimestamp(value) {
|
|
18600
18678
|
return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
|
|
18601
18679
|
}
|
|
@@ -18613,7 +18691,11 @@ async function aggregateTraces(client, schema, plan, timeoutMs) {
|
|
|
18613
18691
|
}
|
|
18614
18692
|
return {
|
|
18615
18693
|
rows: resultRows.map((row) => {
|
|
18616
|
-
const shaped = { measures: Object.fromEntries(plan.measures.map((measure, index) => [measure.name,
|
|
18694
|
+
const shaped = { measures: Object.fromEntries(plan.measures.map((measure, index) => [measure.name, nullableNumber(row[`m${index}`])])) };
|
|
18695
|
+
if ("costCoverage" in row) shaped.cost = {
|
|
18696
|
+
coverage: nullableNumber(row.costCoverage),
|
|
18697
|
+
unit: row.costUnit ?? null
|
|
18698
|
+
};
|
|
18617
18699
|
if (plan.dimensions.length > 0) shaped.dimensions = Object.fromEntries(plan.dimensions.map((dimension, index) => [dimension, row[`d${index}`] ?? null]));
|
|
18618
18700
|
if (plan.interval !== void 0) shaped.bucket = toIsoTimestamp(row.bucket);
|
|
18619
18701
|
return shaped;
|