@mastra/pg 1.30.0-alpha.1 → 1.30.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +166 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +166 -0
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +3 -2
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/span-query.d.ts +43 -0
- package/dist/storage/domains/observability/v-next/span-query.d.ts.map +1 -0
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +7 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -18256,6 +18256,166 @@ async function queryThreads(client, schema, plan, timeoutMs) {
|
|
|
18256
18256
|
}) : null }
|
|
18257
18257
|
});
|
|
18258
18258
|
}
|
|
18259
|
+
/** Compile a span-row filter with exactly the same rules as trace span predicates. */
|
|
18260
|
+
function compileSpanQueryPredicate(predicate, offset) {
|
|
18261
|
+
return compileScalarPredicate(predicate, SPAN_FIELDS, offset);
|
|
18262
|
+
}
|
|
18263
|
+
//#endregion
|
|
18264
|
+
//#region src/storage/domains/observability/v-next/span-query.ts
|
|
18265
|
+
const identityFields = [
|
|
18266
|
+
"organizationId",
|
|
18267
|
+
"resourceId",
|
|
18268
|
+
"traceId",
|
|
18269
|
+
"spanId"
|
|
18270
|
+
];
|
|
18271
|
+
const fields = [
|
|
18272
|
+
...identityFields,
|
|
18273
|
+
"parentSpanId",
|
|
18274
|
+
"name",
|
|
18275
|
+
"spanType",
|
|
18276
|
+
"entityType",
|
|
18277
|
+
"entityId",
|
|
18278
|
+
"entityName",
|
|
18279
|
+
"entityVersionId",
|
|
18280
|
+
"parentEntityVersionId",
|
|
18281
|
+
"rootEntityVersionId",
|
|
18282
|
+
"runId",
|
|
18283
|
+
"sessionId",
|
|
18284
|
+
"userId"
|
|
18285
|
+
];
|
|
18286
|
+
const identities = identityFields.map((field) => `"${field}"`).join(", ");
|
|
18287
|
+
const identityOrder = identityFields.map((field) => `"${field}" COLLATE "C" ASC NULLS LAST`).join(", ");
|
|
18288
|
+
function selectedKeys(rows, values) {
|
|
18289
|
+
return rows.map((row) => `(${identityFields.map((field) => {
|
|
18290
|
+
values.push(row[field]);
|
|
18291
|
+
return `"${field}" ${field === "traceId" || field === "spanId" ? "=" : "IS NOT DISTINCT FROM"} $${values.length}::text`;
|
|
18292
|
+
}).join(" AND ")})`).join(" OR ");
|
|
18293
|
+
}
|
|
18294
|
+
function afterCursor(plan, values) {
|
|
18295
|
+
if (!plan.cursor) return "TRUE";
|
|
18296
|
+
const cursor = plan.cursor;
|
|
18297
|
+
values.push(cursor.sortValue);
|
|
18298
|
+
const timestamp = `$${values.length}::timestamptz`;
|
|
18299
|
+
const field = `s."${plan.orderBy.field}"`;
|
|
18300
|
+
const terms = [`${field} ${plan.orderBy.direction === "asc" ? ">" : "<"} ${timestamp}`];
|
|
18301
|
+
const equal = [`${field} = ${timestamp}`];
|
|
18302
|
+
for (const key of identityFields) {
|
|
18303
|
+
const ref = `s."${key}" COLLATE "C"`;
|
|
18304
|
+
const value = cursor[key];
|
|
18305
|
+
if (value === null) equal.push(`${ref} IS NULL`);
|
|
18306
|
+
else {
|
|
18307
|
+
values.push(value);
|
|
18308
|
+
const parameter = `$${values.length}::text COLLATE "C"`;
|
|
18309
|
+
terms.push(`(${equal.join(" AND ")} AND (${ref} > ${parameter} OR ${ref} IS NULL))`);
|
|
18310
|
+
equal.push(`${ref} = ${parameter}`);
|
|
18311
|
+
}
|
|
18312
|
+
}
|
|
18313
|
+
return `(${terms.join(" OR ")})`;
|
|
18314
|
+
}
|
|
18315
|
+
function compilePostgresSpanQuery(schema, plan) {
|
|
18316
|
+
const values = [plan.timeRange.from, plan.timeRange.to];
|
|
18317
|
+
const scope = [];
|
|
18318
|
+
if (plan.scope) {
|
|
18319
|
+
values.push(plan.scope.organizationId);
|
|
18320
|
+
scope.push(`"organizationId" = $${values.length}`);
|
|
18321
|
+
if (plan.scope.resourceId !== void 0) {
|
|
18322
|
+
values.push(plan.scope.resourceId);
|
|
18323
|
+
scope.push(`"resourceId" = $${values.length}`);
|
|
18324
|
+
}
|
|
18325
|
+
}
|
|
18326
|
+
const predicate = plan.where ? compileSpanQueryPredicate(plan.where, values.length + 1) : {
|
|
18327
|
+
sql: "TRUE",
|
|
18328
|
+
values: []
|
|
18329
|
+
};
|
|
18330
|
+
values.push(...predicate.values);
|
|
18331
|
+
const after = afterCursor(plan, values);
|
|
18332
|
+
values.push(plan.limit + 1);
|
|
18333
|
+
const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
18334
|
+
return {
|
|
18335
|
+
text: `WITH candidate_ids AS MATERIALIZED (
|
|
18336
|
+
SELECT DISTINCT ${identities} FROM ${table}
|
|
18337
|
+
WHERE "startedAt" >= $1 AND "startedAt" < $2 AND "endedAt" >= $1 AND NOT "isPending"
|
|
18338
|
+
${scope.length ? `AND ${scope.join(" AND ")}` : ""}
|
|
18339
|
+
), current_spans AS MATERIALIZED (
|
|
18340
|
+
SELECT DISTINCT ON (${identities})
|
|
18341
|
+
${fields.map((field) => `"${field}"`).join(", ")}, "startedAt", "endedAt", "cursorId"::text AS version,
|
|
18342
|
+
CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
|
|
18343
|
+
CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider,
|
|
18344
|
+
(EXTRACT(EPOCH FROM ("endedAt" - "startedAt")) * 1000)::float8 AS "durationMs",
|
|
18345
|
+
CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status,
|
|
18346
|
+
error IS NOT NULL AS "hasError"
|
|
18347
|
+
FROM ${table} e
|
|
18348
|
+
WHERE NOT "isPending" AND "endedAt" >= $1 AND (
|
|
18349
|
+
"organizationId" IS NULL, COALESCE("organizationId", ''), "resourceId" IS NULL, COALESCE("resourceId", ''), "traceId", "spanId"
|
|
18350
|
+
) IN (
|
|
18351
|
+
SELECT "organizationId" IS NULL, COALESCE("organizationId", ''), "resourceId" IS NULL, COALESCE("resourceId", ''), "traceId", "spanId" FROM candidate_ids
|
|
18352
|
+
) ${scope.length ? `AND ${scope.join(" AND ")}` : ""}
|
|
18353
|
+
ORDER BY ${identities}, "endedAt" DESC, "cursorId" DESC
|
|
18354
|
+
), candidates AS (
|
|
18355
|
+
SELECT *, CASE WHEN "hasError" THEN 'error' ELSE NULL END AS error FROM current_spans
|
|
18356
|
+
)
|
|
18357
|
+
SELECT ${[
|
|
18358
|
+
...identityFields,
|
|
18359
|
+
"parentSpanId",
|
|
18360
|
+
"name",
|
|
18361
|
+
"spanType",
|
|
18362
|
+
"entityType",
|
|
18363
|
+
"entityId",
|
|
18364
|
+
"entityName",
|
|
18365
|
+
"model",
|
|
18366
|
+
"provider",
|
|
18367
|
+
"startedAt",
|
|
18368
|
+
"endedAt",
|
|
18369
|
+
"durationMs",
|
|
18370
|
+
"status",
|
|
18371
|
+
"version"
|
|
18372
|
+
].map((field) => `s."${field}"`).join(", ")}
|
|
18373
|
+
FROM candidates s WHERE s."startedAt" >= $1 AND s."startedAt" < $2 AND (${predicate.sql}) AND ${after}
|
|
18374
|
+
ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"}, ${identityOrder}
|
|
18375
|
+
LIMIT $${values.length}`,
|
|
18376
|
+
values
|
|
18377
|
+
};
|
|
18378
|
+
}
|
|
18379
|
+
async function querySpans(client, schema, plan, timeoutMs) {
|
|
18380
|
+
const deadline = performance.now() + coreStorage.resolveTraceQueryTimeoutMs(timeoutMs);
|
|
18381
|
+
return runWithPostgresTraceQueryTimeout(client, timeoutMs, async (tx) => {
|
|
18382
|
+
const query = compilePostgresSpanQuery(schema, plan);
|
|
18383
|
+
const rows = await tx.any(query.text, query.values);
|
|
18384
|
+
const selected = rows.map(({ version: _version, startedAt, endedAt, ...row }) => ({
|
|
18385
|
+
...row,
|
|
18386
|
+
startedAt: startedAt.toISOString(),
|
|
18387
|
+
endedAt: endedAt.toISOString()
|
|
18388
|
+
}));
|
|
18389
|
+
const page = rows.slice(0, plan.limit);
|
|
18390
|
+
if (!page.length) return coreStorage.buildSpanQueryResponse(plan, selected, [], []);
|
|
18391
|
+
const remaining = async () => {
|
|
18392
|
+
const ms = Math.floor(deadline - performance.now());
|
|
18393
|
+
if (ms <= 0) throw new coreStorage.TraceQueryExecutionError();
|
|
18394
|
+
await tx.query(`SELECT set_config('statement_timeout', $1, true)`, [`${ms}ms`]);
|
|
18395
|
+
};
|
|
18396
|
+
await remaining();
|
|
18397
|
+
const payloadValues = [];
|
|
18398
|
+
const payloadWhere = page.map((row) => {
|
|
18399
|
+
const key = selectedKeys([row], payloadValues);
|
|
18400
|
+
payloadValues.push(row.version);
|
|
18401
|
+
return `(${key} AND "cursorId" = $${payloadValues.length}::bigint)`;
|
|
18402
|
+
}).join(" OR ");
|
|
18403
|
+
const payloads = await tx.any(`SELECT ${identities},
|
|
18404
|
+
left(input::text, ${coreStorage.SPAN_QUERY_MAX_PREVIEW_CHARACTERS + 1}) AS "inputPreview", left(output::text, ${coreStorage.SPAN_QUERY_MAX_PREVIEW_CHARACTERS + 1}) AS "outputPreview"
|
|
18405
|
+
FROM ${qualifiedTable(schema, TABLE_SPAN_EVENTS)} WHERE ${payloadWhere}`, payloadValues);
|
|
18406
|
+
await remaining();
|
|
18407
|
+
const metricValues = [];
|
|
18408
|
+
const metricWhere = selectedKeys(page, metricValues);
|
|
18409
|
+
const metrics = await tx.any(`SELECT ${identities}, name, "estimatedCost", "costUnit",
|
|
18410
|
+
"costMetadata" ->> 'allocation' AS allocation, COALESCE("costMetadata" ? 'error', false) AS "costError"
|
|
18411
|
+
FROM (SELECT DISTINCT ON (${identities}, "metricId") ${identities}, name, "estimatedCost", "costUnit", "costMetadata" FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)}
|
|
18412
|
+
WHERE (${metricWhere}) AND name LIKE 'mastra_model_%'
|
|
18413
|
+
ORDER BY ${identities}, "metricId", "cursorId" DESC) m
|
|
18414
|
+
LIMIT ${coreStorage.SPAN_QUERY_MAX_COST_METRICS + 1}`, metricValues);
|
|
18415
|
+
if (metrics.length > coreStorage.SPAN_QUERY_MAX_COST_METRICS) throw new coreStorage.TraceQueryResourceLimitError();
|
|
18416
|
+
return coreStorage.buildSpanQueryResponse(plan, selected, payloads, metrics);
|
|
18417
|
+
}, { repeatableRead: true });
|
|
18418
|
+
}
|
|
18259
18419
|
//#endregion
|
|
18260
18420
|
//#region src/storage/domains/observability/v-next/trace-aggregate.ts
|
|
18261
18421
|
/** Trace-root column expressions (alias `r`) for each groupable dimension; same values `where` sees. */
|
|
@@ -19151,6 +19311,7 @@ async function dangerouslyClearTracing(client, schema) {
|
|
|
19151
19311
|
* application database — observability writes will degrade app performance.
|
|
19152
19312
|
* Use it through `MastraCompositeStore` with a dedicated Postgres connection.
|
|
19153
19313
|
*/
|
|
19314
|
+
const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? ["span-query"] : [];
|
|
19154
19315
|
function wrapError(op, error, details) {
|
|
19155
19316
|
if (error instanceof MastraError || error instanceof coreStorage.TraceQueryCursorError || error instanceof coreStorage.TraceQueryExecutionError || error instanceof coreStorage.TraceQueryResourceLimitError) throw error;
|
|
19156
19317
|
throw new MastraError({
|
|
@@ -19340,6 +19501,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
19340
19501
|
"metric-discovery",
|
|
19341
19502
|
"trace-query",
|
|
19342
19503
|
"trace-aggregate",
|
|
19504
|
+
...spanQueryFeatures,
|
|
19343
19505
|
"trace-query-root-duration",
|
|
19344
19506
|
"trace-query-discovery",
|
|
19345
19507
|
"thread-query",
|
|
@@ -19359,6 +19521,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
19359
19521
|
"delta-polling",
|
|
19360
19522
|
"trace-query",
|
|
19361
19523
|
"trace-aggregate",
|
|
19524
|
+
...spanQueryFeatures,
|
|
19362
19525
|
"trace-query-root-duration",
|
|
19363
19526
|
"trace-query-discovery",
|
|
19364
19527
|
"thread-query",
|
|
@@ -19407,6 +19570,9 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
19407
19570
|
async listTraces(args) {
|
|
19408
19571
|
return this.#run("LIST_TRACES", () => listTraces(this.#readClient, this.#schema, args));
|
|
19409
19572
|
}
|
|
19573
|
+
async querySpans(plan) {
|
|
19574
|
+
return this.#run("QUERY_SPANS", () => querySpans(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
19575
|
+
}
|
|
19410
19576
|
async queryTraces(plan) {
|
|
19411
19577
|
return this.#run("QUERY_TRACES", () => queryTraces(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
19412
19578
|
}
|