@mastra/pg 1.22.3 → 1.23.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/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-deployment-workers.md +3 -0
- package/dist/docs/references/docs-storage.md +1 -0
- package/dist/docs/references/reference-rag-metadata-filters.md +1 -0
- package/dist/index.cjs +358 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +358 -11
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +5 -2
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +10 -0
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -0
- package/dist/storage/domains/observability/v-next/tracing.d.ts +7 -0
- package/dist/storage/domains/observability/v-next/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 +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ErrorCategory, ErrorDomain, MastraError } from "@mastra/core/error";
|
|
2
|
+
import * as coreStorage from "@mastra/core/storage";
|
|
2
3
|
import { AgentsStorage, BRANCH_SPAN_TYPES, BackgroundTasksStorage, BlobStore, ChannelsStorage, DATASETS_SCHEMA, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, DatasetsStorage, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, EntityType, ExperimentsStorage, FactoryStorage, FavoritesStorage, KNOWLEDGE_ACTIVITY_SCHEMA, KNOWLEDGE_CURSORS_SCHEMA, KNOWLEDGE_MENTIONS_SCHEMA, KNOWLEDGE_NODES_SCHEMA, KNOWLEDGE_RECORDS_SCHEMA, KNOWLEDGE_SEMANTIC_OUTBOX_SCHEMA, KnowledgeConflictError, KnowledgeNotFoundError, KnowledgeStorage, MCPClientsStorage, MCPServersStorage, METRIC_DISTINCT_COLUMNS, MastraCompositeStore, MemoryStorage, NotificationsStorage, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, ObservabilityStorage, PromptBlocksStorage, SchedulesStorage, ScorerDefinitionsStorage, ScoresStorage, SkillsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, TABLE_BACKGROUND_TASKS, TABLE_CHANNEL_CONFIG, TABLE_CHANNEL_INSTALLATIONS, TABLE_CONFIGS, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, TABLE_FAVORITES, TABLE_KNOWLEDGE_ACTIVITY, TABLE_KNOWLEDGE_CURSORS, TABLE_KNOWLEDGE_MENTIONS, TABLE_KNOWLEDGE_NODES, TABLE_KNOWLEDGE_RECORDS, TABLE_KNOWLEDGE_SEMANTIC_OUTBOX, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, TABLE_MESSAGES, TABLE_NOTIFICATIONS, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, TABLE_RESOURCES, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEMAS, TABLE_SCORERS, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, TABLE_SKILLS, TABLE_SKILL_BLOBS, TABLE_SKILL_VERSIONS, TABLE_SPANS, TABLE_THREADS, TABLE_THREAD_STATE, TABLE_TOOL_PROVIDER_CONNECTIONS, TABLE_WORKFLOW_DEFINITIONS, TABLE_WORKFLOW_SNAPSHOT, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, ThreadStateStorage, ToolProviderConnectionsStorage, TraceStatus, UniqueViolationError, WorkflowDefinitionsStorage, WorkflowsStorage, WorkspacesStorage, assertKnowledgeCeilingRaised, assertKnowledgeScopeWithinCeiling, calculatePagination, canonicalizeKnowledgeScope, createKnowledgeUlid, createStorageErrorId, createVectorErrorId, ensureDate, getDefaultValue, getSqlType, hasErrorCode, isKnowledgeScopeVisible, knowledgeScopeKey, knowledgeSemanticDocumentId, knowledgeSemanticIdempotencyKey, listBranchesArgsSchema, listFeedbackArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listTracesArgsSchema, matchesExpectedWorkflowStatus, mergeWorkflowStepResult, normalizePerPage, normalizeScheduleTarget, parseDuration, parseKnowledgeNodeCursor, parseKnowledgeWikilinks, safelyParseJSON, storageMessageMatchesMetadataFilter, toTraceSpans, transformScoreRow, validateStorageMetadataFilter } from "@mastra/core/storage";
|
|
3
4
|
import { parseFieldKey, parseSqlIdentifier } from "@mastra/core/utils";
|
|
4
5
|
import { MastraVector, validateTopK, validateUpsertInput } from "@mastra/core/vector";
|
|
@@ -12145,12 +12146,20 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
|
|
|
12145
12146
|
};
|
|
12146
12147
|
const lastBufferedAtTime = input.lastBufferedAtTime ? input.lastBufferedAtTime.toISOString() : null;
|
|
12147
12148
|
if ((await this.#db.client.query(`UPDATE ${tableName} SET
|
|
12148
|
-
"bufferedObservationChunks" =
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12152
|
-
|
|
12149
|
+
"bufferedObservationChunks" = CASE
|
|
12150
|
+
WHEN EXISTS (
|
|
12151
|
+
SELECT 1
|
|
12152
|
+
FROM jsonb_array_elements(COALESCE("bufferedObservationChunks", '[]'::jsonb)) AS chunk
|
|
12153
|
+
WHERE chunk->>'cycleId' = $2
|
|
12154
|
+
) THEN COALESCE("bufferedObservationChunks", '[]'::jsonb)
|
|
12155
|
+
ELSE COALESCE("bufferedObservationChunks", '[]'::jsonb) || $1::jsonb
|
|
12156
|
+
END,
|
|
12157
|
+
"lastBufferedAtTime" = COALESCE($3, "lastBufferedAtTime"),
|
|
12158
|
+
"updatedAt" = $4,
|
|
12159
|
+
"updatedAtZ" = $5
|
|
12160
|
+
WHERE id = $6`, [
|
|
12153
12161
|
JSON.stringify([newChunk]),
|
|
12162
|
+
input.chunk.cycleId,
|
|
12154
12163
|
lastBufferedAtTime,
|
|
12155
12164
|
nowStr,
|
|
12156
12165
|
nowStr,
|
|
@@ -13480,6 +13489,7 @@ var ObservabilityPG = class ObservabilityPG extends ObservabilityStorage {
|
|
|
13480
13489
|
}
|
|
13481
13490
|
}
|
|
13482
13491
|
async batchDeleteTraces(args) {
|
|
13492
|
+
this.assertUnscopedBatchDeleteTraces(args);
|
|
13483
13493
|
try {
|
|
13484
13494
|
const tableName = getTableName$5({
|
|
13485
13495
|
indexName: TABLE_SPANS,
|
|
@@ -16715,6 +16725,304 @@ async function getScorePercentiles(client, schema, args) {
|
|
|
16715
16725
|
return { series: percentileSeriesFromRows(await client.manyOrNone(sql, acc.params), args.percentiles) };
|
|
16716
16726
|
}
|
|
16717
16727
|
//#endregion
|
|
16728
|
+
//#region src/storage/domains/observability/v-next/trace-query.ts
|
|
16729
|
+
const TRACE_STATUS_SQL = `CASE WHEN r."error" IS NOT NULL THEN 'error' ELSE 'success' END`;
|
|
16730
|
+
const TRACE_FIELDS = {
|
|
16731
|
+
traceId: "r.\"traceId\"",
|
|
16732
|
+
threadId: "r.\"threadId\"",
|
|
16733
|
+
resourceId: "r.\"resourceId\"",
|
|
16734
|
+
startedAt: "r.\"startedAt\"",
|
|
16735
|
+
endedAt: "r.\"endedAt\"",
|
|
16736
|
+
entityName: "r.\"entityName\"",
|
|
16737
|
+
entityType: "r.\"entityType\"",
|
|
16738
|
+
environment: "r.\"environment\"",
|
|
16739
|
+
status: TRACE_STATUS_SQL
|
|
16740
|
+
};
|
|
16741
|
+
const SPAN_FIELDS = {
|
|
16742
|
+
spanType: "s.\"spanType\"",
|
|
16743
|
+
error: "s.\"error\""
|
|
16744
|
+
};
|
|
16745
|
+
const SCORE_FIELDS = {
|
|
16746
|
+
scorerId: "s.\"scorerId\"",
|
|
16747
|
+
score: "s.\"score\""
|
|
16748
|
+
};
|
|
16749
|
+
const TRACE_SELECT = `
|
|
16750
|
+
r."traceId" AS "traceId",
|
|
16751
|
+
r."spanId" AS "rootSpanId",
|
|
16752
|
+
r."threadId" AS "threadId",
|
|
16753
|
+
r."resourceId" AS "resourceId",
|
|
16754
|
+
r."startedAt" AS "startedAt",
|
|
16755
|
+
r."endedAt" AS "endedAt",
|
|
16756
|
+
r."entityName" AS "entityName",
|
|
16757
|
+
r."entityType" AS "entityType",
|
|
16758
|
+
r."environment" AS "environment",
|
|
16759
|
+
${TRACE_STATUS_SQL} AS "status"`;
|
|
16760
|
+
function fieldSql(registry, field) {
|
|
16761
|
+
const sql = registry[field];
|
|
16762
|
+
if (sql === void 0) throw new Error(`Unsupported trusted trace-query field: ${field}`);
|
|
16763
|
+
return sql;
|
|
16764
|
+
}
|
|
16765
|
+
function placeholders(values, offset) {
|
|
16766
|
+
return values.map((_, index) => `$${offset + index}`).join(", ");
|
|
16767
|
+
}
|
|
16768
|
+
function compileScalarPredicate(predicate, registry, parameterOffset) {
|
|
16769
|
+
if (predicate.type === "boolean") {
|
|
16770
|
+
const values = [];
|
|
16771
|
+
return {
|
|
16772
|
+
sql: predicate.args.map((arg) => {
|
|
16773
|
+
const compiled = compileScalarPredicate(arg, registry, parameterOffset + values.length);
|
|
16774
|
+
values.push(...compiled.values);
|
|
16775
|
+
return `(${compiled.sql})`;
|
|
16776
|
+
}).join(predicate.operator === "and" ? " AND " : " OR "),
|
|
16777
|
+
values
|
|
16778
|
+
};
|
|
16779
|
+
}
|
|
16780
|
+
if (predicate.type === "not") {
|
|
16781
|
+
const compiled = compileScalarPredicate(predicate.arg, registry, parameterOffset);
|
|
16782
|
+
return {
|
|
16783
|
+
sql: `NOT (${compiled.sql})`,
|
|
16784
|
+
values: compiled.values
|
|
16785
|
+
};
|
|
16786
|
+
}
|
|
16787
|
+
const field = fieldSql(registry, predicate.field);
|
|
16788
|
+
if (predicate.type === "presence") return {
|
|
16789
|
+
sql: `${field} IS ${predicate.operator === "exists" ? "NOT " : ""}NULL`,
|
|
16790
|
+
values: []
|
|
16791
|
+
};
|
|
16792
|
+
if (predicate.type === "membership") {
|
|
16793
|
+
const list = placeholders(predicate.values, parameterOffset);
|
|
16794
|
+
if (predicate.operator === "in") return {
|
|
16795
|
+
sql: `${field} IS NOT NULL AND ${field} IN (${list})`,
|
|
16796
|
+
values: predicate.values
|
|
16797
|
+
};
|
|
16798
|
+
return {
|
|
16799
|
+
sql: `${field} IS NULL OR ${field} NOT IN (${list})`,
|
|
16800
|
+
values: predicate.values
|
|
16801
|
+
};
|
|
16802
|
+
}
|
|
16803
|
+
const parameter = `$${parameterOffset}`;
|
|
16804
|
+
const operators = {
|
|
16805
|
+
lt: "<",
|
|
16806
|
+
lte: "<=",
|
|
16807
|
+
gt: ">",
|
|
16808
|
+
gte: ">="
|
|
16809
|
+
};
|
|
16810
|
+
if (predicate.operator === "eq") return {
|
|
16811
|
+
sql: `${field} IS NOT DISTINCT FROM ${parameter}`,
|
|
16812
|
+
values: [predicate.value]
|
|
16813
|
+
};
|
|
16814
|
+
if (predicate.operator === "ne") return {
|
|
16815
|
+
sql: `${field} IS DISTINCT FROM ${parameter}`,
|
|
16816
|
+
values: [predicate.value]
|
|
16817
|
+
};
|
|
16818
|
+
const operator = operators[predicate.operator];
|
|
16819
|
+
if (operator === void 0) throw new Error(`Unsupported trusted trace-query operator: ${predicate.operator}`);
|
|
16820
|
+
return {
|
|
16821
|
+
sql: `${field} IS NOT NULL AND ${field} ${operator} ${parameter}`,
|
|
16822
|
+
values: [predicate.value]
|
|
16823
|
+
};
|
|
16824
|
+
}
|
|
16825
|
+
function latestRootPredicate$1(spanTable) {
|
|
16826
|
+
return `NOT EXISTS (
|
|
16827
|
+
SELECT 1 FROM ${spanTable} newer
|
|
16828
|
+
WHERE newer."traceId" = r."traceId"
|
|
16829
|
+
AND newer."parentSpanId" IS NULL
|
|
16830
|
+
AND newer."cursorId" > r."cursorId"
|
|
16831
|
+
)`;
|
|
16832
|
+
}
|
|
16833
|
+
function latestSpanPredicate$1(spanTable) {
|
|
16834
|
+
return `NOT EXISTS (
|
|
16835
|
+
SELECT 1 FROM ${spanTable} newer
|
|
16836
|
+
WHERE newer."traceId" = s."traceId"
|
|
16837
|
+
AND newer."spanId" = s."spanId"
|
|
16838
|
+
AND (newer."isPending" < s."isPending" OR (newer."isPending" = s."isPending" AND newer."cursorId" > s."cursorId"))
|
|
16839
|
+
)`;
|
|
16840
|
+
}
|
|
16841
|
+
function latestScorePredicate(scoreTable) {
|
|
16842
|
+
return `NOT EXISTS (
|
|
16843
|
+
SELECT 1 FROM ${scoreTable} newer
|
|
16844
|
+
WHERE newer."scoreId" = s."scoreId"
|
|
16845
|
+
AND newer."cursorId" > s."cursorId"
|
|
16846
|
+
)`;
|
|
16847
|
+
}
|
|
16848
|
+
function collectRelationCollections(predicate, collections = /* @__PURE__ */ new Set()) {
|
|
16849
|
+
if (!predicate) return collections;
|
|
16850
|
+
if (predicate.type === "relation") collections.add(predicate.collection);
|
|
16851
|
+
else if (predicate.type === "boolean") for (const arg of predicate.args) collectRelationCollections(arg, collections);
|
|
16852
|
+
else if (predicate.type === "not") collectRelationCollections(predicate.arg, collections);
|
|
16853
|
+
return collections;
|
|
16854
|
+
}
|
|
16855
|
+
function compilePredicate(predicate, parameterOffset) {
|
|
16856
|
+
if (predicate.type === "relation") {
|
|
16857
|
+
const registry = predicate.collection === "spans" ? SPAN_FIELDS : SCORE_FIELDS;
|
|
16858
|
+
const compiled = compileScalarPredicate(predicate.predicate, registry, parameterOffset);
|
|
16859
|
+
const existence = `EXISTS (
|
|
16860
|
+
SELECT 1 FROM ${predicate.collection === "spans" ? "current_spans" : "current_scores"} s
|
|
16861
|
+
WHERE s."traceId" = r."traceId"
|
|
16862
|
+
AND (${compiled.sql})
|
|
16863
|
+
)`;
|
|
16864
|
+
return {
|
|
16865
|
+
sql: predicate.quantifier === "some" ? existence : `NOT ${existence}`,
|
|
16866
|
+
values: compiled.values
|
|
16867
|
+
};
|
|
16868
|
+
}
|
|
16869
|
+
if (predicate.type === "boolean") {
|
|
16870
|
+
const values = [];
|
|
16871
|
+
return {
|
|
16872
|
+
sql: predicate.args.map((arg) => {
|
|
16873
|
+
const compiled = compilePredicate(arg, parameterOffset + values.length);
|
|
16874
|
+
values.push(...compiled.values);
|
|
16875
|
+
return `(${compiled.sql})`;
|
|
16876
|
+
}).join(predicate.operator === "and" ? " AND " : " OR "),
|
|
16877
|
+
values
|
|
16878
|
+
};
|
|
16879
|
+
}
|
|
16880
|
+
if (predicate.type === "not") {
|
|
16881
|
+
const compiled = compilePredicate(predicate.arg, parameterOffset);
|
|
16882
|
+
return {
|
|
16883
|
+
sql: `NOT (${compiled.sql})`,
|
|
16884
|
+
values: compiled.values
|
|
16885
|
+
};
|
|
16886
|
+
}
|
|
16887
|
+
return compileScalarPredicate(predicate, TRACE_FIELDS, parameterOffset);
|
|
16888
|
+
}
|
|
16889
|
+
function compilePostgresTraceQuery(schema, plan) {
|
|
16890
|
+
const spanTable = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
16891
|
+
const scoreTable = qualifiedTable(schema, TABLE_SCORE_EVENTS);
|
|
16892
|
+
const values = [plan.timeRange.from, plan.timeRange.to];
|
|
16893
|
+
const relationCollections = collectRelationCollections(plan.where);
|
|
16894
|
+
const ctes = [`root_scope AS MATERIALIZED (
|
|
16895
|
+
SELECT *
|
|
16896
|
+
FROM ${spanTable} r
|
|
16897
|
+
WHERE ${[
|
|
16898
|
+
`r."parentSpanId" IS NULL`,
|
|
16899
|
+
latestRootPredicate$1(spanTable),
|
|
16900
|
+
`NOT r."isPending"`,
|
|
16901
|
+
`r."endedAt" IS NOT NULL`,
|
|
16902
|
+
`r."startedAt" >= $1`,
|
|
16903
|
+
`r."startedAt" < $2`
|
|
16904
|
+
].join("\n AND ")}
|
|
16905
|
+
)`];
|
|
16906
|
+
if (relationCollections.has("spans")) ctes.push(`current_spans AS MATERIALIZED (
|
|
16907
|
+
SELECT s."traceId", s."spanType", s."error"
|
|
16908
|
+
FROM ${spanTable} s
|
|
16909
|
+
WHERE s."traceId" IS NOT NULL
|
|
16910
|
+
AND s."traceId" IN (SELECT "traceId" FROM root_scope)
|
|
16911
|
+
AND ${latestSpanPredicate$1(spanTable)}
|
|
16912
|
+
)`);
|
|
16913
|
+
if (relationCollections.has("scores")) ctes.push(`current_scores AS MATERIALIZED (
|
|
16914
|
+
SELECT s."traceId", s."scorerId", s."score"
|
|
16915
|
+
FROM ${scoreTable} s
|
|
16916
|
+
WHERE s."traceId" IS NOT NULL
|
|
16917
|
+
AND s."traceId" IN (SELECT "traceId" FROM root_scope)
|
|
16918
|
+
AND ${latestScorePredicate(scoreTable)}
|
|
16919
|
+
)`);
|
|
16920
|
+
let predicateSql = "TRUE";
|
|
16921
|
+
if (plan.where) {
|
|
16922
|
+
const predicate = compilePredicate(plan.where, values.length + 1);
|
|
16923
|
+
predicateSql = predicate.sql;
|
|
16924
|
+
values.push(...predicate.values);
|
|
16925
|
+
}
|
|
16926
|
+
ctes.push(`candidates AS (
|
|
16927
|
+
SELECT ${TRACE_SELECT}
|
|
16928
|
+
FROM root_scope r
|
|
16929
|
+
WHERE ${predicateSql}
|
|
16930
|
+
)`);
|
|
16931
|
+
const candidates = `WITH ${ctes.join(",\n")}`;
|
|
16932
|
+
if (plan.result === "groups") {
|
|
16933
|
+
const pageCondition = plan.cursor ? `AND "threadId" > $${values.length + 1}` : "";
|
|
16934
|
+
if (plan.cursor) values.push(plan.cursor.threadId);
|
|
16935
|
+
values.push(plan.limit + 1);
|
|
16936
|
+
return {
|
|
16937
|
+
text: `${candidates}
|
|
16938
|
+
SELECT "threadId"
|
|
16939
|
+
FROM candidates
|
|
16940
|
+
WHERE "threadId" IS NOT NULL ${pageCondition}
|
|
16941
|
+
GROUP BY "threadId"
|
|
16942
|
+
ORDER BY "threadId" ASC
|
|
16943
|
+
LIMIT $${values.length}`,
|
|
16944
|
+
values
|
|
16945
|
+
};
|
|
16946
|
+
}
|
|
16947
|
+
const orderField = plan.orderBy.field === "startedAt" ? "\"startedAt\"" : "\"endedAt\"";
|
|
16948
|
+
const direction = plan.orderBy.direction === "asc" ? "ASC" : "DESC";
|
|
16949
|
+
let pageCondition = "";
|
|
16950
|
+
if (plan.cursor) {
|
|
16951
|
+
const comparison = plan.orderBy.direction === "asc" ? ">" : "<";
|
|
16952
|
+
const sortParameter = `$${values.length + 1}`;
|
|
16953
|
+
pageCondition = `WHERE (${orderField} ${comparison} ${sortParameter} OR (${orderField} = ${sortParameter} AND "traceId" > ${`$${values.length + 2}`}))`;
|
|
16954
|
+
values.push(plan.cursor.sortValue, plan.cursor.traceId);
|
|
16955
|
+
}
|
|
16956
|
+
values.push(plan.limit + 1);
|
|
16957
|
+
return {
|
|
16958
|
+
text: `${candidates}
|
|
16959
|
+
SELECT *
|
|
16960
|
+
FROM candidates
|
|
16961
|
+
${pageCondition}
|
|
16962
|
+
ORDER BY ${orderField} ${direction}, "traceId" ASC
|
|
16963
|
+
LIMIT $${values.length}`,
|
|
16964
|
+
values
|
|
16965
|
+
};
|
|
16966
|
+
}
|
|
16967
|
+
function asIsoTimestamp$1(value) {
|
|
16968
|
+
if (value === null || value === void 0) throw new Error("Trace query returned a null timestamp");
|
|
16969
|
+
return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
|
|
16970
|
+
}
|
|
16971
|
+
function isPostgresStatementTimeout(error) {
|
|
16972
|
+
if (!error || typeof error !== "object") return false;
|
|
16973
|
+
const candidate = error;
|
|
16974
|
+
return candidate.code === "57014" && String(candidate.message ?? "").includes("statement timeout");
|
|
16975
|
+
}
|
|
16976
|
+
async function runWithPostgresTraceQueryTimeout(client, timeoutMs, execute) {
|
|
16977
|
+
const resolvedTimeoutMs = coreStorage.resolveTraceQueryTimeoutMs(timeoutMs);
|
|
16978
|
+
try {
|
|
16979
|
+
return await client.tx(async (transaction) => {
|
|
16980
|
+
await transaction.query(`SELECT set_config('statement_timeout', $1, true)`, [`${resolvedTimeoutMs}ms`]);
|
|
16981
|
+
return execute(transaction);
|
|
16982
|
+
});
|
|
16983
|
+
} catch (error) {
|
|
16984
|
+
if (isPostgresStatementTimeout(error)) throw new coreStorage.TraceQueryExecutionError();
|
|
16985
|
+
throw error;
|
|
16986
|
+
}
|
|
16987
|
+
}
|
|
16988
|
+
async function queryTraces(client, schema, plan, timeoutMs) {
|
|
16989
|
+
const query = compilePostgresTraceQuery(schema, plan);
|
|
16990
|
+
const rows = await runWithPostgresTraceQueryTimeout(client, timeoutMs, (transaction) => transaction.any(query.text, query.values));
|
|
16991
|
+
const visibleRows = rows.slice(0, plan.limit);
|
|
16992
|
+
if (plan.result === "groups") {
|
|
16993
|
+
const groups = visibleRows.map((row) => ({ threadId: String(row.threadId) }));
|
|
16994
|
+
const last = groups.at(-1);
|
|
16995
|
+
return coreStorage.traceQueryResponseSchema.parse({
|
|
16996
|
+
groups,
|
|
16997
|
+
page: { next: rows.length > plan.limit && last ? coreStorage.encodeTraceQueryCursor(plan, {
|
|
16998
|
+
result: "groups",
|
|
16999
|
+
threadId: last.threadId
|
|
17000
|
+
}) : null }
|
|
17001
|
+
});
|
|
17002
|
+
}
|
|
17003
|
+
const traces = visibleRows.map((row) => ({
|
|
17004
|
+
traceId: String(row.traceId),
|
|
17005
|
+
rootSpanId: String(row.rootSpanId),
|
|
17006
|
+
threadId: row.threadId == null ? null : String(row.threadId),
|
|
17007
|
+
resourceId: row.resourceId == null ? null : String(row.resourceId),
|
|
17008
|
+
startedAt: asIsoTimestamp$1(row.startedAt),
|
|
17009
|
+
endedAt: asIsoTimestamp$1(row.endedAt),
|
|
17010
|
+
entityName: row.entityName == null ? null : String(row.entityName),
|
|
17011
|
+
entityType: row.entityType == null ? null : String(row.entityType),
|
|
17012
|
+
environment: row.environment == null ? null : String(row.environment),
|
|
17013
|
+
status: row.status
|
|
17014
|
+
}));
|
|
17015
|
+
const last = traces.at(-1);
|
|
17016
|
+
return coreStorage.traceQueryResponseSchema.parse({
|
|
17017
|
+
traces,
|
|
17018
|
+
page: { next: rows.length > plan.limit && last ? coreStorage.encodeTraceQueryCursor(plan, {
|
|
17019
|
+
result: "traces",
|
|
17020
|
+
sortValue: last[plan.orderBy.field],
|
|
17021
|
+
traceId: last.traceId
|
|
17022
|
+
}) : null }
|
|
17023
|
+
});
|
|
17024
|
+
}
|
|
17025
|
+
//#endregion
|
|
16718
17026
|
//#region src/storage/domains/observability/v-next/traces.ts
|
|
16719
17027
|
/**
|
|
16720
17028
|
* Trace / branch list reads for the v-next Postgres observability domain.
|
|
@@ -17364,11 +17672,39 @@ async function getTraceLight(client, schema, args) {
|
|
|
17364
17672
|
spans: rows.map(rowToLightSpanRecord)
|
|
17365
17673
|
};
|
|
17366
17674
|
}
|
|
17675
|
+
/**
|
|
17676
|
+
* Delete traces by traceId, cascading to trace-linked signal events
|
|
17677
|
+
* (metrics, logs, scores, feedback). Signal rows with a NULL traceId are
|
|
17678
|
+
* never affected. When the optional tenant scope (`organizationId` /
|
|
17679
|
+
* `resourceId`) is set, every DELETE additionally requires the row's tenant
|
|
17680
|
+
* columns to match.
|
|
17681
|
+
*/
|
|
17367
17682
|
async function batchDeleteTraces(client, schema, args) {
|
|
17368
17683
|
if (args.traceIds.length === 0) return;
|
|
17369
|
-
const
|
|
17684
|
+
const params = [...args.traceIds];
|
|
17370
17685
|
const placeholders = args.traceIds.map((_, i) => `$${i + 1}`).join(", ");
|
|
17371
|
-
|
|
17686
|
+
let scopeCondition = "";
|
|
17687
|
+
if (args.organizationId !== void 0) {
|
|
17688
|
+
params.push(args.organizationId);
|
|
17689
|
+
scopeCondition += ` AND "organizationId" = $${params.length}`;
|
|
17690
|
+
}
|
|
17691
|
+
if (args.resourceId !== void 0) {
|
|
17692
|
+
params.push(args.resourceId);
|
|
17693
|
+
scopeCondition += ` AND "resourceId" = $${params.length}`;
|
|
17694
|
+
}
|
|
17695
|
+
const tables = [
|
|
17696
|
+
TABLE_SPAN_EVENTS,
|
|
17697
|
+
TABLE_METRIC_EVENTS,
|
|
17698
|
+
TABLE_LOG_EVENTS,
|
|
17699
|
+
TABLE_SCORE_EVENTS,
|
|
17700
|
+
TABLE_FEEDBACK_EVENTS
|
|
17701
|
+
];
|
|
17702
|
+
await client.tx(async (t) => {
|
|
17703
|
+
for (const tableName of tables) {
|
|
17704
|
+
const table = qualifiedTable(schema, tableName);
|
|
17705
|
+
await t.query(`DELETE FROM ${table} WHERE "traceId" IN (${placeholders})${scopeCondition}`, params);
|
|
17706
|
+
}
|
|
17707
|
+
});
|
|
17372
17708
|
}
|
|
17373
17709
|
/** Truncate the span_events table. */
|
|
17374
17710
|
async function dangerouslyClearTracing(client, schema) {
|
|
@@ -17401,7 +17737,7 @@ async function dangerouslyClearTracing(client, schema) {
|
|
|
17401
17737
|
* Use it through `MastraCompositeStore` with a dedicated Postgres connection.
|
|
17402
17738
|
*/
|
|
17403
17739
|
function wrapError(op, error, details) {
|
|
17404
|
-
if (error instanceof MastraError) throw error;
|
|
17740
|
+
if (error instanceof MastraError || error instanceof coreStorage.TraceQueryExecutionError) throw error;
|
|
17405
17741
|
throw new MastraError({
|
|
17406
17742
|
id: createStorageErrorId("PG", op, "FAILED"),
|
|
17407
17743
|
domain: ErrorDomain.STORAGE,
|
|
@@ -17414,6 +17750,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
17414
17750
|
#schema;
|
|
17415
17751
|
#partitioning;
|
|
17416
17752
|
#discoveryConfig;
|
|
17753
|
+
#traceQueryTimeoutMs;
|
|
17417
17754
|
#partitionMode;
|
|
17418
17755
|
constructor(config) {
|
|
17419
17756
|
super();
|
|
@@ -17422,6 +17759,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
17422
17759
|
this.#schema = schemaName ?? "public";
|
|
17423
17760
|
this.#partitioning = config.partitioning ?? {};
|
|
17424
17761
|
this.#discoveryConfig = config.discovery ?? {};
|
|
17762
|
+
this.#traceQueryTimeoutMs = coreStorage.resolveTraceQueryTimeoutMs(config.traceQueryTimeoutMs);
|
|
17425
17763
|
}
|
|
17426
17764
|
/**
|
|
17427
17765
|
* Build the discovery config used at each call site, with the framework
|
|
@@ -17573,11 +17911,16 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
17573
17911
|
};
|
|
17574
17912
|
}
|
|
17575
17913
|
getFeatures() {
|
|
17576
|
-
if (!deltaPollingFeatureEnabled()) return [
|
|
17914
|
+
if (!deltaPollingFeatureEnabled()) return [
|
|
17915
|
+
"metrics",
|
|
17916
|
+
"logs",
|
|
17917
|
+
"trace-query"
|
|
17918
|
+
];
|
|
17577
17919
|
return [
|
|
17578
17920
|
"metrics",
|
|
17579
17921
|
"logs",
|
|
17580
|
-
"delta-polling"
|
|
17922
|
+
"delta-polling",
|
|
17923
|
+
"trace-query"
|
|
17581
17924
|
];
|
|
17582
17925
|
}
|
|
17583
17926
|
async #run(op, fn, details) {
|
|
@@ -17620,6 +17963,9 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
17620
17963
|
async listTraces(args) {
|
|
17621
17964
|
return this.#run("LIST_TRACES", () => listTraces(this.#client, this.#schema, args));
|
|
17622
17965
|
}
|
|
17966
|
+
async queryTraces(plan) {
|
|
17967
|
+
return this.#run("QUERY_TRACES", () => queryTraces(this.#client, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
17968
|
+
}
|
|
17623
17969
|
async listBranches(args) {
|
|
17624
17970
|
return this.#run("LIST_BRANCHES", () => listBranches(this.#client, this.#schema, args));
|
|
17625
17971
|
}
|
|
@@ -22819,7 +23165,8 @@ var PostgresStoreVNext = class extends PostgresStore {
|
|
|
22819
23165
|
client: observabilityClient,
|
|
22820
23166
|
schemaName: obsConfig.schemaName ?? config.schemaName,
|
|
22821
23167
|
partitioning: obsConfig.partitioning,
|
|
22822
|
-
discovery: obsConfig.discovery
|
|
23168
|
+
discovery: obsConfig.discovery,
|
|
23169
|
+
traceQueryTimeoutMs: obsConfig.traceQueryTimeoutMs
|
|
22823
23170
|
});
|
|
22824
23171
|
this.stores = {
|
|
22825
23172
|
...this.stores,
|