@mastra/clickhouse 1.27.0-alpha.2 → 1.28.0-alpha.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/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +128 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +129 -28
- package/dist/index.js.map +1 -1
- package/dist/storage/db/utils.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/ddl.d.ts +8 -3
- 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 +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 +1 -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 +1 -0
- package/dist/storage/domains/observability/v-next/span-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/thread-query.d.ts +1 -0
- package/dist/storage/domains/observability/v-next/thread-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +3 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TupleParam, createClient } from "@clickhouse/client";
|
|
2
2
|
import { ErrorCategory, ErrorDomain, MastraError } from "@mastra/core/error";
|
|
3
3
|
import * as coreStorage from "@mastra/core/storage";
|
|
4
|
-
import { BRANCH_SPAN_TYPES, EntityType, METRIC_DISTINCT_COLUMNS, MastraCompositeStore, MemoryStorage, ObservabilityStorage, SCORERS_SCHEMA, SPAN_SCHEMA, ScoresStorage, TABLE_AGENT_VERSIONS, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, TABLE_FAVORITES, TABLE_HARNESS_SESSIONS, TABLE_KNOWLEDGE_ACTIVITY, TABLE_KNOWLEDGE_MENTIONS, TABLE_KNOWLEDGE_NODES, TABLE_KNOWLEDGE_RECORDS, TABLE_KNOWLEDGE_SEMANTIC_OUTBOX, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, TABLE_MESSAGES, TABLE_NOTIFICATIONS, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, TABLE_RESOURCES, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEMAS, TABLE_SCORERS, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, TABLE_SKILLS, TABLE_SKILL_BLOBS, TABLE_SKILL_VERSIONS, TABLE_SPANS, TABLE_THREADS, TABLE_THREAD_STATE, TABLE_TOOL_PROVIDER_CONNECTIONS, TABLE_TRACES, TABLE_WORKFLOW_DEFINITIONS, TABLE_WORKFLOW_SNAPSHOT, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, TraceStatus, WorkflowsStorage, calculatePagination, computeTraceStatus, createStorageErrorId, getDefaultValue, getSqlType, listBranchesArgsSchema, listFeedbackArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listTracesArgsSchema, normalizePerPage, safelyParseJSON, toTraceSpans, transformScoreRow, validateStorageMetadataFilter } from "@mastra/core/storage";
|
|
4
|
+
import { BRANCH_SPAN_TYPES, EntityType, METRIC_DISTINCT_COLUMNS, MastraCompositeStore, MemoryStorage, ObservabilityStorage, SCORERS_SCHEMA, SPAN_SCHEMA, ScoresStorage, TABLE_AGENT_VERSIONS, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, TABLE_FAVORITES, TABLE_HARNESS_SESSIONS, TABLE_KNOWLEDGE_ACTIVITY, TABLE_KNOWLEDGE_MENTIONS, TABLE_KNOWLEDGE_NODES, TABLE_KNOWLEDGE_RECORDS, TABLE_KNOWLEDGE_SEMANTIC_OUTBOX, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, TABLE_MESSAGES, TABLE_NOTIFICATIONS, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, TABLE_RESOURCES, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEMAS, TABLE_SCORERS, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, TABLE_SKILLS, TABLE_SKILL_BLOBS, TABLE_SKILL_VERSIONS, TABLE_SPANS, TABLE_THREADS, TABLE_THREAD_STATE, TABLE_TOOL_PROVIDER_CONNECTIONS, TABLE_TRACES, TABLE_WORKFLOW_DEFINITIONS, TABLE_WORKFLOW_SNAPSHOT, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, TraceStatus, WorkflowsStorage, calculatePagination, computeTraceStatus, createStorageErrorId, getDefaultValue, getSqlType, getStringAttribute, listBranchesArgsSchema, listFeedbackArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listTracesArgsSchema, normalizePerPage, safelyParseJSON, toTraceSpans, transformScoreRow, validateStorageMetadataFilter } from "@mastra/core/storage";
|
|
5
5
|
import { MessageList } from "@mastra/core/agent";
|
|
6
6
|
import { MastraBase } from "@mastra/core/base";
|
|
7
7
|
import { parseFieldKey } from "@mastra/core/utils";
|
|
@@ -301,7 +301,8 @@ const JSON_FIELDS = [
|
|
|
301
301
|
"output",
|
|
302
302
|
"error",
|
|
303
303
|
"scope",
|
|
304
|
-
"links"
|
|
304
|
+
"links",
|
|
305
|
+
"stopReasonContext"
|
|
305
306
|
];
|
|
306
307
|
const NULLABLE_STRING_FIELDS = ["parentSpanId", "error"];
|
|
307
308
|
function transformRow(row) {
|
|
@@ -2716,6 +2717,17 @@ CREATE TABLE IF NOT EXISTS ${TABLE_SPAN_EVENTS} (
|
|
|
2716
2717
|
endedAt DateTime64(3, 'UTC'),
|
|
2717
2718
|
timeToFirstChunkMs Nullable(Float64),
|
|
2718
2719
|
|
|
2720
|
+
-- Native span fields, stored as supplied (NULL when the producer set none)
|
|
2721
|
+
externalParentSpanId Nullable(String),
|
|
2722
|
+
resumedFromSpanId Nullable(String),
|
|
2723
|
+
model LowCardinality(Nullable(String)),
|
|
2724
|
+
provider LowCardinality(Nullable(String)),
|
|
2725
|
+
outcome LowCardinality(Nullable(String)),
|
|
2726
|
+
stopReason LowCardinality(Nullable(String)),
|
|
2727
|
+
stopReasonContext Nullable(String),
|
|
2728
|
+
timeToFirstTokenMs Nullable(Float64),
|
|
2729
|
+
errorCount Nullable(UInt32),
|
|
2730
|
+
|
|
2719
2731
|
-- Query-relevant flexible fields
|
|
2720
2732
|
tags Array(LowCardinality(String)) DEFAULT [],
|
|
2721
2733
|
metadataSearch Map(LowCardinality(String), String) DEFAULT map(),
|
|
@@ -2790,6 +2802,17 @@ CREATE TABLE IF NOT EXISTS ${TABLE_TRACE_ROOTS} (
|
|
|
2790
2802
|
endedAt DateTime64(3, 'UTC'),
|
|
2791
2803
|
timeToFirstChunkMs Nullable(Float64),
|
|
2792
2804
|
|
|
2805
|
+
-- Native span fields, stored as supplied (NULL when the producer set none)
|
|
2806
|
+
externalParentSpanId Nullable(String),
|
|
2807
|
+
resumedFromSpanId Nullable(String),
|
|
2808
|
+
model LowCardinality(Nullable(String)),
|
|
2809
|
+
provider LowCardinality(Nullable(String)),
|
|
2810
|
+
outcome LowCardinality(Nullable(String)),
|
|
2811
|
+
stopReason LowCardinality(Nullable(String)),
|
|
2812
|
+
stopReasonContext Nullable(String),
|
|
2813
|
+
timeToFirstTokenMs Nullable(Float64),
|
|
2814
|
+
errorCount Nullable(UInt32),
|
|
2815
|
+
|
|
2793
2816
|
-- Query-relevant flexible fields
|
|
2794
2817
|
tags Array(LowCardinality(String)) DEFAULT [],
|
|
2795
2818
|
metadataSearch Map(LowCardinality(String), String) DEFAULT map(),
|
|
@@ -2876,6 +2899,17 @@ CREATE TABLE IF NOT EXISTS ${TABLE_TRACE_BRANCHES} (
|
|
|
2876
2899
|
endedAt DateTime64(3, 'UTC'),
|
|
2877
2900
|
timeToFirstChunkMs Nullable(Float64),
|
|
2878
2901
|
|
|
2902
|
+
-- Native span fields, stored as supplied (NULL when the producer set none)
|
|
2903
|
+
externalParentSpanId Nullable(String),
|
|
2904
|
+
resumedFromSpanId Nullable(String),
|
|
2905
|
+
model LowCardinality(Nullable(String)),
|
|
2906
|
+
provider LowCardinality(Nullable(String)),
|
|
2907
|
+
outcome LowCardinality(Nullable(String)),
|
|
2908
|
+
stopReason LowCardinality(Nullable(String)),
|
|
2909
|
+
stopReasonContext Nullable(String),
|
|
2910
|
+
timeToFirstTokenMs Nullable(Float64),
|
|
2911
|
+
errorCount Nullable(UInt32),
|
|
2912
|
+
|
|
2879
2913
|
-- Query-relevant flexible fields
|
|
2880
2914
|
tags Array(LowCardinality(String)) DEFAULT [],
|
|
2881
2915
|
metadataSearch Map(LowCardinality(String), String) DEFAULT map(),
|
|
@@ -3611,6 +3645,25 @@ function buildAllMvDDL(strategy) {
|
|
|
3611
3645
|
}
|
|
3612
3646
|
/** Discovery-specific refreshable MVs — created separately from core MVs. */
|
|
3613
3647
|
const DISCOVERY_MV_DDL = [DISCOVERY_VALUES_MV_DDL, DISCOVERY_PAIRS_MV_DDL];
|
|
3648
|
+
/**
|
|
3649
|
+
* Span columns added after the first span tables shipped, with their types.
|
|
3650
|
+
* Present on span events, trace roots and trace branches.
|
|
3651
|
+
*/
|
|
3652
|
+
const ADDED_SPAN_COLUMNS = [
|
|
3653
|
+
["inputPreview", "Nullable(String)"],
|
|
3654
|
+
["outputPreview", "Nullable(String)"],
|
|
3655
|
+
["errorPreview", "Nullable(String)"],
|
|
3656
|
+
["timeToFirstChunkMs", "Nullable(Float64)"],
|
|
3657
|
+
["externalParentSpanId", "Nullable(String)"],
|
|
3658
|
+
["resumedFromSpanId", "Nullable(String)"],
|
|
3659
|
+
["model", "LowCardinality(Nullable(String))"],
|
|
3660
|
+
["provider", "LowCardinality(Nullable(String))"],
|
|
3661
|
+
["outcome", "LowCardinality(Nullable(String))"],
|
|
3662
|
+
["stopReason", "LowCardinality(Nullable(String))"],
|
|
3663
|
+
["stopReasonContext", "Nullable(String)"],
|
|
3664
|
+
["timeToFirstTokenMs", "Nullable(Float64)"],
|
|
3665
|
+
["errorCount", "Nullable(UInt32)"]
|
|
3666
|
+
];
|
|
3614
3667
|
const addColumn = (table, name, type) => ({
|
|
3615
3668
|
kind: "column",
|
|
3616
3669
|
table,
|
|
@@ -3635,14 +3688,11 @@ const LOG_SKIP_INDEX_COLUMNS = [
|
|
|
3635
3688
|
"requestId"
|
|
3636
3689
|
];
|
|
3637
3690
|
const ALL_MIGRATIONS = [
|
|
3638
|
-
...[
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
]
|
|
3643
|
-
addColumn(TABLE_SPAN_EVENTS, "inputPreview", "Nullable(String)"),
|
|
3644
|
-
addColumn(TABLE_SPAN_EVENTS, "outputPreview", "Nullable(String)"),
|
|
3645
|
-
addColumn(TABLE_SPAN_EVENTS, "errorPreview", "Nullable(String)"),
|
|
3691
|
+
...ADDED_SPAN_COLUMNS.flatMap(([column, type]) => [
|
|
3692
|
+
addColumn(TABLE_TRACE_ROOTS, column, type),
|
|
3693
|
+
addColumn(TABLE_TRACE_BRANCHES, column, type),
|
|
3694
|
+
addColumn(TABLE_SPAN_EVENTS, column, type)
|
|
3695
|
+
]),
|
|
3646
3696
|
addColumn(TABLE_TRACE_BRANCHES, "entityVersionId", "Nullable(String)"),
|
|
3647
3697
|
addColumn(TABLE_TRACE_BRANCHES, "parentEntityVersionId", "Nullable(String)"),
|
|
3648
3698
|
addColumn(TABLE_TRACE_BRANCHES, "rootEntityVersionId", "Nullable(String)"),
|
|
@@ -3683,10 +3733,7 @@ const ALL_MIGRATIONS = [
|
|
|
3683
3733
|
addBloomIndex(TABLE_METRIC_EVENTS, "idx_sessionId", "sessionId"),
|
|
3684
3734
|
addBloomIndex(TABLE_METRIC_EVENTS, "idx_requestId", "requestId"),
|
|
3685
3735
|
...LOG_SKIP_INDEX_COLUMNS.map((column) => addBloomIndex(TABLE_LOG_EVENTS, `idx_${column}`, column)),
|
|
3686
|
-
addBloomIndex(TABLE_DELETION_REQUESTS, "idx_predicateValues", "predicateValues")
|
|
3687
|
-
addColumn(TABLE_TRACE_ROOTS, "timeToFirstChunkMs", "Nullable(Float64)"),
|
|
3688
|
-
addColumn(TABLE_TRACE_BRANCHES, "timeToFirstChunkMs", "Nullable(Float64)"),
|
|
3689
|
-
addColumn(TABLE_SPAN_EVENTS, "timeToFirstChunkMs", "Nullable(Float64)")
|
|
3736
|
+
addBloomIndex(TABLE_DELETION_REQUESTS, "idx_predicateValues", "predicateValues")
|
|
3690
3737
|
];
|
|
3691
3738
|
const ALL_TABLE_NAMES = [
|
|
3692
3739
|
TABLE_SPAN_EVENTS,
|
|
@@ -3937,6 +3984,11 @@ const PROMOTED_KEYS = /* @__PURE__ */ new Set([
|
|
|
3937
3984
|
"executionSource",
|
|
3938
3985
|
"serviceName"
|
|
3939
3986
|
]);
|
|
3987
|
+
function nullableNumber$1(value) {
|
|
3988
|
+
if (value == null || value === "") return null;
|
|
3989
|
+
const n = Number(value);
|
|
3990
|
+
return Number.isNaN(n) ? null : n;
|
|
3991
|
+
}
|
|
3940
3992
|
function nullableString(value) {
|
|
3941
3993
|
return typeof value === "string" ? value === "" ? null : value : value == null ? null : String(value);
|
|
3942
3994
|
}
|
|
@@ -4018,6 +4070,7 @@ function rowToSpanRecord(row) {
|
|
|
4018
4070
|
const startedAt = toDate(row.startedAt);
|
|
4019
4071
|
const endedAt = row.isEvent ? startedAt : toDateOrNull(row.endedAt);
|
|
4020
4072
|
const error = parseJson(row.error);
|
|
4073
|
+
const attributes = parseJson(row.attributes);
|
|
4021
4074
|
return {
|
|
4022
4075
|
traceId: row.traceId,
|
|
4023
4076
|
spanId: row.spanId,
|
|
@@ -4053,12 +4106,21 @@ function rowToSpanRecord(row) {
|
|
|
4053
4106
|
tags: normalizeTags(row.tags),
|
|
4054
4107
|
metadata: parseJson(row.metadataRaw) ?? void 0,
|
|
4055
4108
|
scope: parseJson(row.scope) ?? void 0,
|
|
4056
|
-
attributes:
|
|
4109
|
+
attributes: attributes ?? void 0,
|
|
4057
4110
|
links: parseJson(row.links) ?? void 0,
|
|
4058
4111
|
input: parseJson(row.input) ?? void 0,
|
|
4059
4112
|
output: parseJson(row.output) ?? void 0,
|
|
4060
4113
|
error: error ?? void 0,
|
|
4061
4114
|
requestContext: parseJson(row.requestContext) ?? void 0,
|
|
4115
|
+
externalParentSpanId: nullableString(row.externalParentSpanId),
|
|
4116
|
+
resumedFromSpanId: nullableString(row.resumedFromSpanId),
|
|
4117
|
+
model: nullableString(row.model) ?? getStringAttribute(attributes, "model"),
|
|
4118
|
+
provider: nullableString(row.provider) ?? getStringAttribute(attributes, "provider"),
|
|
4119
|
+
outcome: nullableString(row.outcome),
|
|
4120
|
+
stopReason: nullableString(row.stopReason),
|
|
4121
|
+
stopReasonContext: parseJson(row.stopReasonContext) ?? null,
|
|
4122
|
+
timeToFirstTokenMs: nullableNumber$1(row.timeToFirstTokenMs),
|
|
4123
|
+
errorCount: nullableNumber$1(row.errorCount),
|
|
4062
4124
|
createdAt: startedAt,
|
|
4063
4125
|
updatedAt: null
|
|
4064
4126
|
};
|
|
@@ -4132,6 +4194,15 @@ function spanRecordToRow(span) {
|
|
|
4132
4194
|
startedAt: toISOString(span.startedAt),
|
|
4133
4195
|
endedAt: toISOString(endedAt),
|
|
4134
4196
|
timeToFirstChunkMs: span.timeToFirstChunkMs ?? null,
|
|
4197
|
+
externalParentSpanId: span.externalParentSpanId ?? null,
|
|
4198
|
+
resumedFromSpanId: span.resumedFromSpanId ?? null,
|
|
4199
|
+
model: span.model ?? null,
|
|
4200
|
+
provider: span.provider ?? null,
|
|
4201
|
+
outcome: span.outcome ?? null,
|
|
4202
|
+
stopReason: span.stopReason ?? null,
|
|
4203
|
+
stopReasonContext: jsonEncode(span.stopReasonContext),
|
|
4204
|
+
timeToFirstTokenMs: span.timeToFirstTokenMs ?? null,
|
|
4205
|
+
errorCount: span.errorCount ?? null,
|
|
4135
4206
|
tags: normalizeTags(span.tags),
|
|
4136
4207
|
metadataSearch: buildMetadataSearch(metadata),
|
|
4137
4208
|
metadataRaw: jsonEncode(metadata),
|
|
@@ -6835,7 +6906,17 @@ const TRACE_STATUS_SQL = `if(isNotNull(r.error), 'error', 'success')`;
|
|
|
6835
6906
|
const timeToFirstChunkSupported = "timeToFirstChunkMs" in (coreStorage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});
|
|
6836
6907
|
/** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */
|
|
6837
6908
|
const timeToFirstChunkSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstChunkMs") === true;
|
|
6838
|
-
|
|
6909
|
+
/** Same rule for time to first token: returned and sorted only when core knows the field. */
|
|
6910
|
+
const timeToFirstTokenSupported = "timeToFirstTokenMs" in (coreStorage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});
|
|
6911
|
+
const timeToFirstTokenSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstTokenMs") === true;
|
|
6912
|
+
const timingFeatures = [
|
|
6913
|
+
...timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [],
|
|
6914
|
+
...timeToFirstChunkSupported && timeToFirstChunkSortSupported ? ["trace-query-time-to-first-chunk-sort"] : [],
|
|
6915
|
+
...timeToFirstTokenSupported ? ["trace-query-time-to-first-token"] : [],
|
|
6916
|
+
...timeToFirstTokenSupported && timeToFirstTokenSortSupported ? ["trace-query-time-to-first-token-sort"] : []
|
|
6917
|
+
];
|
|
6918
|
+
/** Order fields holding numbers that can be empty; the rest are timestamps. */
|
|
6919
|
+
const NUMERIC_ORDER_FIELDS = /* @__PURE__ */ new Set(["timeToFirstChunkMs", "timeToFirstTokenMs"]);
|
|
6839
6920
|
function durationMsSql(startedAt, endedAt) {
|
|
6840
6921
|
return `dateDiff('millisecond', ${startedAt}, ${endedAt})`;
|
|
6841
6922
|
}
|
|
@@ -6888,6 +6969,10 @@ const TRACE_FIELDS = {
|
|
|
6888
6969
|
sql: "r.timeToFirstChunkMs",
|
|
6889
6970
|
parameterType: "Float64"
|
|
6890
6971
|
},
|
|
6972
|
+
timeToFirstTokenMs: {
|
|
6973
|
+
sql: "r.timeToFirstTokenMs",
|
|
6974
|
+
parameterType: "Float64"
|
|
6975
|
+
},
|
|
6891
6976
|
entityId: {
|
|
6892
6977
|
sql: "r.entityId",
|
|
6893
6978
|
parameterType: "String"
|
|
@@ -6954,6 +7039,10 @@ const SPAN_FIELDS = {
|
|
|
6954
7039
|
sql: "s.timeToFirstChunkMs",
|
|
6955
7040
|
parameterType: "Float64"
|
|
6956
7041
|
},
|
|
7042
|
+
timeToFirstTokenMs: {
|
|
7043
|
+
sql: "s.timeToFirstTokenMs",
|
|
7044
|
+
parameterType: "Float64"
|
|
7045
|
+
},
|
|
6957
7046
|
status: {
|
|
6958
7047
|
sql: "s.status",
|
|
6959
7048
|
parameterType: "String"
|
|
@@ -7166,6 +7255,7 @@ const TRACE_SELECT = `
|
|
|
7166
7255
|
r.entityType AS entityType,
|
|
7167
7256
|
r.environment AS environment,
|
|
7168
7257
|
r.timeToFirstChunkMs AS timeToFirstChunkMs,
|
|
7258
|
+
r.timeToFirstTokenMs AS timeToFirstTokenMs,
|
|
7169
7259
|
${TRACE_STATUS_SQL} AS status`;
|
|
7170
7260
|
var ParameterBuilder = class {
|
|
7171
7261
|
params = {};
|
|
@@ -7182,7 +7272,7 @@ function fieldDefinition(registry, field) {
|
|
|
7182
7272
|
return definition;
|
|
7183
7273
|
}
|
|
7184
7274
|
function resolveOrderField(field) {
|
|
7185
|
-
if (field === "startedAt" || field === "endedAt" || field
|
|
7275
|
+
if (field === "startedAt" || field === "endedAt" || NUMERIC_ORDER_FIELDS.has(field)) return field;
|
|
7186
7276
|
throw new Error(`Unsupported trusted trace-query field: ${field}`);
|
|
7187
7277
|
}
|
|
7188
7278
|
function isMetadataField(field) {
|
|
@@ -7372,6 +7462,7 @@ function compileClickHouseTraceScope(selection, relationCollections, parameters,
|
|
|
7372
7462
|
endedAt,
|
|
7373
7463
|
${durationMsSql("startedAt", "endedAt")} AS durationMs,
|
|
7374
7464
|
timeToFirstChunkMs,
|
|
7465
|
+
timeToFirstTokenMs,
|
|
7375
7466
|
if(isNotNull(error), 'error', 'success') AS status,
|
|
7376
7467
|
error,
|
|
7377
7468
|
entityType,
|
|
@@ -7487,7 +7578,7 @@ function traceOrder(plan) {
|
|
|
7487
7578
|
function keysetCursorCondition(plan, order, parameters) {
|
|
7488
7579
|
if (plan.paginationMode !== "keyset" || !plan.cursor) return "";
|
|
7489
7580
|
if (plan.cursor.sortValue === null) return `(isNull(sortValue) AND traceId > ${parameters.add(plan.cursor.traceId, "String")})`;
|
|
7490
|
-
const numeric = order.field
|
|
7581
|
+
const numeric = NUMERIC_ORDER_FIELDS.has(order.field);
|
|
7491
7582
|
const comparison = order.direction === "ASC" ? ">" : "<";
|
|
7492
7583
|
const sortValue = parameters.add(plan.cursor.sortValue, numeric ? "Float64" : "DateTime64(3, 'UTC')");
|
|
7493
7584
|
return `(sortValue ${comparison} ${sortValue} OR (sortValue = ${sortValue} AND traceId > ${parameters.add(plan.cursor.traceId, "String")})${numeric ? " OR isNull(sortValue)" : ""})`;
|
|
@@ -7501,7 +7592,7 @@ function compileClickHouseTraceQueryKeys(plan) {
|
|
|
7501
7592
|
if (plan.paginationMode === "delta") throw new Error("Delta trace queries have no keys statement");
|
|
7502
7593
|
const parameters = new ParameterBuilder();
|
|
7503
7594
|
const order = traceOrder(plan);
|
|
7504
|
-
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);
|
|
7595
|
+
const ctes = compileClickHouseTraceCandidates(plan, "r.traceId AS traceId, r.dedupeKey AS dedupeKey, r.startedAt AS startedAt, r.endedAt AS endedAt, r.timeToFirstChunkMs AS timeToFirstChunkMs, r.timeToFirstTokenMs AS timeToFirstTokenMs", parameters, QUERY_TRACES_SCOPE);
|
|
7505
7596
|
const cursor = keysetCursorCondition(plan, order, parameters);
|
|
7506
7597
|
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")}`;
|
|
7507
7598
|
return {
|
|
@@ -7902,7 +7993,8 @@ async function queryTraces(client, plan, timeoutMs, strategy = null) {
|
|
|
7902
7993
|
entityType: row.entityType == null ? null : String(row.entityType),
|
|
7903
7994
|
environment: row.environment == null ? null : String(row.environment),
|
|
7904
7995
|
status: row.status,
|
|
7905
|
-
...timeToFirstChunkSupported && { timeToFirstChunkMs: row.timeToFirstChunkMs == null ? null : Number(row.timeToFirstChunkMs) }
|
|
7996
|
+
...timeToFirstChunkSupported && { timeToFirstChunkMs: row.timeToFirstChunkMs == null ? null : Number(row.timeToFirstChunkMs) },
|
|
7997
|
+
...timeToFirstTokenSupported && { timeToFirstTokenMs: row.timeToFirstTokenMs == null ? null : Number(row.timeToFirstTokenMs) }
|
|
7906
7998
|
});
|
|
7907
7999
|
if (plan.paginationMode === "delta") {
|
|
7908
8000
|
const rows = await run(compileClickHouseTraceQuery(plan, deltaHead));
|
|
@@ -7925,7 +8017,7 @@ async function queryTraces(client, plan, timeoutMs, strategy = null) {
|
|
|
7925
8017
|
});
|
|
7926
8018
|
}
|
|
7927
8019
|
const keys = await run(compileClickHouseTraceQueryKeys(plan));
|
|
7928
|
-
const sortValue = (value) => plan.orderBy.field
|
|
8020
|
+
const sortValue = (value) => !NUMERIC_ORDER_FIELDS.has(plan.orderBy.field) ? asIsoTimestamp(value) : value == null ? null : Number(value);
|
|
7929
8021
|
let total = Number(keys[0]?.__total ?? 0);
|
|
7930
8022
|
if (plan.paginationMode === "page" && keys.length === 0 && plan.page > 0) {
|
|
7931
8023
|
const [stats] = await run(compileClickHouseTraceQueryTotal(plan));
|
|
@@ -8028,6 +8120,7 @@ const displayFields = [
|
|
|
8028
8120
|
"provider",
|
|
8029
8121
|
"durationMs",
|
|
8030
8122
|
"timeToFirstChunkMs",
|
|
8123
|
+
"timeToFirstTokenMs",
|
|
8031
8124
|
"status"
|
|
8032
8125
|
];
|
|
8033
8126
|
var Parameters = class {
|
|
@@ -8056,7 +8149,7 @@ function afterCursor$1(plan, parameters) {
|
|
|
8056
8149
|
const equal = [];
|
|
8057
8150
|
if (cursor.sortValue === null) equal.push(`isNull(${field})`);
|
|
8058
8151
|
else {
|
|
8059
|
-
const numeric = plan.orderBy.field === "timeToFirstChunkMs";
|
|
8152
|
+
const numeric = plan.orderBy.field === "timeToFirstChunkMs" || plan.orderBy.field === "timeToFirstTokenMs";
|
|
8060
8153
|
const value = parameters.add(cursor.sortValue, numeric ? "Float64" : "DateTime64(3, 'UTC')");
|
|
8061
8154
|
terms.push(`${field} ${plan.orderBy.direction === "asc" ? ">" : "<"} ${value}`);
|
|
8062
8155
|
if (numeric) terms.push(`isNull(${field})`);
|
|
@@ -8152,6 +8245,7 @@ const TRACE_BRANCHES_SPAN_FIELD_COLUMNS = {
|
|
|
8152
8245
|
"startedAt",
|
|
8153
8246
|
"endedAt",
|
|
8154
8247
|
"timeToFirstChunkMs",
|
|
8248
|
+
"timeToFirstTokenMs",
|
|
8155
8249
|
"threadId",
|
|
8156
8250
|
"runId",
|
|
8157
8251
|
"sessionId",
|
|
@@ -8312,12 +8406,13 @@ async function querySpans(client, plan, timeoutMs) {
|
|
|
8312
8406
|
const hydrated = page.flatMap((identity) => {
|
|
8313
8407
|
const row = byIdentity.get(coreStorage.spanQueryIdentityKey(identity));
|
|
8314
8408
|
if (!row) return [];
|
|
8315
|
-
const { inputPreview: _input, outputPreview: _output, errorPreview: _error, timeToFirstChunkMs, ...metadata } = row;
|
|
8409
|
+
const { inputPreview: _input, outputPreview: _output, errorPreview: _error, timeToFirstChunkMs, timeToFirstTokenMs, ...metadata } = row;
|
|
8316
8410
|
return [{
|
|
8317
8411
|
...metadata,
|
|
8318
8412
|
...identity,
|
|
8319
8413
|
durationMs: Number(row.durationMs),
|
|
8320
|
-
...timeToFirstChunkSupported && { timeToFirstChunkMs: timeToFirstChunkMs == null ? null : Number(timeToFirstChunkMs) }
|
|
8414
|
+
...timeToFirstChunkSupported && { timeToFirstChunkMs: timeToFirstChunkMs == null ? null : Number(timeToFirstChunkMs) },
|
|
8415
|
+
...timeToFirstTokenSupported && { timeToFirstTokenMs: timeToFirstTokenMs == null ? null : Number(timeToFirstTokenMs) }
|
|
8321
8416
|
}];
|
|
8322
8417
|
});
|
|
8323
8418
|
let metrics = [];
|
|
@@ -8440,7 +8535,11 @@ function compileClickHouseThreadRowsQuery(plan, strategy = "full") {
|
|
|
8440
8535
|
const after = afterCursor(plan, parameters);
|
|
8441
8536
|
const qualify = plan.timeRange.mode === "traces" ? "s.inWindow > 0" : `s.${plan.timeRange.field} >= ${from} AND s.${plan.timeRange.field} < ${to}`;
|
|
8442
8537
|
const filtered = predicateFields(plan.where);
|
|
8443
|
-
const firstContext = [
|
|
8538
|
+
const firstContext = [
|
|
8539
|
+
...contextFields,
|
|
8540
|
+
"timeToFirstChunkMs",
|
|
8541
|
+
"timeToFirstTokenMs"
|
|
8542
|
+
].filter((field) => field === "resourceId" || filtered.has(field));
|
|
8444
8543
|
const firstFields = [
|
|
8445
8544
|
"startedAt",
|
|
8446
8545
|
"traceId",
|
|
@@ -8464,7 +8563,7 @@ function compileClickHouseThreadRowsQuery(plan, strategy = "full") {
|
|
|
8464
8563
|
...firstContext,
|
|
8465
8564
|
...filtered.has("status") ? ["status"] : []
|
|
8466
8565
|
];
|
|
8467
|
-
const rootExpression = (field) => field === "timeToFirstChunkMs" ?
|
|
8566
|
+
const rootExpression = (field) => field === "timeToFirstChunkMs" || field === "timeToFirstTokenMs" ? `if(spanType = 'agent_run', ${field}, NULL)` : field === "status" ? "if(isNull(error), 'success', 'error')" : field;
|
|
8468
8567
|
const sortedRoots = `roots AS (
|
|
8469
8568
|
SELECT organizationId, traceId, ${rootDataFields.map((field) => `${rootExpression(field)} AS ${field}`).join(", ")}
|
|
8470
8569
|
FROM ${TABLE_TRACE_ROOTS} ${scope.length || strategy === "candidates" ? `WHERE ${[...scope, ...strategy === "candidates" ? [candidateTracesFilter] : []].join(" AND ")}` : ""}
|
|
@@ -8568,6 +8667,7 @@ async function queryThreadRows(client, plan, timeoutMs, strategy = "auto") {
|
|
|
8568
8667
|
for (const batch of batches([...roots.values()])) stored.push(...await run({
|
|
8569
8668
|
query: `SELECT organizationId, traceId, spanId, startedAt, endedAt,
|
|
8570
8669
|
${contextFields.join(", ")}, if(spanType = 'agent_run', timeToFirstChunkMs, NULL) AS timeToFirstChunkMs,
|
|
8670
|
+
if(spanType = 'agent_run', timeToFirstTokenMs, NULL) AS timeToFirstTokenMs,
|
|
8571
8671
|
if(isNull(error), 'success', 'error') AS status, ${PREVIEW_COLUMNS.join(", ")}
|
|
8572
8672
|
FROM ${TABLE_TRACE_ROOTS} WHERE ${rootWhere}
|
|
8573
8673
|
ORDER BY ${ROOT_VERSION_ORDER} LIMIT 1 BY organizationId, traceId, spanId`,
|
|
@@ -8601,6 +8701,7 @@ async function queryThreadRows(client, plan, timeoutMs, strategy = "auto") {
|
|
|
8601
8701
|
endedAt: iso(row.endedAt),
|
|
8602
8702
|
traceCount: Number(row.traceCount),
|
|
8603
8703
|
timeToFirstChunkMs: first.timeToFirstChunkMs,
|
|
8704
|
+
...timeToFirstTokenSupported && { timeToFirstTokenMs: first.timeToFirstTokenMs },
|
|
8604
8705
|
inputPreview: resolveStoredPreviews(first).inputPreview,
|
|
8605
8706
|
outputPreview: resolveStoredPreviews(last).outputPreview,
|
|
8606
8707
|
errorPreview: resolveStoredPreviews(last).errorPreview
|
|
@@ -10257,7 +10358,7 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
10257
10358
|
"trace-query-tenant-scope",
|
|
10258
10359
|
"feedback",
|
|
10259
10360
|
"trace-query-context-ids",
|
|
10260
|
-
...
|
|
10361
|
+
...timingFeatures,
|
|
10261
10362
|
"trace-query-root-span-fields",
|
|
10262
10363
|
"trace-query-root-entity-id",
|
|
10263
10364
|
"trace-aggregate",
|
|
@@ -10282,7 +10383,7 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
|
|
|
10282
10383
|
"trace-query-tenant-scope",
|
|
10283
10384
|
"feedback",
|
|
10284
10385
|
"trace-query-context-ids",
|
|
10285
|
-
...
|
|
10386
|
+
...timingFeatures,
|
|
10286
10387
|
"trace-query-root-span-fields",
|
|
10287
10388
|
"trace-query-root-entity-id",
|
|
10288
10389
|
"trace-aggregate",
|