@mastra/clickhouse 1.14.0 → 1.15.0-alpha.1
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 +42 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-storage-composite.md +58 -0
- package/dist/index.cjs +87 -118
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +88 -119
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +7 -0
- package/dist/storage/domains/memory/index.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/trace-roots.d.ts +6 -10
- package/dist/storage/domains/observability/v-next/trace-roots.d.ts.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# @mastra/clickhouse
|
|
2
2
|
|
|
3
|
+
## 1.15.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed resource-scoped message includes across storage adapters so included context cannot cross resource boundaries. ([#20984](https://github.com/mastra-ai/mastra/pull/20984))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`6445eba`](https://github.com/mastra-ai/mastra/commit/6445eba6020abac681aba1cc9289f446cb400cbe), [`df31eb0`](https://github.com/mastra-ai/mastra/commit/df31eb0c7087d782a0d9346e467f9a4af4b0eef6), [`fcd0667`](https://github.com/mastra-ai/mastra/commit/fcd0667a4e378be35c9a1b1eb19cce78fbfd7282), [`bab06b1`](https://github.com/mastra-ai/mastra/commit/bab06b18923873a584bdfc71a6b4ec7fb4727fb7)]:
|
|
10
|
+
- @mastra/core@1.58.0-alpha.5
|
|
11
|
+
|
|
12
|
+
## 1.15.0-alpha.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- Memory list reads now surface database errors instead of silently returning empty results. ([#17910](https://github.com/mastra-ai/mastra/pull/17910))
|
|
17
|
+
|
|
18
|
+
Previously, the paginated memory reads (`listThreads`, `listMessages`, `listMessagesByResourceId`, and `listMessagesById`) caught backend failures, logged them, and returned an empty payload like `{ threads: [], total: 0, hasMore: false }`. A transient outage (locked table, dropped connection) was therefore indistinguishable from a genuinely empty result, so an agent reading conversation history during a brief failure would treat it as "no history" and could overwrite real state. These methods now re-throw the failure as a `MastraError`. Validation (USER) errors and genuinely empty results are unchanged.
|
|
19
|
+
|
|
20
|
+
**Behavior change**
|
|
21
|
+
|
|
22
|
+
Callers that previously received an empty result on a backend failure will now receive a thrown `MastraError`. If you call these read methods directly (rather than through an agent, which already surfaces errors), wrap them so a transient outage doesn't crash the caller:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
try {
|
|
26
|
+
const { threads } = await storage.listThreads({ resourceId });
|
|
27
|
+
// ...use threads
|
|
28
|
+
} catch (error) {
|
|
29
|
+
// a real backend failure. Decide whether to retry, surface, or degrade.
|
|
30
|
+
// An empty thread list no longer hides here; it only means "no threads".
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- Fixed the ClickHouse lightweight trace list: responses no longer carry the `input`, `output` and `attributes` payload blobs, and delta polling now works. ([#20677](https://github.com/mastra-ai/mastra/pull/20677))
|
|
37
|
+
|
|
38
|
+
`listTracesLight` rows now carry a short `inputPreview` in place of the full input, plus the span `metadata` and a computed `status`, so Studio's configurable trace columns keep working — in both page and delta mode. Response payloads stay small as prompts grow. There is no schema change and no migration.
|
|
39
|
+
|
|
40
|
+
Requires `@mastra/core` >= 1.57.0, which ships the shared `buildInputPreview` and `computeTraceStatus` helpers this store now imports (peer dependency bumped accordingly).
|
|
41
|
+
|
|
42
|
+
- Updated dependencies [[`e7109ee`](https://github.com/mastra-ai/mastra/commit/e7109ee6f731bacc79c885906f3c7dca8d8f013a), [`772c0c8`](https://github.com/mastra-ai/mastra/commit/772c0c897cec383258de2e6178147f8014767c7b), [`578bf2e`](https://github.com/mastra-ai/mastra/commit/578bf2e6a88e9d5b8bf502204e15a95dfbb679ae), [`06b2d87`](https://github.com/mastra-ai/mastra/commit/06b2d87e63bcdd0ed59215c6789692b9b12de376), [`ac01d63`](https://github.com/mastra-ai/mastra/commit/ac01d6355974aec73fdb8781449ed12bac582094), [`a810a05`](https://github.com/mastra-ai/mastra/commit/a810a058f62ad407cfc1701e0be36ae91145d7cf), [`f8da216`](https://github.com/mastra-ai/mastra/commit/f8da21633e7eb0e31c9ce0fc30567870d19416d3), [`6104347`](https://github.com/mastra-ai/mastra/commit/61043473ba6bfd0a25156824e853e13165562e6c), [`45bfb88`](https://github.com/mastra-ai/mastra/commit/45bfb88fd52f1dd3be20e2a38905777c96499c90), [`e3b9307`](https://github.com/mastra-ai/mastra/commit/e3b9307098daefbfae2a52ae2ef51bc9fc701190), [`d6834c5`](https://github.com/mastra-ai/mastra/commit/d6834c5a7866b16734d23900163c2414ed70d791), [`c52d346`](https://github.com/mastra-ai/mastra/commit/c52d3462ec831a5d95926ecd3d3373f5928ad2e5), [`0023e79`](https://github.com/mastra-ai/mastra/commit/0023e7919431078280abd11c89d1edeae35fcc69), [`c2ad51e`](https://github.com/mastra-ai/mastra/commit/c2ad51e2467f901eecba8c9f4a45e22a50bd7c18), [`3dc97ea`](https://github.com/mastra-ai/mastra/commit/3dc97ea415fad353b48a13095fad1835933cc12a), [`3d01cd3`](https://github.com/mastra-ai/mastra/commit/3d01cd387321b6f9c5cac31d487c84bf51b19c78), [`7bf3086`](https://github.com/mastra-ai/mastra/commit/7bf308663f0115ca74ad20554ade740f06640859), [`a8dd139`](https://github.com/mastra-ai/mastra/commit/a8dd1391a9fe9a6632c25809ef236980afa9a020), [`e5786be`](https://github.com/mastra-ai/mastra/commit/e5786be02bb903073082bd9d6da880ebaacc343f), [`2093fbd`](https://github.com/mastra-ai/mastra/commit/2093fbd53bb744bae19ec89f6d73db9a66fbe8a7), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`7b4393d`](https://github.com/mastra-ai/mastra/commit/7b4393d557411fdcf07b0e30e5acaf7cc85154ae)]:
|
|
43
|
+
- @mastra/core@1.58.0-alpha.1
|
|
44
|
+
|
|
3
45
|
## 1.14.0
|
|
4
46
|
|
|
5
47
|
### Minor Changes
|
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.
|
|
6
|
+
version: "1.15.0-alpha.1"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -251,6 +251,64 @@ const memoryStore = await storage.getStore('memory')
|
|
|
251
251
|
const thread = await memoryStore?.getThreadById({ threadId: '...' })
|
|
252
252
|
```
|
|
253
253
|
|
|
254
|
+
## Closing connections
|
|
255
|
+
|
|
256
|
+
`close()` releases the connections of the stores a composite was built from: the `default` and `editor` stores, plus any domain that owns its own client. Each store is closed once, even when it backs several domains. When passed to the Mastra class, `close()` is called by `shutdown()`:
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
import { MastraCompositeStore } from '@mastra/core/storage'
|
|
260
|
+
import { PostgresStore } from '@mastra/pg'
|
|
261
|
+
import { Mastra } from '@mastra/core'
|
|
262
|
+
|
|
263
|
+
const pgStore = new PostgresStore({
|
|
264
|
+
id: 'pg-storage',
|
|
265
|
+
connectionString: process.env.DATABASE_URL,
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
export const mastra = new Mastra({
|
|
269
|
+
storage: new MastraCompositeStore({ id: 'composite', default: pgStore }),
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
process.on('SIGTERM', async () => {
|
|
273
|
+
// Releases the Postgres pool, so the process can exit
|
|
274
|
+
await mastra.shutdown()
|
|
275
|
+
})
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
A store you construct only to supply a domain isn't reachable through the composite. Keep a reference to it and close it yourself:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
import { MastraCompositeStore } from '@mastra/core/storage'
|
|
282
|
+
import { ClickhouseStore } from '@mastra/clickhouse'
|
|
283
|
+
import { PostgresStore } from '@mastra/pg'
|
|
284
|
+
import { Mastra } from '@mastra/core'
|
|
285
|
+
|
|
286
|
+
const pgStore = new PostgresStore({
|
|
287
|
+
id: 'pg-storage',
|
|
288
|
+
connectionString: process.env.DATABASE_URL,
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
const clickhouseStore = new ClickhouseStore({
|
|
292
|
+
id: 'clickhouse-storage',
|
|
293
|
+
url: process.env.CLICKHOUSE_URL,
|
|
294
|
+
username: process.env.CLICKHOUSE_USERNAME,
|
|
295
|
+
password: process.env.CLICKHOUSE_PASSWORD,
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
export const mastra = new Mastra({
|
|
299
|
+
storage: new MastraCompositeStore({
|
|
300
|
+
id: 'composite',
|
|
301
|
+
default: pgStore,
|
|
302
|
+
domains: { observability: clickhouseStore.stores?.observability },
|
|
303
|
+
}),
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
process.on('SIGTERM', async () => {
|
|
307
|
+
await mastra.shutdown()
|
|
308
|
+
await clickhouseStore.close()
|
|
309
|
+
})
|
|
310
|
+
```
|
|
311
|
+
|
|
254
312
|
## Use cases
|
|
255
313
|
|
|
256
314
|
### Separate databases for different workloads
|
package/dist/index.cjs
CHANGED
|
@@ -1185,7 +1185,10 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
|
|
|
1185
1185
|
hasMore: false
|
|
1186
1186
|
};
|
|
1187
1187
|
if (perPageForQuery === 0 && include && include.length > 0) {
|
|
1188
|
-
const includeResult = await this._getIncludedMessages({
|
|
1188
|
+
const includeResult = await this._getIncludedMessages({
|
|
1189
|
+
include,
|
|
1190
|
+
resourceId
|
|
1191
|
+
});
|
|
1189
1192
|
const list = new _mastra_core_agent.MessageList().add(includeResult, "memory");
|
|
1190
1193
|
return {
|
|
1191
1194
|
messages: this._sortMessages(list.get.all.db(), field, direction),
|
|
@@ -1252,7 +1255,10 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
|
|
|
1252
1255
|
};
|
|
1253
1256
|
const messageIds = new Set(paginatedMessages.map((m) => m.id));
|
|
1254
1257
|
if (include && include.length > 0) {
|
|
1255
|
-
const includeMessages = await this._getIncludedMessages({
|
|
1258
|
+
const includeMessages = await this._getIncludedMessages({
|
|
1259
|
+
include,
|
|
1260
|
+
resourceId
|
|
1261
|
+
});
|
|
1256
1262
|
for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
|
|
1257
1263
|
paginatedMessages.push(includeMsg);
|
|
1258
1264
|
messageIds.add(includeMsg.id);
|
|
@@ -1270,6 +1276,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
|
|
|
1270
1276
|
hasMore: metadataFilter && perPageForResponse !== false ? offset + paginatedCount < total : perPageForResponse === false ? false : allThreadMessagesReturned ? false : offset + paginatedCount < total
|
|
1271
1277
|
};
|
|
1272
1278
|
} catch (error) {
|
|
1279
|
+
if (error instanceof _mastra_core_error.MastraError && error.category === _mastra_core_error.ErrorCategory.USER) throw error;
|
|
1273
1280
|
const mastraError = new _mastra_core_error.MastraError({
|
|
1274
1281
|
id: (0, _mastra_core_storage.createStorageErrorId)("CLICKHOUSE", "LIST_MESSAGES", "FAILED"),
|
|
1275
1282
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -1281,13 +1288,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
|
|
|
1281
1288
|
}, error);
|
|
1282
1289
|
this.logger?.error?.(mastraError.toString());
|
|
1283
1290
|
this.logger?.trackException?.(mastraError);
|
|
1284
|
-
|
|
1285
|
-
messages: [],
|
|
1286
|
-
total: 0,
|
|
1287
|
-
page,
|
|
1288
|
-
perPage: perPageForResponse,
|
|
1289
|
-
hasMore: false
|
|
1290
|
-
};
|
|
1291
|
+
throw mastraError;
|
|
1291
1292
|
}
|
|
1292
1293
|
}
|
|
1293
1294
|
_sortMessages(messages, field, direction) {
|
|
@@ -1300,15 +1301,24 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
|
|
|
1300
1301
|
return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
|
|
1301
1302
|
});
|
|
1302
1303
|
}
|
|
1303
|
-
|
|
1304
|
+
/**
|
|
1305
|
+
* Fetches the messages named by `include` together with their surrounding context.
|
|
1306
|
+
*
|
|
1307
|
+
* @param include - Message ids to pin, each with an optional before/after window.
|
|
1308
|
+
* @param resourceId - When set, restricts both the pinned messages and their context
|
|
1309
|
+
* to that resource so an id from another resource returns nothing.
|
|
1310
|
+
*/
|
|
1311
|
+
async _getIncludedMessages({ include, resourceId }) {
|
|
1304
1312
|
if (!include || include.length === 0) return [];
|
|
1305
1313
|
const targetIds = include.map((inc) => inc.id).filter(Boolean);
|
|
1306
1314
|
if (targetIds.length === 0) return [];
|
|
1307
1315
|
const { messages: targetDocs } = await this.listMessagesById({ messageIds: targetIds });
|
|
1308
|
-
const
|
|
1316
|
+
const scopedTargetDocs = resourceId ? targetDocs.filter((msg) => msg.resourceId === resourceId) : targetDocs;
|
|
1317
|
+
const targetMap = new Map(scopedTargetDocs.map((msg) => [msg.id, {
|
|
1309
1318
|
threadId: msg.threadId,
|
|
1310
1319
|
createdAt: msg.createdAt
|
|
1311
1320
|
}]));
|
|
1321
|
+
const resourceCondition = resourceId ? ` AND "resourceId" = {var_resource:String}` : "";
|
|
1312
1322
|
const unionQueries = [];
|
|
1313
1323
|
const params = {};
|
|
1314
1324
|
let paramIdx = 1;
|
|
@@ -1323,7 +1333,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
|
|
|
1323
1333
|
SELECT id, content, role, type, "createdAt", thread_id AS "threadId", "resourceId"
|
|
1324
1334
|
FROM "${_mastra_core_storage.TABLE_MESSAGES}"
|
|
1325
1335
|
WHERE thread_id = {${threadParam}:String}
|
|
1326
|
-
AND createdAt <= parseDateTime64BestEffort({${createdAtParam}:String}, 3)
|
|
1336
|
+
AND createdAt <= parseDateTime64BestEffort({${createdAtParam}:String}, 3)${resourceCondition}
|
|
1327
1337
|
ORDER BY createdAt DESC, id DESC
|
|
1328
1338
|
LIMIT {${limitParam}:Int64}
|
|
1329
1339
|
`);
|
|
@@ -1339,7 +1349,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
|
|
|
1339
1349
|
SELECT id, content, role, type, "createdAt", thread_id AS "threadId", "resourceId"
|
|
1340
1350
|
FROM "${_mastra_core_storage.TABLE_MESSAGES}"
|
|
1341
1351
|
WHERE thread_id = {${threadParam2}:String}
|
|
1342
|
-
AND createdAt > parseDateTime64BestEffort({${createdAtParam2}:String}, 3)
|
|
1352
|
+
AND createdAt > parseDateTime64BestEffort({${createdAtParam2}:String}, 3)${resourceCondition}
|
|
1343
1353
|
ORDER BY createdAt ASC, id ASC
|
|
1344
1354
|
LIMIT {${limitParam2}:Int64}
|
|
1345
1355
|
`);
|
|
@@ -1350,6 +1360,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
|
|
|
1350
1360
|
}
|
|
1351
1361
|
}
|
|
1352
1362
|
if (unionQueries.length === 0) return [];
|
|
1363
|
+
if (resourceId) params.var_resource = resourceId;
|
|
1353
1364
|
let finalQuery;
|
|
1354
1365
|
if (unionQueries.length === 1) finalQuery = unionQueries[0];
|
|
1355
1366
|
else finalQuery = `SELECT * FROM (${unionQueries.join(" UNION ALL ")}) ORDER BY "createdAt" ASC, id ASC`;
|
|
@@ -3873,6 +3884,7 @@ function rowToSpanRecord(row) {
|
|
|
3873
3884
|
function rowToLightSpanRecord(row) {
|
|
3874
3885
|
const startedAt = toDate(row.startedAt);
|
|
3875
3886
|
const endedAt = row.isEvent ? startedAt : toDateOrNull(row.endedAt);
|
|
3887
|
+
const error = parseJson(row.error) ?? void 0;
|
|
3876
3888
|
return {
|
|
3877
3889
|
traceId: row.traceId,
|
|
3878
3890
|
spanId: row.spanId,
|
|
@@ -3885,7 +3897,13 @@ function rowToLightSpanRecord(row) {
|
|
|
3885
3897
|
entityType: nullableEntityType(row.entityType),
|
|
3886
3898
|
entityId: nullableString(row.entityId),
|
|
3887
3899
|
entityName: nullableString(row.entityName),
|
|
3888
|
-
error
|
|
3900
|
+
error,
|
|
3901
|
+
status: (0, _mastra_core_storage.computeTraceStatus)({
|
|
3902
|
+
error,
|
|
3903
|
+
endedAt
|
|
3904
|
+
}),
|
|
3905
|
+
metadata: parseJson(row.metadataRaw) ?? void 0,
|
|
3906
|
+
inputPreview: (0, _mastra_core_storage.buildInputPreview)(row.input ?? null),
|
|
3889
3907
|
createdAt: startedAt,
|
|
3890
3908
|
updatedAt: null
|
|
3891
3909
|
};
|
|
@@ -6208,93 +6226,48 @@ async function getRootSpan(client, args) {
|
|
|
6208
6226
|
return { span: rowToSpanRecord(rows[0]) };
|
|
6209
6227
|
}
|
|
6210
6228
|
/**
|
|
6211
|
-
*
|
|
6229
|
+
* Columns a trace list renders. `input` is selected only so the row mapper can
|
|
6230
|
+
* derive a short `inputPreview` at read time (see `rowToLightSpanRecord`); the
|
|
6231
|
+
* raw blob itself never leaves the store.
|
|
6212
6232
|
*/
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
LIMIT 1 BY dedupeKey
|
|
6240
|
-
)
|
|
6241
|
-
`,
|
|
6242
|
-
query_params: params,
|
|
6243
|
-
format: "JSONEachRow",
|
|
6244
|
-
clickhouse_settings: CH_SETTINGS
|
|
6245
|
-
})).json();
|
|
6246
|
-
const total = Number(countRows[0]?.cnt ?? 0);
|
|
6247
|
-
if (total === 0) return {
|
|
6248
|
-
pagination: {
|
|
6249
|
-
total: 0,
|
|
6250
|
-
page,
|
|
6251
|
-
perPage,
|
|
6252
|
-
hasMore: false
|
|
6253
|
-
},
|
|
6254
|
-
spans: []
|
|
6255
|
-
};
|
|
6256
|
-
const rows = await (await client.query({
|
|
6257
|
-
query: `
|
|
6258
|
-
SELECT ${selectClause} FROM (
|
|
6259
|
-
SELECT ${selectClause}
|
|
6260
|
-
FROM ${TABLE_TRACE_ROOTS} r
|
|
6261
|
-
${whereClause}
|
|
6262
|
-
ORDER BY dedupeKey
|
|
6263
|
-
LIMIT 1 BY dedupeKey
|
|
6264
|
-
)
|
|
6265
|
-
ORDER BY ${orderClause}
|
|
6266
|
-
LIMIT {limit:UInt32}
|
|
6267
|
-
OFFSET {offset:UInt32}
|
|
6268
|
-
`,
|
|
6269
|
-
query_params: {
|
|
6270
|
-
...params,
|
|
6271
|
-
limit: perPage,
|
|
6272
|
-
offset: page * perPage
|
|
6273
|
-
},
|
|
6274
|
-
format: "JSONEachRow",
|
|
6275
|
-
clickhouse_settings: CH_SETTINGS
|
|
6276
|
-
})).json();
|
|
6277
|
-
return {
|
|
6278
|
-
pagination: {
|
|
6279
|
-
total,
|
|
6280
|
-
page,
|
|
6281
|
-
perPage,
|
|
6282
|
-
hasMore: (page + 1) * perPage < total
|
|
6283
|
-
},
|
|
6284
|
-
spans: mapRows(rows)
|
|
6285
|
-
};
|
|
6286
|
-
}
|
|
6233
|
+
const LIGHT_TRACE_ROOT_FIELDS = [
|
|
6234
|
+
"traceId",
|
|
6235
|
+
"spanId",
|
|
6236
|
+
"parentSpanId",
|
|
6237
|
+
"name",
|
|
6238
|
+
"spanType",
|
|
6239
|
+
"isEvent",
|
|
6240
|
+
"startedAt",
|
|
6241
|
+
"endedAt",
|
|
6242
|
+
"entityType",
|
|
6243
|
+
"entityId",
|
|
6244
|
+
"entityName",
|
|
6245
|
+
"error",
|
|
6246
|
+
"metadataRaw",
|
|
6247
|
+
"input"
|
|
6248
|
+
];
|
|
6249
|
+
const FULL_PROJECTION = {
|
|
6250
|
+
innerSelect: "*",
|
|
6251
|
+
outerSelect: "*",
|
|
6252
|
+
deltaSelect: "r.* EXCEPT(startedAt, traceId, dedupeKey)"
|
|
6253
|
+
};
|
|
6254
|
+
const LIGHT_PROJECTION = {
|
|
6255
|
+
innerSelect: ["dedupeKey", ...LIGHT_TRACE_ROOT_FIELDS].join(", "),
|
|
6256
|
+
outerSelect: LIGHT_TRACE_ROOT_FIELDS.join(", "),
|
|
6257
|
+
deltaSelect: LIGHT_TRACE_ROOT_FIELDS.filter((field) => field !== "startedAt" && field !== "traceId").map((field) => `r.${field}`).join(", ")
|
|
6258
|
+
};
|
|
6287
6259
|
/**
|
|
6288
|
-
*
|
|
6260
|
+
* Shared implementation behind listTraces and listTracesLight.
|
|
6289
6261
|
*
|
|
6290
6262
|
* Reads from trace_roots (root spans only).
|
|
6291
|
-
*
|
|
6263
|
+
* Page mode uses a two-stage query for ReplacingMergeTree deduplication:
|
|
6292
6264
|
* Inner: filter + deterministic ORDER BY + LIMIT 1 BY dedupeKey
|
|
6293
6265
|
* Outer: final ordering + pagination
|
|
6266
|
+
* Delta mode joins the append-only delta table and returns only rows past the cursor.
|
|
6294
6267
|
*
|
|
6295
6268
|
* hasChildError is handled via EXISTS subquery against span_events.
|
|
6296
6269
|
*/
|
|
6297
|
-
async function
|
|
6270
|
+
async function listTraceRows(client, args, strategy, projection, mapRows) {
|
|
6298
6271
|
const { mode, filters, pagination, orderBy, after, limit } = _mastra_core_storage.listTracesArgsSchema.parse(args);
|
|
6299
6272
|
const page = pagination?.page ?? 0;
|
|
6300
6273
|
const perPage = pagination?.perPage ?? 10;
|
|
@@ -6324,10 +6297,11 @@ async function listTraces(client, args, strategy) {
|
|
|
6324
6297
|
},
|
|
6325
6298
|
deltaCursor: streamHeadCursor
|
|
6326
6299
|
};
|
|
6327
|
-
const
|
|
6300
|
+
const afterCursor = validateCursorId(after);
|
|
6301
|
+
const rows = await queryTracesAfterCursor(client, projection.deltaSelect, whereClause, params, limit, afterCursor);
|
|
6328
6302
|
const visibleRows = rows.slice(0, limit);
|
|
6329
6303
|
return {
|
|
6330
|
-
spans: (
|
|
6304
|
+
spans: mapRows(visibleRows),
|
|
6331
6305
|
delta: {
|
|
6332
6306
|
limit,
|
|
6333
6307
|
hasMore: rows.length > limit
|
|
@@ -6362,10 +6336,10 @@ async function listTraces(client, args, strategy) {
|
|
|
6362
6336
|
spans: [],
|
|
6363
6337
|
...deltaCursorEnabled ? { deltaCursor: currentDeltaCursor } : {}
|
|
6364
6338
|
};
|
|
6365
|
-
const
|
|
6339
|
+
const rows = await (await client.query({
|
|
6366
6340
|
query: `
|
|
6367
|
-
SELECT
|
|
6368
|
-
SELECT
|
|
6341
|
+
SELECT ${projection.outerSelect} FROM (
|
|
6342
|
+
SELECT ${projection.innerSelect}
|
|
6369
6343
|
FROM ${TABLE_TRACE_ROOTS} r
|
|
6370
6344
|
${whereClause}
|
|
6371
6345
|
ORDER BY dedupeKey
|
|
@@ -6382,7 +6356,7 @@ async function listTraces(client, args, strategy) {
|
|
|
6382
6356
|
},
|
|
6383
6357
|
format: "JSONEachRow",
|
|
6384
6358
|
clickhouse_settings: CH_SETTINGS
|
|
6385
|
-
})).json()
|
|
6359
|
+
})).json();
|
|
6386
6360
|
return {
|
|
6387
6361
|
pagination: {
|
|
6388
6362
|
total,
|
|
@@ -6390,32 +6364,27 @@ async function listTraces(client, args, strategy) {
|
|
|
6390
6364
|
perPage,
|
|
6391
6365
|
hasMore: (page + 1) * perPage < total
|
|
6392
6366
|
},
|
|
6393
|
-
spans: (
|
|
6367
|
+
spans: mapRows(rows),
|
|
6394
6368
|
...deltaCursorEnabled ? { deltaCursor: currentDeltaCursor } : {}
|
|
6395
6369
|
};
|
|
6396
6370
|
}
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
"entityName",
|
|
6409
|
-
"error"
|
|
6410
|
-
].join(", ");
|
|
6411
|
-
async function listTracesLight(client, args) {
|
|
6412
|
-
return listTraceRows(client, args, LIGHT_TRACE_ROOT_COLUMNS, (rows) => rows.map(rowToLightSpanRecord));
|
|
6371
|
+
/** List traces with optional filtering, pagination, and ordering. */
|
|
6372
|
+
async function listTraces(client, args, strategy) {
|
|
6373
|
+
return listTraceRows(client, args, strategy, FULL_PROJECTION, (rows) => (0, _mastra_core_storage.toTraceSpans)(rows.map(rowToSpanRecord)));
|
|
6374
|
+
}
|
|
6375
|
+
/**
|
|
6376
|
+
* List traces projecting only the columns a trace list renders.
|
|
6377
|
+
* Skips the attributes/output blobs and reduces `input` to a short preview in
|
|
6378
|
+
* the mapper, so the response payload stays flat as traces grow.
|
|
6379
|
+
*/
|
|
6380
|
+
async function listTracesLight(client, args, strategy) {
|
|
6381
|
+
return listTraceRows(client, args, strategy, LIGHT_PROJECTION, (rows) => rows.map(rowToLightSpanRecord));
|
|
6413
6382
|
}
|
|
6414
|
-
async function queryTracesAfterCursor(client, whereClause, params, limit, cursorId) {
|
|
6383
|
+
async function queryTracesAfterCursor(client, deltaSelect, whereClause, params, limit, cursorId) {
|
|
6415
6384
|
return await (await client.query({
|
|
6416
6385
|
query: `
|
|
6417
6386
|
SELECT
|
|
6418
|
-
|
|
6387
|
+
${deltaSelect},
|
|
6419
6388
|
r.startedAt AS startedAt,
|
|
6420
6389
|
r.traceId AS traceId,
|
|
6421
6390
|
r.dedupeKey AS dedupeKey,
|
|
@@ -7392,7 +7361,7 @@ var ObservabilityStorageClickhouseVNext = class extends _mastra_core_storage.Obs
|
|
|
7392
7361
|
}
|
|
7393
7362
|
async listTracesLight(args) {
|
|
7394
7363
|
try {
|
|
7395
|
-
return await listTracesLight(this.#client, args);
|
|
7364
|
+
return await listTracesLight(this.#client, args, this.#deltaCursorStrategy);
|
|
7396
7365
|
} catch (error) {
|
|
7397
7366
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
7398
7367
|
throw new _mastra_core_error.MastraError({
|