@mastra/clickhouse 1.26.0-alpha.4 → 1.26.0-alpha.5
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 +68 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +68 -50
- 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/thread-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 +41 -15
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-clickhouse
|
|
|
3
3
|
description: Documentation for @mastra/clickhouse. Use when working with @mastra/clickhouse APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/clickhouse"
|
|
6
|
-
version: "1.26.0-alpha.
|
|
6
|
+
version: "1.26.0-alpha.5"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
package/dist/index.cjs
CHANGED
|
@@ -6924,6 +6924,10 @@ const TRACE_FIELDS = {
|
|
|
6924
6924
|
sql: "r.timeToFirstChunkMs",
|
|
6925
6925
|
parameterType: "Float64"
|
|
6926
6926
|
},
|
|
6927
|
+
entityId: {
|
|
6928
|
+
sql: "r.entityId",
|
|
6929
|
+
parameterType: "String"
|
|
6930
|
+
},
|
|
6927
6931
|
entityName: {
|
|
6928
6932
|
sql: "r.entityName",
|
|
6929
6933
|
parameterType: "String"
|
|
@@ -7322,6 +7326,28 @@ function compileTenantScope(scope, parameters) {
|
|
|
7322
7326
|
if (scope.resourceId !== void 0) sql += `\n AND resourceId = ${parameters.add(scope.resourceId, "String")}`;
|
|
7323
7327
|
return sql;
|
|
7324
7328
|
}
|
|
7329
|
+
/**
|
|
7330
|
+
* Order of the versions of one root span, current version first. `mastra_trace_roots` has no
|
|
7331
|
+
* version column, so until a background merge runs, every export of a root is its own row with the
|
|
7332
|
+
* same sort key, and merges never meet versions that ended on different days (it is partitioned by
|
|
7333
|
+
* `endedAt`). The version that ended last is current, as a resumed or completed root is exported
|
|
7334
|
+
* again with a later `endedAt`; a pending copy stores `endedAt = startedAt` and can lack `threadId`,
|
|
7335
|
+
* so a copy with a thread wins an equal-time tie. Remaining ties are broken by insertion order, last
|
|
7336
|
+
* insert first: the part's first block number, then the row's offset in the part. Tied versions
|
|
7337
|
+
* share a partition and sort key, so a merge meets them and keeps the last insert too, and reads
|
|
7338
|
+
* pick the same version before and after it. Both are virtual columns, so the order reads nothing
|
|
7339
|
+
* beyond `endedAt` and `threadId`.
|
|
7340
|
+
*
|
|
7341
|
+
* Merges don't follow this order across `endedAt`: within one day's partition a merge keeps the last
|
|
7342
|
+
* insert, not the version that ended last. If an outdated export of a root is redelivered after its
|
|
7343
|
+
* current version, on the same day, reads pick the current version until a merge, and the outdated
|
|
7344
|
+
* one afterwards (last write wins, as in the PG and DuckDB stores). Making merges keep the version
|
|
7345
|
+
* that ended last needs `ReplacingMergeTree(endedAt)`, a schema change.
|
|
7346
|
+
*
|
|
7347
|
+
* Every root collapse uses this order: trace rows, aggregates, thread rows and the discovery reads.
|
|
7348
|
+
*/
|
|
7349
|
+
const ROOT_VERSION_ORDER = `endedAt DESC, isNotNull(threadId) DESC, toUInt64(splitByChar('_', _part)[2]) DESC,
|
|
7350
|
+
_part_offset DESC`;
|
|
7325
7351
|
function compileClickHouseTraceScope(selection, relationCollections, parameters, scope, seedConjuncts = [], options = {}) {
|
|
7326
7352
|
const from = parameters.add(selection.timeRange.from, "DateTime64(3, 'UTC')");
|
|
7327
7353
|
const to = parameters.add(selection.timeRange.to, "DateTime64(3, 'UTC')");
|
|
@@ -7345,7 +7371,15 @@ function compileClickHouseTraceScope(selection, relationCollections, parameters,
|
|
|
7345
7371
|
SELECT *
|
|
7346
7372
|
FROM ${TABLE_TRACE_ROOTS} r
|
|
7347
7373
|
WHERE startedAt >= ${from}
|
|
7348
|
-
AND startedAt < ${to}${tenant}${
|
|
7374
|
+
AND startedAt < ${to}${tenant}${bound}${seedFilter ? `
|
|
7375
|
+
AND traceId IN (
|
|
7376
|
+
SELECT traceId
|
|
7377
|
+
FROM ${TABLE_TRACE_ROOTS} r
|
|
7378
|
+
WHERE startedAt >= ${from}
|
|
7379
|
+
AND startedAt < ${to}${tenant}${seedFilter}
|
|
7380
|
+
)` : ""}
|
|
7381
|
+
ORDER BY startedAt, traceId, spanId, ${ROOT_VERSION_ORDER}
|
|
7382
|
+
LIMIT 1 BY traceId
|
|
7349
7383
|
)`] : [`current_roots AS (
|
|
7350
7384
|
SELECT *
|
|
7351
7385
|
FROM ${TABLE_TRACE_ROOTS}
|
|
@@ -7355,7 +7389,7 @@ function compileClickHouseTraceScope(selection, relationCollections, parameters,
|
|
|
7355
7389
|
WHERE startedAt >= ${from}
|
|
7356
7390
|
AND startedAt < ${to}${tenant}${seedFilter}
|
|
7357
7391
|
)${tenant}
|
|
7358
|
-
ORDER BY traceId,
|
|
7392
|
+
ORDER BY traceId, startedAt, spanId, ${ROOT_VERSION_ORDER}
|
|
7359
7393
|
LIMIT 1 BY traceId
|
|
7360
7394
|
)`, `root_scope AS (
|
|
7361
7395
|
SELECT *
|
|
@@ -7485,11 +7519,7 @@ function traceOrder(plan) {
|
|
|
7485
7519
|
direction: plan.orderBy.direction === "asc" ? "ASC" : "DESC"
|
|
7486
7520
|
};
|
|
7487
7521
|
}
|
|
7488
|
-
/**
|
|
7489
|
-
* Keyset cursor on a trace's sort value. Applied after each trace is reduced to one sort value:
|
|
7490
|
-
* filtering root rows first would let a trace with several roots (or unmerged copies with
|
|
7491
|
-
* different `endedAt`) come back on a later page under a root that sorts after the cursor.
|
|
7492
|
-
*/
|
|
7522
|
+
/** Keyset cursor on a trace's sort value (the current root's), with traceId breaking ties. */
|
|
7493
7523
|
function keysetCursorCondition(plan, order, parameters) {
|
|
7494
7524
|
if (plan.paginationMode !== "keyset" || !plan.cursor) return "";
|
|
7495
7525
|
if (plan.cursor.sortValue === null) return `(isNull(sortValue) AND traceId > ${parameters.add(plan.cursor.traceId, "String")})`;
|
|
@@ -7500,9 +7530,8 @@ function keysetCursorCondition(plan, order, parameters) {
|
|
|
7500
7530
|
}
|
|
7501
7531
|
/**
|
|
7502
7532
|
* First statement of keyset and page mode: the page's traces (after the keyset cursor, `limit + 1`
|
|
7503
|
-
* for keyset mode, `perPage` at the page offset for page mode) as
|
|
7504
|
-
* number of matching traces on every row.
|
|
7505
|
-
* value and the key, so the key always names a row with that sort value. No blob columns are read.
|
|
7533
|
+
* for keyset mode, `perPage` at the page offset for page mode) as keys of their current roots, and
|
|
7534
|
+
* the number of matching traces on every row. No blob columns are read.
|
|
7506
7535
|
*/
|
|
7507
7536
|
function compileClickHouseTraceQueryKeys(plan) {
|
|
7508
7537
|
if (plan.paginationMode === "delta") throw new Error("Delta trace queries have no keys statement");
|
|
@@ -7510,19 +7539,12 @@ function compileClickHouseTraceQueryKeys(plan) {
|
|
|
7510
7539
|
const order = traceOrder(plan);
|
|
7511
7540
|
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);
|
|
7512
7541
|
const cursor = keysetCursorCondition(plan, order, parameters);
|
|
7513
|
-
const pick = order.direction === "DESC" ? "max" : "min";
|
|
7514
|
-
const rootOrder = order.field === "timeToFirstChunkMs" ? `ifNull(${order.field}, ${pick === "max" ? "-inf" : "inf"})` : order.field;
|
|
7515
7542
|
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")}`;
|
|
7516
7543
|
return {
|
|
7517
|
-
query: `WITH ${ctes.join(",\n")}
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
FROM candidates
|
|
7522
|
-
GROUP BY traceId${cursor ? `\n HAVING ${cursor}` : ""}
|
|
7523
|
-
)
|
|
7524
|
-
SELECT traceId, root.1 AS dedupeKey, sortValue, root.2 AS rootStartedAt, count() OVER () AS __total
|
|
7525
|
-
FROM per_trace
|
|
7544
|
+
query: `WITH ${ctes.join(",\n")}
|
|
7545
|
+
SELECT traceId, dedupeKey, ${order.field} AS sortValue, startedAt AS rootStartedAt, endedAt AS rootEndedAt,
|
|
7546
|
+
count() OVER () AS __total
|
|
7547
|
+
FROM candidates${cursor ? `\nWHERE ${cursor}` : ""}
|
|
7526
7548
|
ORDER BY sortValue ${order.direction} NULLS LAST, traceId ASC
|
|
7527
7549
|
${limit}`,
|
|
7528
7550
|
query_params: parameters.params,
|
|
@@ -7530,27 +7552,28 @@ ${limit}`,
|
|
|
7530
7552
|
};
|
|
7531
7553
|
}
|
|
7532
7554
|
/**
|
|
7533
|
-
* Second statement of keyset and page mode: the rows of the keyed roots, with `metadata`
|
|
7534
|
-
*
|
|
7535
|
-
*
|
|
7536
|
-
*
|
|
7555
|
+
* Second statement of keyset and page mode: the rows of the keyed roots, with `metadata` and the
|
|
7556
|
+
* stored previews, read by sort key and `endedAt`, so only the keyed version's rows match. Versions
|
|
7557
|
+
* that end at the same instant are ordered as in the keys statement (ROOT_VERSION_ORDER). The
|
|
7558
|
+
* relation-free `where` conjuncts are re-applied, so a version written between the two statements
|
|
7559
|
+
* that doesn't match isn't returned.
|
|
7560
|
+
*
|
|
7561
|
+
* Trade-off of matching on `endedAt`: if a newer version is written between the two statements and
|
|
7562
|
+
* a same-day merge then drops the keyed version, the trace has no row and drops off the page. Without
|
|
7563
|
+
* `endedAt` the lookup would find the replacement, but could also return a version other than the
|
|
7564
|
+
* keyed one whenever both are unmerged. The window is the gap between the two statements.
|
|
7537
7565
|
*/
|
|
7538
7566
|
function compileClickHouseTraceRowsByKey(plan, keys) {
|
|
7539
7567
|
const parameters = new ParameterBuilder();
|
|
7540
7568
|
const order = traceOrder(plan);
|
|
7541
7569
|
const ts = (value) => parameters.add(value, "DateTime64(3, 'UTC')");
|
|
7542
|
-
const
|
|
7543
|
-
const tuples = keys.map((key) => {
|
|
7544
|
-
const started = ts(key.rootStartedAt);
|
|
7545
|
-
const id = `${parameters.add(key.traceId, "String")}, ${parameters.add(key.dedupeKey, "String")}`;
|
|
7546
|
-
return byEnd ? `(${started}, ${id}, ${ts(String(key.sortValue))})` : `(${started}, ${id})`;
|
|
7547
|
-
});
|
|
7570
|
+
const tuples = keys.map((key) => `(${ts(key.rootStartedAt)}, ${parameters.add(key.traceId, "String")}, ${parameters.add(key.dedupeKey, "String")}, ${ts(key.rootEndedAt)})`);
|
|
7548
7571
|
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("");
|
|
7549
7572
|
return {
|
|
7550
7573
|
query: `SELECT ${TRACE_SELECT}
|
|
7551
7574
|
FROM ${TABLE_TRACE_ROOTS} r
|
|
7552
|
-
WHERE (r.startedAt, r.traceId, r.dedupeKey
|
|
7553
|
-
ORDER BY ${order.field} ${order.direction} NULLS LAST, traceId ASC
|
|
7575
|
+
WHERE (r.startedAt, r.traceId, r.dedupeKey, r.endedAt) IN (${tuples.join(", ")})${compileTenantScope(plan.scope, parameters)}${predicate}
|
|
7576
|
+
ORDER BY ${order.field} ${order.direction} NULLS LAST, traceId ASC, ${ROOT_VERSION_ORDER}
|
|
7554
7577
|
LIMIT 1 BY traceId`,
|
|
7555
7578
|
query_params: parameters.params
|
|
7556
7579
|
};
|
|
@@ -7569,9 +7592,7 @@ FROM candidates`,
|
|
|
7569
7592
|
/**
|
|
7570
7593
|
* The list statement of groups and delta mode (rows without `metadata` and the previews). Keyset
|
|
7571
7594
|
* and page mode list with compileClickHouseTraceQueryKeys and compileClickHouseTraceRowsByKey.
|
|
7572
|
-
*
|
|
7573
|
-
* mode under the row that sorts first in the list order, as in the keys statement; ties go to the
|
|
7574
|
-
* lowest dedupeKey, then the latest endedAt, so every poll picks the same row.
|
|
7595
|
+
* Candidates hold one current root per trace, as in the keys statement.
|
|
7575
7596
|
*/
|
|
7576
7597
|
function compileClickHouseTraceQuery(plan, deltaHead) {
|
|
7577
7598
|
const parameters = new ParameterBuilder();
|
|
@@ -7592,7 +7613,6 @@ LIMIT ${limit}`,
|
|
|
7592
7613
|
};
|
|
7593
7614
|
}
|
|
7594
7615
|
if (plan.paginationMode !== "delta") throw new Error("Keyset and page trace queries use compileClickHouseTraceQueryKeys and compileClickHouseTraceRowsByKey");
|
|
7595
|
-
const order = traceOrder(plan);
|
|
7596
7616
|
const watermark = _mastra_core_storage.getTraceQueryDeltaWatermark(plan, "clickhouse");
|
|
7597
7617
|
const after = watermark ? parseDeltaWatermark(watermark) : {
|
|
7598
7618
|
cursorId: "0",
|
|
@@ -7611,8 +7631,7 @@ LIMIT ${limit}`,
|
|
|
7611
7631
|
SELECT c.*, toString(d.latestCursorId) AS __delta_cursor
|
|
7612
7632
|
FROM candidates c
|
|
7613
7633
|
INNER JOIN delta_candidates d ON c.traceId = d.traceId
|
|
7614
|
-
ORDER BY d.latestCursorId ASC, c.traceId ASC
|
|
7615
|
-
LIMIT 1 BY c.traceId
|
|
7634
|
+
ORDER BY d.latestCursorId ASC, c.traceId ASC
|
|
7616
7635
|
LIMIT ${limit}`,
|
|
7617
7636
|
query_params: parameters.params,
|
|
7618
7637
|
sharedSnapshot: true
|
|
@@ -7656,6 +7675,7 @@ function compileClickHouseTraceRootPayloads(keys, scope, columns = "payload") {
|
|
|
7656
7675
|
query: `SELECT traceId, spanId AS rootSpanId, dedupeKey, organizationId, resourceId, ${columns === "payload" ? `metadataRaw AS metadata, ${PREVIEW_COLUMNS.join(", ")}` : "input, output, error"}
|
|
7657
7676
|
FROM ${TABLE_TRACE_ROOTS}
|
|
7658
7677
|
WHERE (startedAt, traceId, dedupeKey, endedAt, ifNull(organizationId, ''), isNull(organizationId), ifNull(resourceId, ''), isNull(resourceId)) IN (${tuples.join(", ")})${compileTenantScope(scope, parameters)}
|
|
7678
|
+
ORDER BY ${ROOT_VERSION_ORDER}
|
|
7659
7679
|
LIMIT 1 BY traceId, dedupeKey, organizationId, resourceId`,
|
|
7660
7680
|
query_params: parameters.params
|
|
7661
7681
|
};
|
|
@@ -7952,7 +7972,8 @@ async function queryTraces(client, plan, timeoutMs, strategy = null) {
|
|
|
7952
7972
|
traceId: String(key.traceId),
|
|
7953
7973
|
dedupeKey: String(key.dedupeKey),
|
|
7954
7974
|
sortValue: sortValue(key.sortValue),
|
|
7955
|
-
rootStartedAt: asIsoTimestamp(key.rootStartedAt)
|
|
7975
|
+
rootStartedAt: asIsoTimestamp(key.rootStartedAt),
|
|
7976
|
+
rootEndedAt: asIsoTimestamp(key.rootEndedAt)
|
|
7956
7977
|
})))) : [];
|
|
7957
7978
|
if (plan.paginationMode === "page") return _mastra_core_storage.traceQueryResponseSchema.parse({
|
|
7958
7979
|
traces: await toTraceRecords(rows),
|
|
@@ -8361,7 +8382,7 @@ function compileClickHouseThreadRowsQuery(plan, strategy = "full") {
|
|
|
8361
8382
|
const sortedRoots = `roots AS (
|
|
8362
8383
|
SELECT organizationId, traceId, ${rootDataFields.map((field) => `${rootExpression(field)} AS ${field}`).join(", ")}
|
|
8363
8384
|
FROM ${TABLE_TRACE_ROOTS} ${scope.length || strategy === "candidates" ? `WHERE ${[...scope, ...strategy === "candidates" ? [candidateTracesFilter] : []].join(" AND ")}` : ""}
|
|
8364
|
-
ORDER BY organizationId, traceId, startedAt ASC, spanId,
|
|
8385
|
+
ORDER BY organizationId, traceId, startedAt ASC, spanId, ${ROOT_VERSION_ORDER}
|
|
8365
8386
|
LIMIT 1 BY organizationId, traceId
|
|
8366
8387
|
)`;
|
|
8367
8388
|
return {
|
|
@@ -8463,7 +8484,7 @@ async function queryThreadRows(client, plan, timeoutMs, strategy = "auto") {
|
|
|
8463
8484
|
${contextFields.join(", ")}, if(spanType = 'agent_run', timeToFirstChunkMs, NULL) AS timeToFirstChunkMs,
|
|
8464
8485
|
if(isNull(error), 'success', 'error') AS status, ${PREVIEW_COLUMNS.join(", ")}
|
|
8465
8486
|
FROM ${TABLE_TRACE_ROOTS} WHERE ${rootWhere}
|
|
8466
|
-
ORDER BY
|
|
8487
|
+
ORDER BY ${ROOT_VERSION_ORDER} LIMIT 1 BY organizationId, traceId, spanId`,
|
|
8467
8488
|
query_params: { roots: keys(batch) }
|
|
8468
8489
|
}));
|
|
8469
8490
|
const byRoot = new Map(stored.map((row) => [rootKey(row), row]));
|
|
@@ -8471,7 +8492,7 @@ async function queryThreadRows(client, plan, timeoutMs, strategy = "auto") {
|
|
|
8471
8492
|
for (const batch of batches(missing, 32)) {
|
|
8472
8493
|
const payloads = await run({
|
|
8473
8494
|
query: `SELECT organizationId, traceId, spanId, input, output, error FROM ${TABLE_TRACE_ROOTS}
|
|
8474
|
-
WHERE ${rootWhere} ORDER BY
|
|
8495
|
+
WHERE ${rootWhere} ORDER BY ${ROOT_VERSION_ORDER} LIMIT 1 BY organizationId, traceId, spanId`,
|
|
8475
8496
|
query_params: { roots: keys(batch) }
|
|
8476
8497
|
});
|
|
8477
8498
|
for (const payload of payloads) {
|
|
@@ -8540,6 +8561,7 @@ const DIMENSION_SQL = {
|
|
|
8540
8561
|
entityName: "r.entityName",
|
|
8541
8562
|
name: "r.name",
|
|
8542
8563
|
spanType: "r.spanType",
|
|
8564
|
+
entityId: "r.entityId",
|
|
8543
8565
|
environment: "r.environment",
|
|
8544
8566
|
status: TRACE_STATUS_SQL,
|
|
8545
8567
|
serviceName: "r.serviceName",
|
|
@@ -8578,12 +8600,6 @@ const COMPARISON_SQL = {
|
|
|
8578
8600
|
function compileClickHouseTraceAggregate(plan) {
|
|
8579
8601
|
const parameters = new ParameterBuilder();
|
|
8580
8602
|
const ctes = compileClickHouseTraceCandidates(plan, "*", parameters, { oneRootPerTrace: true });
|
|
8581
|
-
ctes.push(`trace_roots AS (
|
|
8582
|
-
SELECT *
|
|
8583
|
-
FROM candidates
|
|
8584
|
-
ORDER BY traceId, dedupeKey
|
|
8585
|
-
LIMIT 1 BY traceId
|
|
8586
|
-
)`);
|
|
8587
8603
|
const dimensionSql = (field) => {
|
|
8588
8604
|
if (field.startsWith("metadata.")) return traceMetadataValueSql(parameters.add(field.slice(9), "String"));
|
|
8589
8605
|
const sql = Object.hasOwn(DIMENSION_SQL, field) ? DIMENSION_SQL[field] : void 0;
|
|
@@ -8617,7 +8633,7 @@ function compileClickHouseTraceAggregate(plan) {
|
|
|
8617
8633
|
}
|
|
8618
8634
|
ctes.push(`facts AS (
|
|
8619
8635
|
SELECT ${factColumns.join(",\n ")}
|
|
8620
|
-
FROM
|
|
8636
|
+
FROM candidates r${usageJoin}
|
|
8621
8637
|
)`);
|
|
8622
8638
|
const mixedUnitsSql = "minOrNull(unitMin) != maxOrNull(unitMax)";
|
|
8623
8639
|
const measureSql = (name) => {
|
|
@@ -10123,6 +10139,7 @@ var ObservabilityStorageClickhouseVNext = class extends _mastra_core_storage.Obs
|
|
|
10123
10139
|
"trace-query-context-ids",
|
|
10124
10140
|
...timeToFirstChunkFeatures,
|
|
10125
10141
|
"trace-query-root-span-fields",
|
|
10142
|
+
"trace-query-root-entity-id",
|
|
10126
10143
|
"trace-aggregate",
|
|
10127
10144
|
...spanQueryFeatures,
|
|
10128
10145
|
...threadQueryFeatures
|
|
@@ -10146,6 +10163,7 @@ var ObservabilityStorageClickhouseVNext = class extends _mastra_core_storage.Obs
|
|
|
10146
10163
|
"trace-query-context-ids",
|
|
10147
10164
|
...timeToFirstChunkFeatures,
|
|
10148
10165
|
"trace-query-root-span-fields",
|
|
10166
|
+
"trace-query-root-entity-id",
|
|
10149
10167
|
"trace-aggregate",
|
|
10150
10168
|
...spanQueryFeatures,
|
|
10151
10169
|
...threadQueryFeatures
|