@mastra/clickhouse 1.20.0-alpha.2 → 1.20.0-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/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +241 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +241 -44
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts +8 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/score-current.d.ts +3 -0
- package/dist/storage/domains/observability/v-next/score-current.d.ts.map +1 -0
- package/dist/storage/domains/observability/v-next/scores.d.ts +1 -0
- package/dist/storage/domains/observability/v-next/scores.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +1 -0
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/tracing.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-clickhouse
|
|
|
3
3
|
description: Documentation for @mastra/clickhouse. Use when working with @mastra/clickhouse APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/clickhouse"
|
|
6
|
-
version: "1.20.0-alpha.
|
|
6
|
+
version: "1.20.0-alpha.3"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
package/dist/index.cjs
CHANGED
|
@@ -2569,6 +2569,8 @@ const TABLE_TRACE_BRANCHES_DELTA = "mastra_trace_branches_delta";
|
|
|
2569
2569
|
const TABLE_METRIC_EVENTS = "mastra_metric_events";
|
|
2570
2570
|
const TABLE_LOG_EVENTS = "mastra_log_events";
|
|
2571
2571
|
const TABLE_SCORE_EVENTS = "mastra_score_events";
|
|
2572
|
+
const TABLE_SCORE_EVENTS_CURRENT = "mastra_score_events_current";
|
|
2573
|
+
const TABLE_SCORE_EVENTS_CURRENT_BACKFILL = "mastra_score_events_current_backfill";
|
|
2572
2574
|
const TABLE_FEEDBACK_EVENTS = "mastra_feedback_events";
|
|
2573
2575
|
const TABLE_DELETION_REQUESTS = "mastra_deletion_requests";
|
|
2574
2576
|
const TABLE_METRIC_EVENTS_DELTA = "mastra_metric_events_delta";
|
|
@@ -2584,6 +2586,7 @@ const MV_TRACE_BRANCHES_DELTA = "mastra_mv_trace_branches_delta";
|
|
|
2584
2586
|
const MV_METRIC_EVENTS_DELTA = "mastra_mv_metric_events_delta";
|
|
2585
2587
|
const MV_LOG_EVENTS_DELTA = "mastra_mv_log_events_delta";
|
|
2586
2588
|
const MV_SCORE_EVENTS_DELTA = "mastra_mv_score_events_delta";
|
|
2589
|
+
const MV_SCORE_EVENTS_CURRENT = "mastra_mv_score_events_current";
|
|
2587
2590
|
const MV_FEEDBACK_EVENTS_DELTA = "mastra_mv_feedback_events_delta";
|
|
2588
2591
|
const MV_DISCOVERY_VALUES = "mastra_mv_discovery_values";
|
|
2589
2592
|
const MV_DISCOVERY_PAIRS = "mastra_mv_discovery_pairs";
|
|
@@ -3101,19 +3104,53 @@ FROM (
|
|
|
3101
3104
|
)
|
|
3102
3105
|
`;
|
|
3103
3106
|
}
|
|
3104
|
-
const
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
+
const SCORE_EVENT_COLUMN_NAMES = [
|
|
3108
|
+
"timestamp",
|
|
3109
|
+
"scoreId",
|
|
3110
|
+
"writeVersion",
|
|
3111
|
+
"traceId",
|
|
3112
|
+
"spanId",
|
|
3113
|
+
"experimentId",
|
|
3114
|
+
"scoreTraceId",
|
|
3115
|
+
"entityType",
|
|
3116
|
+
"entityId",
|
|
3117
|
+
"entityName",
|
|
3118
|
+
"entityVersionId",
|
|
3119
|
+
"parentEntityVersionId",
|
|
3120
|
+
"parentEntityType",
|
|
3121
|
+
"parentEntityId",
|
|
3122
|
+
"parentEntityName",
|
|
3123
|
+
"rootEntityVersionId",
|
|
3124
|
+
"rootEntityType",
|
|
3125
|
+
"rootEntityId",
|
|
3126
|
+
"rootEntityName",
|
|
3127
|
+
"userId",
|
|
3128
|
+
"organizationId",
|
|
3129
|
+
"resourceId",
|
|
3130
|
+
"runId",
|
|
3131
|
+
"sessionId",
|
|
3132
|
+
"threadId",
|
|
3133
|
+
"requestId",
|
|
3134
|
+
"environment",
|
|
3135
|
+
"executionSource",
|
|
3136
|
+
"serviceName",
|
|
3137
|
+
"scorerId",
|
|
3138
|
+
"scorerVersion",
|
|
3139
|
+
"scoreSource",
|
|
3140
|
+
"score",
|
|
3141
|
+
"reason",
|
|
3142
|
+
"tags",
|
|
3143
|
+
"metadata",
|
|
3144
|
+
"scope"
|
|
3145
|
+
];
|
|
3146
|
+
const SCORE_EVENT_COLUMNS_DDL = `
|
|
3107
3147
|
timestamp DateTime64(3, 'UTC'),
|
|
3108
|
-
|
|
3109
|
-
-- IDs
|
|
3110
3148
|
scoreId String,
|
|
3149
|
+
writeVersion UInt64 DEFAULT 0,
|
|
3111
3150
|
traceId Nullable(String),
|
|
3112
3151
|
spanId Nullable(String),
|
|
3113
3152
|
experimentId Nullable(String),
|
|
3114
3153
|
scoreTraceId Nullable(String),
|
|
3115
|
-
|
|
3116
|
-
-- Entity hierarchy
|
|
3117
3154
|
entityType LowCardinality(Nullable(String)),
|
|
3118
3155
|
entityId Nullable(String),
|
|
3119
3156
|
entityName Nullable(String),
|
|
@@ -3126,8 +3163,6 @@ CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS} (
|
|
|
3126
3163
|
rootEntityType LowCardinality(Nullable(String)),
|
|
3127
3164
|
rootEntityId Nullable(String),
|
|
3128
3165
|
rootEntityName Nullable(String),
|
|
3129
|
-
|
|
3130
|
-
-- Context
|
|
3131
3166
|
userId Nullable(String),
|
|
3132
3167
|
organizationId Nullable(String),
|
|
3133
3168
|
resourceId Nullable(String),
|
|
@@ -3138,30 +3173,48 @@ CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS} (
|
|
|
3138
3173
|
environment LowCardinality(Nullable(String)),
|
|
3139
3174
|
executionSource LowCardinality(Nullable(String)),
|
|
3140
3175
|
serviceName LowCardinality(Nullable(String)),
|
|
3141
|
-
|
|
3142
|
-
-- Scorer identity
|
|
3143
3176
|
scorerId LowCardinality(String),
|
|
3144
3177
|
scorerVersion LowCardinality(Nullable(String)),
|
|
3145
3178
|
scoreSource LowCardinality(Nullable(String)),
|
|
3146
|
-
|
|
3147
|
-
-- Score value
|
|
3148
3179
|
score Float64,
|
|
3149
|
-
|
|
3150
|
-
-- Information-only
|
|
3151
3180
|
reason Nullable(String),
|
|
3152
|
-
|
|
3153
|
-
-- Query-relevant flexible fields
|
|
3154
3181
|
tags Array(LowCardinality(String)) DEFAULT [],
|
|
3155
|
-
|
|
3156
|
-
-- Information-only JSON payloads
|
|
3157
3182
|
metadata Nullable(String),
|
|
3158
3183
|
scope Nullable(String)
|
|
3184
|
+
`;
|
|
3185
|
+
const SCORE_EVENTS_DDL = `
|
|
3186
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS} (
|
|
3187
|
+
${SCORE_EVENT_COLUMNS_DDL},
|
|
3188
|
+
INDEX idx_scoreId scoreId TYPE bloom_filter(0.01) GRANULARITY 1
|
|
3159
3189
|
)
|
|
3160
3190
|
ENGINE = ReplacingMergeTree
|
|
3161
3191
|
PARTITION BY toDate(timestamp)
|
|
3162
3192
|
ORDER BY (traceId, timestamp, scoreId)
|
|
3163
3193
|
SETTINGS allow_nullable_key = 1
|
|
3164
3194
|
`;
|
|
3195
|
+
const SCORE_EVENTS_CURRENT_DDL = `
|
|
3196
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS_CURRENT} (
|
|
3197
|
+
${SCORE_EVENT_COLUMNS_DDL}
|
|
3198
|
+
)
|
|
3199
|
+
ENGINE = ReplacingMergeTree(writeVersion)
|
|
3200
|
+
PARTITION BY cityHash64(scoreId) % 64
|
|
3201
|
+
ORDER BY scoreId
|
|
3202
|
+
`;
|
|
3203
|
+
const SCORE_EVENTS_CURRENT_BACKFILL_DDL = `
|
|
3204
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS_CURRENT_BACKFILL} (
|
|
3205
|
+
marker String,
|
|
3206
|
+
completedAt DateTime64(3, 'UTC')
|
|
3207
|
+
)
|
|
3208
|
+
ENGINE = ReplacingMergeTree(completedAt)
|
|
3209
|
+
ORDER BY marker
|
|
3210
|
+
`;
|
|
3211
|
+
const SCORE_EVENTS_CURRENT_MV_DDL = `
|
|
3212
|
+
CREATE MATERIALIZED VIEW IF NOT EXISTS ${MV_SCORE_EVENTS_CURRENT}
|
|
3213
|
+
TO ${TABLE_SCORE_EVENTS_CURRENT}
|
|
3214
|
+
AS
|
|
3215
|
+
SELECT ${SCORE_EVENT_COLUMN_NAMES.join(", ")}
|
|
3216
|
+
FROM ${TABLE_SCORE_EVENTS}
|
|
3217
|
+
`;
|
|
3165
3218
|
function buildScoreEventsDeltaDDL() {
|
|
3166
3219
|
return `
|
|
3167
3220
|
CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS_DELTA} (
|
|
@@ -3435,6 +3488,8 @@ const BASE_TABLE_DDL = [
|
|
|
3435
3488
|
METRIC_EVENTS_DDL,
|
|
3436
3489
|
LOG_EVENTS_DDL,
|
|
3437
3490
|
SCORE_EVENTS_DDL,
|
|
3491
|
+
SCORE_EVENTS_CURRENT_DDL,
|
|
3492
|
+
SCORE_EVENTS_CURRENT_BACKFILL_DDL,
|
|
3438
3493
|
FEEDBACK_EVENTS_DDL,
|
|
3439
3494
|
DELETION_REQUESTS_DDL,
|
|
3440
3495
|
DISCOVERY_VALUES_DDL,
|
|
@@ -3453,7 +3508,11 @@ function buildDeltaTableDDL() {
|
|
|
3453
3508
|
function buildAllTableDDL() {
|
|
3454
3509
|
return [...BASE_TABLE_DDL, ...buildDeltaTableDDL()];
|
|
3455
3510
|
}
|
|
3456
|
-
const BASE_MV_DDL = [
|
|
3511
|
+
const BASE_MV_DDL = [
|
|
3512
|
+
TRACE_ROOTS_MV_DDL,
|
|
3513
|
+
TRACE_BRANCHES_MV_DDL,
|
|
3514
|
+
SCORE_EVENTS_CURRENT_MV_DDL
|
|
3515
|
+
];
|
|
3457
3516
|
function buildDeltaMvDDL(strategy) {
|
|
3458
3517
|
return [
|
|
3459
3518
|
buildTraceRootsDeltaMvDDL(strategy),
|
|
@@ -3475,11 +3534,11 @@ const addColumn = (table, name, type) => ({
|
|
|
3475
3534
|
name,
|
|
3476
3535
|
sql: `ALTER TABLE ${table} ADD COLUMN IF NOT EXISTS ${name} ${type}`
|
|
3477
3536
|
});
|
|
3478
|
-
const addBloomIndex = (table, name, column) => ({
|
|
3537
|
+
const addBloomIndex = (table, name, column, granularity = 2) => ({
|
|
3479
3538
|
kind: "index",
|
|
3480
3539
|
table,
|
|
3481
3540
|
name,
|
|
3482
|
-
sql: `ALTER TABLE ${table} ADD INDEX IF NOT EXISTS ${name} ${column} TYPE bloom_filter(0.01) GRANULARITY
|
|
3541
|
+
sql: `ALTER TABLE ${table} ADD INDEX IF NOT EXISTS ${name} ${column} TYPE bloom_filter(0.01) GRANULARITY ${granularity}`
|
|
3483
3542
|
});
|
|
3484
3543
|
const ALL_MIGRATIONS = [
|
|
3485
3544
|
addColumn(TABLE_SPAN_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
@@ -3494,9 +3553,11 @@ const ALL_MIGRATIONS = [
|
|
|
3494
3553
|
addColumn(TABLE_LOG_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3495
3554
|
addColumn(TABLE_LOG_EVENTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3496
3555
|
addColumn(TABLE_LOG_EVENTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3556
|
+
addColumn(TABLE_SCORE_EVENTS, "writeVersion", "UInt64 DEFAULT 0"),
|
|
3497
3557
|
addColumn(TABLE_SCORE_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3498
3558
|
addColumn(TABLE_SCORE_EVENTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3499
3559
|
addColumn(TABLE_SCORE_EVENTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3560
|
+
addBloomIndex(TABLE_SCORE_EVENTS, "idx_scoreId", "scoreId", 1),
|
|
3500
3561
|
addColumn(TABLE_FEEDBACK_EVENTS, "writeVersion", "UInt64 DEFAULT 0"),
|
|
3501
3562
|
addColumn(TABLE_FEEDBACK_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3502
3563
|
addColumn(TABLE_FEEDBACK_EVENTS, "reviewStatus", "LowCardinality(String) DEFAULT 'needs-review'"),
|
|
@@ -3522,6 +3583,8 @@ const ALL_TABLE_NAMES = [
|
|
|
3522
3583
|
TABLE_METRIC_EVENTS,
|
|
3523
3584
|
TABLE_LOG_EVENTS,
|
|
3524
3585
|
TABLE_SCORE_EVENTS,
|
|
3586
|
+
TABLE_SCORE_EVENTS_CURRENT,
|
|
3587
|
+
TABLE_SCORE_EVENTS_CURRENT_BACKFILL,
|
|
3525
3588
|
TABLE_FEEDBACK_EVENTS,
|
|
3526
3589
|
TABLE_DELETION_REQUESTS,
|
|
3527
3590
|
TABLE_METRIC_EVENTS_DELTA,
|
|
@@ -3539,6 +3602,7 @@ const SIGNAL_TTL_COLUMNS = {
|
|
|
3539
3602
|
[TABLE_METRIC_EVENTS]: "timestamp",
|
|
3540
3603
|
[TABLE_LOG_EVENTS]: "timestamp",
|
|
3541
3604
|
[TABLE_SCORE_EVENTS]: "timestamp",
|
|
3605
|
+
[TABLE_SCORE_EVENTS_CURRENT]: "timestamp",
|
|
3542
3606
|
[TABLE_FEEDBACK_EVENTS]: "timestamp"
|
|
3543
3607
|
};
|
|
3544
3608
|
/** Maps each signal key to the table(s) it controls. */
|
|
@@ -3550,7 +3614,7 @@ const SIGNAL_TO_TABLES = {
|
|
|
3550
3614
|
],
|
|
3551
3615
|
logs: [TABLE_LOG_EVENTS],
|
|
3552
3616
|
metrics: [TABLE_METRIC_EVENTS],
|
|
3553
|
-
scores: [TABLE_SCORE_EVENTS],
|
|
3617
|
+
scores: [TABLE_SCORE_EVENTS, TABLE_SCORE_EVENTS_CURRENT],
|
|
3554
3618
|
feedback: [TABLE_FEEDBACK_EVENTS]
|
|
3555
3619
|
};
|
|
3556
3620
|
const RETENTION_MANAGED_TABLES = [...Object.keys(SIGNAL_TTL_COLUMNS), TABLE_DELETION_REQUESTS];
|
|
@@ -5970,6 +6034,36 @@ async function migrateSignalTables(client, logger) {
|
|
|
5970
6034
|
}
|
|
5971
6035
|
}
|
|
5972
6036
|
//#endregion
|
|
6037
|
+
//#region src/storage/domains/observability/v-next/score-current.ts
|
|
6038
|
+
const SCORE_CURRENT_BACKFILL_MARKER = "v1";
|
|
6039
|
+
async function backfillCurrentScores(client) {
|
|
6040
|
+
const markerRows = await (await client.query({
|
|
6041
|
+
query: `SELECT count() AS count
|
|
6042
|
+
FROM ${TABLE_SCORE_EVENTS_CURRENT_BACKFILL} FINAL
|
|
6043
|
+
WHERE marker = {marker:String}`,
|
|
6044
|
+
query_params: { marker: SCORE_CURRENT_BACKFILL_MARKER },
|
|
6045
|
+
format: "JSONEachRow"
|
|
6046
|
+
})).json();
|
|
6047
|
+
if (Number(markerRows[0]?.count ?? 0) > 0) return;
|
|
6048
|
+
const columns = SCORE_EVENT_COLUMN_NAMES.join(", ");
|
|
6049
|
+
await client.command({
|
|
6050
|
+
query: `INSERT INTO ${TABLE_SCORE_EVENTS_CURRENT} (${columns})
|
|
6051
|
+
SELECT ${columns}
|
|
6052
|
+
FROM (
|
|
6053
|
+
SELECT *, cityHash64(tuple(*)) AS _currentScoreFingerprint
|
|
6054
|
+
FROM ${TABLE_SCORE_EVENTS} FINAL
|
|
6055
|
+
ORDER BY scoreId, writeVersion DESC, timestamp DESC, _currentScoreFingerprint DESC
|
|
6056
|
+
LIMIT 1 BY scoreId
|
|
6057
|
+
)`,
|
|
6058
|
+
clickhouse_settings: { max_bytes_ratio_before_external_sort: .5 }
|
|
6059
|
+
});
|
|
6060
|
+
await client.command({
|
|
6061
|
+
query: `INSERT INTO ${TABLE_SCORE_EVENTS_CURRENT_BACKFILL} (marker, completedAt)
|
|
6062
|
+
VALUES ({marker:String}, now64(3, 'UTC'))`,
|
|
6063
|
+
query_params: { marker: SCORE_CURRENT_BACKFILL_MARKER }
|
|
6064
|
+
});
|
|
6065
|
+
}
|
|
6066
|
+
//#endregion
|
|
5973
6067
|
//#region src/storage/domains/observability/v-next/scores.ts
|
|
5974
6068
|
const SCORE_TYPED_COLUMNS = /* @__PURE__ */ new Set([
|
|
5975
6069
|
"timestamp",
|
|
@@ -6046,6 +6140,13 @@ function mergeFilters(...parts) {
|
|
|
6046
6140
|
function toWhereClause(filter) {
|
|
6047
6141
|
return filter.conditions.length ? `WHERE ${filter.conditions.join(" AND ")}` : "";
|
|
6048
6142
|
}
|
|
6143
|
+
function currentScoresRelation(sourcePredicate) {
|
|
6144
|
+
return `(
|
|
6145
|
+
SELECT *
|
|
6146
|
+
FROM ${TABLE_SCORE_EVENTS_CURRENT} FINAL
|
|
6147
|
+
${sourcePredicate ? `WHERE ${sourcePredicate}` : ""}
|
|
6148
|
+
)`;
|
|
6149
|
+
}
|
|
6049
6150
|
function buildScoreIdentityFilter(args) {
|
|
6050
6151
|
const conditions = ["scorerId = {olapScorerId:String}"];
|
|
6051
6152
|
const params = { olapScorerId: args.scorerId };
|
|
@@ -6081,6 +6182,24 @@ async function queryJson(client, query, params) {
|
|
|
6081
6182
|
clickhouse_settings: CH_SETTINGS
|
|
6082
6183
|
})).json();
|
|
6083
6184
|
}
|
|
6185
|
+
async function scoreRowsWithWriteVersions(client, scores) {
|
|
6186
|
+
const scoreIds = [...new Set(scores.flatMap((score) => score.scoreId ? [score.scoreId] : []))];
|
|
6187
|
+
const existingVersions = [];
|
|
6188
|
+
const lookupBatchSize = 1e3;
|
|
6189
|
+
for (let offset = 0; offset < scoreIds.length; offset += lookupBatchSize) existingVersions.push(...await queryJson(client, `SELECT scoreId, toString(max(writeVersion)) AS writeVersion
|
|
6190
|
+
FROM ${TABLE_SCORE_EVENTS}
|
|
6191
|
+
WHERE scoreId IN ({scoreIds:Array(String)})
|
|
6192
|
+
GROUP BY scoreId`, { scoreIds: scoreIds.slice(offset, offset + lookupBatchSize) }));
|
|
6193
|
+
const versions = new Map(existingVersions.map((row) => [row.scoreId, BigInt(row.writeVersion)]));
|
|
6194
|
+
return scores.map((score) => {
|
|
6195
|
+
const writeVersion = score.scoreId ? (versions.get(score.scoreId) ?? 0n) + 1n : 1n;
|
|
6196
|
+
if (score.scoreId) versions.set(score.scoreId, writeVersion);
|
|
6197
|
+
return {
|
|
6198
|
+
...scoreRecordToRow(score),
|
|
6199
|
+
writeVersion: writeVersion.toString()
|
|
6200
|
+
};
|
|
6201
|
+
});
|
|
6202
|
+
}
|
|
6084
6203
|
async function createScore(client, args) {
|
|
6085
6204
|
await batchCreateScores(client, { scores: [args.score] });
|
|
6086
6205
|
}
|
|
@@ -6088,7 +6207,7 @@ async function batchCreateScores(client, args) {
|
|
|
6088
6207
|
if (args.scores.length === 0) return;
|
|
6089
6208
|
await client.insert({
|
|
6090
6209
|
table: TABLE_SCORE_EVENTS,
|
|
6091
|
-
values: args.scores
|
|
6210
|
+
values: await scoreRowsWithWriteVersions(client, args.scores),
|
|
6092
6211
|
format: "JSONEachRow",
|
|
6093
6212
|
clickhouse_settings: CH_INSERT_SETTINGS
|
|
6094
6213
|
});
|
|
@@ -6131,10 +6250,11 @@ async function deleteScores(client, args, replication) {
|
|
|
6131
6250
|
conditions.push("resourceId = {delResourceId:String}");
|
|
6132
6251
|
params.delResourceId = args.resourceId;
|
|
6133
6252
|
}
|
|
6134
|
-
|
|
6135
|
-
|
|
6253
|
+
const clickhouse_settings = { lightweight_deletes_sync: isReplicationConfigured(replication) ? "2" : "1" };
|
|
6254
|
+
for (const table of [TABLE_SCORE_EVENTS_CURRENT, TABLE_SCORE_EVENTS]) await client.command({
|
|
6255
|
+
query: `DELETE FROM ${table} WHERE ${conditions.join(" AND ")}`,
|
|
6136
6256
|
query_params: params,
|
|
6137
|
-
clickhouse_settings
|
|
6257
|
+
clickhouse_settings
|
|
6138
6258
|
});
|
|
6139
6259
|
}
|
|
6140
6260
|
async function listScores(client, args, strategy) {
|
|
@@ -6168,8 +6288,9 @@ async function listScores(client, args, strategy) {
|
|
|
6168
6288
|
};
|
|
6169
6289
|
}
|
|
6170
6290
|
const currentDeltaCursor = deltaCursorEnabled ? await getDeltaCursor$2(client, whereClause, filter.params) : void 0;
|
|
6171
|
-
const
|
|
6172
|
-
const
|
|
6291
|
+
const scoresRelation = currentScoresRelation();
|
|
6292
|
+
const countResult = await queryJson(client, `SELECT count() AS total FROM ${scoresRelation} AS s ${whereClause}`, filter.params);
|
|
6293
|
+
const rows = await queryJson(client, `SELECT * FROM ${scoresRelation} AS s ${whereClause} ORDER BY ${orderBy} LIMIT {limit:UInt32} OFFSET {offset:UInt32}`, {
|
|
6173
6294
|
...filter.params,
|
|
6174
6295
|
limit: pagination.limit,
|
|
6175
6296
|
offset: pagination.offset
|
|
@@ -6228,14 +6349,15 @@ function buildScoresCursor(row) {
|
|
|
6228
6349
|
return row.cursorId ?? "0";
|
|
6229
6350
|
}
|
|
6230
6351
|
async function getScoreById(client, scoreId) {
|
|
6231
|
-
const rows = await queryJson(client, `SELECT * FROM ${
|
|
6352
|
+
const rows = await queryJson(client, `SELECT * FROM ${currentScoresRelation("scoreId = {scoreId:String}")} LIMIT 1`, { scoreId });
|
|
6232
6353
|
return rows[0] ? rowToScoreRecord(rows[0]) : null;
|
|
6233
6354
|
}
|
|
6234
6355
|
async function getScoreAggregate(client, args) {
|
|
6235
6356
|
const aggSql = getAggregationSql(args.aggregation);
|
|
6236
6357
|
const identity = buildScoreIdentityFilter(args);
|
|
6237
6358
|
const combined = mergeFilters(identity, buildScoresFilterConditions(args.filters));
|
|
6238
|
-
const
|
|
6359
|
+
const whereClause = toWhereClause(combined);
|
|
6360
|
+
const result = await queryJson(client, `SELECT ${aggSql} AS value FROM ${currentScoresRelation()} ${whereClause}`, combined.params);
|
|
6239
6361
|
const value = result[0]?.value == null ? null : Number(result[0]?.value);
|
|
6240
6362
|
if (args.comparePeriod && args.filters?.timestamp) {
|
|
6241
6363
|
const ts = args.filters.timestamp;
|
|
@@ -6269,7 +6391,8 @@ async function getScoreAggregate(client, args) {
|
|
|
6269
6391
|
endExclusive: ts.endExclusive
|
|
6270
6392
|
}
|
|
6271
6393
|
}));
|
|
6272
|
-
const
|
|
6394
|
+
const prevWhereClause = toWhereClause(prevCombined);
|
|
6395
|
+
const prevResult = await queryJson(client, `SELECT ${aggSql} AS value FROM ${currentScoresRelation()} ${prevWhereClause}`, prevCombined.params);
|
|
6273
6396
|
const previousValue = prevResult[0]?.value == null ? null : Number(prevResult[0]?.value);
|
|
6274
6397
|
let changePercent = null;
|
|
6275
6398
|
if (previousValue !== null && previousValue !== 0 && value !== null) changePercent = (value - previousValue) / Math.abs(previousValue) * 100;
|
|
@@ -6287,7 +6410,7 @@ async function getScoreBreakdown(client, args) {
|
|
|
6287
6410
|
const combined = mergeFilters(buildScoreIdentityFilter(args), buildScoresFilterConditions(args.filters));
|
|
6288
6411
|
const whereClause = toWhereClause(combined);
|
|
6289
6412
|
const resolved = resolveScoreGroupBy(args.groupBy);
|
|
6290
|
-
return { groups: (await queryJson(client, `SELECT ${resolved.map((e) => e.selectSql).join(", ")}, ${aggSql} AS value FROM ${
|
|
6413
|
+
return { groups: (await queryJson(client, `SELECT ${resolved.map((e) => e.selectSql).join(", ")}, ${aggSql} AS value FROM ${currentScoresRelation()} ${whereClause} GROUP BY ${resolved.map((e) => e.groupSql).join(", ")} ORDER BY value DESC`, combined.params)).map((row) => ({
|
|
6291
6414
|
dimensions: Object.fromEntries(resolved.map((entry, index) => {
|
|
6292
6415
|
const v = row[`group_by_${index}`];
|
|
6293
6416
|
return [entry.key, v == null ? null : String(v)];
|
|
@@ -6306,7 +6429,7 @@ async function getScoreTimeSeries(client, args) {
|
|
|
6306
6429
|
SELECT toStartOfInterval(timestamp, ${intervalSql}) AS bucket,
|
|
6307
6430
|
${resolved.map((e) => e.selectSql).join(", ")},
|
|
6308
6431
|
${aggSql} AS value
|
|
6309
|
-
FROM ${
|
|
6432
|
+
FROM ${currentScoresRelation()} ${whereClause}
|
|
6310
6433
|
GROUP BY bucket, ${resolved.map((e) => e.groupSql).join(", ")}
|
|
6311
6434
|
ORDER BY bucket
|
|
6312
6435
|
`, combined.params);
|
|
@@ -6328,7 +6451,7 @@ async function getScoreTimeSeries(client, args) {
|
|
|
6328
6451
|
const rows = await queryJson(client, `
|
|
6329
6452
|
SELECT toStartOfInterval(timestamp, ${intervalSql}) AS bucket,
|
|
6330
6453
|
${aggSql} AS value
|
|
6331
|
-
FROM ${
|
|
6454
|
+
FROM ${currentScoresRelation()} ${whereClause}
|
|
6332
6455
|
GROUP BY bucket
|
|
6333
6456
|
ORDER BY bucket
|
|
6334
6457
|
`, combined.params);
|
|
@@ -6351,7 +6474,7 @@ async function getScorePercentiles(client, args) {
|
|
|
6351
6474
|
const rows = await queryJson(client, `
|
|
6352
6475
|
SELECT toStartOfInterval(timestamp, ${intervalSql}) AS bucket,
|
|
6353
6476
|
quantile(${p})(score) AS pvalue
|
|
6354
|
-
FROM ${
|
|
6477
|
+
FROM ${currentScoresRelation()}
|
|
6355
6478
|
${whereClause}
|
|
6356
6479
|
GROUP BY bucket
|
|
6357
6480
|
ORDER BY bucket
|
|
@@ -6720,11 +6843,9 @@ function compileClickHouseTraceScope(selection, relationCollections, parameters)
|
|
|
6720
6843
|
entityVersionId,
|
|
6721
6844
|
parentEntityVersionId,
|
|
6722
6845
|
rootEntityVersionId
|
|
6723
|
-
FROM ${
|
|
6724
|
-
WHERE isNotNull(traceId)
|
|
6725
|
-
AND traceId IN (SELECT traceId FROM root_scope)
|
|
6726
|
-
ORDER BY scoreId, timestamp DESC
|
|
6727
|
-
LIMIT 1 BY scoreId
|
|
6846
|
+
FROM ${currentScoresRelation()} AS current
|
|
6847
|
+
WHERE isNotNull(current.traceId)
|
|
6848
|
+
AND current.traceId IN (SELECT traceId FROM root_scope)
|
|
6728
6849
|
)`);
|
|
6729
6850
|
if (relationCollections.has("feedback")) ctes.push(`current_feedback AS (
|
|
6730
6851
|
SELECT
|
|
@@ -6773,6 +6894,46 @@ LIMIT ${parameters.add(plan.limit + 1, "UInt64")}`,
|
|
|
6773
6894
|
};
|
|
6774
6895
|
const orderField = resolveOrderField(plan.orderBy.field);
|
|
6775
6896
|
const direction = plan.orderBy.direction === "asc" ? "ASC" : "DESC";
|
|
6897
|
+
if (plan.paginationMode === "page") return {
|
|
6898
|
+
query: `${candidates},
|
|
6899
|
+
page_rows AS (
|
|
6900
|
+
SELECT *, row_number() OVER (ORDER BY ${orderField} ${direction}, traceId ASC) AS __row_position
|
|
6901
|
+
FROM candidates
|
|
6902
|
+
ORDER BY ${orderField} ${direction}, traceId ASC
|
|
6903
|
+
LIMIT ${parameters.add(plan.perPage, "UInt64")} OFFSET ${parameters.add(plan.page * plan.perPage, "UInt64")}
|
|
6904
|
+
),
|
|
6905
|
+
page_total AS (
|
|
6906
|
+
SELECT count() AS total
|
|
6907
|
+
FROM candidates
|
|
6908
|
+
)
|
|
6909
|
+
SELECT page_rows.*, page_total.total, 0 AS __metadata
|
|
6910
|
+
FROM page_rows
|
|
6911
|
+
CROSS JOIN page_total
|
|
6912
|
+
UNION ALL
|
|
6913
|
+
SELECT
|
|
6914
|
+
'' AS traceId,
|
|
6915
|
+
'' AS rootSpanId,
|
|
6916
|
+
'' AS name,
|
|
6917
|
+
CAST(NULL, 'Nullable(String)') AS entityId,
|
|
6918
|
+
CAST(NULL, 'Nullable(String)') AS parentSpanId,
|
|
6919
|
+
CAST(NULL, 'Nullable(String)') AS metadata,
|
|
6920
|
+
CAST(NULL, 'Nullable(String)') AS input,
|
|
6921
|
+
CAST(NULL, 'Nullable(String)') AS threadId,
|
|
6922
|
+
CAST(NULL, 'Nullable(String)') AS resourceId,
|
|
6923
|
+
toDateTime64(0, 3, 'UTC') AS startedAt,
|
|
6924
|
+
toDateTime64(0, 3, 'UTC') AS endedAt,
|
|
6925
|
+
CAST(NULL, 'Nullable(String)') AS entityName,
|
|
6926
|
+
CAST(NULL, 'Nullable(String)') AS entityType,
|
|
6927
|
+
CAST(NULL, 'Nullable(String)') AS environment,
|
|
6928
|
+
'' AS status,
|
|
6929
|
+
0 AS __row_position,
|
|
6930
|
+
page_total.total AS total,
|
|
6931
|
+
1 AS __metadata
|
|
6932
|
+
FROM page_total
|
|
6933
|
+
ORDER BY __metadata ASC, __row_position ASC`,
|
|
6934
|
+
query_params: parameters.params,
|
|
6935
|
+
sharedSnapshot: true
|
|
6936
|
+
};
|
|
6776
6937
|
let pageCondition = "";
|
|
6777
6938
|
if (plan.cursor) {
|
|
6778
6939
|
const comparison = plan.orderBy.direction === "asc" ? ">" : "<";
|
|
@@ -6919,7 +7080,8 @@ async function runWithClickHouseTraceQueryTimeout(client, limits, compiled, quer
|
|
|
6919
7080
|
clickhouse_settings: {
|
|
6920
7081
|
...CH_SETTINGS,
|
|
6921
7082
|
max_execution_time: resolvedTimeoutMs / 1e3,
|
|
6922
|
-
...limits.memoryLimitBytes === void 0 ? {} : { max_memory_usage: String(limits.memoryLimitBytes) }
|
|
7083
|
+
...limits.memoryLimitBytes === void 0 ? {} : { max_memory_usage: String(limits.memoryLimitBytes) },
|
|
7084
|
+
...compiled.sharedSnapshot ? { enable_shared_storage_snapshot_in_query: 1 } : {}
|
|
6923
7085
|
}
|
|
6924
7086
|
})).json();
|
|
6925
7087
|
} catch (error) {
|
|
@@ -6950,6 +7112,37 @@ async function getTraceQueryValues(client, plan, limits) {
|
|
|
6950
7112
|
});
|
|
6951
7113
|
}
|
|
6952
7114
|
async function queryTraces(client, plan, timeoutMs) {
|
|
7115
|
+
if (plan.paginationMode === "page") {
|
|
7116
|
+
const rows = await runWithClickHouseTraceQueryTimeout(client, { timeoutMs }, compileClickHouseTraceQuery(plan));
|
|
7117
|
+
const total = Number(rows.at(-1)?.total ?? 0);
|
|
7118
|
+
const traces = rows.filter((row) => Number(row.__metadata) === 0).map((row) => ({
|
|
7119
|
+
traceId: String(row.traceId),
|
|
7120
|
+
rootSpanId: String(row.rootSpanId),
|
|
7121
|
+
name: row.name,
|
|
7122
|
+
entityId: row.entityId ?? null,
|
|
7123
|
+
parentSpanId: row.parentSpanId ?? null,
|
|
7124
|
+
createdAt: asIsoTimestamp(row.startedAt),
|
|
7125
|
+
metadata: parseJson(row.metadata) ?? null,
|
|
7126
|
+
inputPreview: _mastra_core_storage.buildInputPreview(row.input) ?? null,
|
|
7127
|
+
threadId: row.threadId == null ? null : String(row.threadId),
|
|
7128
|
+
resourceId: row.resourceId == null ? null : String(row.resourceId),
|
|
7129
|
+
startedAt: asIsoTimestamp(row.startedAt),
|
|
7130
|
+
endedAt: asIsoTimestamp(row.endedAt),
|
|
7131
|
+
entityName: row.entityName == null ? null : String(row.entityName),
|
|
7132
|
+
entityType: row.entityType == null ? null : String(row.entityType),
|
|
7133
|
+
environment: row.environment == null ? null : String(row.environment),
|
|
7134
|
+
status: row.status
|
|
7135
|
+
}));
|
|
7136
|
+
return _mastra_core_storage.traceQueryResponseSchema.parse({
|
|
7137
|
+
traces,
|
|
7138
|
+
pagination: {
|
|
7139
|
+
total,
|
|
7140
|
+
page: plan.page,
|
|
7141
|
+
perPage: plan.perPage,
|
|
7142
|
+
hasMore: (plan.page + 1) * plan.perPage < total
|
|
7143
|
+
}
|
|
7144
|
+
});
|
|
7145
|
+
}
|
|
6953
7146
|
const rows = await runWithClickHouseTraceQueryTimeout(client, { timeoutMs }, compileClickHouseTraceQuery(plan));
|
|
6954
7147
|
const visibleRows = rows.slice(0, plan.limit);
|
|
6955
7148
|
if (plan.result === "groups") {
|
|
@@ -7455,6 +7648,7 @@ async function batchDeleteTraces(client, args, replication) {
|
|
|
7455
7648
|
TABLE_METRIC_EVENTS,
|
|
7456
7649
|
TABLE_LOG_EVENTS,
|
|
7457
7650
|
TABLE_SCORE_EVENTS,
|
|
7651
|
+
TABLE_SCORE_EVENTS_CURRENT,
|
|
7458
7652
|
TABLE_FEEDBACK_EVENTS
|
|
7459
7653
|
];
|
|
7460
7654
|
await Promise.all([...tracingTables.map((table) => client.command({
|
|
@@ -8134,10 +8328,13 @@ var ObservabilityStorageClickhouseVNext = class extends _mastra_core_storage.Obs
|
|
|
8134
8328
|
else if (existingStrategy) this.#deltaCursorStrategy = existingStrategy;
|
|
8135
8329
|
else this.#deltaCursorStrategy = await detectDeltaCursorStrategy(this.#client, void 0, existingStrategy);
|
|
8136
8330
|
await reconcileDiscoveryTables(this.#client, this.#replication);
|
|
8137
|
-
const
|
|
8138
|
-
for (const ddl of
|
|
8331
|
+
const coreTableDdl = this.#deltaCursorStrategy === null ? BASE_TABLE_DDL : buildAllTableDDL();
|
|
8332
|
+
for (const ddl of coreTableDdl) await this.#client.command({ query: applyReplicationToDDL(ddl, this.#replication) });
|
|
8139
8333
|
const pendingMigrations = await filterAppliedMigrations(this.#client, ALL_MIGRATIONS);
|
|
8140
8334
|
for (const migration of pendingMigrations) await this.#client.command({ query: addOnClusterToDDL(migration.sql, this.#replication) });
|
|
8335
|
+
const coreMvDdl = this.#deltaCursorStrategy === null ? BASE_MV_DDL : buildAllMvDDL(this.#deltaCursorStrategy);
|
|
8336
|
+
for (const ddl of coreMvDdl) await this.#client.command({ query: applyReplicationToDDL(ddl, this.#replication) });
|
|
8337
|
+
await backfillCurrentScores(this.#client);
|
|
8141
8338
|
if (this.#retention) await this.applyRetention();
|
|
8142
8339
|
if (this.#deltaCursorStrategy === "serial") for (const counterName of DELTA_CURSOR_COUNTER_NAMES) await this.#client.query({
|
|
8143
8340
|
query: `SELECT generateSerialID({counterName:String}) AS cursorId`,
|