@mastra/clickhouse 1.4.2-alpha.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +255 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +255 -9
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +2 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts +4 -4
- package/dist/storage/domains/observability/v-next/ddl.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/helpers.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +15 -4
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/migration.d.ts +20 -0
- package/dist/storage/domains/observability/v-next/migration.d.ts.map +1 -0
- package/dist/storage/domains/observability/v-next/tracing.d.ts +5 -1
- package/dist/storage/domains/observability/v-next/tracing.d.ts.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -2428,6 +2428,49 @@ time for large tables. Please ensure you have a backup before proceeding.
|
|
|
2428
2428
|
);
|
|
2429
2429
|
}
|
|
2430
2430
|
}
|
|
2431
|
+
async getTraceLight(args) {
|
|
2432
|
+
const { traceId } = args;
|
|
2433
|
+
try {
|
|
2434
|
+
const engine = TABLE_ENGINES[TABLE_SPANS] ?? "MergeTree()";
|
|
2435
|
+
const result = await this.client.query({
|
|
2436
|
+
query: `
|
|
2437
|
+
SELECT traceId, spanId, parentSpanId, name,
|
|
2438
|
+
entityType, entityId, entityName,
|
|
2439
|
+
spanType, error, isEvent,
|
|
2440
|
+
startedAt, endedAt, createdAt, updatedAt
|
|
2441
|
+
FROM ${TABLE_SPANS} ${engine.startsWith("ReplacingMergeTree") ? "FINAL" : ""}
|
|
2442
|
+
WHERE traceId = {traceId:String}
|
|
2443
|
+
ORDER BY startedAt ASC
|
|
2444
|
+
`,
|
|
2445
|
+
query_params: { traceId },
|
|
2446
|
+
format: "JSONEachRow",
|
|
2447
|
+
clickhouse_settings: {
|
|
2448
|
+
date_time_input_format: "best_effort",
|
|
2449
|
+
date_time_output_format: "iso",
|
|
2450
|
+
use_client_time_zone: 1,
|
|
2451
|
+
output_format_json_quote_64bit_integers: 0
|
|
2452
|
+
}
|
|
2453
|
+
});
|
|
2454
|
+
const rows = await result.json();
|
|
2455
|
+
if (!rows || rows.length === 0) {
|
|
2456
|
+
return null;
|
|
2457
|
+
}
|
|
2458
|
+
return {
|
|
2459
|
+
traceId,
|
|
2460
|
+
spans: transformRows(rows)
|
|
2461
|
+
};
|
|
2462
|
+
} catch (error) {
|
|
2463
|
+
throw new MastraError(
|
|
2464
|
+
{
|
|
2465
|
+
id: createStorageErrorId("CLICKHOUSE", "GET_TRACE_LIGHT", "FAILED"),
|
|
2466
|
+
domain: ErrorDomain.STORAGE,
|
|
2467
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2468
|
+
details: { traceId }
|
|
2469
|
+
},
|
|
2470
|
+
error
|
|
2471
|
+
);
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2431
2474
|
async updateSpan(args) {
|
|
2432
2475
|
const { traceId, spanId, updates } = args;
|
|
2433
2476
|
try {
|
|
@@ -2942,6 +2985,7 @@ CREATE TABLE IF NOT EXISTS ${TABLE_METRIC_EVENTS} (
|
|
|
2942
2985
|
timestamp DateTime64(3, 'UTC'),
|
|
2943
2986
|
|
|
2944
2987
|
-- IDs
|
|
2988
|
+
metricId String,
|
|
2945
2989
|
traceId Nullable(String),
|
|
2946
2990
|
spanId Nullable(String),
|
|
2947
2991
|
experimentId Nullable(String),
|
|
@@ -2989,9 +3033,9 @@ CREATE TABLE IF NOT EXISTS ${TABLE_METRIC_EVENTS} (
|
|
|
2989
3033
|
metadata Nullable(String),
|
|
2990
3034
|
scope Nullable(String)
|
|
2991
3035
|
)
|
|
2992
|
-
ENGINE =
|
|
3036
|
+
ENGINE = ReplacingMergeTree
|
|
2993
3037
|
PARTITION BY toDate(timestamp)
|
|
2994
|
-
ORDER BY (name, timestamp)
|
|
3038
|
+
ORDER BY (name, timestamp, metricId)
|
|
2995
3039
|
`;
|
|
2996
3040
|
var LOG_EVENTS_DDL = `
|
|
2997
3041
|
CREATE TABLE IF NOT EXISTS ${TABLE_LOG_EVENTS} (
|
|
@@ -2999,6 +3043,7 @@ CREATE TABLE IF NOT EXISTS ${TABLE_LOG_EVENTS} (
|
|
|
2999
3043
|
timestamp DateTime64(3, 'UTC'),
|
|
3000
3044
|
|
|
3001
3045
|
-- IDs
|
|
3046
|
+
logId String,
|
|
3002
3047
|
traceId Nullable(String),
|
|
3003
3048
|
spanId Nullable(String),
|
|
3004
3049
|
experimentId Nullable(String),
|
|
@@ -3041,10 +3086,9 @@ CREATE TABLE IF NOT EXISTS ${TABLE_LOG_EVENTS} (
|
|
|
3041
3086
|
metadata Nullable(String),
|
|
3042
3087
|
scope Nullable(String)
|
|
3043
3088
|
)
|
|
3044
|
-
ENGINE =
|
|
3089
|
+
ENGINE = ReplacingMergeTree
|
|
3045
3090
|
PARTITION BY toDate(timestamp)
|
|
3046
|
-
ORDER BY (timestamp,
|
|
3047
|
-
SETTINGS allow_nullable_key = 1
|
|
3091
|
+
ORDER BY (timestamp, logId)
|
|
3048
3092
|
`;
|
|
3049
3093
|
var SCORE_EVENTS_DDL = `
|
|
3050
3094
|
CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS} (
|
|
@@ -3052,6 +3096,7 @@ CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS} (
|
|
|
3052
3096
|
timestamp DateTime64(3, 'UTC'),
|
|
3053
3097
|
|
|
3054
3098
|
-- IDs
|
|
3099
|
+
scoreId String,
|
|
3055
3100
|
traceId Nullable(String),
|
|
3056
3101
|
spanId Nullable(String),
|
|
3057
3102
|
experimentId Nullable(String),
|
|
@@ -3101,9 +3146,9 @@ CREATE TABLE IF NOT EXISTS ${TABLE_SCORE_EVENTS} (
|
|
|
3101
3146
|
metadata Nullable(String),
|
|
3102
3147
|
scope Nullable(String)
|
|
3103
3148
|
)
|
|
3104
|
-
ENGINE =
|
|
3149
|
+
ENGINE = ReplacingMergeTree
|
|
3105
3150
|
PARTITION BY toDate(timestamp)
|
|
3106
|
-
ORDER BY (traceId, timestamp)
|
|
3151
|
+
ORDER BY (traceId, timestamp, scoreId)
|
|
3107
3152
|
SETTINGS allow_nullable_key = 1
|
|
3108
3153
|
`;
|
|
3109
3154
|
var FEEDBACK_EVENTS_DDL = `
|
|
@@ -3112,6 +3157,7 @@ CREATE TABLE IF NOT EXISTS ${TABLE_FEEDBACK_EVENTS} (
|
|
|
3112
3157
|
timestamp DateTime64(3, 'UTC'),
|
|
3113
3158
|
|
|
3114
3159
|
-- IDs
|
|
3160
|
+
feedbackId String,
|
|
3115
3161
|
traceId Nullable(String),
|
|
3116
3162
|
spanId Nullable(String),
|
|
3117
3163
|
experimentId Nullable(String),
|
|
@@ -3164,9 +3210,9 @@ CREATE TABLE IF NOT EXISTS ${TABLE_FEEDBACK_EVENTS} (
|
|
|
3164
3210
|
metadata Nullable(String),
|
|
3165
3211
|
scope Nullable(String)
|
|
3166
3212
|
)
|
|
3167
|
-
ENGINE =
|
|
3213
|
+
ENGINE = ReplacingMergeTree
|
|
3168
3214
|
PARTITION BY toDate(timestamp)
|
|
3169
|
-
ORDER BY (traceId, timestamp)
|
|
3215
|
+
ORDER BY (traceId, timestamp, feedbackId)
|
|
3170
3216
|
SETTINGS allow_nullable_key = 1
|
|
3171
3217
|
`;
|
|
3172
3218
|
var DISCOVERY_VALUES_DDL = `
|
|
@@ -3521,6 +3567,7 @@ function spanRecordToRow(span) {
|
|
|
3521
3567
|
}
|
|
3522
3568
|
function rowToLogRecord(row) {
|
|
3523
3569
|
return {
|
|
3570
|
+
logId: row.logId,
|
|
3524
3571
|
timestamp: toDate(row.timestamp),
|
|
3525
3572
|
level: row.level,
|
|
3526
3573
|
message: row.message,
|
|
@@ -3557,6 +3604,7 @@ function rowToLogRecord(row) {
|
|
|
3557
3604
|
}
|
|
3558
3605
|
function logRecordToRow(log) {
|
|
3559
3606
|
return {
|
|
3607
|
+
logId: log.logId,
|
|
3560
3608
|
timestamp: toISOString(log.timestamp),
|
|
3561
3609
|
level: log.level,
|
|
3562
3610
|
message: log.message,
|
|
@@ -3593,6 +3641,7 @@ function logRecordToRow(log) {
|
|
|
3593
3641
|
}
|
|
3594
3642
|
function rowToMetricRecord(row) {
|
|
3595
3643
|
return {
|
|
3644
|
+
metricId: row.metricId,
|
|
3596
3645
|
timestamp: toDate(row.timestamp),
|
|
3597
3646
|
name: row.name,
|
|
3598
3647
|
value: Number(row.value),
|
|
@@ -3634,6 +3683,7 @@ function rowToMetricRecord(row) {
|
|
|
3634
3683
|
}
|
|
3635
3684
|
function metricRecordToRow(metric) {
|
|
3636
3685
|
return {
|
|
3686
|
+
metricId: metric.metricId,
|
|
3637
3687
|
timestamp: toISOString(metric.timestamp),
|
|
3638
3688
|
name: metric.name,
|
|
3639
3689
|
value: metric.value,
|
|
@@ -3675,6 +3725,7 @@ function metricRecordToRow(metric) {
|
|
|
3675
3725
|
}
|
|
3676
3726
|
function rowToScoreRecord(row) {
|
|
3677
3727
|
return {
|
|
3728
|
+
scoreId: row.scoreId,
|
|
3678
3729
|
timestamp: toDate(row.timestamp),
|
|
3679
3730
|
// Core score/feedback shapes still type traceId as required for now.
|
|
3680
3731
|
traceId: nullableString(row.traceId),
|
|
@@ -3717,6 +3768,7 @@ function scoreRecordToRow(score) {
|
|
|
3717
3768
|
const metadata = score.metadata ?? null;
|
|
3718
3769
|
const scoreSource = score.scoreSource ?? score.source ?? null;
|
|
3719
3770
|
return {
|
|
3771
|
+
scoreId: score.scoreId,
|
|
3720
3772
|
timestamp: toISOString(score.timestamp),
|
|
3721
3773
|
traceId: score.traceId ?? null,
|
|
3722
3774
|
spanId: score.spanId ?? null,
|
|
@@ -3759,6 +3811,7 @@ function rowToFeedbackRecord(row) {
|
|
|
3759
3811
|
const feedbackSource = nullableString(row.feedbackSource);
|
|
3760
3812
|
const feedbackUserId = nullableString(row.feedbackUserId) ?? nullableString(row.userId);
|
|
3761
3813
|
return {
|
|
3814
|
+
feedbackId: row.feedbackId,
|
|
3762
3815
|
timestamp: toDate(row.timestamp),
|
|
3763
3816
|
// Core score/feedback shapes still type traceId as required for now.
|
|
3764
3817
|
traceId: nullableString(row.traceId),
|
|
@@ -3802,6 +3855,7 @@ function feedbackRecordToRow(feedback) {
|
|
|
3802
3855
|
const feedbackSource = feedback.feedbackSource ?? feedback.source ?? "";
|
|
3803
3856
|
const feedbackUserId = feedback.feedbackUserId ?? feedback.userId ?? null;
|
|
3804
3857
|
return {
|
|
3858
|
+
feedbackId: feedback.feedbackId,
|
|
3805
3859
|
timestamp: toISOString(feedback.timestamp),
|
|
3806
3860
|
traceId: feedback.traceId ?? null,
|
|
3807
3861
|
spanId: feedback.spanId ?? null,
|
|
@@ -4921,6 +4975,93 @@ async function getMetricLabelValues(client, args) {
|
|
|
4921
4975
|
);
|
|
4922
4976
|
return { values: rows.map((r) => r.value) };
|
|
4923
4977
|
}
|
|
4978
|
+
var SIGNAL_MIGRATIONS = [
|
|
4979
|
+
{ table: TABLE_METRIC_EVENTS, createDDL: METRIC_EVENTS_DDL, idColumn: "metricId" },
|
|
4980
|
+
{ table: TABLE_LOG_EVENTS, createDDL: LOG_EVENTS_DDL, idColumn: "logId" },
|
|
4981
|
+
{ table: TABLE_SCORE_EVENTS, createDDL: SCORE_EVENTS_DDL, idColumn: "scoreId" },
|
|
4982
|
+
{ table: TABLE_FEEDBACK_EVENTS, createDDL: FEEDBACK_EVENTS_DDL, idColumn: "feedbackId" }
|
|
4983
|
+
];
|
|
4984
|
+
async function getTableEngine(client, table) {
|
|
4985
|
+
const result = await client.query({
|
|
4986
|
+
query: `SELECT engine FROM system.tables WHERE database = currentDatabase() AND name = {table:String}`,
|
|
4987
|
+
query_params: { table },
|
|
4988
|
+
format: "JSONEachRow"
|
|
4989
|
+
});
|
|
4990
|
+
const rows = await result.json();
|
|
4991
|
+
return rows[0]?.engine ?? null;
|
|
4992
|
+
}
|
|
4993
|
+
async function getTableColumns(client, table) {
|
|
4994
|
+
const result = await client.query({ query: `DESCRIBE TABLE ${table}`, format: "JSONEachRow" });
|
|
4995
|
+
const rows = await result.json();
|
|
4996
|
+
return rows.map((r) => r.name);
|
|
4997
|
+
}
|
|
4998
|
+
function buildTemporaryTableDDL(createDDL, table, tempTable) {
|
|
4999
|
+
return createDDL.replace(`CREATE TABLE IF NOT EXISTS ${table}`, `CREATE TABLE ${tempTable}`);
|
|
5000
|
+
}
|
|
5001
|
+
async function dropTableIfExists(client, table) {
|
|
5002
|
+
if (await getTableEngine(client, table) !== null) {
|
|
5003
|
+
await client.command({ query: `DROP TABLE ${table}` });
|
|
5004
|
+
}
|
|
5005
|
+
}
|
|
5006
|
+
function createMigrationError(args, error) {
|
|
5007
|
+
return new MastraError(
|
|
5008
|
+
{
|
|
5009
|
+
id: createStorageErrorId("CLICKHOUSE", "MIGRATE_SIGNAL_TABLES", "FAILED"),
|
|
5010
|
+
domain: ErrorDomain.STORAGE,
|
|
5011
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
5012
|
+
details: args
|
|
5013
|
+
},
|
|
5014
|
+
error
|
|
5015
|
+
);
|
|
5016
|
+
}
|
|
5017
|
+
async function checkSignalTablesMigrationStatus(client) {
|
|
5018
|
+
const tables = [];
|
|
5019
|
+
for (const { table, idColumn } of SIGNAL_MIGRATIONS) {
|
|
5020
|
+
const engine = await getTableEngine(client, table);
|
|
5021
|
+
if (!engine || engine === "ReplacingMergeTree") {
|
|
5022
|
+
continue;
|
|
5023
|
+
}
|
|
5024
|
+
tables.push({ table, engine, idColumn });
|
|
5025
|
+
}
|
|
5026
|
+
return {
|
|
5027
|
+
needsMigration: tables.length > 0,
|
|
5028
|
+
tables
|
|
5029
|
+
};
|
|
5030
|
+
}
|
|
5031
|
+
async function migrateSignalTables(client, logger) {
|
|
5032
|
+
for (const { table, createDDL, idColumn } of SIGNAL_MIGRATIONS) {
|
|
5033
|
+
const engine = await getTableEngine(client, table);
|
|
5034
|
+
if (!engine || engine === "ReplacingMergeTree") continue;
|
|
5035
|
+
logger?.info?.(`Migrating ${table} from ${engine} to ReplacingMergeTree with ${idColumn} column`);
|
|
5036
|
+
const temp = `${table}_migrating_${Date.now()}`;
|
|
5037
|
+
try {
|
|
5038
|
+
await client.command({ query: buildTemporaryTableDDL(createDDL, table, temp) });
|
|
5039
|
+
const newColumns = await getTableColumns(client, temp);
|
|
5040
|
+
const currentColumns = new Set(await getTableColumns(client, table));
|
|
5041
|
+
const columnList = newColumns.map((c) => `"${c}"`).join(", ");
|
|
5042
|
+
const selectExprs = newColumns.map((c) => {
|
|
5043
|
+
if (c === idColumn) {
|
|
5044
|
+
return currentColumns.has(c) ? `COALESCE(nullIf("${c}", ''), toString(generateUUIDv4())) AS "${c}"` : `toString(generateUUIDv4()) AS "${c}"`;
|
|
5045
|
+
}
|
|
5046
|
+
return currentColumns.has(c) ? `"${c}"` : `NULL AS "${c}"`;
|
|
5047
|
+
}).join(", ");
|
|
5048
|
+
await client.command({
|
|
5049
|
+
query: `INSERT INTO ${temp} (${columnList}) SELECT ${selectExprs} FROM ${table}`
|
|
5050
|
+
});
|
|
5051
|
+
await client.command({ query: `EXCHANGE TABLES ${temp} AND ${table}` });
|
|
5052
|
+
await client.command({ query: `DROP TABLE ${temp}` });
|
|
5053
|
+
logger?.info?.(`Successfully migrated ${table}`);
|
|
5054
|
+
} catch (error) {
|
|
5055
|
+
logger?.error?.(`Migration of ${table} failed: ${error.message}`);
|
|
5056
|
+
try {
|
|
5057
|
+
await dropTableIfExists(client, temp);
|
|
5058
|
+
} catch (restoreError) {
|
|
5059
|
+
logger?.error?.(`Failed to clean up temporary table ${temp}: ${restoreError.message}`);
|
|
5060
|
+
}
|
|
5061
|
+
throw createMigrationError({ table, idColumn }, error);
|
|
5062
|
+
}
|
|
5063
|
+
}
|
|
5064
|
+
}
|
|
4924
5065
|
var SCORE_TYPED_COLUMNS = /* @__PURE__ */ new Set([
|
|
4925
5066
|
"timestamp",
|
|
4926
5067
|
"traceId",
|
|
@@ -5384,6 +5525,31 @@ async function getTrace(client, args) {
|
|
|
5384
5525
|
const spans = rows.map(rowToSpanRecord);
|
|
5385
5526
|
return { traceId: args.traceId, spans };
|
|
5386
5527
|
}
|
|
5528
|
+
async function getTraceLight(client, args) {
|
|
5529
|
+
const result = await client.query({
|
|
5530
|
+
query: `
|
|
5531
|
+
SELECT traceId, spanId, parentSpanId, name,
|
|
5532
|
+
entityType, entityId, entityName,
|
|
5533
|
+
spanType, error, isEvent,
|
|
5534
|
+
startedAt, endedAt
|
|
5535
|
+
FROM (
|
|
5536
|
+
SELECT *
|
|
5537
|
+
FROM ${TABLE_SPAN_EVENTS}
|
|
5538
|
+
WHERE traceId = {traceId:String}
|
|
5539
|
+
ORDER BY dedupeKey, endedAt DESC
|
|
5540
|
+
LIMIT 1 BY dedupeKey
|
|
5541
|
+
)
|
|
5542
|
+
ORDER BY startedAt ASC
|
|
5543
|
+
`,
|
|
5544
|
+
query_params: { traceId: args.traceId },
|
|
5545
|
+
format: "JSONEachRow",
|
|
5546
|
+
clickhouse_settings: CH_SETTINGS
|
|
5547
|
+
});
|
|
5548
|
+
const rows = await result.json();
|
|
5549
|
+
if (!rows || rows.length === 0) return null;
|
|
5550
|
+
const spans = rows.map(rowToSpanRecord);
|
|
5551
|
+
return { traceId: args.traceId, spans };
|
|
5552
|
+
}
|
|
5387
5553
|
async function batchDeleteTraces(client, args) {
|
|
5388
5554
|
if (args.traceIds.length === 0) return;
|
|
5389
5555
|
const params = {};
|
|
@@ -5412,6 +5578,32 @@ async function batchDeleteTraces(client, args) {
|
|
|
5412
5578
|
}
|
|
5413
5579
|
|
|
5414
5580
|
// src/storage/domains/observability/v-next/index.ts
|
|
5581
|
+
function buildSignalMigrationRequiredMessage(args) {
|
|
5582
|
+
const tableList = args.tables.map((table) => ` - ${table.table} (${table.engine})`).join("\n");
|
|
5583
|
+
return `
|
|
5584
|
+
===========================================================================
|
|
5585
|
+
MIGRATION REQUIRED: ${args.store} observability signal tables need signal IDs
|
|
5586
|
+
===========================================================================
|
|
5587
|
+
|
|
5588
|
+
The following signal tables still use the legacy schema and must be migrated
|
|
5589
|
+
before observability storage can initialize:
|
|
5590
|
+
|
|
5591
|
+
${tableList}
|
|
5592
|
+
|
|
5593
|
+
To fix this, run the manual migration command:
|
|
5594
|
+
|
|
5595
|
+
npx mastra migrate
|
|
5596
|
+
|
|
5597
|
+
This command will:
|
|
5598
|
+
1. Create replacement signal tables with signal-ID dedupe keys
|
|
5599
|
+
2. Backfill missing signal IDs for legacy rows
|
|
5600
|
+
3. Swap the migrated tables into place
|
|
5601
|
+
|
|
5602
|
+
WARNING: This migration recreates the signal tables and may take significant
|
|
5603
|
+
time for large databases. Please ensure you have a backup before proceeding.
|
|
5604
|
+
===========================================================================
|
|
5605
|
+
`;
|
|
5606
|
+
}
|
|
5415
5607
|
var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
5416
5608
|
#client;
|
|
5417
5609
|
#retention;
|
|
@@ -5425,6 +5617,18 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
5425
5617
|
// Initialization
|
|
5426
5618
|
// -------------------------------------------------------------------------
|
|
5427
5619
|
async init() {
|
|
5620
|
+
const migrationStatus = await checkSignalTablesMigrationStatus(this.#client);
|
|
5621
|
+
if (migrationStatus.needsMigration) {
|
|
5622
|
+
throw new MastraError({
|
|
5623
|
+
id: createStorageErrorId("CLICKHOUSE", "MIGRATION_REQUIRED", "SIGNAL_TABLES"),
|
|
5624
|
+
domain: ErrorDomain.STORAGE,
|
|
5625
|
+
category: ErrorCategory.USER,
|
|
5626
|
+
text: buildSignalMigrationRequiredMessage({
|
|
5627
|
+
store: "ClickHouse",
|
|
5628
|
+
tables: migrationStatus.tables.map(({ table, engine }) => ({ table, engine }))
|
|
5629
|
+
})
|
|
5630
|
+
});
|
|
5631
|
+
}
|
|
5428
5632
|
try {
|
|
5429
5633
|
for (const ddl of [...ALL_TABLE_DDL, ...ALL_MV_DDL]) {
|
|
5430
5634
|
await this.#client.command({ query: ddl });
|
|
@@ -5439,6 +5643,9 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
5439
5643
|
}
|
|
5440
5644
|
}
|
|
5441
5645
|
} catch (error) {
|
|
5646
|
+
if (error instanceof MastraError) {
|
|
5647
|
+
throw error;
|
|
5648
|
+
}
|
|
5442
5649
|
throw new MastraError(
|
|
5443
5650
|
{
|
|
5444
5651
|
id: createStorageErrorId("CLICKHOUSE", "VNEXT_INIT", "FAILED"),
|
|
@@ -5460,6 +5667,29 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
5460
5667
|
} catch {
|
|
5461
5668
|
}
|
|
5462
5669
|
}
|
|
5670
|
+
/**
|
|
5671
|
+
* Manually migrate legacy signal tables to the signal-ID ReplacingMergeTree schema.
|
|
5672
|
+
* The public method name is historical; the CLI still calls `migrateSpans()`
|
|
5673
|
+
* for observability migrations even though this now also migrates signal tables.
|
|
5674
|
+
*/
|
|
5675
|
+
async migrateSpans() {
|
|
5676
|
+
const migrationStatus = await checkSignalTablesMigrationStatus(this.#client);
|
|
5677
|
+
if (!migrationStatus.needsMigration) {
|
|
5678
|
+
return {
|
|
5679
|
+
success: true,
|
|
5680
|
+
alreadyMigrated: true,
|
|
5681
|
+
duplicatesRemoved: 0,
|
|
5682
|
+
message: "Migration already complete. Signal tables already use signal-ID dedupe keys."
|
|
5683
|
+
};
|
|
5684
|
+
}
|
|
5685
|
+
await migrateSignalTables(this.#client, this.logger);
|
|
5686
|
+
return {
|
|
5687
|
+
success: true,
|
|
5688
|
+
alreadyMigrated: false,
|
|
5689
|
+
duplicatesRemoved: 0,
|
|
5690
|
+
message: `Migration complete. Migrated signal tables: ${migrationStatus.tables.map((t) => t.table).join(", ")}.`
|
|
5691
|
+
};
|
|
5692
|
+
}
|
|
5463
5693
|
// -------------------------------------------------------------------------
|
|
5464
5694
|
// Strategy
|
|
5465
5695
|
// -------------------------------------------------------------------------
|
|
@@ -5555,6 +5785,22 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
5555
5785
|
);
|
|
5556
5786
|
}
|
|
5557
5787
|
}
|
|
5788
|
+
async getTraceLight(args) {
|
|
5789
|
+
try {
|
|
5790
|
+
return await getTraceLight(this.#client, args);
|
|
5791
|
+
} catch (error) {
|
|
5792
|
+
if (error instanceof MastraError) throw error;
|
|
5793
|
+
throw new MastraError(
|
|
5794
|
+
{
|
|
5795
|
+
id: createStorageErrorId("CLICKHOUSE", "GET_TRACE_LIGHT", "FAILED"),
|
|
5796
|
+
domain: ErrorDomain.STORAGE,
|
|
5797
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
5798
|
+
details: { traceId: args.traceId }
|
|
5799
|
+
},
|
|
5800
|
+
error
|
|
5801
|
+
);
|
|
5802
|
+
}
|
|
5803
|
+
}
|
|
5558
5804
|
async listTraces(args) {
|
|
5559
5805
|
try {
|
|
5560
5806
|
return await listTraces(this.#client, args);
|