@mastra/duckdb 1.5.1 → 1.5.2-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.
@@ -1,4 +1,4 @@
1
- import { DuckDBConnection } from './chunk-4LIZE4MC.js';
1
+ import { DuckDBConnection } from './chunk-SBS7DUKU.js';
2
2
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
3
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';
@@ -2676,6 +2676,44 @@ var SPAN_RECONSTRUCT_SELECT_LIGHT = `
2676
2676
  ${argMaxNonNull("error")}
2677
2677
  FROM span_events
2678
2678
  `;
2679
+ var POSTAGG_FILTER_COLUMNS = {
2680
+ status: ["endedAt", "error"],
2681
+ endedAt: ["endedAt"],
2682
+ tags: ["tags"],
2683
+ metadata: ["metadata"],
2684
+ scope: ["scope"]
2685
+ };
2686
+ function buildPostAggReconstructSelect(postAgg, orderByField) {
2687
+ const columns = /* @__PURE__ */ new Set();
2688
+ if (orderByField === "endedAt") columns.add("endedAt");
2689
+ for (const key of Object.keys(postAgg)) {
2690
+ for (const column of POSTAGG_FILTER_COLUMNS[key] ?? []) {
2691
+ columns.add(column);
2692
+ }
2693
+ }
2694
+ const argMaxCols = [...columns].map((col) => `${argMaxNonNull(col)},`).join("\n ");
2695
+ return `
2696
+ SELECT
2697
+ traceId, spanId,
2698
+ ${argMaxCols}
2699
+ coalesce(min(timestamp) FILTER (WHERE eventType = 'start'), min(timestamp)) as startedAt
2700
+ FROM span_events
2701
+ `;
2702
+ }
2703
+ function reconstructForAnchors(reconstructSelect, anchorCte) {
2704
+ return `
2705
+ ${reconstructSelect}
2706
+ WHERE timestamp >= (SELECT min(anchorStartedAt) FROM ${anchorCte})
2707
+ AND (traceId, spanId) IN (SELECT traceId, spanId FROM ${anchorCte})
2708
+ GROUP BY traceId, spanId`;
2709
+ }
2710
+ function reconstructForAnchorsWithBoundParam(reconstructSelect, anchorCte) {
2711
+ return `
2712
+ ${reconstructSelect}
2713
+ WHERE timestamp >= ?
2714
+ AND (traceId, spanId) IN (SELECT traceId, spanId FROM ${anchorCte})
2715
+ GROUP BY traceId, spanId`;
2716
+ }
2679
2717
  function rowToLightSpanRecord(row) {
2680
2718
  return {
2681
2719
  traceId: row.traceId,
@@ -3021,15 +3059,13 @@ async function listTraceRows(db, args, reconstructSelect, mapRow, toSpans) {
3021
3059
  const total2 = Number(countResult2[0]?.total ?? 0);
3022
3060
  const pageSql = `
3023
3061
  WITH page_roots AS (
3024
- SELECT traceId, spanId
3062
+ SELECT traceId, spanId, timestamp AS anchorStartedAt
3025
3063
  FROM span_events AS ${outerAlias}
3026
3064
  ${prefilterWhere}
3027
3065
  ${prefilterOrderBy}
3028
3066
  LIMIT ? OFFSET ?
3029
3067
  )
3030
- ${reconstructSelect}
3031
- WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM page_roots)
3032
- GROUP BY traceId, spanId
3068
+ ${reconstructForAnchors(reconstructSelect, "page_roots")}
3033
3069
  ${buildOrderByClause(orderBy)}
3034
3070
  `;
3035
3071
  const rows2 = await db.query(pageSql, [...prefilterParams, perPage, offset]);
@@ -3052,7 +3088,7 @@ async function listTraceRows(db, args, reconstructSelect, mapRow, toSpans) {
3052
3088
  ${prefilterWhere}
3053
3089
  ),
3054
3090
  root_spans AS (
3055
- ${reconstructSelect}
3091
+ ${buildPostAggReconstructSelect(postAgg, orderBy.field)}
3056
3092
  WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_roots)
3057
3093
  GROUP BY traceId, spanId
3058
3094
  )
@@ -3066,8 +3102,13 @@ async function listTraceRows(db, args, reconstructSelect, mapRow, toSpans) {
3066
3102
  const countResult = await db.query(countSql, [...prefilterParams, ...postAggParams]);
3067
3103
  const total = Number(countResult[0]?.total ?? 0);
3068
3104
  const dataSql = `
3069
- ${cteSql}
3070
- SELECT * FROM root_spans ${postAggWhere} ${orderByClause} ${paginationClause}
3105
+ ${cteSql},
3106
+ page_roots AS (
3107
+ SELECT traceId, spanId, startedAt AS anchorStartedAt
3108
+ FROM root_spans ${postAggWhere} ${orderByClause} ${paginationClause}
3109
+ )
3110
+ ${reconstructForAnchors(reconstructSelect, "page_roots")}
3111
+ ${orderByClause}
3071
3112
  `;
3072
3113
  const rows = await db.query(dataSql, [...prefilterParams, ...postAggParams, ...paginationParams]);
3073
3114
  const spans = rows.map((row) => mapRow(row));
@@ -3079,8 +3120,6 @@ async function listTraceRows(db, args, reconstructSelect, mapRow, toSpans) {
3079
3120
  async function listTraces(db, args) {
3080
3121
  const { mode, filters, pagination, orderBy, after, limit } = listTracesArgsSchema.parse(args);
3081
3122
  const filterRecord = filters ?? {};
3082
- const page = Number(pagination.page);
3083
- const perPage = Number(pagination.perPage);
3084
3123
  if (mode === "delta") {
3085
3124
  assertDeltaPollingEnabled();
3086
3125
  const streamHeadCursor = await getTraceStreamHeadCursor(db);
@@ -3092,135 +3131,78 @@ async function listTraces(db, args) {
3092
3131
  };
3093
3132
  }
3094
3133
  const afterCursorId = validateCursorId(after);
3095
- const { prefilter: prefilter2, postAgg: postAgg2, hasChildError: hasChildError2 } = partitionAnchorFilters(filterRecord);
3096
- const { clause: prefilterClause2, params: prefilterParams2 } = buildWhereClause(prefilter2);
3097
- const prefilterParts2 = [
3134
+ const { prefilter, postAgg, hasChildError } = partitionAnchorFilters(filterRecord);
3135
+ const { clause: prefilterClause, params: prefilterParams } = buildWhereClause(prefilter);
3136
+ const prefilterParts = [
3098
3137
  `eventType = 'start'`,
3099
3138
  `parentSpanId IS NULL`,
3100
3139
  `cursorId IS NOT NULL`,
3101
3140
  `cursorId > CAST(? AS BIGINT)`
3102
3141
  ];
3103
- if (prefilterClause2) prefilterParts2.push(prefilterClause2.replace(/^WHERE\s+/i, ""));
3104
- const prefilterWhere2 = `WHERE ${prefilterParts2.join(" AND ")}`;
3105
- const { clause: postAggClause2, params: postAggParams2 } = buildWhereClause(postAgg2);
3106
- const postAggParts2 = [];
3107
- if (postAggClause2) postAggParts2.push(postAggClause2.replace(/^WHERE\s+/i, ""));
3108
- const childErrorClause2 = buildHasChildErrorClause(hasChildError2, "root_spans");
3109
- if (childErrorClause2) postAggParts2.push(childErrorClause2);
3110
- const postAggWhere2 = postAggParts2.length > 0 ? `WHERE ${postAggParts2.join(" AND ")}` : "";
3111
- const outerAlias2 = "outer_root";
3112
- const dataSql2 = `
3142
+ if (prefilterClause) prefilterParts.push(prefilterClause.replace(/^WHERE\s+/i, ""));
3143
+ const prefilterWhere = `WHERE ${prefilterParts.join(" AND ")}`;
3144
+ const { clause: postAggClause, params: postAggParams } = buildWhereClause(postAgg);
3145
+ const postAggParts = [];
3146
+ if (postAggClause) postAggParts.push(postAggClause.replace(/^WHERE\s+/i, ""));
3147
+ const childErrorClause = buildHasChildErrorClause(hasChildError, "root_spans");
3148
+ if (childErrorClause) postAggParts.push(childErrorClause);
3149
+ const postAggWhere = postAggParts.length > 0 ? `WHERE ${postAggParts.join(" AND ")}` : "";
3150
+ const outerAlias = "outer_root";
3151
+ const boundResult = await db.query(
3152
+ `SELECT min(timestamp) as minTs FROM span_events AS ${outerAlias} ${prefilterWhere}`,
3153
+ [afterCursorId, ...prefilterParams]
3154
+ );
3155
+ const minTs = boundResult[0]?.minTs ?? null;
3156
+ if (minTs === null) {
3157
+ return {
3158
+ spans: [],
3159
+ delta: { limit, hasMore: false },
3160
+ deltaCursor: streamHeadCursor
3161
+ };
3162
+ }
3163
+ const dataSql = `
3113
3164
  WITH candidate_roots AS (
3114
3165
  SELECT traceId, spanId, cursorId
3115
- FROM span_events AS ${outerAlias2}
3116
- ${prefilterWhere2}
3166
+ FROM span_events AS ${outerAlias}
3167
+ ${prefilterWhere}
3117
3168
  ),
3118
3169
  root_spans AS (
3119
3170
  SELECT reconstructed.*, candidate_roots.cursorId AS anchorCursorId
3120
3171
  FROM (
3121
- ${SPAN_RECONSTRUCT_SELECT}
3122
- WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_roots)
3123
- GROUP BY traceId, spanId
3172
+ ${reconstructForAnchorsWithBoundParam(SPAN_RECONSTRUCT_SELECT, "candidate_roots")}
3124
3173
  ) AS reconstructed
3125
3174
  INNER JOIN candidate_roots USING (traceId, spanId)
3126
3175
  )
3127
- SELECT * FROM root_spans ${postAggWhere2} ORDER BY anchorCursorId ASC LIMIT ?
3176
+ SELECT * FROM root_spans ${postAggWhere} ORDER BY anchorCursorId ASC LIMIT ?
3128
3177
  `;
3129
- const rows2 = await db.query(dataSql2, [
3178
+ const rows = await db.query(dataSql, [
3130
3179
  afterCursorId,
3131
- ...prefilterParams2,
3132
- ...postAggParams2,
3180
+ ...prefilterParams,
3181
+ minTs,
3182
+ ...postAggParams,
3133
3183
  limit + 1
3134
3184
  ]);
3135
- const visibleRows = rows2.slice(0, limit).map((row) => ({
3185
+ const visibleRows = rows.slice(0, limit).map((row) => ({
3136
3186
  cursorId: row.anchorCursorId,
3137
3187
  span: rowToSpanRecord(row)
3138
3188
  }));
3139
3189
  return {
3140
3190
  spans: toTraceSpans(visibleRows.map((row) => row.span)),
3141
- delta: { limit, hasMore: rows2.length > limit },
3191
+ delta: { limit, hasMore: rows.length > limit },
3142
3192
  deltaCursor: visibleRows.length > 0 ? encodeDeltaCursor(visibleRows[visibleRows.length - 1]?.cursorId) : streamHeadCursor
3143
3193
  };
3144
3194
  }
3145
- const { prefilter, postAgg, hasChildError } = partitionAnchorFilters(filterRecord);
3146
- const { clause: prefilterClause, params: prefilterParams } = buildWhereClause(prefilter);
3147
- const prefilterParts = [`eventType = 'start'`, `parentSpanId IS NULL`];
3148
- if (prefilterClause) prefilterParts.push(prefilterClause.replace(/^WHERE\s+/i, ""));
3149
- const prefilterWhere = `WHERE ${prefilterParts.join(" AND ")}`;
3150
- const outerAlias = "outer_root";
3151
- const orderDir = orderBy.direction.toUpperCase();
3152
- if (orderDir !== "ASC" && orderDir !== "DESC") {
3153
- throw new Error(`Invalid sort direction: ${orderBy.direction}`);
3154
- }
3155
3195
  const currentDeltaCursor = deltaPollingFeatureEnabled() ? await getTraceDeltaCursor(db, filters) : void 0;
3156
- const canOrderInPrefilter = SAFE_PREFILTER_ORDER_FIELDS.has(orderBy.field);
3157
- const hasPostAggFilters = Object.keys(postAgg).length > 0 || hasChildError !== void 0 || !canOrderInPrefilter;
3158
- if (!hasPostAggFilters) {
3159
- const prefilterOrderBy = `ORDER BY timestamp ${orderDir}`;
3160
- const offset = page * perPage;
3161
- const countSql2 = `
3162
- SELECT COUNT(*) as total
3163
- FROM span_events AS ${outerAlias}
3164
- ${prefilterWhere}
3165
- `;
3166
- const countResult2 = await db.query(countSql2, prefilterParams);
3167
- const total2 = Number(countResult2[0]?.total ?? 0);
3168
- const pageSql = `
3169
- WITH page_roots AS (
3170
- SELECT traceId, spanId
3171
- FROM span_events AS ${outerAlias}
3172
- ${prefilterWhere}
3173
- ${prefilterOrderBy}
3174
- LIMIT ? OFFSET ?
3175
- )
3176
- ${SPAN_RECONSTRUCT_SELECT}
3177
- WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM page_roots)
3178
- GROUP BY traceId, spanId
3179
- ${buildOrderByClause(orderBy)}
3180
- `;
3181
- const rows2 = await db.query(pageSql, [...prefilterParams, perPage, offset]);
3182
- const spans2 = rows2.map((row) => rowToSpanRecord(row));
3183
- return {
3184
- pagination: { total: total2, page, perPage, hasMore: (page + 1) * perPage < total2 },
3185
- spans: toTraceSpans(spans2),
3186
- ...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
3187
- };
3188
- }
3189
- const { clause: postAggClause, params: postAggParams } = buildWhereClause(postAgg);
3190
- const postAggParts = [];
3191
- if (postAggClause) postAggParts.push(postAggClause.replace(/^WHERE\s+/i, ""));
3192
- const childErrorClause = buildHasChildErrorClause(hasChildError, "root_spans");
3193
- if (childErrorClause) postAggParts.push(childErrorClause);
3194
- const postAggWhere = postAggParts.length > 0 ? `WHERE ${postAggParts.join(" AND ")}` : "";
3195
- const cteSql = `
3196
- WITH candidate_roots AS (
3197
- SELECT traceId, spanId
3198
- FROM span_events AS ${outerAlias}
3199
- ${prefilterWhere}
3200
- ),
3201
- root_spans AS (
3202
- ${SPAN_RECONSTRUCT_SELECT}
3203
- WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_roots)
3204
- GROUP BY traceId, spanId
3205
- )
3206
- `;
3207
- const orderByClause = buildOrderByClause(orderBy);
3208
- const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
3209
- const countSql = `
3210
- ${cteSql}
3211
- SELECT COUNT(*) as total FROM root_spans ${postAggWhere}
3212
- `;
3213
- const countResult = await db.query(countSql, [...prefilterParams, ...postAggParams]);
3214
- const total = Number(countResult[0]?.total ?? 0);
3215
- const dataSql = `
3216
- ${cteSql}
3217
- SELECT * FROM root_spans ${postAggWhere} ${orderByClause} ${paginationClause}
3218
- `;
3219
- const rows = await db.query(dataSql, [...prefilterParams, ...postAggParams, ...paginationParams]);
3220
- const spans = rows.map((row) => rowToSpanRecord(row));
3196
+ const { pagination: resultPagination, spans } = await listTraceRows(
3197
+ db,
3198
+ { filters, pagination, orderBy },
3199
+ SPAN_RECONSTRUCT_SELECT,
3200
+ rowToSpanRecord,
3201
+ toTraceSpans
3202
+ );
3221
3203
  return {
3222
- pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
3223
- spans: toTraceSpans(spans),
3204
+ pagination: resultPagination,
3205
+ spans,
3224
3206
  ...deltaPollingFeatureEnabled() ? { deltaCursor: currentDeltaCursor } : {}
3225
3207
  };
3226
3208
  }
@@ -3304,6 +3286,18 @@ async function listBranches(db, args) {
3304
3286
  const { clause: postAggClause2, params: postAggParams2 } = buildWhereClause(postAgg2);
3305
3287
  const postAggWhere2 = postAggClause2 ? postAggClause2 : "";
3306
3288
  const outerAlias2 = "outer_anchor";
3289
+ const boundResult = await db.query(
3290
+ `SELECT min(timestamp) as minTs FROM span_events AS ${outerAlias2} ${prefilterWhere2}`,
3291
+ prefilterParams2
3292
+ );
3293
+ const minTs = boundResult[0]?.minTs ?? null;
3294
+ if (minTs === null) {
3295
+ return {
3296
+ branches: [],
3297
+ delta: { limit, hasMore: false },
3298
+ deltaCursor: streamHeadCursor
3299
+ };
3300
+ }
3307
3301
  const dataSql2 = `
3308
3302
  WITH candidate_anchors AS (
3309
3303
  SELECT traceId, spanId, cursorId
@@ -3313,15 +3307,18 @@ async function listBranches(db, args) {
3313
3307
  branch_anchors AS (
3314
3308
  SELECT reconstructed.*, candidate_anchors.cursorId AS anchorCursorId
3315
3309
  FROM (
3316
- ${SPAN_RECONSTRUCT_SELECT}
3317
- WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_anchors)
3318
- GROUP BY traceId, spanId
3310
+ ${reconstructForAnchorsWithBoundParam(SPAN_RECONSTRUCT_SELECT, "candidate_anchors")}
3319
3311
  ) AS reconstructed
3320
3312
  INNER JOIN candidate_anchors USING (traceId, spanId)
3321
3313
  )
3322
3314
  SELECT * FROM branch_anchors ${postAggWhere2} ORDER BY anchorCursorId ASC LIMIT ?
3323
3315
  `;
3324
- const rows2 = await db.query(dataSql2, [...prefilterParams2, ...postAggParams2, limit + 1]);
3316
+ const rows2 = await db.query(dataSql2, [
3317
+ ...prefilterParams2,
3318
+ minTs,
3319
+ ...postAggParams2,
3320
+ limit + 1
3321
+ ]);
3325
3322
  const visibleRows = rows2.slice(0, limit).map((row) => ({
3326
3323
  cursorId: row.anchorCursorId,
3327
3324
  branch: rowToSpanRecord(row)
@@ -3374,15 +3371,13 @@ async function listBranches(db, args) {
3374
3371
  }
3375
3372
  const pageSql = `
3376
3373
  WITH page_anchors AS (
3377
- SELECT traceId, spanId
3374
+ SELECT traceId, spanId, timestamp AS anchorStartedAt
3378
3375
  FROM span_events AS ${outerAlias}
3379
3376
  ${prefilterWhere}
3380
3377
  ${prefilterOrderBy}
3381
3378
  LIMIT ? OFFSET ?
3382
3379
  )
3383
- ${SPAN_RECONSTRUCT_SELECT}
3384
- WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM page_anchors)
3385
- GROUP BY traceId, spanId
3380
+ ${reconstructForAnchors(SPAN_RECONSTRUCT_SELECT, "page_anchors")}
3386
3381
  ${buildOrderByClause(orderBy)}
3387
3382
  `;
3388
3383
  const rows2 = await db.query(pageSql, [...prefilterParams, perPage, offset]);
@@ -3404,7 +3399,7 @@ async function listBranches(db, args) {
3404
3399
  ${prefilterWhere}
3405
3400
  ),
3406
3401
  branch_anchors AS (
3407
- ${SPAN_RECONSTRUCT_SELECT}
3402
+ ${buildPostAggReconstructSelect(postAgg, orderBy.field)}
3408
3403
  WHERE (traceId, spanId) IN (SELECT traceId, spanId FROM candidate_anchors)
3409
3404
  GROUP BY traceId, spanId
3410
3405
  )
@@ -3423,8 +3418,13 @@ async function listBranches(db, args) {
3423
3418
  };
3424
3419
  }
3425
3420
  const dataSql = `
3426
- ${cteSql}
3427
- SELECT * FROM branch_anchors ${postAggWhere} ${orderByClause} ${paginationClause}
3421
+ ${cteSql},
3422
+ page_anchors AS (
3423
+ SELECT traceId, spanId, startedAt AS anchorStartedAt
3424
+ FROM branch_anchors ${postAggWhere} ${orderByClause} ${paginationClause}
3425
+ )
3426
+ ${reconstructForAnchors(SPAN_RECONSTRUCT_SELECT, "page_anchors")}
3427
+ ${orderByClause}
3428
3428
  `;
3429
3429
  const rows = await db.query(dataSql, [...prefilterParams, ...postAggParams, ...paginationParams]);
3430
3430
  const spans = rows.map((row) => rowToSpanRecord(row));
@@ -3802,5 +3802,5 @@ var ObservabilityStorageDuckDB = class extends ObservabilityStorage {
3802
3802
  };
3803
3803
 
3804
3804
  export { ObservabilityStorageDuckDB };
3805
- //# sourceMappingURL=observability-M35AJUGT.js.map
3806
- //# sourceMappingURL=observability-M35AJUGT.js.map
3805
+ //# sourceMappingURL=observability-ZEJILRUN.js.map
3806
+ //# sourceMappingURL=observability-ZEJILRUN.js.map