@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/index.js
CHANGED
|
@@ -2546,6 +2546,8 @@ const TABLE_TRACE_BRANCHES_DELTA = "mastra_trace_branches_delta";
|
|
|
2546
2546
|
const TABLE_METRIC_EVENTS = "mastra_metric_events";
|
|
2547
2547
|
const TABLE_LOG_EVENTS = "mastra_log_events";
|
|
2548
2548
|
const TABLE_SCORE_EVENTS = "mastra_score_events";
|
|
2549
|
+
const TABLE_SCORE_EVENTS_CURRENT = "mastra_score_events_current";
|
|
2550
|
+
const TABLE_SCORE_EVENTS_CURRENT_BACKFILL = "mastra_score_events_current_backfill";
|
|
2549
2551
|
const TABLE_FEEDBACK_EVENTS = "mastra_feedback_events";
|
|
2550
2552
|
const TABLE_DELETION_REQUESTS = "mastra_deletion_requests";
|
|
2551
2553
|
const TABLE_METRIC_EVENTS_DELTA = "mastra_metric_events_delta";
|
|
@@ -2561,6 +2563,7 @@ const MV_TRACE_BRANCHES_DELTA = "mastra_mv_trace_branches_delta";
|
|
|
2561
2563
|
const MV_METRIC_EVENTS_DELTA = "mastra_mv_metric_events_delta";
|
|
2562
2564
|
const MV_LOG_EVENTS_DELTA = "mastra_mv_log_events_delta";
|
|
2563
2565
|
const MV_SCORE_EVENTS_DELTA = "mastra_mv_score_events_delta";
|
|
2566
|
+
const MV_SCORE_EVENTS_CURRENT = "mastra_mv_score_events_current";
|
|
2564
2567
|
const MV_FEEDBACK_EVENTS_DELTA = "mastra_mv_feedback_events_delta";
|
|
2565
2568
|
const MV_DISCOVERY_VALUES = "mastra_mv_discovery_values";
|
|
2566
2569
|
const MV_DISCOVERY_PAIRS = "mastra_mv_discovery_pairs";
|
|
@@ -3078,19 +3081,53 @@ FROM (
|
|
|
3078
3081
|
)
|
|
3079
3082
|
`;
|
|
3080
3083
|
}
|
|
3081
|
-
const
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
+
const SCORE_EVENT_COLUMN_NAMES = [
|
|
3085
|
+
"timestamp",
|
|
3086
|
+
"scoreId",
|
|
3087
|
+
"writeVersion",
|
|
3088
|
+
"traceId",
|
|
3089
|
+
"spanId",
|
|
3090
|
+
"experimentId",
|
|
3091
|
+
"scoreTraceId",
|
|
3092
|
+
"entityType",
|
|
3093
|
+
"entityId",
|
|
3094
|
+
"entityName",
|
|
3095
|
+
"entityVersionId",
|
|
3096
|
+
"parentEntityVersionId",
|
|
3097
|
+
"parentEntityType",
|
|
3098
|
+
"parentEntityId",
|
|
3099
|
+
"parentEntityName",
|
|
3100
|
+
"rootEntityVersionId",
|
|
3101
|
+
"rootEntityType",
|
|
3102
|
+
"rootEntityId",
|
|
3103
|
+
"rootEntityName",
|
|
3104
|
+
"userId",
|
|
3105
|
+
"organizationId",
|
|
3106
|
+
"resourceId",
|
|
3107
|
+
"runId",
|
|
3108
|
+
"sessionId",
|
|
3109
|
+
"threadId",
|
|
3110
|
+
"requestId",
|
|
3111
|
+
"environment",
|
|
3112
|
+
"executionSource",
|
|
3113
|
+
"serviceName",
|
|
3114
|
+
"scorerId",
|
|
3115
|
+
"scorerVersion",
|
|
3116
|
+
"scoreSource",
|
|
3117
|
+
"score",
|
|
3118
|
+
"reason",
|
|
3119
|
+
"tags",
|
|
3120
|
+
"metadata",
|
|
3121
|
+
"scope"
|
|
3122
|
+
];
|
|
3123
|
+
const SCORE_EVENT_COLUMNS_DDL = `
|
|
3084
3124
|
timestamp DateTime64(3, 'UTC'),
|
|
3085
|
-
|
|
3086
|
-
-- IDs
|
|
3087
3125
|
scoreId String,
|
|
3126
|
+
writeVersion UInt64 DEFAULT 0,
|
|
3088
3127
|
traceId Nullable(String),
|
|
3089
3128
|
spanId Nullable(String),
|
|
3090
3129
|
experimentId Nullable(String),
|
|
3091
3130
|
scoreTraceId Nullable(String),
|
|
3092
|
-
|
|
3093
|
-
-- Entity hierarchy
|
|
3094
3131
|
entityType LowCardinality(Nullable(String)),
|
|
3095
3132
|
entityId Nullable(String),
|
|
3096
3133
|
entityName Nullable(String),
|
|
@@ -3103,8 +3140,6 @@ CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS} (
|
|
|
3103
3140
|
rootEntityType LowCardinality(Nullable(String)),
|
|
3104
3141
|
rootEntityId Nullable(String),
|
|
3105
3142
|
rootEntityName Nullable(String),
|
|
3106
|
-
|
|
3107
|
-
-- Context
|
|
3108
3143
|
userId Nullable(String),
|
|
3109
3144
|
organizationId Nullable(String),
|
|
3110
3145
|
resourceId Nullable(String),
|
|
@@ -3115,30 +3150,48 @@ CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS} (
|
|
|
3115
3150
|
environment LowCardinality(Nullable(String)),
|
|
3116
3151
|
executionSource LowCardinality(Nullable(String)),
|
|
3117
3152
|
serviceName LowCardinality(Nullable(String)),
|
|
3118
|
-
|
|
3119
|
-
-- Scorer identity
|
|
3120
3153
|
scorerId LowCardinality(String),
|
|
3121
3154
|
scorerVersion LowCardinality(Nullable(String)),
|
|
3122
3155
|
scoreSource LowCardinality(Nullable(String)),
|
|
3123
|
-
|
|
3124
|
-
-- Score value
|
|
3125
3156
|
score Float64,
|
|
3126
|
-
|
|
3127
|
-
-- Information-only
|
|
3128
3157
|
reason Nullable(String),
|
|
3129
|
-
|
|
3130
|
-
-- Query-relevant flexible fields
|
|
3131
3158
|
tags Array(LowCardinality(String)) DEFAULT [],
|
|
3132
|
-
|
|
3133
|
-
-- Information-only JSON payloads
|
|
3134
3159
|
metadata Nullable(String),
|
|
3135
3160
|
scope Nullable(String)
|
|
3161
|
+
`;
|
|
3162
|
+
const SCORE_EVENTS_DDL = `
|
|
3163
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS} (
|
|
3164
|
+
${SCORE_EVENT_COLUMNS_DDL},
|
|
3165
|
+
INDEX idx_scoreId scoreId TYPE bloom_filter(0.01) GRANULARITY 1
|
|
3136
3166
|
)
|
|
3137
3167
|
ENGINE = ReplacingMergeTree
|
|
3138
3168
|
PARTITION BY toDate(timestamp)
|
|
3139
3169
|
ORDER BY (traceId, timestamp, scoreId)
|
|
3140
3170
|
SETTINGS allow_nullable_key = 1
|
|
3141
3171
|
`;
|
|
3172
|
+
const SCORE_EVENTS_CURRENT_DDL = `
|
|
3173
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS_CURRENT} (
|
|
3174
|
+
${SCORE_EVENT_COLUMNS_DDL}
|
|
3175
|
+
)
|
|
3176
|
+
ENGINE = ReplacingMergeTree(writeVersion)
|
|
3177
|
+
PARTITION BY cityHash64(scoreId) % 64
|
|
3178
|
+
ORDER BY scoreId
|
|
3179
|
+
`;
|
|
3180
|
+
const SCORE_EVENTS_CURRENT_BACKFILL_DDL = `
|
|
3181
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS_CURRENT_BACKFILL} (
|
|
3182
|
+
marker String,
|
|
3183
|
+
completedAt DateTime64(3, 'UTC')
|
|
3184
|
+
)
|
|
3185
|
+
ENGINE = ReplacingMergeTree(completedAt)
|
|
3186
|
+
ORDER BY marker
|
|
3187
|
+
`;
|
|
3188
|
+
const SCORE_EVENTS_CURRENT_MV_DDL = `
|
|
3189
|
+
CREATE MATERIALIZED VIEW IF NOT EXISTS ${MV_SCORE_EVENTS_CURRENT}
|
|
3190
|
+
TO ${TABLE_SCORE_EVENTS_CURRENT}
|
|
3191
|
+
AS
|
|
3192
|
+
SELECT ${SCORE_EVENT_COLUMN_NAMES.join(", ")}
|
|
3193
|
+
FROM ${TABLE_SCORE_EVENTS}
|
|
3194
|
+
`;
|
|
3142
3195
|
function buildScoreEventsDeltaDDL() {
|
|
3143
3196
|
return `
|
|
3144
3197
|
CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS_DELTA} (
|
|
@@ -3412,6 +3465,8 @@ const BASE_TABLE_DDL = [
|
|
|
3412
3465
|
METRIC_EVENTS_DDL,
|
|
3413
3466
|
LOG_EVENTS_DDL,
|
|
3414
3467
|
SCORE_EVENTS_DDL,
|
|
3468
|
+
SCORE_EVENTS_CURRENT_DDL,
|
|
3469
|
+
SCORE_EVENTS_CURRENT_BACKFILL_DDL,
|
|
3415
3470
|
FEEDBACK_EVENTS_DDL,
|
|
3416
3471
|
DELETION_REQUESTS_DDL,
|
|
3417
3472
|
DISCOVERY_VALUES_DDL,
|
|
@@ -3430,7 +3485,11 @@ function buildDeltaTableDDL() {
|
|
|
3430
3485
|
function buildAllTableDDL() {
|
|
3431
3486
|
return [...BASE_TABLE_DDL, ...buildDeltaTableDDL()];
|
|
3432
3487
|
}
|
|
3433
|
-
const BASE_MV_DDL = [
|
|
3488
|
+
const BASE_MV_DDL = [
|
|
3489
|
+
TRACE_ROOTS_MV_DDL,
|
|
3490
|
+
TRACE_BRANCHES_MV_DDL,
|
|
3491
|
+
SCORE_EVENTS_CURRENT_MV_DDL
|
|
3492
|
+
];
|
|
3434
3493
|
function buildDeltaMvDDL(strategy) {
|
|
3435
3494
|
return [
|
|
3436
3495
|
buildTraceRootsDeltaMvDDL(strategy),
|
|
@@ -3452,11 +3511,11 @@ const addColumn = (table, name, type) => ({
|
|
|
3452
3511
|
name,
|
|
3453
3512
|
sql: `ALTER TABLE ${table} ADD COLUMN IF NOT EXISTS ${name} ${type}`
|
|
3454
3513
|
});
|
|
3455
|
-
const addBloomIndex = (table, name, column) => ({
|
|
3514
|
+
const addBloomIndex = (table, name, column, granularity = 2) => ({
|
|
3456
3515
|
kind: "index",
|
|
3457
3516
|
table,
|
|
3458
3517
|
name,
|
|
3459
|
-
sql: `ALTER TABLE ${table} ADD INDEX IF NOT EXISTS ${name} ${column} TYPE bloom_filter(0.01) GRANULARITY
|
|
3518
|
+
sql: `ALTER TABLE ${table} ADD INDEX IF NOT EXISTS ${name} ${column} TYPE bloom_filter(0.01) GRANULARITY ${granularity}`
|
|
3460
3519
|
});
|
|
3461
3520
|
const ALL_MIGRATIONS = [
|
|
3462
3521
|
addColumn(TABLE_SPAN_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
@@ -3471,9 +3530,11 @@ const ALL_MIGRATIONS = [
|
|
|
3471
3530
|
addColumn(TABLE_LOG_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3472
3531
|
addColumn(TABLE_LOG_EVENTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3473
3532
|
addColumn(TABLE_LOG_EVENTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3533
|
+
addColumn(TABLE_SCORE_EVENTS, "writeVersion", "UInt64 DEFAULT 0"),
|
|
3474
3534
|
addColumn(TABLE_SCORE_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3475
3535
|
addColumn(TABLE_SCORE_EVENTS, "parentEntityVersionId", "Nullable(String)"),
|
|
3476
3536
|
addColumn(TABLE_SCORE_EVENTS, "rootEntityVersionId", "Nullable(String)"),
|
|
3537
|
+
addBloomIndex(TABLE_SCORE_EVENTS, "idx_scoreId", "scoreId", 1),
|
|
3477
3538
|
addColumn(TABLE_FEEDBACK_EVENTS, "writeVersion", "UInt64 DEFAULT 0"),
|
|
3478
3539
|
addColumn(TABLE_FEEDBACK_EVENTS, "entityVersionId", "Nullable(String)"),
|
|
3479
3540
|
addColumn(TABLE_FEEDBACK_EVENTS, "reviewStatus", "LowCardinality(String) DEFAULT 'needs-review'"),
|
|
@@ -3499,6 +3560,8 @@ const ALL_TABLE_NAMES = [
|
|
|
3499
3560
|
TABLE_METRIC_EVENTS,
|
|
3500
3561
|
TABLE_LOG_EVENTS,
|
|
3501
3562
|
TABLE_SCORE_EVENTS,
|
|
3563
|
+
TABLE_SCORE_EVENTS_CURRENT,
|
|
3564
|
+
TABLE_SCORE_EVENTS_CURRENT_BACKFILL,
|
|
3502
3565
|
TABLE_FEEDBACK_EVENTS,
|
|
3503
3566
|
TABLE_DELETION_REQUESTS,
|
|
3504
3567
|
TABLE_METRIC_EVENTS_DELTA,
|
|
@@ -3516,6 +3579,7 @@ const SIGNAL_TTL_COLUMNS = {
|
|
|
3516
3579
|
[TABLE_METRIC_EVENTS]: "timestamp",
|
|
3517
3580
|
[TABLE_LOG_EVENTS]: "timestamp",
|
|
3518
3581
|
[TABLE_SCORE_EVENTS]: "timestamp",
|
|
3582
|
+
[TABLE_SCORE_EVENTS_CURRENT]: "timestamp",
|
|
3519
3583
|
[TABLE_FEEDBACK_EVENTS]: "timestamp"
|
|
3520
3584
|
};
|
|
3521
3585
|
/** Maps each signal key to the table(s) it controls. */
|
|
@@ -3527,7 +3591,7 @@ const SIGNAL_TO_TABLES = {
|
|
|
3527
3591
|
],
|
|
3528
3592
|
logs: [TABLE_LOG_EVENTS],
|
|
3529
3593
|
metrics: [TABLE_METRIC_EVENTS],
|
|
3530
|
-
scores: [TABLE_SCORE_EVENTS],
|
|
3594
|
+
scores: [TABLE_SCORE_EVENTS, TABLE_SCORE_EVENTS_CURRENT],
|
|
3531
3595
|
feedback: [TABLE_FEEDBACK_EVENTS]
|
|
3532
3596
|
};
|
|
3533
3597
|
const RETENTION_MANAGED_TABLES = [...Object.keys(SIGNAL_TTL_COLUMNS), TABLE_DELETION_REQUESTS];
|
|
@@ -5947,6 +6011,36 @@ async function migrateSignalTables(client, logger) {
|
|
|
5947
6011
|
}
|
|
5948
6012
|
}
|
|
5949
6013
|
//#endregion
|
|
6014
|
+
//#region src/storage/domains/observability/v-next/score-current.ts
|
|
6015
|
+
const SCORE_CURRENT_BACKFILL_MARKER = "v1";
|
|
6016
|
+
async function backfillCurrentScores(client) {
|
|
6017
|
+
const markerRows = await (await client.query({
|
|
6018
|
+
query: `SELECT count() AS count
|
|
6019
|
+
FROM ${TABLE_SCORE_EVENTS_CURRENT_BACKFILL} FINAL
|
|
6020
|
+
WHERE marker = {marker:String}`,
|
|
6021
|
+
query_params: { marker: SCORE_CURRENT_BACKFILL_MARKER },
|
|
6022
|
+
format: "JSONEachRow"
|
|
6023
|
+
})).json();
|
|
6024
|
+
if (Number(markerRows[0]?.count ?? 0) > 0) return;
|
|
6025
|
+
const columns = SCORE_EVENT_COLUMN_NAMES.join(", ");
|
|
6026
|
+
await client.command({
|
|
6027
|
+
query: `INSERT INTO ${TABLE_SCORE_EVENTS_CURRENT} (${columns})
|
|
6028
|
+
SELECT ${columns}
|
|
6029
|
+
FROM (
|
|
6030
|
+
SELECT *, cityHash64(tuple(*)) AS _currentScoreFingerprint
|
|
6031
|
+
FROM ${TABLE_SCORE_EVENTS} FINAL
|
|
6032
|
+
ORDER BY scoreId, writeVersion DESC, timestamp DESC, _currentScoreFingerprint DESC
|
|
6033
|
+
LIMIT 1 BY scoreId
|
|
6034
|
+
)`,
|
|
6035
|
+
clickhouse_settings: { max_bytes_ratio_before_external_sort: .5 }
|
|
6036
|
+
});
|
|
6037
|
+
await client.command({
|
|
6038
|
+
query: `INSERT INTO ${TABLE_SCORE_EVENTS_CURRENT_BACKFILL} (marker, completedAt)
|
|
6039
|
+
VALUES ({marker:String}, now64(3, 'UTC'))`,
|
|
6040
|
+
query_params: { marker: SCORE_CURRENT_BACKFILL_MARKER }
|
|
6041
|
+
});
|
|
6042
|
+
}
|
|
6043
|
+
//#endregion
|
|
5950
6044
|
//#region src/storage/domains/observability/v-next/scores.ts
|
|
5951
6045
|
const SCORE_TYPED_COLUMNS = /* @__PURE__ */ new Set([
|
|
5952
6046
|
"timestamp",
|
|
@@ -6023,6 +6117,13 @@ function mergeFilters(...parts) {
|
|
|
6023
6117
|
function toWhereClause(filter) {
|
|
6024
6118
|
return filter.conditions.length ? `WHERE ${filter.conditions.join(" AND ")}` : "";
|
|
6025
6119
|
}
|
|
6120
|
+
function currentScoresRelation(sourcePredicate) {
|
|
6121
|
+
return `(
|
|
6122
|
+
SELECT *
|
|
6123
|
+
FROM ${TABLE_SCORE_EVENTS_CURRENT} FINAL
|
|
6124
|
+
${sourcePredicate ? `WHERE ${sourcePredicate}` : ""}
|
|
6125
|
+
)`;
|
|
6126
|
+
}
|
|
6026
6127
|
function buildScoreIdentityFilter(args) {
|
|
6027
6128
|
const conditions = ["scorerId = {olapScorerId:String}"];
|
|
6028
6129
|
const params = { olapScorerId: args.scorerId };
|
|
@@ -6058,6 +6159,24 @@ async function queryJson(client, query, params) {
|
|
|
6058
6159
|
clickhouse_settings: CH_SETTINGS
|
|
6059
6160
|
})).json();
|
|
6060
6161
|
}
|
|
6162
|
+
async function scoreRowsWithWriteVersions(client, scores) {
|
|
6163
|
+
const scoreIds = [...new Set(scores.flatMap((score) => score.scoreId ? [score.scoreId] : []))];
|
|
6164
|
+
const existingVersions = [];
|
|
6165
|
+
const lookupBatchSize = 1e3;
|
|
6166
|
+
for (let offset = 0; offset < scoreIds.length; offset += lookupBatchSize) existingVersions.push(...await queryJson(client, `SELECT scoreId, toString(max(writeVersion)) AS writeVersion
|
|
6167
|
+
FROM ${TABLE_SCORE_EVENTS}
|
|
6168
|
+
WHERE scoreId IN ({scoreIds:Array(String)})
|
|
6169
|
+
GROUP BY scoreId`, { scoreIds: scoreIds.slice(offset, offset + lookupBatchSize) }));
|
|
6170
|
+
const versions = new Map(existingVersions.map((row) => [row.scoreId, BigInt(row.writeVersion)]));
|
|
6171
|
+
return scores.map((score) => {
|
|
6172
|
+
const writeVersion = score.scoreId ? (versions.get(score.scoreId) ?? 0n) + 1n : 1n;
|
|
6173
|
+
if (score.scoreId) versions.set(score.scoreId, writeVersion);
|
|
6174
|
+
return {
|
|
6175
|
+
...scoreRecordToRow(score),
|
|
6176
|
+
writeVersion: writeVersion.toString()
|
|
6177
|
+
};
|
|
6178
|
+
});
|
|
6179
|
+
}
|
|
6061
6180
|
async function createScore(client, args) {
|
|
6062
6181
|
await batchCreateScores(client, { scores: [args.score] });
|
|
6063
6182
|
}
|
|
@@ -6065,7 +6184,7 @@ async function batchCreateScores(client, args) {
|
|
|
6065
6184
|
if (args.scores.length === 0) return;
|
|
6066
6185
|
await client.insert({
|
|
6067
6186
|
table: TABLE_SCORE_EVENTS,
|
|
6068
|
-
values: args.scores
|
|
6187
|
+
values: await scoreRowsWithWriteVersions(client, args.scores),
|
|
6069
6188
|
format: "JSONEachRow",
|
|
6070
6189
|
clickhouse_settings: CH_INSERT_SETTINGS
|
|
6071
6190
|
});
|
|
@@ -6108,10 +6227,11 @@ async function deleteScores(client, args, replication) {
|
|
|
6108
6227
|
conditions.push("resourceId = {delResourceId:String}");
|
|
6109
6228
|
params.delResourceId = args.resourceId;
|
|
6110
6229
|
}
|
|
6111
|
-
|
|
6112
|
-
|
|
6230
|
+
const clickhouse_settings = { lightweight_deletes_sync: isReplicationConfigured(replication) ? "2" : "1" };
|
|
6231
|
+
for (const table of [TABLE_SCORE_EVENTS_CURRENT, TABLE_SCORE_EVENTS]) await client.command({
|
|
6232
|
+
query: `DELETE FROM ${table} WHERE ${conditions.join(" AND ")}`,
|
|
6113
6233
|
query_params: params,
|
|
6114
|
-
clickhouse_settings
|
|
6234
|
+
clickhouse_settings
|
|
6115
6235
|
});
|
|
6116
6236
|
}
|
|
6117
6237
|
async function listScores(client, args, strategy) {
|
|
@@ -6145,8 +6265,9 @@ async function listScores(client, args, strategy) {
|
|
|
6145
6265
|
};
|
|
6146
6266
|
}
|
|
6147
6267
|
const currentDeltaCursor = deltaCursorEnabled ? await getDeltaCursor$2(client, whereClause, filter.params) : void 0;
|
|
6148
|
-
const
|
|
6149
|
-
const
|
|
6268
|
+
const scoresRelation = currentScoresRelation();
|
|
6269
|
+
const countResult = await queryJson(client, `SELECT count() AS total FROM ${scoresRelation} AS s ${whereClause}`, filter.params);
|
|
6270
|
+
const rows = await queryJson(client, `SELECT * FROM ${scoresRelation} AS s ${whereClause} ORDER BY ${orderBy} LIMIT {limit:UInt32} OFFSET {offset:UInt32}`, {
|
|
6150
6271
|
...filter.params,
|
|
6151
6272
|
limit: pagination.limit,
|
|
6152
6273
|
offset: pagination.offset
|
|
@@ -6205,14 +6326,15 @@ function buildScoresCursor(row) {
|
|
|
6205
6326
|
return row.cursorId ?? "0";
|
|
6206
6327
|
}
|
|
6207
6328
|
async function getScoreById(client, scoreId) {
|
|
6208
|
-
const rows = await queryJson(client, `SELECT * FROM ${
|
|
6329
|
+
const rows = await queryJson(client, `SELECT * FROM ${currentScoresRelation("scoreId = {scoreId:String}")} LIMIT 1`, { scoreId });
|
|
6209
6330
|
return rows[0] ? rowToScoreRecord(rows[0]) : null;
|
|
6210
6331
|
}
|
|
6211
6332
|
async function getScoreAggregate(client, args) {
|
|
6212
6333
|
const aggSql = getAggregationSql(args.aggregation);
|
|
6213
6334
|
const identity = buildScoreIdentityFilter(args);
|
|
6214
6335
|
const combined = mergeFilters(identity, buildScoresFilterConditions(args.filters));
|
|
6215
|
-
const
|
|
6336
|
+
const whereClause = toWhereClause(combined);
|
|
6337
|
+
const result = await queryJson(client, `SELECT ${aggSql} AS value FROM ${currentScoresRelation()} ${whereClause}`, combined.params);
|
|
6216
6338
|
const value = result[0]?.value == null ? null : Number(result[0]?.value);
|
|
6217
6339
|
if (args.comparePeriod && args.filters?.timestamp) {
|
|
6218
6340
|
const ts = args.filters.timestamp;
|
|
@@ -6246,7 +6368,8 @@ async function getScoreAggregate(client, args) {
|
|
|
6246
6368
|
endExclusive: ts.endExclusive
|
|
6247
6369
|
}
|
|
6248
6370
|
}));
|
|
6249
|
-
const
|
|
6371
|
+
const prevWhereClause = toWhereClause(prevCombined);
|
|
6372
|
+
const prevResult = await queryJson(client, `SELECT ${aggSql} AS value FROM ${currentScoresRelation()} ${prevWhereClause}`, prevCombined.params);
|
|
6250
6373
|
const previousValue = prevResult[0]?.value == null ? null : Number(prevResult[0]?.value);
|
|
6251
6374
|
let changePercent = null;
|
|
6252
6375
|
if (previousValue !== null && previousValue !== 0 && value !== null) changePercent = (value - previousValue) / Math.abs(previousValue) * 100;
|
|
@@ -6264,7 +6387,7 @@ async function getScoreBreakdown(client, args) {
|
|
|
6264
6387
|
const combined = mergeFilters(buildScoreIdentityFilter(args), buildScoresFilterConditions(args.filters));
|
|
6265
6388
|
const whereClause = toWhereClause(combined);
|
|
6266
6389
|
const resolved = resolveScoreGroupBy(args.groupBy);
|
|
6267
|
-
return { groups: (await queryJson(client, `SELECT ${resolved.map((e) => e.selectSql).join(", ")}, ${aggSql} AS value FROM ${
|
|
6390
|
+
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) => ({
|
|
6268
6391
|
dimensions: Object.fromEntries(resolved.map((entry, index) => {
|
|
6269
6392
|
const v = row[`group_by_${index}`];
|
|
6270
6393
|
return [entry.key, v == null ? null : String(v)];
|
|
@@ -6283,7 +6406,7 @@ async function getScoreTimeSeries(client, args) {
|
|
|
6283
6406
|
SELECT toStartOfInterval(timestamp, ${intervalSql}) AS bucket,
|
|
6284
6407
|
${resolved.map((e) => e.selectSql).join(", ")},
|
|
6285
6408
|
${aggSql} AS value
|
|
6286
|
-
FROM ${
|
|
6409
|
+
FROM ${currentScoresRelation()} ${whereClause}
|
|
6287
6410
|
GROUP BY bucket, ${resolved.map((e) => e.groupSql).join(", ")}
|
|
6288
6411
|
ORDER BY bucket
|
|
6289
6412
|
`, combined.params);
|
|
@@ -6305,7 +6428,7 @@ async function getScoreTimeSeries(client, args) {
|
|
|
6305
6428
|
const rows = await queryJson(client, `
|
|
6306
6429
|
SELECT toStartOfInterval(timestamp, ${intervalSql}) AS bucket,
|
|
6307
6430
|
${aggSql} AS value
|
|
6308
|
-
FROM ${
|
|
6431
|
+
FROM ${currentScoresRelation()} ${whereClause}
|
|
6309
6432
|
GROUP BY bucket
|
|
6310
6433
|
ORDER BY bucket
|
|
6311
6434
|
`, combined.params);
|
|
@@ -6328,7 +6451,7 @@ async function getScorePercentiles(client, args) {
|
|
|
6328
6451
|
const rows = await queryJson(client, `
|
|
6329
6452
|
SELECT toStartOfInterval(timestamp, ${intervalSql}) AS bucket,
|
|
6330
6453
|
quantile(${p})(score) AS pvalue
|
|
6331
|
-
FROM ${
|
|
6454
|
+
FROM ${currentScoresRelation()}
|
|
6332
6455
|
${whereClause}
|
|
6333
6456
|
GROUP BY bucket
|
|
6334
6457
|
ORDER BY bucket
|
|
@@ -6697,11 +6820,9 @@ function compileClickHouseTraceScope(selection, relationCollections, parameters)
|
|
|
6697
6820
|
entityVersionId,
|
|
6698
6821
|
parentEntityVersionId,
|
|
6699
6822
|
rootEntityVersionId
|
|
6700
|
-
FROM ${
|
|
6701
|
-
WHERE isNotNull(traceId)
|
|
6702
|
-
AND traceId IN (SELECT traceId FROM root_scope)
|
|
6703
|
-
ORDER BY scoreId, timestamp DESC
|
|
6704
|
-
LIMIT 1 BY scoreId
|
|
6823
|
+
FROM ${currentScoresRelation()} AS current
|
|
6824
|
+
WHERE isNotNull(current.traceId)
|
|
6825
|
+
AND current.traceId IN (SELECT traceId FROM root_scope)
|
|
6705
6826
|
)`);
|
|
6706
6827
|
if (relationCollections.has("feedback")) ctes.push(`current_feedback AS (
|
|
6707
6828
|
SELECT
|
|
@@ -6750,6 +6871,46 @@ LIMIT ${parameters.add(plan.limit + 1, "UInt64")}`,
|
|
|
6750
6871
|
};
|
|
6751
6872
|
const orderField = resolveOrderField(plan.orderBy.field);
|
|
6752
6873
|
const direction = plan.orderBy.direction === "asc" ? "ASC" : "DESC";
|
|
6874
|
+
if (plan.paginationMode === "page") return {
|
|
6875
|
+
query: `${candidates},
|
|
6876
|
+
page_rows AS (
|
|
6877
|
+
SELECT *, row_number() OVER (ORDER BY ${orderField} ${direction}, traceId ASC) AS __row_position
|
|
6878
|
+
FROM candidates
|
|
6879
|
+
ORDER BY ${orderField} ${direction}, traceId ASC
|
|
6880
|
+
LIMIT ${parameters.add(plan.perPage, "UInt64")} OFFSET ${parameters.add(plan.page * plan.perPage, "UInt64")}
|
|
6881
|
+
),
|
|
6882
|
+
page_total AS (
|
|
6883
|
+
SELECT count() AS total
|
|
6884
|
+
FROM candidates
|
|
6885
|
+
)
|
|
6886
|
+
SELECT page_rows.*, page_total.total, 0 AS __metadata
|
|
6887
|
+
FROM page_rows
|
|
6888
|
+
CROSS JOIN page_total
|
|
6889
|
+
UNION ALL
|
|
6890
|
+
SELECT
|
|
6891
|
+
'' AS traceId,
|
|
6892
|
+
'' AS rootSpanId,
|
|
6893
|
+
'' AS name,
|
|
6894
|
+
CAST(NULL, 'Nullable(String)') AS entityId,
|
|
6895
|
+
CAST(NULL, 'Nullable(String)') AS parentSpanId,
|
|
6896
|
+
CAST(NULL, 'Nullable(String)') AS metadata,
|
|
6897
|
+
CAST(NULL, 'Nullable(String)') AS input,
|
|
6898
|
+
CAST(NULL, 'Nullable(String)') AS threadId,
|
|
6899
|
+
CAST(NULL, 'Nullable(String)') AS resourceId,
|
|
6900
|
+
toDateTime64(0, 3, 'UTC') AS startedAt,
|
|
6901
|
+
toDateTime64(0, 3, 'UTC') AS endedAt,
|
|
6902
|
+
CAST(NULL, 'Nullable(String)') AS entityName,
|
|
6903
|
+
CAST(NULL, 'Nullable(String)') AS entityType,
|
|
6904
|
+
CAST(NULL, 'Nullable(String)') AS environment,
|
|
6905
|
+
'' AS status,
|
|
6906
|
+
0 AS __row_position,
|
|
6907
|
+
page_total.total AS total,
|
|
6908
|
+
1 AS __metadata
|
|
6909
|
+
FROM page_total
|
|
6910
|
+
ORDER BY __metadata ASC, __row_position ASC`,
|
|
6911
|
+
query_params: parameters.params,
|
|
6912
|
+
sharedSnapshot: true
|
|
6913
|
+
};
|
|
6753
6914
|
let pageCondition = "";
|
|
6754
6915
|
if (plan.cursor) {
|
|
6755
6916
|
const comparison = plan.orderBy.direction === "asc" ? ">" : "<";
|
|
@@ -6896,7 +7057,8 @@ async function runWithClickHouseTraceQueryTimeout(client, limits, compiled, quer
|
|
|
6896
7057
|
clickhouse_settings: {
|
|
6897
7058
|
...CH_SETTINGS,
|
|
6898
7059
|
max_execution_time: resolvedTimeoutMs / 1e3,
|
|
6899
|
-
...limits.memoryLimitBytes === void 0 ? {} : { max_memory_usage: String(limits.memoryLimitBytes) }
|
|
7060
|
+
...limits.memoryLimitBytes === void 0 ? {} : { max_memory_usage: String(limits.memoryLimitBytes) },
|
|
7061
|
+
...compiled.sharedSnapshot ? { enable_shared_storage_snapshot_in_query: 1 } : {}
|
|
6900
7062
|
}
|
|
6901
7063
|
})).json();
|
|
6902
7064
|
} catch (error) {
|
|
@@ -6927,6 +7089,37 @@ async function getTraceQueryValues(client, plan, limits) {
|
|
|
6927
7089
|
});
|
|
6928
7090
|
}
|
|
6929
7091
|
async function queryTraces(client, plan, timeoutMs) {
|
|
7092
|
+
if (plan.paginationMode === "page") {
|
|
7093
|
+
const rows = await runWithClickHouseTraceQueryTimeout(client, { timeoutMs }, compileClickHouseTraceQuery(plan));
|
|
7094
|
+
const total = Number(rows.at(-1)?.total ?? 0);
|
|
7095
|
+
const traces = rows.filter((row) => Number(row.__metadata) === 0).map((row) => ({
|
|
7096
|
+
traceId: String(row.traceId),
|
|
7097
|
+
rootSpanId: String(row.rootSpanId),
|
|
7098
|
+
name: row.name,
|
|
7099
|
+
entityId: row.entityId ?? null,
|
|
7100
|
+
parentSpanId: row.parentSpanId ?? null,
|
|
7101
|
+
createdAt: asIsoTimestamp(row.startedAt),
|
|
7102
|
+
metadata: parseJson(row.metadata) ?? null,
|
|
7103
|
+
inputPreview: coreStorage.buildInputPreview(row.input) ?? null,
|
|
7104
|
+
threadId: row.threadId == null ? null : String(row.threadId),
|
|
7105
|
+
resourceId: row.resourceId == null ? null : String(row.resourceId),
|
|
7106
|
+
startedAt: asIsoTimestamp(row.startedAt),
|
|
7107
|
+
endedAt: asIsoTimestamp(row.endedAt),
|
|
7108
|
+
entityName: row.entityName == null ? null : String(row.entityName),
|
|
7109
|
+
entityType: row.entityType == null ? null : String(row.entityType),
|
|
7110
|
+
environment: row.environment == null ? null : String(row.environment),
|
|
7111
|
+
status: row.status
|
|
7112
|
+
}));
|
|
7113
|
+
return coreStorage.traceQueryResponseSchema.parse({
|
|
7114
|
+
traces,
|
|
7115
|
+
pagination: {
|
|
7116
|
+
total,
|
|
7117
|
+
page: plan.page,
|
|
7118
|
+
perPage: plan.perPage,
|
|
7119
|
+
hasMore: (plan.page + 1) * plan.perPage < total
|
|
7120
|
+
}
|
|
7121
|
+
});
|
|
7122
|
+
}
|
|
6930
7123
|
const rows = await runWithClickHouseTraceQueryTimeout(client, { timeoutMs }, compileClickHouseTraceQuery(plan));
|
|
6931
7124
|
const visibleRows = rows.slice(0, plan.limit);
|
|
6932
7125
|
if (plan.result === "groups") {
|
|
@@ -7432,6 +7625,7 @@ async function batchDeleteTraces(client, args, replication) {
|
|
|
7432
7625
|
TABLE_METRIC_EVENTS,
|
|
7433
7626
|
TABLE_LOG_EVENTS,
|
|
7434
7627
|
TABLE_SCORE_EVENTS,
|
|
7628
|
+
TABLE_SCORE_EVENTS_CURRENT,
|
|
7435
7629
|
TABLE_FEEDBACK_EVENTS
|
|
7436
7630
|
];
|
|
7437
7631
|
await Promise.all([...tracingTables.map((table) => client.command({
|
|
@@ -8111,10 +8305,13 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
8111
8305
|
else if (existingStrategy) this.#deltaCursorStrategy = existingStrategy;
|
|
8112
8306
|
else this.#deltaCursorStrategy = await detectDeltaCursorStrategy(this.#client, void 0, existingStrategy);
|
|
8113
8307
|
await reconcileDiscoveryTables(this.#client, this.#replication);
|
|
8114
|
-
const
|
|
8115
|
-
for (const ddl of
|
|
8308
|
+
const coreTableDdl = this.#deltaCursorStrategy === null ? BASE_TABLE_DDL : buildAllTableDDL();
|
|
8309
|
+
for (const ddl of coreTableDdl) await this.#client.command({ query: applyReplicationToDDL(ddl, this.#replication) });
|
|
8116
8310
|
const pendingMigrations = await filterAppliedMigrations(this.#client, ALL_MIGRATIONS);
|
|
8117
8311
|
for (const migration of pendingMigrations) await this.#client.command({ query: addOnClusterToDDL(migration.sql, this.#replication) });
|
|
8312
|
+
const coreMvDdl = this.#deltaCursorStrategy === null ? BASE_MV_DDL : buildAllMvDDL(this.#deltaCursorStrategy);
|
|
8313
|
+
for (const ddl of coreMvDdl) await this.#client.command({ query: applyReplicationToDDL(ddl, this.#replication) });
|
|
8314
|
+
await backfillCurrentScores(this.#client);
|
|
8118
8315
|
if (this.#retention) await this.applyRetention();
|
|
8119
8316
|
if (this.#deltaCursorStrategy === "serial") for (const counterName of DELTA_CURSOR_COUNTER_NAMES) await this.#client.query({
|
|
8120
8317
|
query: `SELECT generateSerialID({counterName:String}) AS cursorId`,
|