@mastra/clickhouse 1.26.0-alpha.3 → 1.26.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/integrations-databases-clickhouse.md +1 -1
- package/dist/index.cjs +40 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +40 -25
- package/dist/index.js.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/span-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +3 -3
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6846,7 +6846,9 @@ const TRACE_STATUS_SQL = `if(isNotNull(r.error), 'error', 'success')`;
|
|
|
6846
6846
|
* Core before 1.68 has no field registry at all.
|
|
6847
6847
|
*/
|
|
6848
6848
|
const timeToFirstChunkSupported = "timeToFirstChunkMs" in (coreStorage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});
|
|
6849
|
-
|
|
6849
|
+
/** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */
|
|
6850
|
+
const timeToFirstChunkSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstChunkMs") === true;
|
|
6851
|
+
const timeToFirstChunkFeatures = timeToFirstChunkSupported ? timeToFirstChunkSortSupported ? ["trace-query-time-to-first-chunk", "trace-query-time-to-first-chunk-sort"] : ["trace-query-time-to-first-chunk"] : [];
|
|
6850
6852
|
function durationMsSql(startedAt, endedAt) {
|
|
6851
6853
|
return `dateDiff('millisecond', ${startedAt}, ${endedAt})`;
|
|
6852
6854
|
}
|
|
@@ -7189,7 +7191,7 @@ function fieldDefinition(registry, field) {
|
|
|
7189
7191
|
return definition;
|
|
7190
7192
|
}
|
|
7191
7193
|
function resolveOrderField(field) {
|
|
7192
|
-
if (field === "startedAt" || field === "endedAt") return field;
|
|
7194
|
+
if (field === "startedAt" || field === "endedAt" || field === "timeToFirstChunkMs") return field;
|
|
7193
7195
|
throw new Error(`Unsupported trusted trace-query field: ${field}`);
|
|
7194
7196
|
}
|
|
7195
7197
|
function isMetadataField(field) {
|
|
@@ -7467,9 +7469,11 @@ function traceOrder(plan) {
|
|
|
7467
7469
|
*/
|
|
7468
7470
|
function keysetCursorCondition(plan, order, parameters) {
|
|
7469
7471
|
if (plan.paginationMode !== "keyset" || !plan.cursor) return "";
|
|
7472
|
+
if (plan.cursor.sortValue === null) return `(isNull(sortValue) AND traceId > ${parameters.add(plan.cursor.traceId, "String")})`;
|
|
7473
|
+
const numeric = order.field === "timeToFirstChunkMs";
|
|
7470
7474
|
const comparison = order.direction === "ASC" ? ">" : "<";
|
|
7471
|
-
const sortValue = parameters.add(plan.cursor.sortValue, "DateTime64(3, 'UTC')");
|
|
7472
|
-
return `(sortValue ${comparison} ${sortValue} OR (sortValue = ${sortValue} AND traceId > ${parameters.add(plan.cursor.traceId, "String")}))`;
|
|
7475
|
+
const sortValue = parameters.add(plan.cursor.sortValue, numeric ? "Float64" : "DateTime64(3, 'UTC')");
|
|
7476
|
+
return `(sortValue ${comparison} ${sortValue} OR (sortValue = ${sortValue} AND traceId > ${parameters.add(plan.cursor.traceId, "String")})${numeric ? " OR isNull(sortValue)" : ""})`;
|
|
7473
7477
|
}
|
|
7474
7478
|
/**
|
|
7475
7479
|
* First statement of keyset and page mode: the page's traces (after the keyset cursor, `limit + 1`
|
|
@@ -7481,21 +7485,22 @@ function compileClickHouseTraceQueryKeys(plan) {
|
|
|
7481
7485
|
if (plan.paginationMode === "delta") throw new Error("Delta trace queries have no keys statement");
|
|
7482
7486
|
const parameters = new ParameterBuilder();
|
|
7483
7487
|
const order = traceOrder(plan);
|
|
7484
|
-
const ctes = compileClickHouseTraceCandidates(plan, "r.traceId AS traceId, r.dedupeKey AS dedupeKey, r.startedAt AS startedAt, r.endedAt AS endedAt", parameters, QUERY_TRACES_SCOPE);
|
|
7488
|
+
const ctes = compileClickHouseTraceCandidates(plan, "r.traceId AS traceId, r.dedupeKey AS dedupeKey, r.startedAt AS startedAt, r.endedAt AS endedAt, r.timeToFirstChunkMs AS timeToFirstChunkMs", parameters, QUERY_TRACES_SCOPE);
|
|
7485
7489
|
const cursor = keysetCursorCondition(plan, order, parameters);
|
|
7486
7490
|
const pick = order.direction === "DESC" ? "max" : "min";
|
|
7491
|
+
const rootOrder = order.field === "timeToFirstChunkMs" ? `ifNull(${order.field}, ${pick === "max" ? "-inf" : "inf"})` : order.field;
|
|
7487
7492
|
const limit = plan.paginationMode === "page" ? `LIMIT ${parameters.add(plan.perPage, "UInt64")} OFFSET ${parameters.add(plan.page * plan.perPage, "UInt64")}` : `LIMIT ${parameters.add(plan.limit + 1, "UInt64")}`;
|
|
7488
7493
|
return {
|
|
7489
7494
|
query: `WITH ${ctes.join(",\n")},
|
|
7490
7495
|
per_trace AS (
|
|
7491
7496
|
SELECT traceId, ${pick}(${order.field}) AS sortValue,
|
|
7492
|
-
${pick === "max" ? "argMax" : "argMin"}((dedupeKey, startedAt), ${
|
|
7497
|
+
${pick === "max" ? "argMax" : "argMin"}((dedupeKey, startedAt), ${rootOrder}) AS root
|
|
7493
7498
|
FROM candidates
|
|
7494
7499
|
GROUP BY traceId${cursor ? `\n HAVING ${cursor}` : ""}
|
|
7495
7500
|
)
|
|
7496
7501
|
SELECT traceId, root.1 AS dedupeKey, sortValue, root.2 AS rootStartedAt, count() OVER () AS __total
|
|
7497
7502
|
FROM per_trace
|
|
7498
|
-
ORDER BY sortValue ${order.direction}, traceId ASC
|
|
7503
|
+
ORDER BY sortValue ${order.direction} NULLS LAST, traceId ASC
|
|
7499
7504
|
${limit}`,
|
|
7500
7505
|
query_params: parameters.params,
|
|
7501
7506
|
sharedSnapshot: true
|
|
@@ -7513,16 +7518,16 @@ function compileClickHouseTraceRowsByKey(plan, keys) {
|
|
|
7513
7518
|
const ts = (value) => parameters.add(value, "DateTime64(3, 'UTC')");
|
|
7514
7519
|
const byEnd = order.field === "endedAt";
|
|
7515
7520
|
const tuples = keys.map((key) => {
|
|
7516
|
-
const started = ts(
|
|
7521
|
+
const started = ts(key.rootStartedAt);
|
|
7517
7522
|
const id = `${parameters.add(key.traceId, "String")}, ${parameters.add(key.dedupeKey, "String")}`;
|
|
7518
|
-
return byEnd ? `(${started}, ${id}, ${ts(key.sortValue)})` : `(${started}, ${id})`;
|
|
7523
|
+
return byEnd ? `(${started}, ${id}, ${ts(String(key.sortValue))})` : `(${started}, ${id})`;
|
|
7519
7524
|
});
|
|
7520
7525
|
const predicate = (plan.where ? (plan.where.type === "boolean" && plan.where.operator === "and" ? plan.where.args : [plan.where]).filter((conjunct) => collectRelationCollections(conjunct).size === 0) : []).map((conjunct) => `\n AND (${compilePredicate(conjunct, parameters)})`).join("");
|
|
7521
7526
|
return {
|
|
7522
7527
|
query: `SELECT ${TRACE_SELECT}
|
|
7523
7528
|
FROM ${TABLE_TRACE_ROOTS} r
|
|
7524
7529
|
WHERE (r.startedAt, r.traceId, r.dedupeKey${byEnd ? ", r.endedAt" : ""}) IN (${tuples.join(", ")})${compileTenantScope(plan.scope, parameters)}${predicate}
|
|
7525
|
-
ORDER BY ${order.field} ${order.direction}, traceId ASC
|
|
7530
|
+
ORDER BY ${order.field} ${order.direction} NULLS LAST, traceId ASC
|
|
7526
7531
|
LIMIT 1 BY traceId`,
|
|
7527
7532
|
query_params: parameters.params
|
|
7528
7533
|
};
|
|
@@ -7913,6 +7918,7 @@ async function queryTraces(client, plan, timeoutMs, strategy = null) {
|
|
|
7913
7918
|
});
|
|
7914
7919
|
}
|
|
7915
7920
|
const keys = await run(compileClickHouseTraceQueryKeys(plan));
|
|
7921
|
+
const sortValue = (value) => plan.orderBy.field !== "timeToFirstChunkMs" ? asIsoTimestamp(value) : value == null ? null : Number(value);
|
|
7916
7922
|
let total = Number(keys[0]?.__total ?? 0);
|
|
7917
7923
|
if (plan.paginationMode === "page" && keys.length === 0 && plan.page > 0) {
|
|
7918
7924
|
const [stats] = await run(compileClickHouseTraceQueryTotal(plan));
|
|
@@ -7922,7 +7928,7 @@ async function queryTraces(client, plan, timeoutMs, strategy = null) {
|
|
|
7922
7928
|
const rows = visible.length > 0 ? await run(compileClickHouseTraceRowsByKey(plan, visible.map((key) => ({
|
|
7923
7929
|
traceId: String(key.traceId),
|
|
7924
7930
|
dedupeKey: String(key.dedupeKey),
|
|
7925
|
-
sortValue:
|
|
7931
|
+
sortValue: sortValue(key.sortValue),
|
|
7926
7932
|
rootStartedAt: asIsoTimestamp(key.rootStartedAt)
|
|
7927
7933
|
})))) : [];
|
|
7928
7934
|
if (plan.paginationMode === "page") return coreStorage.traceQueryResponseSchema.parse({
|
|
@@ -7940,7 +7946,7 @@ async function queryTraces(client, plan, timeoutMs, strategy = null) {
|
|
|
7940
7946
|
traces: await toTraceRecords(rows),
|
|
7941
7947
|
page: { next: keys.length > plan.limit && lastKey ? coreStorage.encodeTraceQueryCursor(plan, {
|
|
7942
7948
|
result: "traces",
|
|
7943
|
-
sortValue:
|
|
7949
|
+
sortValue: sortValue(lastKey.sortValue),
|
|
7944
7950
|
traceId: String(lastKey.traceId)
|
|
7945
7951
|
}) : null }
|
|
7946
7952
|
});
|
|
@@ -8020,10 +8026,10 @@ const displayFields = [
|
|
|
8020
8026
|
];
|
|
8021
8027
|
var Parameters = class {
|
|
8022
8028
|
values = {};
|
|
8023
|
-
add(value,
|
|
8029
|
+
add(value, type = typeof value === "number" ? "UInt64" : "String") {
|
|
8024
8030
|
const name = `span_${Object.keys(this.values).length}`;
|
|
8025
|
-
this.values[name] =
|
|
8026
|
-
return `{${name}:${
|
|
8031
|
+
this.values[name] = type === "DateTime64(3, 'UTC')" ? new Date(value).toISOString().replace("T", " ").replace(/Z$/, "") : value;
|
|
8032
|
+
return `{${name}:${type}}`;
|
|
8027
8033
|
}
|
|
8028
8034
|
};
|
|
8029
8035
|
function identityValues(row) {
|
|
@@ -8039,10 +8045,17 @@ function identityValues(row) {
|
|
|
8039
8045
|
function afterCursor$1(plan, parameters) {
|
|
8040
8046
|
if (!plan.cursor) return "1";
|
|
8041
8047
|
const cursor = plan.cursor;
|
|
8042
|
-
const timestamp = parameters.add(cursor.sortValue, true);
|
|
8043
8048
|
const field = `s.${plan.orderBy.field}`;
|
|
8044
|
-
const terms = [
|
|
8045
|
-
const equal = [
|
|
8049
|
+
const terms = [];
|
|
8050
|
+
const equal = [];
|
|
8051
|
+
if (cursor.sortValue === null) equal.push(`isNull(${field})`);
|
|
8052
|
+
else {
|
|
8053
|
+
const numeric = plan.orderBy.field === "timeToFirstChunkMs";
|
|
8054
|
+
const value = parameters.add(cursor.sortValue, numeric ? "Float64" : "DateTime64(3, 'UTC')");
|
|
8055
|
+
terms.push(`${field} ${plan.orderBy.direction === "asc" ? ">" : "<"} ${value}`);
|
|
8056
|
+
if (numeric) terms.push(`isNull(${field})`);
|
|
8057
|
+
equal.push(`${field} = ${value}`);
|
|
8058
|
+
}
|
|
8046
8059
|
for (const key of identityFields) {
|
|
8047
8060
|
const value = cursor[key];
|
|
8048
8061
|
if (value === null) equal.push(`isNull(s.${key})`);
|
|
@@ -8070,8 +8083,8 @@ function fieldExpression(field) {
|
|
|
8070
8083
|
}
|
|
8071
8084
|
function compileClickHouseSpanQuery(plan) {
|
|
8072
8085
|
const parameters = new Parameters();
|
|
8073
|
-
const from = parameters.add(plan.timeRange.from,
|
|
8074
|
-
const to = parameters.add(plan.timeRange.to,
|
|
8086
|
+
const from = parameters.add(plan.timeRange.from, "DateTime64(3, 'UTC')");
|
|
8087
|
+
const to = parameters.add(plan.timeRange.to, "DateTime64(3, 'UTC')");
|
|
8075
8088
|
const scope = [];
|
|
8076
8089
|
if (plan.scope) {
|
|
8077
8090
|
scope.push(`organizationId = ${parameters.add(plan.scope.organizationId)}`);
|
|
@@ -8084,6 +8097,7 @@ function compileClickHouseSpanQuery(plan) {
|
|
|
8084
8097
|
const selectionFields = [.../* @__PURE__ */ new Set([
|
|
8085
8098
|
"startedAt",
|
|
8086
8099
|
"endedAt",
|
|
8100
|
+
plan.orderBy.field,
|
|
8087
8101
|
...predicateFields$1(plan.where)
|
|
8088
8102
|
])].filter((field) => !new Set(identityFields).has(field));
|
|
8089
8103
|
const expressions = selectionFields.map(fieldExpression);
|
|
@@ -8097,13 +8111,14 @@ function compileClickHouseSpanQuery(plan) {
|
|
|
8097
8111
|
ORDER BY ${identities}, e.endedAt DESC
|
|
8098
8112
|
LIMIT 1 BY ${identities}
|
|
8099
8113
|
)
|
|
8100
|
-
SELECT ${[
|
|
8114
|
+
SELECT ${[.../* @__PURE__ */ new Set([
|
|
8101
8115
|
...identityFields,
|
|
8102
8116
|
"startedAt",
|
|
8103
|
-
"endedAt"
|
|
8104
|
-
|
|
8117
|
+
"endedAt",
|
|
8118
|
+
plan.orderBy.field
|
|
8119
|
+
])].map((field) => `s.${field}`).join(", ")}
|
|
8105
8120
|
FROM candidates s WHERE s.startedAt >= ${from} AND s.startedAt < ${to} AND (${predicate.sql}) AND ${after}
|
|
8106
|
-
ORDER BY s.${plan.orderBy.field} ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"}, ${identityFields.map((field) => `s.${field} ASC NULLS LAST`).join(", ")}
|
|
8121
|
+
ORDER BY s.${plan.orderBy.field} ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"} NULLS LAST, ${identityFields.map((field) => `s.${field} ASC NULLS LAST`).join(", ")}
|
|
8107
8122
|
LIMIT ${parameters.add(plan.limit + 1)}`,
|
|
8108
8123
|
query_params: {
|
|
8109
8124
|
...parameters.values,
|
|
@@ -8195,7 +8210,7 @@ async function querySpans(client, plan, timeoutMs) {
|
|
|
8195
8210
|
resourceId: last.resourceId,
|
|
8196
8211
|
traceId: last.traceId,
|
|
8197
8212
|
spanId: last.spanId,
|
|
8198
|
-
sortValue: last[plan.orderBy.field]
|
|
8213
|
+
sortValue: last[plan.orderBy.field] ?? null
|
|
8199
8214
|
}) : null;
|
|
8200
8215
|
return result;
|
|
8201
8216
|
}
|