@mastra/clickhouse 1.28.0-alpha.0 → 1.28.0-alpha.2
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 +83 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +83 -20
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/preview-compat.d.ts +3 -0
- package/dist/storage/domains/observability/v-next/preview-compat.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/span-query.d.ts +3 -0
- package/dist/storage/domains/observability/v-next/span-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-aggregate.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +7 -0
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -759,6 +759,7 @@ var ClickhouseDB = class extends MastraBase {
|
|
|
759
759
|
const rawUpdatedAt = filteredRecord.updatedAt || /* @__PURE__ */ new Date();
|
|
760
760
|
if ("createdAt" in filteredRecord || (await this.getTableColumns(tableName)).has("createdAt")) filteredRecord.createdAt = rawCreatedAt instanceof Date ? rawCreatedAt.toISOString() : rawCreatedAt;
|
|
761
761
|
if ("updatedAt" in filteredRecord || (await this.getTableColumns(tableName)).has("updatedAt")) filteredRecord.updatedAt = rawUpdatedAt instanceof Date ? rawUpdatedAt.toISOString() : rawUpdatedAt;
|
|
762
|
+
for (const [key, value] of Object.entries(filteredRecord)) if (TABLE_SCHEMAS[tableName]?.[key]?.type === "timestamp" && typeof value === "number") filteredRecord[key] = new Date(value).toISOString();
|
|
762
763
|
await this.client.insert({
|
|
763
764
|
table: tableName,
|
|
764
765
|
values: [filteredRecord],
|
|
@@ -2271,12 +2272,12 @@ var ObservabilityStorageClickhouse = class extends ObservabilityStorage {
|
|
|
2271
2272
|
}
|
|
2272
2273
|
});
|
|
2273
2274
|
const data = { ...updates };
|
|
2274
|
-
if (data.endedAt instanceof Date) data.endedAt = data.endedAt.
|
|
2275
|
-
if (data.startedAt instanceof Date) data.startedAt = data.startedAt.
|
|
2275
|
+
if (data.endedAt instanceof Date) data.endedAt = data.endedAt.toISOString();
|
|
2276
|
+
if (data.startedAt instanceof Date) data.startedAt = data.startedAt.toISOString();
|
|
2276
2277
|
const updated = {
|
|
2277
2278
|
...existing,
|
|
2278
2279
|
...data,
|
|
2279
|
-
updatedAt: Date.
|
|
2280
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2280
2281
|
};
|
|
2281
2282
|
await this.client.insert({
|
|
2282
2283
|
table: TABLE_SPANS,
|
|
@@ -2514,7 +2515,7 @@ var ObservabilityStorageClickhouse = class extends ObservabilityStorage {
|
|
|
2514
2515
|
}
|
|
2515
2516
|
async batchUpdateSpans(args) {
|
|
2516
2517
|
try {
|
|
2517
|
-
const now = Date.
|
|
2518
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2518
2519
|
if (args.records.length === 0) return;
|
|
2519
2520
|
const keyParams = {};
|
|
2520
2521
|
const keyTuples = args.records.map((record, i) => {
|
|
@@ -2547,8 +2548,8 @@ var ObservabilityStorageClickhouse = class extends ObservabilityStorage {
|
|
|
2547
2548
|
const existing = current.get(key);
|
|
2548
2549
|
if (!existing) continue;
|
|
2549
2550
|
const updates = { ...record.updates };
|
|
2550
|
-
if (updates.startedAt instanceof Date) updates.startedAt = updates.startedAt.
|
|
2551
|
-
if (updates.endedAt instanceof Date) updates.endedAt = updates.endedAt.
|
|
2551
|
+
if (updates.startedAt instanceof Date) updates.startedAt = updates.startedAt.toISOString();
|
|
2552
|
+
if (updates.endedAt instanceof Date) updates.endedAt = updates.endedAt.toISOString();
|
|
2552
2553
|
current.set(key, {
|
|
2553
2554
|
...existing,
|
|
2554
2555
|
...updates,
|
|
@@ -6915,6 +6916,13 @@ const timingFeatures = [
|
|
|
6915
6916
|
...timeToFirstTokenSupported ? ["trace-query-time-to-first-token"] : [],
|
|
6916
6917
|
...timeToFirstTokenSupported && timeToFirstTokenSortSupported ? ["trace-query-time-to-first-token-sort"] : []
|
|
6917
6918
|
];
|
|
6919
|
+
/**
|
|
6920
|
+
* Outcome fields follow the same rule: core before them rejects their predicates and strict rows,
|
|
6921
|
+
* so they are only returned and declared when core knows them.
|
|
6922
|
+
*/
|
|
6923
|
+
const spanQueryOutcomeFieldsSupported = "outcome" in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {});
|
|
6924
|
+
const traceQueryOutcomeFieldsSupported = "outcome" in (coreStorage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});
|
|
6925
|
+
const outcomeFeatures = [...spanQueryOutcomeFieldsSupported ? ["span-query-outcome-fields"] : [], ...traceQueryOutcomeFieldsSupported ? ["trace-query-outcome-fields"] : []];
|
|
6918
6926
|
/** Order fields holding numbers that can be empty; the rest are timestamps. */
|
|
6919
6927
|
const NUMERIC_ORDER_FIELDS = /* @__PURE__ */ new Set(["timeToFirstChunkMs", "timeToFirstTokenMs"]);
|
|
6920
6928
|
function durationMsSql(startedAt, endedAt) {
|
|
@@ -7001,6 +7009,14 @@ const TRACE_FIELDS = {
|
|
|
7001
7009
|
sql: TRACE_STATUS_SQL,
|
|
7002
7010
|
parameterType: "String"
|
|
7003
7011
|
},
|
|
7012
|
+
outcome: {
|
|
7013
|
+
sql: "r.outcome",
|
|
7014
|
+
parameterType: "String"
|
|
7015
|
+
},
|
|
7016
|
+
stopReason: {
|
|
7017
|
+
sql: "r.stopReason",
|
|
7018
|
+
parameterType: "String"
|
|
7019
|
+
},
|
|
7004
7020
|
tags: {
|
|
7005
7021
|
sql: "r.tags",
|
|
7006
7022
|
parameterType: "String"
|
|
@@ -7047,6 +7063,14 @@ const SPAN_FIELDS = {
|
|
|
7047
7063
|
sql: "s.status",
|
|
7048
7064
|
parameterType: "String"
|
|
7049
7065
|
},
|
|
7066
|
+
outcome: {
|
|
7067
|
+
sql: "s.outcome",
|
|
7068
|
+
parameterType: "String"
|
|
7069
|
+
},
|
|
7070
|
+
stopReason: {
|
|
7071
|
+
sql: "s.stopReason",
|
|
7072
|
+
parameterType: "String"
|
|
7073
|
+
},
|
|
7050
7074
|
error: {
|
|
7051
7075
|
sql: "s.error",
|
|
7052
7076
|
parameterType: "String"
|
|
@@ -7256,6 +7280,9 @@ const TRACE_SELECT = `
|
|
|
7256
7280
|
r.environment AS environment,
|
|
7257
7281
|
r.timeToFirstChunkMs AS timeToFirstChunkMs,
|
|
7258
7282
|
r.timeToFirstTokenMs AS timeToFirstTokenMs,
|
|
7283
|
+
r.outcome AS outcome,
|
|
7284
|
+
r.stopReason AS stopReason,
|
|
7285
|
+
r.stopReasonContext AS stopReasonContext,
|
|
7259
7286
|
${TRACE_STATUS_SQL} AS status`;
|
|
7260
7287
|
var ParameterBuilder = class {
|
|
7261
7288
|
params = {};
|
|
@@ -7456,14 +7483,16 @@ function compileClickHouseTraceScope(selection, relationCollections, parameters,
|
|
|
7456
7483
|
traceId,
|
|
7457
7484
|
name,
|
|
7458
7485
|
spanType,
|
|
7459
|
-
if(JSONType(attributes, 'model') = 'String', JSONExtractString(attributes, 'model'), NULL) AS model,
|
|
7460
|
-
if(JSONType(attributes, 'provider') = 'String', JSONExtractString(attributes, 'provider'), NULL) AS provider,
|
|
7486
|
+
coalesce(model, if(JSONType(attributes, 'model') = 'String', JSONExtractString(attributes, 'model'), NULL)) AS model,
|
|
7487
|
+
coalesce(provider, if(JSONType(attributes, 'provider') = 'String', JSONExtractString(attributes, 'provider'), NULL)) AS provider,
|
|
7461
7488
|
startedAt,
|
|
7462
7489
|
endedAt,
|
|
7463
7490
|
${durationMsSql("startedAt", "endedAt")} AS durationMs,
|
|
7464
7491
|
timeToFirstChunkMs,
|
|
7465
7492
|
timeToFirstTokenMs,
|
|
7466
7493
|
if(isNotNull(error), 'error', 'success') AS status,
|
|
7494
|
+
outcome,
|
|
7495
|
+
stopReason,
|
|
7467
7496
|
error,
|
|
7468
7497
|
entityType,
|
|
7469
7498
|
entityId,
|
|
@@ -7567,7 +7596,7 @@ const QUERY_TRACES_SCOPE = {
|
|
|
7567
7596
|
oneRootPerTrace: true,
|
|
7568
7597
|
spanExistence: true
|
|
7569
7598
|
};
|
|
7570
|
-
const TRACE_LIST_SELECT = TRACE_SELECT.split("\n").filter((line) => !/ AS (metadata|inputPreview|outputPreview|errorPreview),$/.test(line)).join("\n");
|
|
7599
|
+
const TRACE_LIST_SELECT = TRACE_SELECT.split("\n").filter((line) => !/ AS (metadata|inputPreview|outputPreview|errorPreview|stopReasonContext),$/.test(line)).join("\n");
|
|
7571
7600
|
function traceOrder(plan) {
|
|
7572
7601
|
return {
|
|
7573
7602
|
field: resolveOrderField(plan.orderBy.field),
|
|
@@ -7727,7 +7756,7 @@ function compileClickHouseTraceRootPayloads(keys, scope, columns = "payload") {
|
|
|
7727
7756
|
const tenant = (value) => `${parameters.add(value ?? "", "String")}, ${value === null ? 1 : 0}`;
|
|
7728
7757
|
const tuples = keys.map((key) => `(${parameters.add(key.startedAt, "DateTime64(3, 'UTC')")}, ${parameters.add(key.traceId, "String")}, ${parameters.add(key.dedupeKey, "String")}, ${parameters.add(key.endedAt, "DateTime64(3, 'UTC')")}, ${tenant(key.organizationId)}, ${tenant(key.resourceId)})`);
|
|
7729
7758
|
return {
|
|
7730
|
-
query: `SELECT traceId, spanId AS rootSpanId, dedupeKey, organizationId, resourceId, ${columns === "payload" ? `metadataRaw AS metadata, ${PREVIEW_COLUMNS.join(", ")}` : "input, output, error"}
|
|
7759
|
+
query: `SELECT traceId, spanId AS rootSpanId, dedupeKey, organizationId, resourceId, ${columns === "payload" ? `metadataRaw AS metadata, stopReasonContext, ${PREVIEW_COLUMNS.join(", ")}` : "input, output, error"}
|
|
7731
7760
|
FROM ${TABLE_TRACE_ROOTS}
|
|
7732
7761
|
WHERE (startedAt, traceId, dedupeKey, endedAt, ifNull(organizationId, ''), isNull(organizationId), ifNull(resourceId, ''), isNull(resourceId)) IN (${tuples.join(", ")})${compileTenantScope(scope, parameters)}
|
|
7733
7762
|
ORDER BY ${ROOT_VERSION_ORDER}
|
|
@@ -7994,7 +8023,12 @@ async function queryTraces(client, plan, timeoutMs, strategy = null) {
|
|
|
7994
8023
|
environment: row.environment == null ? null : String(row.environment),
|
|
7995
8024
|
status: row.status,
|
|
7996
8025
|
...timeToFirstChunkSupported && { timeToFirstChunkMs: row.timeToFirstChunkMs == null ? null : Number(row.timeToFirstChunkMs) },
|
|
7997
|
-
...timeToFirstTokenSupported && { timeToFirstTokenMs: row.timeToFirstTokenMs == null ? null : Number(row.timeToFirstTokenMs) }
|
|
8026
|
+
...timeToFirstTokenSupported && { timeToFirstTokenMs: row.timeToFirstTokenMs == null ? null : Number(row.timeToFirstTokenMs) },
|
|
8027
|
+
...traceQueryOutcomeFieldsSupported && {
|
|
8028
|
+
outcome: row.outcome == null ? null : String(row.outcome),
|
|
8029
|
+
stopReason: row.stopReason == null ? null : String(row.stopReason),
|
|
8030
|
+
stopReasonContext: parseJson(row.stopReasonContext) ?? null
|
|
8031
|
+
}
|
|
7998
8032
|
});
|
|
7999
8033
|
if (plan.paginationMode === "delta") {
|
|
8000
8034
|
const rows = await run(compileClickHouseTraceQuery(plan, deltaHead));
|
|
@@ -8121,7 +8155,10 @@ const displayFields = [
|
|
|
8121
8155
|
"durationMs",
|
|
8122
8156
|
"timeToFirstChunkMs",
|
|
8123
8157
|
"timeToFirstTokenMs",
|
|
8124
|
-
"status"
|
|
8158
|
+
"status",
|
|
8159
|
+
"outcome",
|
|
8160
|
+
"stopReason",
|
|
8161
|
+
"stopReasonContext"
|
|
8125
8162
|
];
|
|
8126
8163
|
var Parameters = class {
|
|
8127
8164
|
values = {};
|
|
@@ -8173,13 +8210,18 @@ function predicateFields$1(predicate, fields = /* @__PURE__ */ new Set()) {
|
|
|
8173
8210
|
else fields.add(predicate.field);
|
|
8174
8211
|
return fields;
|
|
8175
8212
|
}
|
|
8213
|
+
/** Selection and filter expressions read only columns; `model`/`provider` read their dedicated columns. */
|
|
8176
8214
|
function fieldExpression(field) {
|
|
8177
|
-
if (field === "model" || field === "provider") return `if(JSONType(e.attributes, '${field}') = 'String', JSONExtractString(e.attributes, '${field}'), NULL)`;
|
|
8178
8215
|
if (field === "durationMs") return "dateDiff('millisecond', e.startedAt, e.endedAt)";
|
|
8179
8216
|
if (field === "status") return "if(isNull(e.error), 'success', 'error')";
|
|
8180
8217
|
if (field === "error") return "if(isNull(e.error), NULL, 'error')";
|
|
8181
8218
|
return `e.${field}`;
|
|
8182
8219
|
}
|
|
8220
|
+
/** Returned values fall back to span attributes for rows written before the dedicated columns existed. */
|
|
8221
|
+
function displayExpression(field) {
|
|
8222
|
+
if (field === "model" || field === "provider") return `coalesce(e.${field}, if(JSONType(e.attributes, '${field}') = 'String', JSONExtractString(e.attributes, '${field}'), NULL))`;
|
|
8223
|
+
return fieldExpression(field);
|
|
8224
|
+
}
|
|
8183
8225
|
function compileClickHouseSpanQuery(plan) {
|
|
8184
8226
|
const parameters = new Parameters();
|
|
8185
8227
|
const from = parameters.add(plan.timeRange.from, "DateTime64(3, 'UTC')");
|
|
@@ -8266,7 +8308,11 @@ const TRACE_BRANCHES_SPAN_FIELD_COLUMNS = {
|
|
|
8266
8308
|
"rootEntityType",
|
|
8267
8309
|
"rootEntityId",
|
|
8268
8310
|
"rootEntityName",
|
|
8269
|
-
"rootEntityVersionId"
|
|
8311
|
+
"rootEntityVersionId",
|
|
8312
|
+
"model",
|
|
8313
|
+
"provider",
|
|
8314
|
+
"outcome",
|
|
8315
|
+
"stopReason"
|
|
8270
8316
|
].map((field) => [field, sameColumn(field)])),
|
|
8271
8317
|
status: ["error"],
|
|
8272
8318
|
error: ["error"],
|
|
@@ -8379,7 +8425,7 @@ async function querySpans(client, plan, timeoutMs) {
|
|
|
8379
8425
|
const pageParameter = (rows) => rows.map((row) => new TupleParam([...identityValues(row), row.endedAt.replace("T", " ").replace(/Z$/, "")]));
|
|
8380
8426
|
const rowsWithPreviews = await run({
|
|
8381
8427
|
query: `SELECT ${identities}, ${[...displayFields, ...PREVIEW_COLUMNS].map((field, index) => `data.${index + 1} AS ${field}`).join(", ")}
|
|
8382
|
-
FROM (SELECT ${identities}, any(tuple(${[...displayFields.map(
|
|
8428
|
+
FROM (SELECT ${identities}, any(tuple(${[...displayFields.map(displayExpression), ...PREVIEW_COLUMNS].join(", ")})) AS data
|
|
8383
8429
|
FROM ${TABLE_SPAN_EVENTS} e WHERE ${payloadWhere} GROUP BY ${identities})`,
|
|
8384
8430
|
query_params: { page: pageParameter(page) }
|
|
8385
8431
|
});
|
|
@@ -8406,13 +8452,18 @@ async function querySpans(client, plan, timeoutMs) {
|
|
|
8406
8452
|
const hydrated = page.flatMap((identity) => {
|
|
8407
8453
|
const row = byIdentity.get(coreStorage.spanQueryIdentityKey(identity));
|
|
8408
8454
|
if (!row) return [];
|
|
8409
|
-
const { inputPreview: _input, outputPreview: _output, errorPreview: _error, timeToFirstChunkMs, timeToFirstTokenMs, ...metadata } = row;
|
|
8455
|
+
const { inputPreview: _input, outputPreview: _output, errorPreview: _error, timeToFirstChunkMs, timeToFirstTokenMs, outcome, stopReason, stopReasonContext, ...metadata } = row;
|
|
8410
8456
|
return [{
|
|
8411
8457
|
...metadata,
|
|
8412
8458
|
...identity,
|
|
8413
8459
|
durationMs: Number(row.durationMs),
|
|
8414
8460
|
...timeToFirstChunkSupported && { timeToFirstChunkMs: timeToFirstChunkMs == null ? null : Number(timeToFirstChunkMs) },
|
|
8415
|
-
...timeToFirstTokenSupported && { timeToFirstTokenMs: timeToFirstTokenMs == null ? null : Number(timeToFirstTokenMs) }
|
|
8461
|
+
...timeToFirstTokenSupported && { timeToFirstTokenMs: timeToFirstTokenMs == null ? null : Number(timeToFirstTokenMs) },
|
|
8462
|
+
...spanQueryOutcomeFieldsSupported && {
|
|
8463
|
+
outcome: outcome ?? null,
|
|
8464
|
+
stopReason: stopReason ?? null,
|
|
8465
|
+
stopReasonContext: parseJson(stopReasonContext) ?? null
|
|
8466
|
+
}
|
|
8416
8467
|
}];
|
|
8417
8468
|
});
|
|
8418
8469
|
let metrics = [];
|
|
@@ -8727,6 +8778,8 @@ const DIMENSION_SQL = {
|
|
|
8727
8778
|
entityId: "r.entityId",
|
|
8728
8779
|
environment: "r.environment",
|
|
8729
8780
|
status: TRACE_STATUS_SQL,
|
|
8781
|
+
outcome: "r.outcome",
|
|
8782
|
+
stopReason: "r.stopReason",
|
|
8730
8783
|
serviceName: "r.serviceName",
|
|
8731
8784
|
executionSource: "r.executionSource",
|
|
8732
8785
|
threadId: "r.threadId",
|
|
@@ -8749,6 +8802,8 @@ const SPAN_DIMENSION_SQL = Object.fromEntries([
|
|
|
8749
8802
|
"rootEntityName",
|
|
8750
8803
|
"environment",
|
|
8751
8804
|
"status",
|
|
8805
|
+
"outcome",
|
|
8806
|
+
"stopReason",
|
|
8752
8807
|
"serviceName",
|
|
8753
8808
|
"executionSource",
|
|
8754
8809
|
"threadId",
|
|
@@ -8756,7 +8811,9 @@ const SPAN_DIMENSION_SQL = Object.fromEntries([
|
|
|
8756
8811
|
"userId",
|
|
8757
8812
|
"sessionId",
|
|
8758
8813
|
"organizationId",
|
|
8759
|
-
"experimentId"
|
|
8814
|
+
"experimentId",
|
|
8815
|
+
"model",
|
|
8816
|
+
"provider"
|
|
8760
8817
|
].map((field) => [field, `r.${field}`]));
|
|
8761
8818
|
const PERCENTILES = {
|
|
8762
8819
|
"duration.p50": .5,
|
|
@@ -9918,8 +9975,12 @@ function buildBranchCursor(row) {
|
|
|
9918
9975
|
return row.cursorId ?? "0";
|
|
9919
9976
|
}
|
|
9920
9977
|
// src/storage/domains/observability/v-next/index.ts
|
|
9921
|
-
const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? [
|
|
9922
|
-
|
|
9978
|
+
const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? [
|
|
9979
|
+
"span-query",
|
|
9980
|
+
"span-query-context-fields",
|
|
9981
|
+
..."model" in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {}) ? ["span-query-model-fields"] : []
|
|
9982
|
+
] : [];
|
|
9983
|
+
const spanAggregateFeatures = typeof coreStorage.planSpanAggregate === "function" ? ["span-aggregate", ..."model" in (coreStorage.SPAN_AGGREGATE_DIMENSION_REGISTRY ?? {}) ? ["span-aggregate-model-dimensions"] : []] : [];
|
|
9923
9984
|
const threadQueryFeatures = typeof coreStorage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [];
|
|
9924
9985
|
function buildSignalMigrationRequiredMessage(args) {
|
|
9925
9986
|
const tableList = args.tables.map((table) => ` - ${table.table} (${table.engine})`).join("\n");
|
|
@@ -10359,6 +10420,7 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
10359
10420
|
"feedback",
|
|
10360
10421
|
"trace-query-context-ids",
|
|
10361
10422
|
...timingFeatures,
|
|
10423
|
+
...outcomeFeatures,
|
|
10362
10424
|
"trace-query-root-span-fields",
|
|
10363
10425
|
"trace-query-root-entity-id",
|
|
10364
10426
|
"trace-aggregate",
|
|
@@ -10384,6 +10446,7 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
10384
10446
|
"feedback",
|
|
10385
10447
|
"trace-query-context-ids",
|
|
10386
10448
|
...timingFeatures,
|
|
10449
|
+
...outcomeFeatures,
|
|
10387
10450
|
"trace-query-root-span-fields",
|
|
10388
10451
|
"trace-query-root-entity-id",
|
|
10389
10452
|
"trace-aggregate",
|