@mastra/duckdb 1.15.0 → 1.16.0-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/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-storage-retention.md +1 -1
- package/dist/{features-BI3qUHJ7.js → features-B8gl38Ue.js} +5 -6
- package/dist/{features-BI3qUHJ7.js.map → features-B8gl38Ue.js.map} +1 -1
- package/dist/{features-CFAYHYYE.cjs → features-DH60yLCA.cjs} +11 -7
- package/dist/{features-CFAYHYYE.cjs.map → features-DH60yLCA.cjs.map} +1 -1
- package/dist/index.cjs +10 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +10 -8
- package/dist/index.js.map +1 -1
- package/dist/{observability-642joQI8.js → observability-Chrw9Di2.js} +192 -86
- package/dist/observability-Chrw9Di2.js.map +1 -0
- package/dist/{observability-C9FRo6K3.cjs → observability-Dlt85fvH.cjs} +192 -86
- package/dist/observability-Dlt85fvH.cjs.map +1 -0
- package/dist/storage/domains/observability/ddl.d.ts +1 -1
- package/dist/storage/domains/observability/ddl.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +3 -2
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/span-query.d.ts +8 -0
- package/dist/storage/domains/observability/span-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/trace-aggregate.d.ts +7 -1
- package/dist/storage/domains/observability/trace-aggregate.d.ts.map +1 -1
- package/dist/storage/domains/observability/tracing.d.ts.map +1 -1
- package/dist/storage/features.d.ts +1 -0
- package/dist/storage/features.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/observability-642joQI8.js.map +0 -1
- package/dist/observability-C9FRo6K3.cjs.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
const require_features = require("./features-
|
|
1
|
+
const require_features = require("./features-DH60yLCA.cjs");
|
|
2
2
|
let _mastra_core_error = require("@mastra/core/error");
|
|
3
3
|
let _mastra_core_storage = require("@mastra/core/storage");
|
|
4
4
|
_mastra_core_storage = require_features.__toESM(_mastra_core_storage, 1);
|
|
5
5
|
let _mastra_core_features = require("@mastra/core/features");
|
|
6
6
|
let _mastra_core_observability = require("@mastra/core/observability");
|
|
7
7
|
let _mastra_core_utils = require("@mastra/core/utils");
|
|
8
|
-
|
|
8
|
+
// src/storage/retention.ts
|
|
9
9
|
function cutoffFor(policy, now = Date.now()) {
|
|
10
10
|
return new Date((0, _mastra_core_storage.retentionCutoffMs)(policy, now));
|
|
11
11
|
}
|
|
@@ -30,8 +30,7 @@ function resolveTargets({ policies, descriptor, order }) {
|
|
|
30
30
|
order
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
//#region src/storage/domains/observability/ddl.ts
|
|
33
|
+
// src/storage/domains/observability/ddl.ts
|
|
35
34
|
/**
|
|
36
35
|
* DDL statements for DuckDB observability tables.
|
|
37
36
|
* All tables use append-only patterns with a single `timestamp` column.
|
|
@@ -80,6 +79,12 @@ CREATE TABLE IF NOT EXISTS span_events (
|
|
|
80
79
|
entityVersionId VARCHAR,
|
|
81
80
|
parentEntityVersionId VARCHAR,
|
|
82
81
|
rootEntityVersionId VARCHAR,
|
|
82
|
+
parentEntityType VARCHAR,
|
|
83
|
+
parentEntityId VARCHAR,
|
|
84
|
+
parentEntityName VARCHAR,
|
|
85
|
+
rootEntityType VARCHAR,
|
|
86
|
+
rootEntityId VARCHAR,
|
|
87
|
+
rootEntityName VARCHAR,
|
|
83
88
|
|
|
84
89
|
-- Context
|
|
85
90
|
userId VARCHAR,
|
|
@@ -372,6 +377,12 @@ const ALL_MIGRATIONS = [
|
|
|
372
377
|
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS hasOutputPayload BOOLEAN`,
|
|
373
378
|
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS hasErrorPayload BOOLEAN`,
|
|
374
379
|
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS timeToFirstChunkMs DOUBLE`,
|
|
380
|
+
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS parentEntityType VARCHAR`,
|
|
381
|
+
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS parentEntityId VARCHAR`,
|
|
382
|
+
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS parentEntityName VARCHAR`,
|
|
383
|
+
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS rootEntityType VARCHAR`,
|
|
384
|
+
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS rootEntityId VARCHAR`,
|
|
385
|
+
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS rootEntityName VARCHAR`,
|
|
375
386
|
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
|
|
376
387
|
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
|
|
377
388
|
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS parentEntityVersionId VARCHAR`,
|
|
@@ -481,8 +492,7 @@ const ALL_MIGRATIONS = [
|
|
|
481
492
|
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS reviewStatus VARCHAR DEFAULT 'needs-review'`,
|
|
482
493
|
`ALTER TABLE feedback_events ALTER COLUMN traceId DROP NOT NULL`
|
|
483
494
|
];
|
|
484
|
-
|
|
485
|
-
//#region src/storage/domains/observability/discovery.ts
|
|
495
|
+
// src/storage/domains/observability/discovery.ts
|
|
486
496
|
function unionDistinctQueries(selects, orderBy) {
|
|
487
497
|
return `${selects.join("\nUNION\n")}\nORDER BY ${orderBy}`;
|
|
488
498
|
}
|
|
@@ -550,8 +560,7 @@ async function getTags(db, args) {
|
|
|
550
560
|
buildSelect("log_events")
|
|
551
561
|
], "tag"), params)).map((r) => r.tag) };
|
|
552
562
|
}
|
|
553
|
-
|
|
554
|
-
//#region src/storage/domains/observability/filters.ts
|
|
563
|
+
// src/storage/domains/observability/filters.ts
|
|
555
564
|
function buildJsonPath(key) {
|
|
556
565
|
try {
|
|
557
566
|
return `$.${(0, _mastra_core_utils.parseFieldKey)(key)}`;
|
|
@@ -701,8 +710,7 @@ function buildPaginationClause(pagination) {
|
|
|
701
710
|
params: [pagination.perPage, offset]
|
|
702
711
|
};
|
|
703
712
|
}
|
|
704
|
-
|
|
705
|
-
//#region src/storage/domains/observability/preview-compat.ts
|
|
713
|
+
// src/storage/domains/observability/preview-compat.ts
|
|
706
714
|
const generator = _mastra_core_storage.buildStoredPreview;
|
|
707
715
|
const canGeneratePreviews = typeof generator === "function";
|
|
708
716
|
/** SQL detection only; preview formatting stays in TypeScript. Empty strings are intentional. */
|
|
@@ -759,8 +767,7 @@ function buildSpanQueryResponse(...args) {
|
|
|
759
767
|
}
|
|
760
768
|
return response;
|
|
761
769
|
}
|
|
762
|
-
|
|
763
|
-
//#region src/storage/domains/observability/helpers.ts
|
|
770
|
+
// src/storage/domains/observability/helpers.ts
|
|
764
771
|
/** Shorthand for {@link DuckDBConnection.sqlValue}. */
|
|
765
772
|
const v = require_features.DuckDBConnection.sqlValue;
|
|
766
773
|
/** Serialize a value to JSON then SQL-escape it, or return 'NULL'. */
|
|
@@ -852,8 +859,7 @@ function previewFromPayload(value) {
|
|
|
852
859
|
function apiPreview(value) {
|
|
853
860
|
return readPreview(value);
|
|
854
861
|
}
|
|
855
|
-
|
|
856
|
-
//#region src/storage/domains/observability/polling.ts
|
|
862
|
+
// src/storage/domains/observability/polling.ts
|
|
857
863
|
const OBSERVABILITY_DELTA_POLLING_FEATURE = "observability-delta-polling";
|
|
858
864
|
function deltaPollingFeatureEnabled() {
|
|
859
865
|
return _mastra_core_features.coreFeatures.has(OBSERVABILITY_DELTA_POLLING_FEATURE);
|
|
@@ -885,8 +891,7 @@ function extendWhereClause(baseClause, extraConditions) {
|
|
|
885
891
|
if (!baseClause) return `WHERE ${conditions.join(" AND ")}`;
|
|
886
892
|
return `${baseClause} AND ${conditions.join(" AND ")}`;
|
|
887
893
|
}
|
|
888
|
-
|
|
889
|
-
//#region src/storage/domains/observability/review-status.ts
|
|
894
|
+
// src/storage/domains/observability/review-status.ts
|
|
890
895
|
const FEEDBACK_REVIEW_STATUSES = ["needs-review", "reviewed"];
|
|
891
896
|
function isFeedbackReviewStatus(value) {
|
|
892
897
|
return FEEDBACK_REVIEW_STATUSES.some((status) => status === value);
|
|
@@ -910,8 +915,7 @@ function parseUpdateFeedbackReviewStatusArgs(args) {
|
|
|
910
915
|
reviewStatus: args.reviewStatus
|
|
911
916
|
};
|
|
912
917
|
}
|
|
913
|
-
|
|
914
|
-
//#region src/storage/domains/observability/feedback.ts
|
|
918
|
+
// src/storage/domains/observability/feedback.ts
|
|
915
919
|
const FEEDBACK_UPSERT_CLAUSE = `ON CONFLICT (feedbackId) DO UPDATE SET ${[
|
|
916
920
|
"timestamp",
|
|
917
921
|
"cursorId",
|
|
@@ -1440,8 +1444,7 @@ async function getFeedbackPercentiles(db, args) {
|
|
|
1440
1444
|
}
|
|
1441
1445
|
return { series };
|
|
1442
1446
|
}
|
|
1443
|
-
|
|
1444
|
-
//#region src/storage/domains/observability/logs.ts
|
|
1447
|
+
// src/storage/domains/observability/logs.ts
|
|
1445
1448
|
const COLUMNS_SQL$1 = [
|
|
1446
1449
|
"logId",
|
|
1447
1450
|
"timestamp",
|
|
@@ -1624,8 +1627,7 @@ async function getDeltaCursor$2(db, filterClause, filterParams) {
|
|
|
1624
1627
|
async function getStreamHeadCursor$2(db) {
|
|
1625
1628
|
return encodeDeltaCursor((await db.query(`SELECT max(cursorId) AS cursorId FROM log_events`))[0]?.cursorId);
|
|
1626
1629
|
}
|
|
1627
|
-
|
|
1628
|
-
//#region src/storage/domains/observability/metrics.ts
|
|
1630
|
+
// src/storage/domains/observability/metrics.ts
|
|
1629
1631
|
const METRIC_FILTER_FIELD_MAPPINGS = {
|
|
1630
1632
|
traceIds: "traceId",
|
|
1631
1633
|
experimentIds: "experimentId"
|
|
@@ -2158,8 +2160,7 @@ async function getMetricLabelValues(db, args) {
|
|
|
2158
2160
|
if (args.limit) params.push(args.limit);
|
|
2159
2161
|
return { values: (await db.query(`SELECT DISTINCT json_extract_string(labels, ?) AS val FROM metric_events WHERE ${conditions.join(" AND ")} ORDER BY val ${limitClause}`, [labelPath, ...params])).map((r) => r.val) };
|
|
2160
2162
|
}
|
|
2161
|
-
|
|
2162
|
-
//#region src/storage/domains/observability/migration.ts
|
|
2163
|
+
// src/storage/domains/observability/migration.ts
|
|
2163
2164
|
const CURSOR_ID_TABLES = [
|
|
2164
2165
|
"span_events",
|
|
2165
2166
|
"metric_events",
|
|
@@ -2308,8 +2309,7 @@ async function migrateSignalTables(db, logger) {
|
|
|
2308
2309
|
}
|
|
2309
2310
|
}
|
|
2310
2311
|
}
|
|
2311
|
-
|
|
2312
|
-
//#region src/storage/domains/observability/scores.ts
|
|
2312
|
+
// src/storage/domains/observability/scores.ts
|
|
2313
2313
|
const SCORE_UPSERT_CLAUSE = `ON CONFLICT (scoreId) DO UPDATE SET ${[
|
|
2314
2314
|
"timestamp",
|
|
2315
2315
|
"traceId",
|
|
@@ -2820,8 +2820,7 @@ async function getScorePercentiles(db, args) {
|
|
|
2820
2820
|
}
|
|
2821
2821
|
return { series };
|
|
2822
2822
|
}
|
|
2823
|
-
|
|
2824
|
-
//#region src/storage/domains/observability/trace-query.ts
|
|
2823
|
+
// src/storage/domains/observability/trace-query.ts
|
|
2825
2824
|
const TRACE_STATUS_SQL = `CASE WHEN r.error IS NOT NULL THEN 'error' ELSE 'success' END`;
|
|
2826
2825
|
function durationMsSql(startedAt, endedAt) {
|
|
2827
2826
|
return `date_diff('millisecond', ${startedAt}, ${endedAt})`;
|
|
@@ -3948,23 +3947,15 @@ function compileThreadQueryPredicate(predicate) {
|
|
|
3948
3947
|
parameterType: rule.valueKind === "timestamp" ? "timestamp" : "scalar"
|
|
3949
3948
|
}])));
|
|
3950
3949
|
}
|
|
3951
|
-
|
|
3952
|
-
//#region src/storage/domains/observability/span-query.ts
|
|
3950
|
+
// src/storage/domains/observability/span-query.ts
|
|
3953
3951
|
const identityFields = [
|
|
3954
3952
|
"organizationId",
|
|
3955
3953
|
"resourceId",
|
|
3956
3954
|
"traceId",
|
|
3957
3955
|
"spanId"
|
|
3958
3956
|
];
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
"parentEntityId",
|
|
3962
|
-
"parentEntityName",
|
|
3963
|
-
"rootEntityType",
|
|
3964
|
-
"rootEntityId",
|
|
3965
|
-
"rootEntityName",
|
|
3966
|
-
"executionSource"
|
|
3967
|
-
]);
|
|
3957
|
+
/** Span rows store the execution source as `source`. */
|
|
3958
|
+
const columnSql = (field) => field === "executionSource" ? "e.source AS executionSource" : `e.${field}`;
|
|
3968
3959
|
const identities = identityFields.join(", ");
|
|
3969
3960
|
const fields = [
|
|
3970
3961
|
...identityFields,
|
|
@@ -4028,7 +4019,11 @@ function afterCursor(plan) {
|
|
|
4028
4019
|
values
|
|
4029
4020
|
};
|
|
4030
4021
|
}
|
|
4031
|
-
|
|
4022
|
+
/**
|
|
4023
|
+
* The spans `querySpans()` selects, as CTEs ending in `selected`: the current completed copy of
|
|
4024
|
+
* each span that started in the window and matches `where`. Values are in placeholder order.
|
|
4025
|
+
*/
|
|
4026
|
+
function compileDuckDBSpanSelection(plan) {
|
|
4032
4027
|
const values = [plan.timeRange.from, plan.timeRange.to];
|
|
4033
4028
|
const scope = [];
|
|
4034
4029
|
if (plan.scope) {
|
|
@@ -4043,28 +4038,44 @@ function compileDuckDBSpanQuery(plan) {
|
|
|
4043
4038
|
sql: "TRUE",
|
|
4044
4039
|
values: []
|
|
4045
4040
|
};
|
|
4046
|
-
|
|
4047
|
-
values.push(plan.timeRange.from, plan.timeRange.to, ...predicate.values, ...after.values, plan.limit + 1);
|
|
4041
|
+
values.push(plan.timeRange.from, plan.timeRange.to, ...predicate.values);
|
|
4048
4042
|
const join = identityFields.map((field) => `e.${field} IS NOT DISTINCT FROM c.${field}`).join(" AND ");
|
|
4043
|
+
const partition = identityFields.map((field) => `e.${field}`).join(", ");
|
|
4049
4044
|
const legacyModelFields = _mastra_core_storage.SPAN_QUERY_FIELD_REGISTRY ? "" : `CASE WHEN json_type(e.attributes, '$.model') = 'VARCHAR' THEN json_extract_string(e.attributes, '$.model') END AS model,
|
|
4050
4045
|
CASE WHEN json_type(e.attributes, '$.provider') = 'VARCHAR' THEN json_extract_string(e.attributes, '$.provider') END AS provider,`;
|
|
4051
4046
|
return {
|
|
4052
|
-
|
|
4047
|
+
ctes: [
|
|
4048
|
+
`candidates AS MATERIALIZED (
|
|
4053
4049
|
SELECT ${identities} FROM span_events
|
|
4054
4050
|
WHERE eventType = 'start' AND timestamp >= CAST(? AS TIMESTAMP) AND timestamp < CAST(? AS TIMESTAMP)
|
|
4055
4051
|
${scope.length ? `AND ${scope.join(" AND ")}` : ""}
|
|
4056
4052
|
GROUP BY ${identities}
|
|
4057
|
-
)
|
|
4058
|
-
|
|
4059
|
-
|
|
4053
|
+
)`,
|
|
4054
|
+
`span_versions AS (
|
|
4055
|
+
SELECT ${fields.map(columnSql).join(", ")},
|
|
4056
|
+
min(e.timestamp) FILTER (WHERE e.eventType = 'start') OVER (PARTITION BY ${partition}) AS startedAt, e.endedAt, e.cursorId,
|
|
4060
4057
|
${legacyModelFields}
|
|
4061
|
-
date_diff('millisecond', min(e.timestamp) FILTER (WHERE e.eventType = 'start') OVER (PARTITION BY ${
|
|
4058
|
+
date_diff('millisecond', min(e.timestamp) FILTER (WHERE e.eventType = 'start') OVER (PARTITION BY ${partition}), e.endedAt) AS durationMs,
|
|
4062
4059
|
CASE WHEN e.error IS NULL THEN 'success' ELSE 'error' END AS status,
|
|
4063
4060
|
CASE WHEN e.error IS NULL THEN NULL ELSE 'error' END AS error,
|
|
4064
|
-
row_number() OVER (PARTITION BY ${
|
|
4061
|
+
row_number() OVER (PARTITION BY ${partition}
|
|
4065
4062
|
ORDER BY CASE WHEN e.endedAt IS NULL THEN 1 ELSE 0 END, e.cursorId DESC NULLS LAST, e.endedAt DESC) AS rank
|
|
4066
4063
|
FROM span_events e INNER JOIN candidates c ON ${join}
|
|
4067
|
-
)
|
|
4064
|
+
)`,
|
|
4065
|
+
`selected AS (
|
|
4066
|
+
SELECT * FROM span_versions s
|
|
4067
|
+
WHERE rank = 1 AND endedAt IS NOT NULL AND startedAt >= CAST(? AS TIMESTAMP) AND startedAt < CAST(? AS TIMESTAMP) AND (${predicate.sql})
|
|
4068
|
+
)`
|
|
4069
|
+
],
|
|
4070
|
+
values
|
|
4071
|
+
};
|
|
4072
|
+
}
|
|
4073
|
+
function compileDuckDBSpanQuery(plan) {
|
|
4074
|
+
const { ctes, values } = compileDuckDBSpanSelection(plan);
|
|
4075
|
+
const after = afterCursor(plan);
|
|
4076
|
+
values.push(...after.values, plan.limit + 1);
|
|
4077
|
+
return {
|
|
4078
|
+
sql: `WITH ${ctes.join(", ")}
|
|
4068
4079
|
SELECT ${[
|
|
4069
4080
|
...fields,
|
|
4070
4081
|
"startedAt",
|
|
@@ -4073,7 +4084,7 @@ function compileDuckDBSpanQuery(plan) {
|
|
|
4073
4084
|
"status",
|
|
4074
4085
|
"cursorId"
|
|
4075
4086
|
].map((field) => `s.${field}`).join(", ")}
|
|
4076
|
-
FROM
|
|
4087
|
+
FROM selected s WHERE ${after.sql}
|
|
4077
4088
|
ORDER BY s.${plan.orderBy.field} ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"} NULLS LAST, ${identityFields.map((field) => `s.${field} ASC NULLS LAST`).join(", ")}
|
|
4078
4089
|
LIMIT ?`,
|
|
4079
4090
|
values
|
|
@@ -4153,8 +4164,7 @@ async function querySpans(db, plan) {
|
|
|
4153
4164
|
}
|
|
4154
4165
|
return buildSpanQueryResponse(plan, hydrated, payloads, metrics);
|
|
4155
4166
|
}
|
|
4156
|
-
|
|
4157
|
-
//#region src/storage/domains/observability/thread-query.ts
|
|
4167
|
+
// src/storage/domains/observability/thread-query.ts
|
|
4158
4168
|
const contextFields = [
|
|
4159
4169
|
"resourceId",
|
|
4160
4170
|
"userId",
|
|
@@ -4404,8 +4414,7 @@ async function queryThreadRows(db, plan, strategy = "auto") {
|
|
|
4404
4414
|
}) : null }
|
|
4405
4415
|
};
|
|
4406
4416
|
}
|
|
4407
|
-
|
|
4408
|
-
//#region src/storage/domains/observability/trace-aggregate.ts
|
|
4417
|
+
// src/storage/domains/observability/trace-aggregate.ts
|
|
4409
4418
|
/** Trace-root column expressions (alias `r`) for each groupable dimension; same values `where` sees. */
|
|
4410
4419
|
const DIMENSION_SQL = {
|
|
4411
4420
|
entityType: "r.entityType",
|
|
@@ -4416,7 +4425,7 @@ const DIMENSION_SQL = {
|
|
|
4416
4425
|
environment: "r.environment",
|
|
4417
4426
|
status: TRACE_STATUS_SQL,
|
|
4418
4427
|
serviceName: "r.serviceName",
|
|
4419
|
-
executionSource: "r.
|
|
4428
|
+
executionSource: "r.source",
|
|
4420
4429
|
threadId: "r.threadId",
|
|
4421
4430
|
resourceId: "r.resourceId",
|
|
4422
4431
|
userId: "r.userId",
|
|
@@ -4424,6 +4433,28 @@ const DIMENSION_SQL = {
|
|
|
4424
4433
|
organizationId: "r.organizationId",
|
|
4425
4434
|
experimentId: "r.experimentId"
|
|
4426
4435
|
};
|
|
4436
|
+
/** Span column expressions (alias `r`, a `selected` span row) for each groupable span dimension. */
|
|
4437
|
+
const SPAN_DIMENSION_SQL = Object.fromEntries([
|
|
4438
|
+
"name",
|
|
4439
|
+
"spanType",
|
|
4440
|
+
"entityType",
|
|
4441
|
+
"entityId",
|
|
4442
|
+
"entityName",
|
|
4443
|
+
"parentEntityType",
|
|
4444
|
+
"parentEntityName",
|
|
4445
|
+
"rootEntityType",
|
|
4446
|
+
"rootEntityName",
|
|
4447
|
+
"environment",
|
|
4448
|
+
"status",
|
|
4449
|
+
"serviceName",
|
|
4450
|
+
"executionSource",
|
|
4451
|
+
"threadId",
|
|
4452
|
+
"resourceId",
|
|
4453
|
+
"userId",
|
|
4454
|
+
"sessionId",
|
|
4455
|
+
"organizationId",
|
|
4456
|
+
"experimentId"
|
|
4457
|
+
].map((field) => [field, `r.${field}`]));
|
|
4427
4458
|
const PERCENTILES = {
|
|
4428
4459
|
"duration.p50": .5,
|
|
4429
4460
|
"duration.p90": .9,
|
|
@@ -4440,18 +4471,47 @@ const COMPARISON_SQL = {
|
|
|
4440
4471
|
};
|
|
4441
4472
|
function compileDuckDBTraceAggregate(plan, options = {}) {
|
|
4442
4473
|
const { ctes, values } = compileDuckDBTraceCandidates(plan, "r.*");
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4474
|
+
return compileDuckDBAggregate(plan, options, {
|
|
4475
|
+
ctes,
|
|
4476
|
+
values,
|
|
4477
|
+
from: "candidates",
|
|
4478
|
+
dimensionSql: (field) => {
|
|
4479
|
+
if (field.startsWith("metadata.")) return {
|
|
4480
|
+
sql: TRACE_METADATA_VALUE_SQL,
|
|
4481
|
+
values: traceMetadataPathValues(field.slice(9))
|
|
4482
|
+
};
|
|
4483
|
+
return {
|
|
4484
|
+
sql: lookupDimensionSql(DIMENSION_SQL, field),
|
|
4485
|
+
values: []
|
|
4486
|
+
};
|
|
4487
|
+
},
|
|
4488
|
+
usageKey: ["traceId"]
|
|
4489
|
+
});
|
|
4490
|
+
}
|
|
4491
|
+
/**
|
|
4492
|
+
* Compiles a trusted span aggregate plan over the spans `querySpans()` selects. Usage is
|
|
4493
|
+
* attributed by `(traceId, spanId)`, so only the span that recorded a metric row carries it.
|
|
4494
|
+
*/
|
|
4495
|
+
function compileDuckDBSpanAggregate(plan, options = {}) {
|
|
4496
|
+
const { ctes, values } = compileDuckDBSpanSelection(plan);
|
|
4497
|
+
return compileDuckDBAggregate(plan, options, {
|
|
4498
|
+
ctes,
|
|
4499
|
+
values,
|
|
4500
|
+
from: "selected",
|
|
4501
|
+
dimensionSql: (field) => ({
|
|
4502
|
+
sql: lookupDimensionSql(SPAN_DIMENSION_SQL, field),
|
|
4452
4503
|
values: []
|
|
4453
|
-
}
|
|
4454
|
-
|
|
4504
|
+
}),
|
|
4505
|
+
usageKey: ["traceId", "spanId"]
|
|
4506
|
+
});
|
|
4507
|
+
}
|
|
4508
|
+
function lookupDimensionSql(columns, field) {
|
|
4509
|
+
const sql = Object.hasOwn(columns, field) ? columns[field] : void 0;
|
|
4510
|
+
if (sql === void 0) throw new Error(`Unsupported trusted aggregate field: ${field}`);
|
|
4511
|
+
return sql;
|
|
4512
|
+
}
|
|
4513
|
+
function compileDuckDBAggregate(plan, options, source) {
|
|
4514
|
+
const { ctes, values, dimensionSql } = source;
|
|
4455
4515
|
const distinctSql = (field) => field === "traceId" ? {
|
|
4456
4516
|
sql: "r.traceId",
|
|
4457
4517
|
values: []
|
|
@@ -4482,16 +4542,18 @@ function compileDuckDBTraceAggregate(plan, options = {}) {
|
|
|
4482
4542
|
const hasCost = measureKinds.has("cost");
|
|
4483
4543
|
if (!hasCost && !measureKinds.has("tokens")) ctes.push(`facts AS (
|
|
4484
4544
|
SELECT ${factColumns.join(",\n ")}
|
|
4485
|
-
FROM
|
|
4545
|
+
FROM ${source.from} r
|
|
4486
4546
|
)`);
|
|
4487
4547
|
else {
|
|
4548
|
+
const keyColumns = source.usageKey.map((key) => `r.${key}`).join(", ");
|
|
4488
4549
|
ctes.push(`base_facts AS (
|
|
4489
|
-
SELECT
|
|
4490
|
-
FROM
|
|
4550
|
+
SELECT ${keyColumns}, ${factColumns.join(",\n ")}
|
|
4551
|
+
FROM ${source.from} r
|
|
4491
4552
|
)`);
|
|
4492
4553
|
ctes.push(...compileUsageCtes(plan, values, {
|
|
4493
4554
|
hasCost,
|
|
4494
|
-
dedupe: !options.metricIdsUnique
|
|
4555
|
+
dedupe: !options.metricIdsUnique,
|
|
4556
|
+
key: source.usageKey
|
|
4495
4557
|
}));
|
|
4496
4558
|
const usageColumns = USAGE_METRIC_NAMES.map((_, index) => `CASE WHEN u.traceId IS NOT NULL THEN COALESCE(u.t${index}, 0) END AS t${index}`);
|
|
4497
4559
|
usageColumns.push(`u.traceId IS NOT NULL AS usageBearing`);
|
|
@@ -4500,7 +4562,7 @@ function compileDuckDBTraceAggregate(plan, options = {}) {
|
|
|
4500
4562
|
SELECT b.*,
|
|
4501
4563
|
${usageColumns.join(",\n ")}
|
|
4502
4564
|
FROM base_facts b
|
|
4503
|
-
LEFT JOIN usage u ON
|
|
4565
|
+
LEFT JOIN usage u ON ${source.usageKey.map((key) => `u.${key} = b.${key}`).join(" AND ")}
|
|
4504
4566
|
)`);
|
|
4505
4567
|
}
|
|
4506
4568
|
const measureSql = (name, alias = "") => {
|
|
@@ -4622,8 +4684,8 @@ function costColumns(alias) {
|
|
|
4622
4684
|
return [`CAST(count_if(${alias}covered) AS DOUBLE) / NULLIF(count_if(${alias}usageBearing), 0) AS costCoverage`, `CASE WHEN ${mixedUnitsSql(alias)} THEN '${mixed}' ELSE min(${alias}unitMin) END AS costUnit`];
|
|
4623
4685
|
}
|
|
4624
4686
|
/**
|
|
4625
|
-
* Builds `usage_bounds`, `usage_rows`, and `usage`: one row per
|
|
4626
|
-
* one token metric row, holding per-name token sums (`t<i>`, indexed by
|
|
4687
|
+
* Builds `usage_bounds`, `usage_rows`, and `usage`: one row per population row (trace, or span)
|
|
4688
|
+
* that has at least one token metric row, keyed by the source's usage key, holding per-name token sums (`t<i>`, indexed by
|
|
4627
4689
|
* `TRACE_AGGREGATE_USAGE_METRIC_NAMES`) and, for cost requests, the trace's pricing state. Metric
|
|
4628
4690
|
* rows are matched by traceId, usage metric name, tenant scope, and `timestamp >= from` only: a
|
|
4629
4691
|
* trace that starts in the window can emit metrics after `to`, and the semi-join bounds the scan.
|
|
@@ -4637,7 +4699,7 @@ function costColumns(alias) {
|
|
|
4637
4699
|
*
|
|
4638
4700
|
* Placeholders are bound in text order: `param` pushes each value as its placeholder is emitted.
|
|
4639
4701
|
*/
|
|
4640
|
-
function compileUsageCtes(plan, values, { hasCost, dedupe }) {
|
|
4702
|
+
function compileUsageCtes(plan, values, { hasCost, dedupe, key }) {
|
|
4641
4703
|
const param = (value) => {
|
|
4642
4704
|
values.push(value);
|
|
4643
4705
|
return "?";
|
|
@@ -4664,9 +4726,10 @@ function compileUsageCtes(plan, values, { hasCost, dedupe }) {
|
|
|
4664
4726
|
CASE WHEN m.name IN (${list(costNames)})
|
|
4665
4727
|
THEN COALESCE(json_type(m.costMetadata, '$.error'), 'NULL') <> 'NULL'
|
|
4666
4728
|
ELSE FALSE
|
|
4667
|
-
END AS hasError
|
|
4729
|
+
END AS hasError,
|
|
4730
|
+
COALESCE(json_extract_string(m.costMetadata, '$.error') = 'partial_cost', FALSE) AS partialCost` : "";
|
|
4668
4731
|
const rows = `usage_rows AS (
|
|
4669
|
-
SELECT ${dedupe ? "DISTINCT ON (m.metricId) " : ""}m.
|
|
4732
|
+
SELECT ${dedupe ? "DISTINCT ON (m.metricId) " : ""}${key.map((column) => `m.${column}`).join(", ")}, m.name, m.value${costSelect}
|
|
4670
4733
|
FROM metric_events m
|
|
4671
4734
|
WHERE m.timestamp >= (SELECT minTs FROM usage_bounds)
|
|
4672
4735
|
AND m.timestamp <= (SELECT maxTs FROM usage_bounds)
|
|
@@ -4675,17 +4738,17 @@ function compileUsageCtes(plan, values, { hasCost, dedupe }) {
|
|
|
4675
4738
|
)`;
|
|
4676
4739
|
const columns = USAGE_METRIC_NAMES.map((name) => `sum(value) FILTER (WHERE name = ${param(name)})`).map((sql, index) => `${sql} AS t${index}`);
|
|
4677
4740
|
if (hasCost) {
|
|
4678
|
-
const priced = "costRow AND estimatedCost IS NOT NULL AND costUnit IS NOT NULL AND NOT hasError";
|
|
4741
|
+
const priced = "costRow AND estimatedCost IS NOT NULL AND costUnit IS NOT NULL AND (NOT hasError OR partialCost)";
|
|
4679
4742
|
columns.push(`sum(estimatedCost) FILTER (WHERE ${priced}) AS cost`, `bool_or(${priced}) AS priced`, `bool_or(costRow AND (hasError OR (estimatedCost IS NOT NULL AND costUnit IS NULL))) AS pricingFailure`, `min(costUnit) FILTER (WHERE ${priced}) AS unitMin`, `max(costUnit) FILTER (WHERE ${priced}) AS unitMax`);
|
|
4680
4743
|
}
|
|
4681
4744
|
return [
|
|
4682
4745
|
bounds,
|
|
4683
4746
|
rows,
|
|
4684
4747
|
`usage AS (
|
|
4685
|
-
SELECT
|
|
4748
|
+
SELECT ${key.join(", ")},
|
|
4686
4749
|
${columns.join(",\n ")}
|
|
4687
4750
|
FROM usage_rows
|
|
4688
|
-
GROUP BY
|
|
4751
|
+
GROUP BY ${key.join(", ")}
|
|
4689
4752
|
)`
|
|
4690
4753
|
];
|
|
4691
4754
|
}
|
|
@@ -4693,7 +4756,12 @@ function nullableNumber(value) {
|
|
|
4693
4756
|
return value === null || value === void 0 ? null : Number(value);
|
|
4694
4757
|
}
|
|
4695
4758
|
async function aggregateTraces(db, plan, options = {}) {
|
|
4696
|
-
|
|
4759
|
+
return runAggregate(db, plan, compileDuckDBTraceAggregate(plan, options));
|
|
4760
|
+
}
|
|
4761
|
+
async function aggregateSpans(db, plan, options = {}) {
|
|
4762
|
+
return runAggregate(db, plan, compileDuckDBSpanAggregate(plan, options));
|
|
4763
|
+
}
|
|
4764
|
+
async function runAggregate(db, plan, compiled) {
|
|
4697
4765
|
let result;
|
|
4698
4766
|
try {
|
|
4699
4767
|
result = await db.query(compiled.sql, compiled.values);
|
|
@@ -4727,8 +4795,7 @@ async function aggregateTraces(db, plan, options = {}) {
|
|
|
4727
4795
|
truncated
|
|
4728
4796
|
};
|
|
4729
4797
|
}
|
|
4730
|
-
|
|
4731
|
-
//#region src/storage/domains/observability/tracing.ts
|
|
4798
|
+
// src/storage/domains/observability/tracing.ts
|
|
4732
4799
|
const COLUMNS_SQL = [
|
|
4733
4800
|
"eventType",
|
|
4734
4801
|
"timestamp",
|
|
@@ -4748,6 +4815,12 @@ const COLUMNS_SQL = [
|
|
|
4748
4815
|
"entityVersionId",
|
|
4749
4816
|
"parentEntityVersionId",
|
|
4750
4817
|
"rootEntityVersionId",
|
|
4818
|
+
"parentEntityType",
|
|
4819
|
+
"parentEntityId",
|
|
4820
|
+
"parentEntityName",
|
|
4821
|
+
"rootEntityType",
|
|
4822
|
+
"rootEntityId",
|
|
4823
|
+
"rootEntityName",
|
|
4751
4824
|
"userId",
|
|
4752
4825
|
"organizationId",
|
|
4753
4826
|
"resourceId",
|
|
@@ -4826,6 +4899,12 @@ const SPAN_RECONSTRUCT_SELECT = `
|
|
|
4826
4899
|
${argMaxNonNull("entityVersionId")},
|
|
4827
4900
|
${argMaxNonNull("parentEntityVersionId")},
|
|
4828
4901
|
${argMaxNonNull("rootEntityVersionId")},
|
|
4902
|
+
${argMaxNonNull("parentEntityType")},
|
|
4903
|
+
${argMaxNonNull("parentEntityId")},
|
|
4904
|
+
${argMaxNonNull("parentEntityName")},
|
|
4905
|
+
${argMaxNonNull("rootEntityType")},
|
|
4906
|
+
${argMaxNonNull("rootEntityId")},
|
|
4907
|
+
${argMaxNonNull("rootEntityName")},
|
|
4829
4908
|
${argMaxNonNull("userId")},
|
|
4830
4909
|
${argMaxNonNull("organizationId")},
|
|
4831
4910
|
${argMaxNonNull("resourceId")},
|
|
@@ -5056,6 +5135,12 @@ function rowToSpanRecord(row) {
|
|
|
5056
5135
|
entityVersionId: row.entityVersionId ?? null,
|
|
5057
5136
|
parentEntityVersionId: row.parentEntityVersionId ?? null,
|
|
5058
5137
|
rootEntityVersionId: row.rootEntityVersionId ?? null,
|
|
5138
|
+
parentEntityType: row.parentEntityType ?? null,
|
|
5139
|
+
parentEntityId: row.parentEntityId ?? null,
|
|
5140
|
+
parentEntityName: row.parentEntityName ?? null,
|
|
5141
|
+
rootEntityType: row.rootEntityType ?? null,
|
|
5142
|
+
rootEntityId: row.rootEntityId ?? null,
|
|
5143
|
+
rootEntityName: row.rootEntityName ?? null,
|
|
5059
5144
|
userId: row.userId ?? null,
|
|
5060
5145
|
organizationId: row.organizationId ?? null,
|
|
5061
5146
|
resourceId: row.resourceId ?? null,
|
|
@@ -5236,6 +5321,12 @@ function toValuesTuple(row) {
|
|
|
5236
5321
|
v(row.entityVersionId),
|
|
5237
5322
|
v(row.parentEntityVersionId),
|
|
5238
5323
|
v(row.rootEntityVersionId),
|
|
5324
|
+
v(row.parentEntityType),
|
|
5325
|
+
v(row.parentEntityId),
|
|
5326
|
+
v(row.parentEntityName),
|
|
5327
|
+
v(row.rootEntityType),
|
|
5328
|
+
v(row.rootEntityId),
|
|
5329
|
+
v(row.rootEntityName),
|
|
5239
5330
|
v(row.userId),
|
|
5240
5331
|
v(row.organizationId),
|
|
5241
5332
|
v(row.resourceId),
|
|
@@ -5289,6 +5380,12 @@ function createStartSpanRow(s) {
|
|
|
5289
5380
|
entityVersionId: s.entityVersionId ?? null,
|
|
5290
5381
|
parentEntityVersionId: s.parentEntityVersionId ?? null,
|
|
5291
5382
|
rootEntityVersionId: s.rootEntityVersionId ?? null,
|
|
5383
|
+
parentEntityType: s.parentEntityType ?? null,
|
|
5384
|
+
parentEntityId: s.parentEntityId ?? null,
|
|
5385
|
+
parentEntityName: s.parentEntityName ?? null,
|
|
5386
|
+
rootEntityType: s.rootEntityType ?? null,
|
|
5387
|
+
rootEntityId: s.rootEntityId ?? null,
|
|
5388
|
+
rootEntityName: s.rootEntityName ?? null,
|
|
5292
5389
|
userId: s.userId ?? null,
|
|
5293
5390
|
organizationId: s.organizationId ?? null,
|
|
5294
5391
|
resourceId: s.resourceId ?? null,
|
|
@@ -5338,6 +5435,12 @@ function createEndSpanRow(s) {
|
|
|
5338
5435
|
entityVersionId: s.entityVersionId ?? null,
|
|
5339
5436
|
parentEntityVersionId: s.parentEntityVersionId ?? null,
|
|
5340
5437
|
rootEntityVersionId: s.rootEntityVersionId ?? null,
|
|
5438
|
+
parentEntityType: s.parentEntityType ?? null,
|
|
5439
|
+
parentEntityId: s.parentEntityId ?? null,
|
|
5440
|
+
parentEntityName: s.parentEntityName ?? null,
|
|
5441
|
+
rootEntityType: s.rootEntityType ?? null,
|
|
5442
|
+
rootEntityId: s.rootEntityId ?? null,
|
|
5443
|
+
rootEntityName: s.rootEntityName ?? null,
|
|
5341
5444
|
userId: s.userId ?? null,
|
|
5342
5445
|
organizationId: s.organizationId ?? null,
|
|
5343
5446
|
resourceId: s.resourceId ?? null,
|
|
@@ -6046,8 +6149,7 @@ async function getBranchStreamHeadCursor(db, userSpanType) {
|
|
|
6046
6149
|
if (userSpanType) return encodeDeltaCursor((await db.query(`SELECT max(cursorId) AS cursorId FROM span_events WHERE eventType = 'start' AND spanType = ? AND cursorId IS NOT NULL`, [userSpanType]))[0]?.cursorId);
|
|
6047
6150
|
return encodeDeltaCursor((await db.query(`SELECT max(cursorId) AS cursorId FROM span_events WHERE eventType = 'start' AND spanType IN (${BRANCH_SPAN_TYPE_PLACEHOLDERS}) AND cursorId IS NOT NULL`, [..._mastra_core_storage.BRANCH_SPAN_TYPES]))[0]?.cursorId);
|
|
6048
6151
|
}
|
|
6049
|
-
|
|
6050
|
-
//#region src/storage/domains/observability/index.ts
|
|
6152
|
+
// src/storage/domains/observability/index.ts
|
|
6051
6153
|
function buildSignalMigrationRequiredMessage(args) {
|
|
6052
6154
|
return `
|
|
6053
6155
|
===========================================================================
|
|
@@ -6181,6 +6283,7 @@ var ObservabilityStorageDuckDB = class ObservabilityStorageDuckDB extends _mastr
|
|
|
6181
6283
|
"trace-query",
|
|
6182
6284
|
"trace-aggregate",
|
|
6183
6285
|
...require_features.spanQueryFeatures,
|
|
6286
|
+
...require_features.spanAggregateFeatures,
|
|
6184
6287
|
...typeof _mastra_core_storage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
|
|
6185
6288
|
"trace-query-root-duration",
|
|
6186
6289
|
"trace-query-discovery",
|
|
@@ -6205,6 +6308,7 @@ var ObservabilityStorageDuckDB = class ObservabilityStorageDuckDB extends _mastr
|
|
|
6205
6308
|
"trace-query",
|
|
6206
6309
|
"trace-aggregate",
|
|
6207
6310
|
...require_features.spanQueryFeatures,
|
|
6311
|
+
...require_features.spanAggregateFeatures,
|
|
6208
6312
|
...typeof _mastra_core_storage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
|
|
6209
6313
|
"trace-query-root-duration",
|
|
6210
6314
|
"trace-query-discovery",
|
|
@@ -6253,6 +6357,9 @@ var ObservabilityStorageDuckDB = class ObservabilityStorageDuckDB extends _mastr
|
|
|
6253
6357
|
async aggregateTraces(plan) {
|
|
6254
6358
|
return aggregateTraces(this.db, plan, { metricIdsUnique: this.metricIdsUnique });
|
|
6255
6359
|
}
|
|
6360
|
+
async aggregateSpans(plan) {
|
|
6361
|
+
return aggregateSpans(this.db, plan, { metricIdsUnique: this.metricIdsUnique });
|
|
6362
|
+
}
|
|
6256
6363
|
async getTraceQueryObservedFields(plan) {
|
|
6257
6364
|
return getTraceQueryObservedFields(this.db, plan);
|
|
6258
6365
|
}
|
|
@@ -6373,7 +6480,6 @@ var ObservabilityStorageDuckDB = class ObservabilityStorageDuckDB extends _mastr
|
|
|
6373
6480
|
return getFeedbackPercentiles(this.db, args);
|
|
6374
6481
|
}
|
|
6375
6482
|
};
|
|
6376
|
-
//#endregion
|
|
6377
6483
|
exports.ObservabilityStorageDuckDB = ObservabilityStorageDuckDB;
|
|
6378
6484
|
|
|
6379
|
-
//# sourceMappingURL=observability-
|
|
6485
|
+
//# sourceMappingURL=observability-Dlt85fvH.cjs.map
|