@mastra/duckdb 1.3.2-alpha.0 → 1.4.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/CHANGELOG.md +20 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +10 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/{observability-J6N3H7W7.cjs → observability-25HVQJC2.cjs} +696 -55
- package/dist/observability-25HVQJC2.cjs.map +1 -0
- package/dist/{observability-TS5QIHIC.js → observability-2MIUMLQP.js} +697 -56
- package/dist/observability-2MIUMLQP.js.map +1 -0
- package/dist/storage/domains/observability/ddl.d.ts +10 -5
- package/dist/storage/domains/observability/ddl.d.ts.map +1 -1
- package/dist/storage/domains/observability/feedback.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +1 -0
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/logs.d.ts.map +1 -1
- package/dist/storage/domains/observability/metrics.d.ts.map +1 -1
- package/dist/storage/domains/observability/migration.d.ts.map +1 -1
- package/dist/storage/domains/observability/polling.d.ts +7 -0
- package/dist/storage/domains/observability/polling.d.ts.map +1 -0
- package/dist/storage/domains/observability/scores.d.ts.map +1 -1
- package/dist/storage/domains/observability/tracing.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/observability-J6N3H7W7.cjs.map +0 -1
- package/dist/observability-TS5QIHIC.js.map +0 -1
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
import { DuckDBConnection } from './chunk-4LIZE4MC.js';
|
|
2
2
|
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
3
|
-
import { BRANCH_SPAN_TYPES, ObservabilityStorage, createStorageErrorId, toTraceSpans, METRIC_DISTINCT_COLUMNS } from '@mastra/core/storage';
|
|
3
|
+
import { BRANCH_SPAN_TYPES, ObservabilityStorage, createStorageErrorId, listTracesArgsSchema, toTraceSpans, listBranchesArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listFeedbackArgsSchema, METRIC_DISTINCT_COLUMNS } from '@mastra/core/storage';
|
|
4
4
|
import { EntityType } from '@mastra/core/observability';
|
|
5
5
|
import { parseFieldKey } from '@mastra/core/utils';
|
|
6
|
+
import { coreFeatures } from '@mastra/core/features';
|
|
6
7
|
|
|
7
8
|
// src/storage/domains/observability/ddl.ts
|
|
9
|
+
var SPAN_EVENTS_CURSOR_SEQUENCE_DDL = `
|
|
10
|
+
CREATE SEQUENCE IF NOT EXISTS span_events_cursor_id_seq START 1
|
|
11
|
+
`;
|
|
12
|
+
var METRIC_EVENTS_CURSOR_SEQUENCE_DDL = `
|
|
13
|
+
CREATE SEQUENCE IF NOT EXISTS metric_events_cursor_id_seq START 1
|
|
14
|
+
`;
|
|
15
|
+
var LOG_EVENTS_CURSOR_SEQUENCE_DDL = `
|
|
16
|
+
CREATE SEQUENCE IF NOT EXISTS log_events_cursor_id_seq START 1
|
|
17
|
+
`;
|
|
18
|
+
var SCORE_EVENTS_CURSOR_SEQUENCE_DDL = `
|
|
19
|
+
CREATE SEQUENCE IF NOT EXISTS score_events_cursor_id_seq START 1
|
|
20
|
+
`;
|
|
21
|
+
var FEEDBACK_EVENTS_CURSOR_SEQUENCE_DDL = `
|
|
22
|
+
CREATE SEQUENCE IF NOT EXISTS feedback_events_cursor_id_seq START 1
|
|
23
|
+
`;
|
|
8
24
|
var SPAN_EVENTS_DDL = `
|
|
9
25
|
CREATE TABLE IF NOT EXISTS span_events (
|
|
10
26
|
-- Event metadata
|
|
11
27
|
eventType VARCHAR NOT NULL,
|
|
12
28
|
timestamp TIMESTAMP NOT NULL,
|
|
29
|
+
cursorId BIGINT DEFAULT nextval('span_events_cursor_id_seq'),
|
|
13
30
|
|
|
14
31
|
-- IDs
|
|
15
32
|
traceId VARCHAR NOT NULL,
|
|
@@ -56,6 +73,7 @@ var METRIC_EVENTS_DDL = `
|
|
|
56
73
|
CREATE TABLE IF NOT EXISTS metric_events (
|
|
57
74
|
-- Event metadata
|
|
58
75
|
timestamp TIMESTAMP NOT NULL,
|
|
76
|
+
cursorId BIGINT DEFAULT nextval('metric_events_cursor_id_seq'),
|
|
59
77
|
|
|
60
78
|
-- IDs
|
|
61
79
|
metricId VARCHAR NOT NULL PRIMARY KEY,
|
|
@@ -108,6 +126,7 @@ var LOG_EVENTS_DDL = `
|
|
|
108
126
|
CREATE TABLE IF NOT EXISTS log_events (
|
|
109
127
|
-- Event metadata
|
|
110
128
|
timestamp TIMESTAMP NOT NULL,
|
|
129
|
+
cursorId BIGINT DEFAULT nextval('log_events_cursor_id_seq'),
|
|
111
130
|
|
|
112
131
|
-- IDs
|
|
113
132
|
logId VARCHAR NOT NULL PRIMARY KEY,
|
|
@@ -155,6 +174,7 @@ var SCORE_EVENTS_DDL = `
|
|
|
155
174
|
CREATE TABLE IF NOT EXISTS score_events (
|
|
156
175
|
-- Event metadata
|
|
157
176
|
timestamp TIMESTAMP NOT NULL,
|
|
177
|
+
cursorId BIGINT DEFAULT nextval('score_events_cursor_id_seq'),
|
|
158
178
|
|
|
159
179
|
-- IDs
|
|
160
180
|
scoreId VARCHAR NOT NULL PRIMARY KEY,
|
|
@@ -206,6 +226,7 @@ var FEEDBACK_EVENTS_DDL = `
|
|
|
206
226
|
CREATE TABLE IF NOT EXISTS feedback_events (
|
|
207
227
|
-- Event metadata
|
|
208
228
|
timestamp TIMESTAMP NOT NULL,
|
|
229
|
+
cursorId BIGINT DEFAULT nextval('feedback_events_cursor_id_seq'),
|
|
209
230
|
|
|
210
231
|
-- IDs
|
|
211
232
|
feedbackId VARCHAR NOT NULL PRIMARY KEY,
|
|
@@ -254,11 +275,32 @@ CREATE TABLE IF NOT EXISTS feedback_events (
|
|
|
254
275
|
metadata JSON,
|
|
255
276
|
scope JSON
|
|
256
277
|
)`;
|
|
257
|
-
var ALL_DDL = [
|
|
278
|
+
var ALL_DDL = [
|
|
279
|
+
SPAN_EVENTS_CURSOR_SEQUENCE_DDL,
|
|
280
|
+
METRIC_EVENTS_CURSOR_SEQUENCE_DDL,
|
|
281
|
+
LOG_EVENTS_CURSOR_SEQUENCE_DDL,
|
|
282
|
+
SCORE_EVENTS_CURSOR_SEQUENCE_DDL,
|
|
283
|
+
FEEDBACK_EVENTS_CURSOR_SEQUENCE_DDL,
|
|
284
|
+
SPAN_EVENTS_DDL,
|
|
285
|
+
METRIC_EVENTS_DDL,
|
|
286
|
+
LOG_EVENTS_DDL,
|
|
287
|
+
SCORE_EVENTS_DDL,
|
|
288
|
+
FEEDBACK_EVENTS_DDL
|
|
289
|
+
];
|
|
258
290
|
var ALL_MIGRATIONS = [
|
|
259
|
-
|
|
291
|
+
`CREATE SEQUENCE IF NOT EXISTS span_events_cursor_id_seq START 1`,
|
|
292
|
+
`CREATE SEQUENCE IF NOT EXISTS metric_events_cursor_id_seq START 1`,
|
|
293
|
+
`CREATE SEQUENCE IF NOT EXISTS log_events_cursor_id_seq START 1`,
|
|
294
|
+
`CREATE SEQUENCE IF NOT EXISTS score_events_cursor_id_seq START 1`,
|
|
295
|
+
`CREATE SEQUENCE IF NOT EXISTS feedback_events_cursor_id_seq START 1`,
|
|
296
|
+
// Span events. Existing rows intentionally keep NULL cursorId values; delta
|
|
297
|
+
// polling only applies to rows written after this migration path is in place.
|
|
298
|
+
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
|
|
299
|
+
`ALTER TABLE span_events ALTER COLUMN cursorId SET DEFAULT nextval('span_events_cursor_id_seq')`,
|
|
260
300
|
`ALTER TABLE span_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
|
|
261
|
-
// Metrics
|
|
301
|
+
// Metrics. Legacy rows remain page-visible but are not part of delta polling.
|
|
302
|
+
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
|
|
303
|
+
`ALTER TABLE metric_events ALTER COLUMN cursorId SET DEFAULT nextval('metric_events_cursor_id_seq')`,
|
|
262
304
|
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
|
|
263
305
|
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS parentEntityVersionId VARCHAR`,
|
|
264
306
|
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS rootEntityVersionId VARCHAR`,
|
|
@@ -282,7 +324,9 @@ var ALL_MIGRATIONS = [
|
|
|
282
324
|
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS costMetadata JSON`,
|
|
283
325
|
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS metadata JSON`,
|
|
284
326
|
`ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS scope JSON`,
|
|
285
|
-
// Logs
|
|
327
|
+
// Logs. Legacy rows remain page-visible but are not part of delta polling.
|
|
328
|
+
`ALTER TABLE log_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
|
|
329
|
+
`ALTER TABLE log_events ALTER COLUMN cursorId SET DEFAULT nextval('log_events_cursor_id_seq')`,
|
|
286
330
|
`ALTER TABLE log_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
|
|
287
331
|
`ALTER TABLE log_events ADD COLUMN IF NOT EXISTS parentEntityVersionId VARCHAR`,
|
|
288
332
|
`ALTER TABLE log_events ADD COLUMN IF NOT EXISTS rootEntityVersionId VARCHAR`,
|
|
@@ -306,7 +350,9 @@ var ALL_MIGRATIONS = [
|
|
|
306
350
|
`ALTER TABLE log_events ADD COLUMN IF NOT EXISTS tags JSON`,
|
|
307
351
|
`ALTER TABLE log_events ADD COLUMN IF NOT EXISTS metadata JSON`,
|
|
308
352
|
`ALTER TABLE log_events ADD COLUMN IF NOT EXISTS scope JSON`,
|
|
309
|
-
// Scores
|
|
353
|
+
// Scores. Legacy rows remain page-visible but are not part of delta polling.
|
|
354
|
+
`ALTER TABLE score_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
|
|
355
|
+
`ALTER TABLE score_events ALTER COLUMN cursorId SET DEFAULT nextval('score_events_cursor_id_seq')`,
|
|
310
356
|
`ALTER TABLE score_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
|
|
311
357
|
`ALTER TABLE score_events ADD COLUMN IF NOT EXISTS parentEntityVersionId VARCHAR`,
|
|
312
358
|
`ALTER TABLE score_events ADD COLUMN IF NOT EXISTS rootEntityVersionId VARCHAR`,
|
|
@@ -334,7 +380,9 @@ var ALL_MIGRATIONS = [
|
|
|
334
380
|
`ALTER TABLE score_events ADD COLUMN IF NOT EXISTS source VARCHAR`,
|
|
335
381
|
`ALTER TABLE score_events ADD COLUMN IF NOT EXISTS scoreSource VARCHAR`,
|
|
336
382
|
`ALTER TABLE score_events ALTER COLUMN traceId DROP NOT NULL`,
|
|
337
|
-
// Feedback
|
|
383
|
+
// Feedback. Legacy rows remain page-visible but are not part of delta polling.
|
|
384
|
+
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
|
|
385
|
+
`ALTER TABLE feedback_events ALTER COLUMN cursorId SET DEFAULT nextval('feedback_events_cursor_id_seq')`,
|
|
338
386
|
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
|
|
339
387
|
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS parentEntityVersionId VARCHAR`,
|
|
340
388
|
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS rootEntityVersionId VARCHAR`,
|
|
@@ -598,6 +646,45 @@ function parseJsonArray(value) {
|
|
|
598
646
|
const parsed = parseJson(value);
|
|
599
647
|
return Array.isArray(parsed) ? parsed : null;
|
|
600
648
|
}
|
|
649
|
+
var OBSERVABILITY_DELTA_POLLING_FEATURE = "observability-delta-polling";
|
|
650
|
+
function deltaPollingFeatureEnabled() {
|
|
651
|
+
return coreFeatures.has(OBSERVABILITY_DELTA_POLLING_FEATURE);
|
|
652
|
+
}
|
|
653
|
+
function assertDeltaPollingEnabled() {
|
|
654
|
+
if (deltaPollingFeatureEnabled()) {
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
throw new MastraError({
|
|
658
|
+
id: "OBSERVABILITY_DELTA_POLLING_NOT_SUPPORTED",
|
|
659
|
+
domain: ErrorDomain.MASTRA_OBSERVABILITY,
|
|
660
|
+
category: ErrorCategory.SYSTEM,
|
|
661
|
+
text: "This storage provider does not support observability delta polling"
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
function encodeDeltaCursor(value) {
|
|
665
|
+
return String(value ?? 0);
|
|
666
|
+
}
|
|
667
|
+
function validateCursorId(cursor) {
|
|
668
|
+
if (!/^\d+$/.test(cursor)) {
|
|
669
|
+
throw new MastraError({
|
|
670
|
+
id: "OBSERVABILITY_INVALID_DELTA_CURSOR",
|
|
671
|
+
domain: ErrorDomain.MASTRA_OBSERVABILITY,
|
|
672
|
+
category: ErrorCategory.USER,
|
|
673
|
+
text: "Invalid observability delta cursor"
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
return cursor;
|
|
677
|
+
}
|
|
678
|
+
function extendWhereClause(baseClause, extraConditions) {
|
|
679
|
+
const conditions = extraConditions.filter(Boolean);
|
|
680
|
+
if (conditions.length === 0) {
|
|
681
|
+
return baseClause;
|
|
682
|
+
}
|
|
683
|
+
if (!baseClause) {
|
|
684
|
+
return `WHERE ${conditions.join(" AND ")}`;
|
|
685
|
+
}
|
|
686
|
+
return `${baseClause} AND ${conditions.join(" AND ")}`;
|
|
687
|
+
}
|
|
601
688
|
|
|
602
689
|
// src/storage/domains/observability/feedback.ts
|
|
603
690
|
var FEEDBACK_GROUP_BY_COLUMNS = /* @__PURE__ */ new Set([
|
|
@@ -897,15 +984,41 @@ async function batchCreateFeedback(db, args) {
|
|
|
897
984
|
);
|
|
898
985
|
}
|
|
899
986
|
async function listFeedback(db, args) {
|
|
900
|
-
const
|
|
901
|
-
const page = Number(
|
|
902
|
-
const perPage = Number(
|
|
903
|
-
const orderBy = { field: args.orderBy?.field ?? "timestamp", direction: args.orderBy?.direction ?? "DESC" };
|
|
987
|
+
const { mode, filters, pagination, orderBy, after, limit } = listFeedbackArgsSchema.parse(args);
|
|
988
|
+
const page = Number(pagination.page);
|
|
989
|
+
const perPage = Number(pagination.perPage);
|
|
904
990
|
const { clause: filterClause, params: filterParams } = buildWhereClause(filters, {
|
|
905
991
|
source: "feedbackSource"
|
|
906
992
|
});
|
|
993
|
+
if (mode === "delta") {
|
|
994
|
+
assertDeltaPollingEnabled();
|
|
995
|
+
const streamHeadCursor = await getStreamHeadCursor(db);
|
|
996
|
+
if (after === void 0) {
|
|
997
|
+
return {
|
|
998
|
+
feedback: [],
|
|
999
|
+
delta: { limit, hasMore: false },
|
|
1000
|
+
deltaCursor: streamHeadCursor
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
const afterCursorId = validateCursorId(after);
|
|
1004
|
+
const deltaWhereClause = extendWhereClause(filterClause, ["cursorId IS NOT NULL", `cursorId > CAST(? AS BIGINT)`]);
|
|
1005
|
+
const rows2 = await db.query(
|
|
1006
|
+
`SELECT * FROM feedback_events ${deltaWhereClause} ORDER BY cursorId ASC LIMIT ?`,
|
|
1007
|
+
[...filterParams, afterCursorId, limit + 1]
|
|
1008
|
+
);
|
|
1009
|
+
const visibleRows = rows2.slice(0, limit).map((row) => ({
|
|
1010
|
+
cursorId: row.cursorId,
|
|
1011
|
+
feedback: rowToFeedbackRecord(row)
|
|
1012
|
+
}));
|
|
1013
|
+
return {
|
|
1014
|
+
feedback: visibleRows.map((row) => row.feedback),
|
|
1015
|
+
delta: { limit, hasMore: rows2.length > limit },
|
|
1016
|
+
deltaCursor: visibleRows.length > 0 ? encodeDeltaCursor(visibleRows[visibleRows.length - 1]?.cursorId) : streamHeadCursor
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
907
1019
|
const orderByClause = buildOrderByClause(orderBy);
|
|
908
1020
|
const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
|
|
1021
|
+
const currentDeltaCursor = deltaPollingFeatureEnabled() ? await getDeltaCursor(db, filterClause, filterParams) : void 0;
|
|
909
1022
|
const countResult = await db.query(
|
|
910
1023
|
`SELECT COUNT(*) as total FROM feedback_events ${filterClause}`,
|
|
911
1024
|
filterParams
|
|
@@ -917,9 +1030,26 @@ async function listFeedback(db, args) {
|
|
|
917
1030
|
);
|
|
918
1031
|
return {
|
|
919
1032
|
pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
|
|
920
|
-
feedback: rows.map((row) => rowToFeedbackRecord(row))
|
|
1033
|
+
feedback: rows.map((row) => rowToFeedbackRecord(row)),
|
|
1034
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
921
1035
|
};
|
|
922
1036
|
}
|
|
1037
|
+
async function getDeltaCursor(db, filterClause, filterParams) {
|
|
1038
|
+
const rows = await db.query(
|
|
1039
|
+
`SELECT max(cursorId) AS cursorId FROM feedback_events ${filterClause}`,
|
|
1040
|
+
filterParams
|
|
1041
|
+
);
|
|
1042
|
+
const cursorId = rows[0]?.cursorId;
|
|
1043
|
+
if (cursorId !== null && cursorId !== void 0) {
|
|
1044
|
+
return encodeDeltaCursor(cursorId);
|
|
1045
|
+
}
|
|
1046
|
+
const streamRows = await db.query(`SELECT max(cursorId) AS cursorId FROM feedback_events`);
|
|
1047
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
1048
|
+
}
|
|
1049
|
+
async function getStreamHeadCursor(db) {
|
|
1050
|
+
const streamRows = await db.query(`SELECT max(cursorId) AS cursorId FROM feedback_events`);
|
|
1051
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
1052
|
+
}
|
|
923
1053
|
async function getFeedbackAggregate(db, args) {
|
|
924
1054
|
const aggSql = getAggregationSql(args.aggregation);
|
|
925
1055
|
const { clause, params } = buildFeedbackWhereClause(args, true);
|
|
@@ -1047,8 +1177,6 @@ async function getFeedbackPercentiles(db, args) {
|
|
|
1047
1177
|
}
|
|
1048
1178
|
return { series };
|
|
1049
1179
|
}
|
|
1050
|
-
|
|
1051
|
-
// src/storage/domains/observability/logs.ts
|
|
1052
1180
|
var COLUMNS = [
|
|
1053
1181
|
"logId",
|
|
1054
1182
|
"timestamp",
|
|
@@ -1164,13 +1292,40 @@ async function batchCreateLogs(db, args) {
|
|
|
1164
1292
|
await db.execute(`INSERT INTO log_events (${COLUMNS_SQL}) VALUES ${tuples.join(",\n")} ON CONFLICT DO NOTHING`);
|
|
1165
1293
|
}
|
|
1166
1294
|
async function listLogs(db, args) {
|
|
1167
|
-
const
|
|
1168
|
-
const
|
|
1169
|
-
const
|
|
1170
|
-
const
|
|
1171
|
-
const { clause: filterClause, params: filterParams } = buildWhereClause(
|
|
1295
|
+
const { mode, filters, pagination, orderBy, after, limit } = listLogsArgsSchema.parse(args);
|
|
1296
|
+
const filterRecord = filters;
|
|
1297
|
+
const page = Number(pagination.page);
|
|
1298
|
+
const perPage = Number(pagination.perPage);
|
|
1299
|
+
const { clause: filterClause, params: filterParams } = buildWhereClause(filterRecord);
|
|
1300
|
+
if (mode === "delta") {
|
|
1301
|
+
assertDeltaPollingEnabled();
|
|
1302
|
+
const streamHeadCursor = await getStreamHeadCursor2(db);
|
|
1303
|
+
if (after === void 0) {
|
|
1304
|
+
return {
|
|
1305
|
+
logs: [],
|
|
1306
|
+
delta: { limit, hasMore: false },
|
|
1307
|
+
deltaCursor: streamHeadCursor
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
const afterCursorId = validateCursorId(after);
|
|
1311
|
+
const deltaWhereClause = extendWhereClause(filterClause, ["cursorId IS NOT NULL", `cursorId > CAST(? AS BIGINT)`]);
|
|
1312
|
+
const rows2 = await db.query(
|
|
1313
|
+
`SELECT * FROM log_events ${deltaWhereClause} ORDER BY cursorId ASC LIMIT ?`,
|
|
1314
|
+
[...filterParams, afterCursorId, limit + 1]
|
|
1315
|
+
);
|
|
1316
|
+
const visibleRows = rows2.slice(0, limit).map((row) => ({
|
|
1317
|
+
cursorId: row.cursorId,
|
|
1318
|
+
log: rowToLogRecord(row)
|
|
1319
|
+
}));
|
|
1320
|
+
return {
|
|
1321
|
+
logs: visibleRows.map((row) => row.log),
|
|
1322
|
+
delta: { limit, hasMore: rows2.length > limit },
|
|
1323
|
+
deltaCursor: visibleRows.length > 0 ? encodeDeltaCursor(visibleRows[visibleRows.length - 1]?.cursorId) : streamHeadCursor
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1172
1326
|
const orderByClause = buildOrderByClause(orderBy);
|
|
1173
1327
|
const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
|
|
1328
|
+
const currentDeltaCursor = deltaPollingFeatureEnabled() ? await getDeltaCursor2(db, filterClause, filterParams) : void 0;
|
|
1174
1329
|
const countResult = await db.query(
|
|
1175
1330
|
`SELECT COUNT(*) as total FROM log_events ${filterClause}`,
|
|
1176
1331
|
filterParams
|
|
@@ -1183,9 +1338,26 @@ async function listLogs(db, args) {
|
|
|
1183
1338
|
const logs = rows.map((row) => rowToLogRecord(row));
|
|
1184
1339
|
return {
|
|
1185
1340
|
pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
|
|
1186
|
-
logs
|
|
1341
|
+
logs,
|
|
1342
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
1187
1343
|
};
|
|
1188
1344
|
}
|
|
1345
|
+
async function getDeltaCursor2(db, filterClause, filterParams) {
|
|
1346
|
+
const rows = await db.query(
|
|
1347
|
+
`SELECT max(cursorId) AS cursorId FROM log_events ${filterClause}`,
|
|
1348
|
+
filterParams
|
|
1349
|
+
);
|
|
1350
|
+
const cursorId = rows[0]?.cursorId;
|
|
1351
|
+
if (cursorId !== null && cursorId !== void 0) {
|
|
1352
|
+
return encodeDeltaCursor(cursorId);
|
|
1353
|
+
}
|
|
1354
|
+
const streamRows = await db.query(`SELECT max(cursorId) AS cursorId FROM log_events`);
|
|
1355
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
1356
|
+
}
|
|
1357
|
+
async function getStreamHeadCursor2(db) {
|
|
1358
|
+
const streamRows = await db.query(`SELECT max(cursorId) AS cursorId FROM log_events`);
|
|
1359
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
1360
|
+
}
|
|
1189
1361
|
function resolveDistinctColumnSql(distinctColumn) {
|
|
1190
1362
|
if (!distinctColumn) {
|
|
1191
1363
|
throw new Error(`count_distinct aggregation requires a 'distinctColumn' argument`);
|
|
@@ -1433,13 +1605,40 @@ async function batchCreateMetrics(db, args) {
|
|
|
1433
1605
|
);
|
|
1434
1606
|
}
|
|
1435
1607
|
async function listMetrics(db, args) {
|
|
1436
|
-
const
|
|
1437
|
-
const
|
|
1438
|
-
const
|
|
1439
|
-
const
|
|
1440
|
-
const { clause: filterClause, params: filterParams } = buildWhereClause(
|
|
1608
|
+
const { mode, filters, pagination, orderBy, after, limit } = listMetricsArgsSchema.parse(args);
|
|
1609
|
+
const filterRecord = filters;
|
|
1610
|
+
const page = Number(pagination.page);
|
|
1611
|
+
const perPage = Number(pagination.perPage);
|
|
1612
|
+
const { clause: filterClause, params: filterParams } = buildWhereClause(filterRecord);
|
|
1613
|
+
if (mode === "delta") {
|
|
1614
|
+
assertDeltaPollingEnabled();
|
|
1615
|
+
const streamHeadCursor = await getStreamHeadCursor3(db);
|
|
1616
|
+
if (after === void 0) {
|
|
1617
|
+
return {
|
|
1618
|
+
metrics: [],
|
|
1619
|
+
delta: { limit, hasMore: false },
|
|
1620
|
+
deltaCursor: streamHeadCursor
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
const afterCursorId = validateCursorId(after);
|
|
1624
|
+
const deltaWhereClause = extendWhereClause(filterClause, ["cursorId IS NOT NULL", `cursorId > CAST(? AS BIGINT)`]);
|
|
1625
|
+
const rows2 = await db.query(
|
|
1626
|
+
`SELECT * FROM metric_events ${deltaWhereClause} ORDER BY cursorId ASC LIMIT ?`,
|
|
1627
|
+
[...filterParams, afterCursorId, limit + 1]
|
|
1628
|
+
);
|
|
1629
|
+
const visibleRows = rows2.slice(0, limit).map((row) => ({
|
|
1630
|
+
cursorId: row.cursorId,
|
|
1631
|
+
metric: rowToMetricRecord(row)
|
|
1632
|
+
}));
|
|
1633
|
+
return {
|
|
1634
|
+
metrics: visibleRows.map((row) => row.metric),
|
|
1635
|
+
delta: { limit, hasMore: rows2.length > limit },
|
|
1636
|
+
deltaCursor: visibleRows.length > 0 ? encodeDeltaCursor(visibleRows[visibleRows.length - 1]?.cursorId) : streamHeadCursor
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1441
1639
|
const orderByClause = buildOrderByClause(orderBy);
|
|
1442
1640
|
const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
|
|
1641
|
+
const currentDeltaCursor = deltaPollingFeatureEnabled() ? await getDeltaCursor3(db, filterClause, filterParams) : void 0;
|
|
1443
1642
|
const countResult = await db.query(
|
|
1444
1643
|
`SELECT COUNT(*) AS total FROM metric_events ${filterClause}`,
|
|
1445
1644
|
filterParams
|
|
@@ -1451,9 +1650,26 @@ async function listMetrics(db, args) {
|
|
|
1451
1650
|
);
|
|
1452
1651
|
return {
|
|
1453
1652
|
pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
|
|
1454
|
-
metrics: rows.map((row) => rowToMetricRecord(row))
|
|
1653
|
+
metrics: rows.map((row) => rowToMetricRecord(row)),
|
|
1654
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
1455
1655
|
};
|
|
1456
1656
|
}
|
|
1657
|
+
async function getDeltaCursor3(db, filterClause, filterParams) {
|
|
1658
|
+
const rows = await db.query(
|
|
1659
|
+
`SELECT max(cursorId) AS cursorId FROM metric_events ${filterClause}`,
|
|
1660
|
+
filterParams
|
|
1661
|
+
);
|
|
1662
|
+
const cursorId = rows[0]?.cursorId;
|
|
1663
|
+
if (cursorId !== null && cursorId !== void 0) {
|
|
1664
|
+
return encodeDeltaCursor(cursorId);
|
|
1665
|
+
}
|
|
1666
|
+
const streamRows = await db.query(`SELECT max(cursorId) AS cursorId FROM metric_events`);
|
|
1667
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
1668
|
+
}
|
|
1669
|
+
async function getStreamHeadCursor3(db) {
|
|
1670
|
+
const streamRows = await db.query(`SELECT max(cursorId) AS cursorId FROM metric_events`);
|
|
1671
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
1672
|
+
}
|
|
1457
1673
|
async function getMetricAggregate(db, args) {
|
|
1458
1674
|
const aggSql = getAggregationSql2(args.aggregation, "value", args.distinctColumn);
|
|
1459
1675
|
const { clause: nameClause, params: nameParams } = buildMetricNameFilter(args.name);
|
|
@@ -1733,10 +1949,30 @@ async function getMetricLabelValues(db, args) {
|
|
|
1733
1949
|
return { values: rows.map((r) => r.val) };
|
|
1734
1950
|
}
|
|
1735
1951
|
var SIGNAL_MIGRATIONS = [
|
|
1736
|
-
{
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1952
|
+
{
|
|
1953
|
+
table: "metric_events",
|
|
1954
|
+
createDDL: METRIC_EVENTS_DDL,
|
|
1955
|
+
idColumn: "metricId",
|
|
1956
|
+
cursorSequenceDDL: METRIC_EVENTS_CURSOR_SEQUENCE_DDL
|
|
1957
|
+
},
|
|
1958
|
+
{
|
|
1959
|
+
table: "log_events",
|
|
1960
|
+
createDDL: LOG_EVENTS_DDL,
|
|
1961
|
+
idColumn: "logId",
|
|
1962
|
+
cursorSequenceDDL: LOG_EVENTS_CURSOR_SEQUENCE_DDL
|
|
1963
|
+
},
|
|
1964
|
+
{
|
|
1965
|
+
table: "score_events",
|
|
1966
|
+
createDDL: SCORE_EVENTS_DDL,
|
|
1967
|
+
idColumn: "scoreId",
|
|
1968
|
+
cursorSequenceDDL: SCORE_EVENTS_CURSOR_SEQUENCE_DDL
|
|
1969
|
+
},
|
|
1970
|
+
{
|
|
1971
|
+
table: "feedback_events",
|
|
1972
|
+
createDDL: FEEDBACK_EVENTS_DDL,
|
|
1973
|
+
idColumn: "feedbackId",
|
|
1974
|
+
cursorSequenceDDL: FEEDBACK_EVENTS_CURSOR_SEQUENCE_DDL
|
|
1975
|
+
}
|
|
1740
1976
|
];
|
|
1741
1977
|
async function tableExists(db, table) {
|
|
1742
1978
|
const rows = await db.query(
|
|
@@ -1796,7 +2032,7 @@ async function checkSignalTablesMigrationStatus(db) {
|
|
|
1796
2032
|
};
|
|
1797
2033
|
}
|
|
1798
2034
|
async function migrateSignalTables(db, logger) {
|
|
1799
|
-
for (const { table, createDDL, idColumn } of SIGNAL_MIGRATIONS) {
|
|
2035
|
+
for (const { table, createDDL, idColumn, cursorSequenceDDL } of SIGNAL_MIGRATIONS) {
|
|
1800
2036
|
if (!await tableExists(db, table)) continue;
|
|
1801
2037
|
if (await hasPrimaryKey(db, table)) continue;
|
|
1802
2038
|
logger?.info?.(`Migrating ${table} to schema with ${idColumn} PRIMARY KEY`);
|
|
@@ -1805,6 +2041,7 @@ async function migrateSignalTables(db, logger) {
|
|
|
1805
2041
|
let originalRenamed = false;
|
|
1806
2042
|
let swapCompleted = false;
|
|
1807
2043
|
try {
|
|
2044
|
+
await db.execute(cursorSequenceDDL);
|
|
1808
2045
|
await db.execute(buildTemporaryTableDDL(createDDL, table, temp));
|
|
1809
2046
|
const newColumns = await getColumns(db, temp);
|
|
1810
2047
|
const currentColumns = new Set(await getColumns(db, table));
|
|
@@ -2136,15 +2373,41 @@ async function batchCreateScores(db, args) {
|
|
|
2136
2373
|
);
|
|
2137
2374
|
}
|
|
2138
2375
|
async function listScores(db, args) {
|
|
2139
|
-
const
|
|
2140
|
-
const page = Number(
|
|
2141
|
-
const perPage = Number(
|
|
2142
|
-
const orderBy = { field: args.orderBy?.field ?? "timestamp", direction: args.orderBy?.direction ?? "DESC" };
|
|
2376
|
+
const { mode, filters, pagination, orderBy, after, limit } = listScoresArgsSchema.parse(args);
|
|
2377
|
+
const page = Number(pagination.page);
|
|
2378
|
+
const perPage = Number(pagination.perPage);
|
|
2143
2379
|
const { clause: filterClause, params: filterParams } = buildWhereClause(filters, {
|
|
2144
2380
|
source: "scoreSource"
|
|
2145
2381
|
});
|
|
2382
|
+
if (mode === "delta") {
|
|
2383
|
+
assertDeltaPollingEnabled();
|
|
2384
|
+
const streamHeadCursor = await getStreamHeadCursor4(db);
|
|
2385
|
+
if (after === void 0) {
|
|
2386
|
+
return {
|
|
2387
|
+
scores: [],
|
|
2388
|
+
delta: { limit, hasMore: false },
|
|
2389
|
+
deltaCursor: streamHeadCursor
|
|
2390
|
+
};
|
|
2391
|
+
}
|
|
2392
|
+
const afterCursorId = validateCursorId(after);
|
|
2393
|
+
const deltaWhereClause = extendWhereClause(filterClause, ["cursorId IS NOT NULL", `cursorId > CAST(? AS BIGINT)`]);
|
|
2394
|
+
const rows2 = await db.query(
|
|
2395
|
+
`SELECT * FROM score_events ${deltaWhereClause} ORDER BY cursorId ASC LIMIT ?`,
|
|
2396
|
+
[...filterParams, afterCursorId, limit + 1]
|
|
2397
|
+
);
|
|
2398
|
+
const visibleRows = rows2.slice(0, limit).map((row) => ({
|
|
2399
|
+
cursorId: row.cursorId,
|
|
2400
|
+
score: rowToScoreRecord(row)
|
|
2401
|
+
}));
|
|
2402
|
+
return {
|
|
2403
|
+
scores: visibleRows.map((row) => row.score),
|
|
2404
|
+
delta: { limit, hasMore: rows2.length > limit },
|
|
2405
|
+
deltaCursor: visibleRows.length > 0 ? encodeDeltaCursor(visibleRows[visibleRows.length - 1]?.cursorId) : streamHeadCursor
|
|
2406
|
+
};
|
|
2407
|
+
}
|
|
2146
2408
|
const orderByClause = buildOrderByClause(orderBy);
|
|
2147
2409
|
const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
|
|
2410
|
+
const currentDeltaCursor = deltaPollingFeatureEnabled() ? await getDeltaCursor4(db, filterClause, filterParams) : void 0;
|
|
2148
2411
|
const countResult = await db.query(
|
|
2149
2412
|
`SELECT COUNT(*) as total FROM score_events ${filterClause}`,
|
|
2150
2413
|
filterParams
|
|
@@ -2156,9 +2419,26 @@ async function listScores(db, args) {
|
|
|
2156
2419
|
);
|
|
2157
2420
|
return {
|
|
2158
2421
|
pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
|
|
2159
|
-
scores: rows.map((row) => rowToScoreRecord(row))
|
|
2422
|
+
scores: rows.map((row) => rowToScoreRecord(row)),
|
|
2423
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
2160
2424
|
};
|
|
2161
2425
|
}
|
|
2426
|
+
async function getDeltaCursor4(db, filterClause, filterParams) {
|
|
2427
|
+
const rows = await db.query(
|
|
2428
|
+
`SELECT max(cursorId) AS cursorId FROM score_events ${filterClause}`,
|
|
2429
|
+
filterParams
|
|
2430
|
+
);
|
|
2431
|
+
const cursorId = rows[0]?.cursorId;
|
|
2432
|
+
if (cursorId !== null && cursorId !== void 0) {
|
|
2433
|
+
return encodeDeltaCursor(cursorId);
|
|
2434
|
+
}
|
|
2435
|
+
const streamRows = await db.query(`SELECT max(cursorId) AS cursorId FROM score_events`);
|
|
2436
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
2437
|
+
}
|
|
2438
|
+
async function getStreamHeadCursor4(db) {
|
|
2439
|
+
const streamRows = await db.query(`SELECT max(cursorId) AS cursorId FROM score_events`);
|
|
2440
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
2441
|
+
}
|
|
2162
2442
|
async function getScoreById(db, scoreId) {
|
|
2163
2443
|
const rows = await db.query(`SELECT * FROM score_events WHERE scoreId = ? LIMIT 1`, [
|
|
2164
2444
|
scoreId
|
|
@@ -2777,13 +3057,152 @@ async function listTraceRows(db, args, reconstructSelect, mapRow, toSpans) {
|
|
|
2777
3057
|
};
|
|
2778
3058
|
}
|
|
2779
3059
|
async function listTraces(db, args) {
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
(
|
|
2786
|
-
|
|
3060
|
+
const { mode, filters, pagination, orderBy, after, limit } = listTracesArgsSchema.parse(args);
|
|
3061
|
+
const filterRecord = filters ?? {};
|
|
3062
|
+
const page = Number(pagination.page);
|
|
3063
|
+
const perPage = Number(pagination.perPage);
|
|
3064
|
+
if (mode === "delta") {
|
|
3065
|
+
assertDeltaPollingEnabled();
|
|
3066
|
+
const streamHeadCursor = await getTraceStreamHeadCursor(db);
|
|
3067
|
+
if (after === void 0) {
|
|
3068
|
+
return {
|
|
3069
|
+
spans: [],
|
|
3070
|
+
delta: { limit, hasMore: false },
|
|
3071
|
+
deltaCursor: streamHeadCursor
|
|
3072
|
+
};
|
|
3073
|
+
}
|
|
3074
|
+
const afterCursorId = validateCursorId(after);
|
|
3075
|
+
const { prefilter: prefilter2, postAgg: postAgg2, hasChildError: hasChildError2 } = partitionAnchorFilters(filterRecord);
|
|
3076
|
+
const { clause: prefilterClause2, params: prefilterParams2 } = buildWhereClause(prefilter2);
|
|
3077
|
+
const prefilterParts2 = [
|
|
3078
|
+
`eventType = 'start'`,
|
|
3079
|
+
`parentSpanId IS NULL`,
|
|
3080
|
+
`cursorId IS NOT NULL`,
|
|
3081
|
+
`cursorId > CAST(? AS BIGINT)`
|
|
3082
|
+
];
|
|
3083
|
+
if (prefilterClause2) prefilterParts2.push(prefilterClause2.replace(/^WHERE\s+/i, ""));
|
|
3084
|
+
const prefilterWhere2 = `WHERE ${prefilterParts2.join(" AND ")}`;
|
|
3085
|
+
const { clause: postAggClause2, params: postAggParams2 } = buildWhereClause(postAgg2);
|
|
3086
|
+
const postAggParts2 = [];
|
|
3087
|
+
if (postAggClause2) postAggParts2.push(postAggClause2.replace(/^WHERE\s+/i, ""));
|
|
3088
|
+
const childErrorClause2 = buildHasChildErrorClause(hasChildError2, "root_spans");
|
|
3089
|
+
if (childErrorClause2) postAggParts2.push(childErrorClause2);
|
|
3090
|
+
const postAggWhere2 = postAggParts2.length > 0 ? `WHERE ${postAggParts2.join(" AND ")}` : "";
|
|
3091
|
+
const outerAlias2 = "outer_root";
|
|
3092
|
+
const dataSql2 = `
|
|
3093
|
+
WITH candidate_roots AS (
|
|
3094
|
+
SELECT traceId, spanId, cursorId
|
|
3095
|
+
FROM span_events AS ${outerAlias2}
|
|
3096
|
+
${prefilterWhere2}
|
|
3097
|
+
),
|
|
3098
|
+
root_spans AS (
|
|
3099
|
+
SELECT reconstructed.*, candidate_roots.cursorId AS anchorCursorId
|
|
3100
|
+
FROM (
|
|
3101
|
+
${SPAN_RECONSTRUCT_SELECT}
|
|
3102
|
+
WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_roots)
|
|
3103
|
+
GROUP BY traceId, spanId
|
|
3104
|
+
) AS reconstructed
|
|
3105
|
+
INNER JOIN candidate_roots USING (traceId, spanId)
|
|
3106
|
+
)
|
|
3107
|
+
SELECT * FROM root_spans ${postAggWhere2} ORDER BY anchorCursorId ASC LIMIT ?
|
|
3108
|
+
`;
|
|
3109
|
+
const rows2 = await db.query(dataSql2, [
|
|
3110
|
+
afterCursorId,
|
|
3111
|
+
...prefilterParams2,
|
|
3112
|
+
...postAggParams2,
|
|
3113
|
+
limit + 1
|
|
3114
|
+
]);
|
|
3115
|
+
const visibleRows = rows2.slice(0, limit).map((row) => ({
|
|
3116
|
+
cursorId: row.anchorCursorId,
|
|
3117
|
+
span: rowToSpanRecord(row)
|
|
3118
|
+
}));
|
|
3119
|
+
return {
|
|
3120
|
+
spans: toTraceSpans(visibleRows.map((row) => row.span)),
|
|
3121
|
+
delta: { limit, hasMore: rows2.length > limit },
|
|
3122
|
+
deltaCursor: visibleRows.length > 0 ? encodeDeltaCursor(visibleRows[visibleRows.length - 1]?.cursorId) : streamHeadCursor
|
|
3123
|
+
};
|
|
3124
|
+
}
|
|
3125
|
+
const { prefilter, postAgg, hasChildError } = partitionAnchorFilters(filterRecord);
|
|
3126
|
+
const { clause: prefilterClause, params: prefilterParams } = buildWhereClause(prefilter);
|
|
3127
|
+
const prefilterParts = [`eventType = 'start'`, `parentSpanId IS NULL`];
|
|
3128
|
+
if (prefilterClause) prefilterParts.push(prefilterClause.replace(/^WHERE\s+/i, ""));
|
|
3129
|
+
const prefilterWhere = `WHERE ${prefilterParts.join(" AND ")}`;
|
|
3130
|
+
const outerAlias = "outer_root";
|
|
3131
|
+
const orderDir = orderBy.direction.toUpperCase();
|
|
3132
|
+
if (orderDir !== "ASC" && orderDir !== "DESC") {
|
|
3133
|
+
throw new Error(`Invalid sort direction: ${orderBy.direction}`);
|
|
3134
|
+
}
|
|
3135
|
+
const currentDeltaCursor = deltaPollingFeatureEnabled() ? await getTraceDeltaCursor(db, filters) : void 0;
|
|
3136
|
+
const canOrderInPrefilter = SAFE_PREFILTER_ORDER_FIELDS.has(orderBy.field);
|
|
3137
|
+
const hasPostAggFilters = Object.keys(postAgg).length > 0 || hasChildError !== void 0 || !canOrderInPrefilter;
|
|
3138
|
+
if (!hasPostAggFilters) {
|
|
3139
|
+
const prefilterOrderBy = `ORDER BY timestamp ${orderDir}`;
|
|
3140
|
+
const offset = page * perPage;
|
|
3141
|
+
const countSql2 = `
|
|
3142
|
+
SELECT COUNT(*) as total
|
|
3143
|
+
FROM span_events AS ${outerAlias}
|
|
3144
|
+
${prefilterWhere}
|
|
3145
|
+
`;
|
|
3146
|
+
const countResult2 = await db.query(countSql2, prefilterParams);
|
|
3147
|
+
const total2 = Number(countResult2[0]?.total ?? 0);
|
|
3148
|
+
const pageSql = `
|
|
3149
|
+
WITH page_roots AS (
|
|
3150
|
+
SELECT traceId, spanId
|
|
3151
|
+
FROM span_events AS ${outerAlias}
|
|
3152
|
+
${prefilterWhere}
|
|
3153
|
+
${prefilterOrderBy}
|
|
3154
|
+
LIMIT ? OFFSET ?
|
|
3155
|
+
)
|
|
3156
|
+
${SPAN_RECONSTRUCT_SELECT}
|
|
3157
|
+
WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM page_roots)
|
|
3158
|
+
GROUP BY traceId, spanId
|
|
3159
|
+
${buildOrderByClause(orderBy)}
|
|
3160
|
+
`;
|
|
3161
|
+
const rows2 = await db.query(pageSql, [...prefilterParams, perPage, offset]);
|
|
3162
|
+
const spans2 = rows2.map((row) => rowToSpanRecord(row));
|
|
3163
|
+
return {
|
|
3164
|
+
pagination: { total: total2, page, perPage, hasMore: (page + 1) * perPage < total2 },
|
|
3165
|
+
spans: toTraceSpans(spans2),
|
|
3166
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
3167
|
+
};
|
|
3168
|
+
}
|
|
3169
|
+
const { clause: postAggClause, params: postAggParams } = buildWhereClause(postAgg);
|
|
3170
|
+
const postAggParts = [];
|
|
3171
|
+
if (postAggClause) postAggParts.push(postAggClause.replace(/^WHERE\s+/i, ""));
|
|
3172
|
+
const childErrorClause = buildHasChildErrorClause(hasChildError, "root_spans");
|
|
3173
|
+
if (childErrorClause) postAggParts.push(childErrorClause);
|
|
3174
|
+
const postAggWhere = postAggParts.length > 0 ? `WHERE ${postAggParts.join(" AND ")}` : "";
|
|
3175
|
+
const cteSql = `
|
|
3176
|
+
WITH candidate_roots AS (
|
|
3177
|
+
SELECT traceId, spanId
|
|
3178
|
+
FROM span_events AS ${outerAlias}
|
|
3179
|
+
${prefilterWhere}
|
|
3180
|
+
),
|
|
3181
|
+
root_spans AS (
|
|
3182
|
+
${SPAN_RECONSTRUCT_SELECT}
|
|
3183
|
+
WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_roots)
|
|
3184
|
+
GROUP BY traceId, spanId
|
|
3185
|
+
)
|
|
3186
|
+
`;
|
|
3187
|
+
const orderByClause = buildOrderByClause(orderBy);
|
|
3188
|
+
const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
|
|
3189
|
+
const countSql = `
|
|
3190
|
+
${cteSql}
|
|
3191
|
+
SELECT COUNT(*) as total FROM root_spans ${postAggWhere}
|
|
3192
|
+
`;
|
|
3193
|
+
const countResult = await db.query(countSql, [...prefilterParams, ...postAggParams]);
|
|
3194
|
+
const total = Number(countResult[0]?.total ?? 0);
|
|
3195
|
+
const dataSql = `
|
|
3196
|
+
${cteSql}
|
|
3197
|
+
SELECT * FROM root_spans ${postAggWhere} ${orderByClause} ${paginationClause}
|
|
3198
|
+
`;
|
|
3199
|
+
const rows = await db.query(dataSql, [...prefilterParams, ...postAggParams, ...paginationParams]);
|
|
3200
|
+
const spans = rows.map((row) => rowToSpanRecord(row));
|
|
3201
|
+
return {
|
|
3202
|
+
pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
|
|
3203
|
+
spans: toTraceSpans(spans),
|
|
3204
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
3205
|
+
};
|
|
2787
3206
|
}
|
|
2788
3207
|
async function listTracesLight(db, args) {
|
|
2789
3208
|
return listTraceRows(
|
|
@@ -2812,18 +3231,88 @@ async function getSpans(db, args) {
|
|
|
2812
3231
|
};
|
|
2813
3232
|
}
|
|
2814
3233
|
async function listBranches(db, args) {
|
|
2815
|
-
const
|
|
2816
|
-
const
|
|
2817
|
-
const
|
|
2818
|
-
const
|
|
2819
|
-
const userSpanType =
|
|
3234
|
+
const { mode, filters, pagination, orderBy, after, limit } = listBranchesArgsSchema.parse(args);
|
|
3235
|
+
const filterRecord = filters ?? {};
|
|
3236
|
+
const page = Number(pagination.page);
|
|
3237
|
+
const perPage = Number(pagination.perPage);
|
|
3238
|
+
const userSpanType = filterRecord.spanType;
|
|
2820
3239
|
if (typeof userSpanType === "string" && !BRANCH_SPAN_TYPES.includes(userSpanType)) {
|
|
3240
|
+
const currentDeltaCursor2 = deltaPollingFeatureEnabled() ? await getBranchDeltaCursor(db, filters) : void 0;
|
|
3241
|
+
if (mode === "delta") {
|
|
3242
|
+
assertDeltaPollingEnabled();
|
|
3243
|
+
return {
|
|
3244
|
+
branches: [],
|
|
3245
|
+
delta: { limit, hasMore: false },
|
|
3246
|
+
deltaCursor: currentDeltaCursor2
|
|
3247
|
+
};
|
|
3248
|
+
}
|
|
2821
3249
|
return {
|
|
2822
3250
|
pagination: { total: 0, page, perPage, hasMore: false },
|
|
2823
|
-
branches: []
|
|
3251
|
+
branches: [],
|
|
3252
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor2 } : {}
|
|
3253
|
+
};
|
|
3254
|
+
}
|
|
3255
|
+
if (mode === "delta") {
|
|
3256
|
+
assertDeltaPollingEnabled();
|
|
3257
|
+
const streamHeadCursor = await getBranchStreamHeadCursor(
|
|
3258
|
+
db,
|
|
3259
|
+
typeof userSpanType === "string" ? userSpanType : null
|
|
3260
|
+
);
|
|
3261
|
+
if (after === void 0) {
|
|
3262
|
+
return {
|
|
3263
|
+
branches: [],
|
|
3264
|
+
delta: { limit, hasMore: false },
|
|
3265
|
+
deltaCursor: streamHeadCursor
|
|
3266
|
+
};
|
|
3267
|
+
}
|
|
3268
|
+
const afterCursorId = validateCursorId(after);
|
|
3269
|
+
const { spanType: _spanType2, ...rest2 } = filterRecord;
|
|
3270
|
+
const { prefilter: prefilter2, postAgg: postAgg2} = partitionAnchorFilters(rest2);
|
|
3271
|
+
const { clause: prefilterClause2, params: prefilterFilterParams2 } = buildWhereClause(prefilter2);
|
|
3272
|
+
const prefilterParts2 = [`eventType = 'start'`, `cursorId IS NOT NULL`, `cursorId > CAST(? AS BIGINT)`];
|
|
3273
|
+
let spanTypeParams2;
|
|
3274
|
+
if (typeof userSpanType === "string") {
|
|
3275
|
+
prefilterParts2.push(`spanType = ?`);
|
|
3276
|
+
spanTypeParams2 = [userSpanType];
|
|
3277
|
+
} else {
|
|
3278
|
+
prefilterParts2.push(`spanType IN (${BRANCH_SPAN_TYPE_PLACEHOLDERS})`);
|
|
3279
|
+
spanTypeParams2 = [...BRANCH_SPAN_TYPES];
|
|
3280
|
+
}
|
|
3281
|
+
if (prefilterClause2) prefilterParts2.push(prefilterClause2.replace(/^WHERE\s+/i, ""));
|
|
3282
|
+
const prefilterWhere2 = `WHERE ${prefilterParts2.join(" AND ")}`;
|
|
3283
|
+
const prefilterParams2 = [afterCursorId, ...spanTypeParams2, ...prefilterFilterParams2];
|
|
3284
|
+
const { clause: postAggClause2, params: postAggParams2 } = buildWhereClause(postAgg2);
|
|
3285
|
+
const postAggWhere2 = postAggClause2 ? postAggClause2 : "";
|
|
3286
|
+
const outerAlias2 = "outer_anchor";
|
|
3287
|
+
const dataSql2 = `
|
|
3288
|
+
WITH candidate_anchors AS (
|
|
3289
|
+
SELECT traceId, spanId, cursorId
|
|
3290
|
+
FROM span_events AS ${outerAlias2}
|
|
3291
|
+
${prefilterWhere2}
|
|
3292
|
+
),
|
|
3293
|
+
branch_anchors AS (
|
|
3294
|
+
SELECT reconstructed.*, candidate_anchors.cursorId AS anchorCursorId
|
|
3295
|
+
FROM (
|
|
3296
|
+
${SPAN_RECONSTRUCT_SELECT}
|
|
3297
|
+
WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_anchors)
|
|
3298
|
+
GROUP BY traceId, spanId
|
|
3299
|
+
) AS reconstructed
|
|
3300
|
+
INNER JOIN candidate_anchors USING (traceId, spanId)
|
|
3301
|
+
)
|
|
3302
|
+
SELECT * FROM branch_anchors ${postAggWhere2} ORDER BY anchorCursorId ASC LIMIT ?
|
|
3303
|
+
`;
|
|
3304
|
+
const rows2 = await db.query(dataSql2, [...prefilterParams2, ...postAggParams2, limit + 1]);
|
|
3305
|
+
const visibleRows = rows2.slice(0, limit).map((row) => ({
|
|
3306
|
+
cursorId: row.anchorCursorId,
|
|
3307
|
+
branch: rowToSpanRecord(row)
|
|
3308
|
+
}));
|
|
3309
|
+
return {
|
|
3310
|
+
branches: toTraceSpans(visibleRows.map((row) => row.branch)),
|
|
3311
|
+
delta: { limit, hasMore: rows2.length > limit },
|
|
3312
|
+
deltaCursor: visibleRows.length > 0 ? encodeDeltaCursor(visibleRows[visibleRows.length - 1]?.cursorId) : streamHeadCursor
|
|
2824
3313
|
};
|
|
2825
3314
|
}
|
|
2826
|
-
const { spanType: _spanType, ...rest } =
|
|
3315
|
+
const { spanType: _spanType, ...rest } = filterRecord;
|
|
2827
3316
|
const { prefilter, postAgg} = partitionAnchorFilters(rest);
|
|
2828
3317
|
const { clause: prefilterClause, params: prefilterFilterParams } = buildWhereClause(prefilter);
|
|
2829
3318
|
const prefilterParts = [`eventType = 'start'`];
|
|
@@ -2843,6 +3332,7 @@ async function listBranches(db, args) {
|
|
|
2843
3332
|
if (orderDir !== "ASC" && orderDir !== "DESC") {
|
|
2844
3333
|
throw new Error(`Invalid sort direction: ${orderBy.direction}`);
|
|
2845
3334
|
}
|
|
3335
|
+
const currentDeltaCursor = deltaPollingFeatureEnabled() ? await getBranchDeltaCursor(db, filters) : void 0;
|
|
2846
3336
|
const canOrderInPrefilter = SAFE_PREFILTER_ORDER_FIELDS.has(orderBy.field);
|
|
2847
3337
|
const hasPostAggFilters = Object.keys(postAgg).length > 0 || !canOrderInPrefilter;
|
|
2848
3338
|
if (!hasPostAggFilters) {
|
|
@@ -2858,7 +3348,8 @@ async function listBranches(db, args) {
|
|
|
2858
3348
|
if (total2 === 0) {
|
|
2859
3349
|
return {
|
|
2860
3350
|
pagination: { total: 0, page, perPage, hasMore: false },
|
|
2861
|
-
branches: []
|
|
3351
|
+
branches: [],
|
|
3352
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
2862
3353
|
};
|
|
2863
3354
|
}
|
|
2864
3355
|
const pageSql = `
|
|
@@ -2878,7 +3369,8 @@ async function listBranches(db, args) {
|
|
|
2878
3369
|
const spans2 = rows2.map((row) => rowToSpanRecord(row));
|
|
2879
3370
|
return {
|
|
2880
3371
|
pagination: { total: total2, page, perPage, hasMore: (page + 1) * perPage < total2 },
|
|
2881
|
-
branches: toTraceSpans(spans2)
|
|
3372
|
+
branches: toTraceSpans(spans2),
|
|
3373
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
2882
3374
|
};
|
|
2883
3375
|
}
|
|
2884
3376
|
const { clause: postAggClause, params: postAggParams } = buildWhereClause(postAgg);
|
|
@@ -2906,7 +3398,8 @@ async function listBranches(db, args) {
|
|
|
2906
3398
|
if (total === 0) {
|
|
2907
3399
|
return {
|
|
2908
3400
|
pagination: { total: 0, page, perPage, hasMore: false },
|
|
2909
|
-
branches: []
|
|
3401
|
+
branches: [],
|
|
3402
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
2910
3403
|
};
|
|
2911
3404
|
}
|
|
2912
3405
|
const dataSql = `
|
|
@@ -2917,9 +3410,151 @@ async function listBranches(db, args) {
|
|
|
2917
3410
|
const spans = rows.map((row) => rowToSpanRecord(row));
|
|
2918
3411
|
return {
|
|
2919
3412
|
pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
|
|
2920
|
-
branches: toTraceSpans(spans)
|
|
3413
|
+
branches: toTraceSpans(spans),
|
|
3414
|
+
...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
|
|
2921
3415
|
};
|
|
2922
3416
|
}
|
|
3417
|
+
async function getTraceDeltaCursor(db, filters) {
|
|
3418
|
+
const { prefilter, postAgg, hasChildError } = partitionAnchorFilters(filters ?? {});
|
|
3419
|
+
const { clause: prefilterClause, params: prefilterParams } = buildWhereClause(prefilter);
|
|
3420
|
+
const prefilterParts = [`eventType = 'start'`, `parentSpanId IS NULL`, `cursorId IS NOT NULL`];
|
|
3421
|
+
if (prefilterClause) prefilterParts.push(prefilterClause.replace(/^WHERE\s+/i, ""));
|
|
3422
|
+
const prefilterWhere = `WHERE ${prefilterParts.join(" AND ")}`;
|
|
3423
|
+
const outerAlias = "outer_root";
|
|
3424
|
+
const { clause: postAggClause, params: postAggParams } = buildWhereClause(postAgg);
|
|
3425
|
+
const postAggParts = [];
|
|
3426
|
+
if (postAggClause) postAggParts.push(postAggClause.replace(/^WHERE\s+/i, ""));
|
|
3427
|
+
const childErrorClause = buildHasChildErrorClause(hasChildError, "root_spans");
|
|
3428
|
+
if (childErrorClause) postAggParts.push(childErrorClause);
|
|
3429
|
+
const postAggWhere = postAggParts.length > 0 ? `WHERE ${postAggParts.join(" AND ")}` : "";
|
|
3430
|
+
if (postAggWhere === "") {
|
|
3431
|
+
const rows2 = await db.query(
|
|
3432
|
+
`SELECT max(cursorId) AS cursorId FROM span_events AS ${outerAlias} ${prefilterWhere}`,
|
|
3433
|
+
prefilterParams
|
|
3434
|
+
);
|
|
3435
|
+
const cursorId2 = rows2[0]?.cursorId;
|
|
3436
|
+
if (cursorId2 !== null && cursorId2 !== void 0) {
|
|
3437
|
+
return encodeDeltaCursor(cursorId2);
|
|
3438
|
+
}
|
|
3439
|
+
const streamRows2 = await db.query(
|
|
3440
|
+
`SELECT max(cursorId) AS cursorId FROM span_events WHERE eventType = 'start' AND parentSpanId IS NULL AND cursorId IS NOT NULL`
|
|
3441
|
+
);
|
|
3442
|
+
return encodeDeltaCursor(streamRows2[0]?.cursorId);
|
|
3443
|
+
}
|
|
3444
|
+
const cteSql = `
|
|
3445
|
+
WITH candidate_roots AS (
|
|
3446
|
+
SELECT traceId, spanId, cursorId
|
|
3447
|
+
FROM span_events AS ${outerAlias}
|
|
3448
|
+
${prefilterWhere}
|
|
3449
|
+
),
|
|
3450
|
+
root_spans AS (
|
|
3451
|
+
SELECT reconstructed.*, candidate_roots.cursorId AS anchorCursorId
|
|
3452
|
+
FROM (
|
|
3453
|
+
${SPAN_RECONSTRUCT_SELECT}
|
|
3454
|
+
WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_roots)
|
|
3455
|
+
GROUP BY traceId, spanId
|
|
3456
|
+
) AS reconstructed
|
|
3457
|
+
INNER JOIN candidate_roots USING (traceId, spanId)
|
|
3458
|
+
)
|
|
3459
|
+
`;
|
|
3460
|
+
const rows = await db.query(
|
|
3461
|
+
`${cteSql} SELECT max(anchorCursorId) AS cursorId FROM root_spans ${postAggWhere}`,
|
|
3462
|
+
[...prefilterParams, ...postAggParams]
|
|
3463
|
+
);
|
|
3464
|
+
const cursorId = rows[0]?.cursorId;
|
|
3465
|
+
if (cursorId !== null && cursorId !== void 0) {
|
|
3466
|
+
return encodeDeltaCursor(cursorId);
|
|
3467
|
+
}
|
|
3468
|
+
const streamRows = await db.query(
|
|
3469
|
+
`SELECT max(cursorId) AS cursorId FROM span_events WHERE eventType = 'start' AND parentSpanId IS NULL AND cursorId IS NOT NULL`
|
|
3470
|
+
);
|
|
3471
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
3472
|
+
}
|
|
3473
|
+
async function getTraceStreamHeadCursor(db) {
|
|
3474
|
+
const streamRows = await db.query(
|
|
3475
|
+
`SELECT max(cursorId) AS cursorId FROM span_events WHERE eventType = 'start' AND parentSpanId IS NULL AND cursorId IS NOT NULL`
|
|
3476
|
+
);
|
|
3477
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
3478
|
+
}
|
|
3479
|
+
async function getBranchDeltaCursor(db, filters) {
|
|
3480
|
+
const filterRecord = filters ?? {};
|
|
3481
|
+
const userSpanType = filterRecord.spanType;
|
|
3482
|
+
const { spanType: _spanType, ...rest } = filterRecord;
|
|
3483
|
+
const { prefilter, postAgg } = partitionAnchorFilters(rest);
|
|
3484
|
+
const { clause: prefilterClause, params: prefilterFilterParams } = buildWhereClause(prefilter);
|
|
3485
|
+
const prefilterParts = [`eventType = 'start'`, `cursorId IS NOT NULL`];
|
|
3486
|
+
let spanTypeParams;
|
|
3487
|
+
if (typeof userSpanType === "string") {
|
|
3488
|
+
prefilterParts.push(`spanType = ?`);
|
|
3489
|
+
spanTypeParams = [userSpanType];
|
|
3490
|
+
} else {
|
|
3491
|
+
prefilterParts.push(`spanType IN (${BRANCH_SPAN_TYPE_PLACEHOLDERS})`);
|
|
3492
|
+
spanTypeParams = [...BRANCH_SPAN_TYPES];
|
|
3493
|
+
}
|
|
3494
|
+
if (prefilterClause) prefilterParts.push(prefilterClause.replace(/^WHERE\s+/i, ""));
|
|
3495
|
+
const prefilterWhere = `WHERE ${prefilterParts.join(" AND ")}`;
|
|
3496
|
+
const prefilterParams = [...spanTypeParams, ...prefilterFilterParams];
|
|
3497
|
+
const outerAlias = "outer_anchor";
|
|
3498
|
+
const { clause: postAggClause, params: postAggParams } = buildWhereClause(postAgg);
|
|
3499
|
+
if (!postAggClause) {
|
|
3500
|
+
const rows2 = await db.query(
|
|
3501
|
+
`SELECT max(cursorId) AS cursorId FROM span_events AS ${outerAlias} ${prefilterWhere}`,
|
|
3502
|
+
prefilterParams
|
|
3503
|
+
);
|
|
3504
|
+
const cursorId2 = rows2[0]?.cursorId;
|
|
3505
|
+
if (cursorId2 !== null && cursorId2 !== void 0) {
|
|
3506
|
+
return encodeDeltaCursor(cursorId2);
|
|
3507
|
+
}
|
|
3508
|
+
const streamRows2 = await db.query(
|
|
3509
|
+
`SELECT max(cursorId) AS cursorId FROM span_events WHERE eventType = 'start' AND spanType IN (${BRANCH_SPAN_TYPE_PLACEHOLDERS}) AND cursorId IS NOT NULL`,
|
|
3510
|
+
[...BRANCH_SPAN_TYPES]
|
|
3511
|
+
);
|
|
3512
|
+
return encodeDeltaCursor(streamRows2[0]?.cursorId);
|
|
3513
|
+
}
|
|
3514
|
+
const cteSql = `
|
|
3515
|
+
WITH candidate_anchors AS (
|
|
3516
|
+
SELECT traceId, spanId, cursorId
|
|
3517
|
+
FROM span_events AS ${outerAlias}
|
|
3518
|
+
${prefilterWhere}
|
|
3519
|
+
),
|
|
3520
|
+
branch_anchors AS (
|
|
3521
|
+
SELECT reconstructed.*, candidate_anchors.cursorId AS anchorCursorId
|
|
3522
|
+
FROM (
|
|
3523
|
+
${SPAN_RECONSTRUCT_SELECT}
|
|
3524
|
+
WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_anchors)
|
|
3525
|
+
GROUP BY traceId, spanId
|
|
3526
|
+
) AS reconstructed
|
|
3527
|
+
INNER JOIN candidate_anchors USING (traceId, spanId)
|
|
3528
|
+
)
|
|
3529
|
+
`;
|
|
3530
|
+
const rows = await db.query(
|
|
3531
|
+
`${cteSql} SELECT max(anchorCursorId) AS cursorId FROM branch_anchors ${postAggClause}`,
|
|
3532
|
+
[...prefilterParams, ...postAggParams]
|
|
3533
|
+
);
|
|
3534
|
+
const cursorId = rows[0]?.cursorId;
|
|
3535
|
+
if (cursorId !== null && cursorId !== void 0) {
|
|
3536
|
+
return encodeDeltaCursor(cursorId);
|
|
3537
|
+
}
|
|
3538
|
+
const streamRows = await db.query(
|
|
3539
|
+
`SELECT max(cursorId) AS cursorId FROM span_events WHERE eventType = 'start' AND spanType IN (${BRANCH_SPAN_TYPE_PLACEHOLDERS}) AND cursorId IS NOT NULL`,
|
|
3540
|
+
[...BRANCH_SPAN_TYPES]
|
|
3541
|
+
);
|
|
3542
|
+
return encodeDeltaCursor(streamRows[0]?.cursorId);
|
|
3543
|
+
}
|
|
3544
|
+
async function getBranchStreamHeadCursor(db, userSpanType) {
|
|
3545
|
+
if (userSpanType) {
|
|
3546
|
+
const rows2 = await db.query(
|
|
3547
|
+
`SELECT max(cursorId) AS cursorId FROM span_events WHERE eventType = 'start' AND spanType = ? AND cursorId IS NOT NULL`,
|
|
3548
|
+
[userSpanType]
|
|
3549
|
+
);
|
|
3550
|
+
return encodeDeltaCursor(rows2[0]?.cursorId);
|
|
3551
|
+
}
|
|
3552
|
+
const rows = await db.query(
|
|
3553
|
+
`SELECT max(cursorId) AS cursorId FROM span_events WHERE eventType = 'start' AND spanType IN (${BRANCH_SPAN_TYPE_PLACEHOLDERS}) AND cursorId IS NOT NULL`,
|
|
3554
|
+
[...BRANCH_SPAN_TYPES]
|
|
3555
|
+
);
|
|
3556
|
+
return encodeDeltaCursor(rows[0]?.cursorId);
|
|
3557
|
+
}
|
|
2923
3558
|
|
|
2924
3559
|
// src/storage/domains/observability/index.ts
|
|
2925
3560
|
function buildSignalMigrationRequiredMessage(args) {
|
|
@@ -3004,6 +3639,12 @@ var ObservabilityStorageDuckDB = class extends ObservabilityStorage {
|
|
|
3004
3639
|
supported: ["event-sourced"]
|
|
3005
3640
|
};
|
|
3006
3641
|
}
|
|
3642
|
+
getFeatures() {
|
|
3643
|
+
if (!deltaPollingFeatureEnabled()) {
|
|
3644
|
+
return void 0;
|
|
3645
|
+
}
|
|
3646
|
+
return ["delta-polling"];
|
|
3647
|
+
}
|
|
3007
3648
|
// Tracing
|
|
3008
3649
|
async createSpan(args) {
|
|
3009
3650
|
return createSpan(this.db, args);
|
|
@@ -3140,5 +3781,5 @@ var ObservabilityStorageDuckDB = class extends ObservabilityStorage {
|
|
|
3140
3781
|
};
|
|
3141
3782
|
|
|
3142
3783
|
export { ObservabilityStorageDuckDB };
|
|
3143
|
-
//# sourceMappingURL=observability-
|
|
3144
|
-
//# sourceMappingURL=observability-
|
|
3784
|
+
//# sourceMappingURL=observability-2MIUMLQP.js.map
|
|
3785
|
+
//# sourceMappingURL=observability-2MIUMLQP.js.map
|