@mastra/pg 1.22.0-alpha.3 → 1.22.0-alpha.4
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 +21 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-storage.md +1 -0
- package/dist/docs/references/integrations-databases-postgresql.md +24 -0
- package/dist/index.cjs +121 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +121 -26
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/background-tasks/index.d.ts +3 -1
- package/dist/storage/domains/background-tasks/index.d.ts.map +1 -1
- package/dist/storage/domains/experiments/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/discovery.d.ts +14 -0
- package/dist/storage/domains/observability/v-next/discovery.d.ts.map +1 -1
- package/dist/storage/factory-storage.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5021,7 +5021,7 @@ var BackgroundTasksPG = class BackgroundTasksPG extends BackgroundTasksStorage {
|
|
|
5021
5021
|
}
|
|
5022
5022
|
});
|
|
5023
5023
|
}
|
|
5024
|
-
async updateTask(taskId, update) {
|
|
5024
|
+
async updateTask(taskId, update, options) {
|
|
5025
5025
|
const setClauses = [];
|
|
5026
5026
|
const params = [];
|
|
5027
5027
|
let paramIdx = 1;
|
|
@@ -5063,10 +5063,15 @@ var BackgroundTasksPG = class BackgroundTasksPG extends BackgroundTasksStorage {
|
|
|
5063
5063
|
const val = update.completedAt?.toISOString() ?? null;
|
|
5064
5064
|
params.push(val, val);
|
|
5065
5065
|
}
|
|
5066
|
-
if (setClauses.length === 0) return;
|
|
5066
|
+
if (setClauses.length === 0) return false;
|
|
5067
5067
|
const table = getTableName$4(getSchemaName$4(this.#schema));
|
|
5068
5068
|
params.push(taskId);
|
|
5069
|
-
|
|
5069
|
+
let where = `"id" = $${paramIdx++}`;
|
|
5070
|
+
if (options?.expectedStatus) {
|
|
5071
|
+
where += ` AND "status" = $${paramIdx}`;
|
|
5072
|
+
params.push(options.expectedStatus);
|
|
5073
|
+
}
|
|
5074
|
+
return ((await this.#db.client.query(`UPDATE ${table} SET ${setClauses.join(", ")} WHERE ${where}`, params)).rowCount ?? 0) > 0;
|
|
5070
5075
|
}
|
|
5071
5076
|
async getTask(taskId) {
|
|
5072
5077
|
const table = getTableName$4(getSchemaName$4(this.#schema));
|
|
@@ -6711,6 +6716,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
6711
6716
|
"tags",
|
|
6712
6717
|
"comment",
|
|
6713
6718
|
"toolMockReport",
|
|
6719
|
+
"metadata",
|
|
6714
6720
|
"organizationId",
|
|
6715
6721
|
"projectId",
|
|
6716
6722
|
"attempt"
|
|
@@ -6907,6 +6913,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
6907
6913
|
input: safelyParseJSON(row.input),
|
|
6908
6914
|
output: row.output ? safelyParseJSON(row.output) : null,
|
|
6909
6915
|
groundTruth: row.groundTruth ? safelyParseJSON(row.groundTruth) : null,
|
|
6916
|
+
metadata: row.metadata ? safelyParseJSON(row.metadata) : null,
|
|
6910
6917
|
error: row.error ? safelyParseJSON(row.error) : null,
|
|
6911
6918
|
startedAt: ensureDate(row.startedAtZ || row.startedAt),
|
|
6912
6919
|
completedAt: ensureDate(row.completedAtZ || row.completedAt),
|
|
@@ -7215,6 +7222,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7215
7222
|
input: input.input,
|
|
7216
7223
|
output: input.output ?? null,
|
|
7217
7224
|
groundTruth: input.groundTruth ?? null,
|
|
7225
|
+
metadata: input.metadata ?? null,
|
|
7218
7226
|
error: input.error ?? null,
|
|
7219
7227
|
startedAt: input.startedAt.toISOString(),
|
|
7220
7228
|
completedAt: input.completedAt.toISOString(),
|
|
@@ -7237,6 +7245,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7237
7245
|
input: input.input,
|
|
7238
7246
|
output: input.output ?? null,
|
|
7239
7247
|
groundTruth: input.groundTruth ?? null,
|
|
7248
|
+
metadata: input.metadata ?? null,
|
|
7240
7249
|
error: input.error ?? null,
|
|
7241
7250
|
startedAt: input.startedAt,
|
|
7242
7251
|
completedAt: input.completedAt,
|
|
@@ -7273,9 +7282,9 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7273
7282
|
const id = crypto.randomUUID();
|
|
7274
7283
|
return t.one(`INSERT INTO ${tableName} (
|
|
7275
7284
|
"id", "experimentId", "itemId", "itemDatasetVersion", "organizationId", "projectId",
|
|
7276
|
-
"input", "output", "groundTruth", "error", "startedAt", "completedAt",
|
|
7285
|
+
"input", "output", "groundTruth", "metadata", "error", "startedAt", "completedAt",
|
|
7277
7286
|
"retryCount", "attempt", "traceId", "status", "tags", "toolMockReport", "createdAt"
|
|
7278
|
-
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
|
|
7287
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)
|
|
7279
7288
|
RETURNING *`, [
|
|
7280
7289
|
id,
|
|
7281
7290
|
input.experimentId,
|
|
@@ -7286,6 +7295,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7286
7295
|
JSON.stringify(input.input),
|
|
7287
7296
|
input.output != null ? JSON.stringify(input.output) : null,
|
|
7288
7297
|
input.groundTruth != null ? JSON.stringify(input.groundTruth) : null,
|
|
7298
|
+
input.metadata != null ? JSON.stringify(input.metadata) : null,
|
|
7289
7299
|
input.error != null ? JSON.stringify(input.error) : null,
|
|
7290
7300
|
input.startedAt.toISOString(),
|
|
7291
7301
|
input.completedAt.toISOString(),
|
|
@@ -7300,9 +7310,9 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7300
7310
|
}
|
|
7301
7311
|
return t.one(`UPDATE ${tableName} SET
|
|
7302
7312
|
"itemDatasetVersion" = $2, "organizationId" = $3, "projectId" = $4,
|
|
7303
|
-
"input" = $5, "output" = $6, "groundTruth" = $7, "
|
|
7304
|
-
"startedAt" = $
|
|
7305
|
-
"traceId" = $
|
|
7313
|
+
"input" = $5, "output" = $6, "groundTruth" = $7, "metadata" = $8, "error" = $9,
|
|
7314
|
+
"startedAt" = $10, "completedAt" = $11, "retryCount" = $12, "attempt" = $13,
|
|
7315
|
+
"traceId" = $14, "status" = $15, "tags" = $16, "toolMockReport" = $17
|
|
7306
7316
|
WHERE "id" = $1 RETURNING *`, [
|
|
7307
7317
|
existing.id,
|
|
7308
7318
|
input.itemDatasetVersion ?? null,
|
|
@@ -7311,6 +7321,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7311
7321
|
JSON.stringify(input.input),
|
|
7312
7322
|
input.output != null ? JSON.stringify(input.output) : null,
|
|
7313
7323
|
input.groundTruth != null ? JSON.stringify(input.groundTruth) : null,
|
|
7324
|
+
input.metadata != null ? JSON.stringify(input.metadata) : null,
|
|
7314
7325
|
input.error != null ? JSON.stringify(input.error) : null,
|
|
7315
7326
|
input.startedAt.toISOString(),
|
|
7316
7327
|
input.completedAt.toISOString(),
|
|
@@ -14417,6 +14428,7 @@ function allIndexDDL(schema) {
|
|
|
14417
14428
|
//#endregion
|
|
14418
14429
|
//#region src/storage/domains/observability/v-next/discovery.ts
|
|
14419
14430
|
const DEFAULT_TTL_SECONDS = 300;
|
|
14431
|
+
const DEFAULT_LOOKBACK_SECONDS = 720 * 60 * 60;
|
|
14420
14432
|
/** All signal tables that contain a column. Used by cross-signal discovery. */
|
|
14421
14433
|
const SIGNAL_TABLES_WITH_CONTEXT = [
|
|
14422
14434
|
TABLE_SPAN_EVENTS,
|
|
@@ -14481,22 +14493,71 @@ function startOrJoinRefresh(dedupeKey, cacheKey, refresh, upsert, logger) {
|
|
|
14481
14493
|
async function readWithRefresh(client, schema, cacheKey, refresh, ttlSeconds, logger) {
|
|
14482
14494
|
const table = qualifiedTable(schema, TABLE_DISCOVERY);
|
|
14483
14495
|
const row = await client.oneOrNone(`SELECT "values", "refreshedAt" FROM ${table} WHERE "cacheKey" = $1`, [cacheKey]);
|
|
14484
|
-
const
|
|
14485
|
-
|
|
14486
|
-
const refreshing = startOrJoinRefresh(`${schema}:${cacheKey}`, cacheKey, refresh, (values) => upsertCache(client, schema, cacheKey, values), logger);
|
|
14496
|
+
const dedupeKey = `${schema}:${cacheKey}`;
|
|
14497
|
+
const startRefresh = () => startOrJoinRefresh(dedupeKey, cacheKey, refresh, (values) => upsertCache(client, schema, cacheKey, values), logger);
|
|
14487
14498
|
if (ttlSeconds <= 0) try {
|
|
14488
|
-
return await
|
|
14499
|
+
return await startRefresh();
|
|
14489
14500
|
} catch {
|
|
14490
14501
|
return row?.values ?? [];
|
|
14491
14502
|
}
|
|
14503
|
+
const refreshedAtMs = row ? new Date(row.refreshedAt).getTime() : 0;
|
|
14504
|
+
if (!(!row || Date.now() - refreshedAtMs > ttlSeconds * 1e3)) return row.values;
|
|
14492
14505
|
if (!row) try {
|
|
14493
|
-
return await
|
|
14506
|
+
return await startRefresh();
|
|
14494
14507
|
} catch {
|
|
14495
14508
|
return [];
|
|
14496
14509
|
}
|
|
14497
|
-
|
|
14510
|
+
const previousRefreshedAt = row.refreshedAt;
|
|
14511
|
+
claimRefresh(client, schema, cacheKey, ttlSeconds).then((claimedAt) => {
|
|
14512
|
+
if (!claimedAt) return;
|
|
14513
|
+
return startRefresh().then(() => {}, () => releaseClaim(client, schema, cacheKey, previousRefreshedAt, claimedAt));
|
|
14514
|
+
}).catch(() => {});
|
|
14498
14515
|
return row.values;
|
|
14499
14516
|
}
|
|
14517
|
+
/**
|
|
14518
|
+
* Try to become the process that refreshes `cacheKey`.
|
|
14519
|
+
*
|
|
14520
|
+
* The conditional UPDATE re-checks staleness in the database and stamps
|
|
14521
|
+
* `refreshedAt` in the same statement, so exactly one caller can transition a
|
|
14522
|
+
* given cache row out of the stale window — losers see zero rows updated and
|
|
14523
|
+
* skip their refresh. This is the cross-process counterpart to
|
|
14524
|
+
* `inFlightRefreshes`: N frontends going stale together run one refresh
|
|
14525
|
+
* instead of N.
|
|
14526
|
+
*
|
|
14527
|
+
* It reuses the cache table rather than an advisory lock because `DbClient`
|
|
14528
|
+
* is pool-backed, so a transaction-scoped lock would mean threading explicit
|
|
14529
|
+
* transaction handling through the discovery read path.
|
|
14530
|
+
*
|
|
14531
|
+
* The stamp is provisional in both directions: a completed refresh overwrites
|
|
14532
|
+
* it via `upsertCache`, and a failed one restores it via `releaseClaim`.
|
|
14533
|
+
*
|
|
14534
|
+
* Returns the exact provisional stamp written by the claim (or `null` when
|
|
14535
|
+
* the claim was lost) so `releaseClaim` can restore the row only while it
|
|
14536
|
+
* still holds this claim's stamp.
|
|
14537
|
+
*/
|
|
14538
|
+
async function claimRefresh(client, schema, cacheKey, ttlSeconds) {
|
|
14539
|
+
const table = qualifiedTable(schema, TABLE_DISCOVERY);
|
|
14540
|
+
return (await client.oneOrNone(`UPDATE ${table} SET "refreshedAt" = NOW()
|
|
14541
|
+
WHERE "cacheKey" = $1 AND "refreshedAt" <= NOW() - ($2 || ' seconds')::interval
|
|
14542
|
+
RETURNING "refreshedAt"::text AS "refreshedAt"`, [cacheKey, Math.floor(ttlSeconds)]))?.refreshedAt ?? null;
|
|
14543
|
+
}
|
|
14544
|
+
/**
|
|
14545
|
+
* Hand back a claim whose refresh failed by restoring the timestamp the
|
|
14546
|
+
* claiming reader observed. Guarded on the row still holding this claim's
|
|
14547
|
+
* exact provisional stamp so a refresh that completed in the meantime
|
|
14548
|
+
* (another process, or a later claim) isn't dragged backwards into staleness.
|
|
14549
|
+
*/
|
|
14550
|
+
async function releaseClaim(client, schema, cacheKey, previousRefreshedAt, claimedAt) {
|
|
14551
|
+
const table = qualifiedTable(schema, TABLE_DISCOVERY);
|
|
14552
|
+
try {
|
|
14553
|
+
await client.query(`UPDATE ${table} SET "refreshedAt" = $2
|
|
14554
|
+
WHERE "cacheKey" = $1 AND "refreshedAt" = $3::timestamptz`, [
|
|
14555
|
+
cacheKey,
|
|
14556
|
+
previousRefreshedAt,
|
|
14557
|
+
claimedAt
|
|
14558
|
+
]);
|
|
14559
|
+
} catch {}
|
|
14560
|
+
}
|
|
14500
14561
|
async function upsertCache(client, schema, cacheKey, values) {
|
|
14501
14562
|
const table = qualifiedTable(schema, TABLE_DISCOVERY);
|
|
14502
14563
|
await client.query(`INSERT INTO ${table} ("cacheKey", "refreshedAt", "values")
|
|
@@ -14505,61 +14566,95 @@ async function upsertCache(client, schema, cacheKey, values) {
|
|
|
14505
14566
|
"refreshedAt" = EXCLUDED."refreshedAt",
|
|
14506
14567
|
"values" = EXCLUDED."values"`, [cacheKey, JSON.stringify(values)]);
|
|
14507
14568
|
}
|
|
14508
|
-
|
|
14569
|
+
/**
|
|
14570
|
+
* Time predicate that bounds a discovery refresh to recent events.
|
|
14571
|
+
*
|
|
14572
|
+
* Each signal table is range-partitioned on its own time column
|
|
14573
|
+
* (`SIGNAL_TIME_COLUMN`: `endedAt` for spans, `timestamp` for everything
|
|
14574
|
+
* else), so the predicate has to be built per table rather than shared across
|
|
14575
|
+
* a UNION. Bounding on that exact column is what lets the planner prune
|
|
14576
|
+
* partitions/chunks instead of scanning all history.
|
|
14577
|
+
*
|
|
14578
|
+
* The interval is interpolated rather than bound to a parameter on purpose:
|
|
14579
|
+
* the UNION branches in `distinctAcrossTables` and `getTags` all reference the
|
|
14580
|
+
* same positional placeholders, so adding a per-branch parameter would break
|
|
14581
|
+
* `$N` numbering. Safety comes from coercing to a finite integer here — the
|
|
14582
|
+
* value originates from `DiscoveryConfig`, never from user input.
|
|
14583
|
+
*/
|
|
14584
|
+
function lookbackPredicate(table, lookbackSeconds) {
|
|
14585
|
+
if (!Number.isFinite(lookbackSeconds) || lookbackSeconds <= 0) return "";
|
|
14586
|
+
const seconds = Math.floor(lookbackSeconds);
|
|
14587
|
+
const timeColumn = SIGNAL_TIME_COLUMN[table];
|
|
14588
|
+
if (!timeColumn) return "";
|
|
14589
|
+
return `AND "${timeColumn}" >= NOW() - INTERVAL '${seconds} seconds'`;
|
|
14590
|
+
}
|
|
14591
|
+
async function distinctAcrossTables(client, schema, column, tables, lookbackSeconds, filterSql = "", filterParams = []) {
|
|
14509
14592
|
const safeColumn = parseSqlIdentifier(column, "column name");
|
|
14510
|
-
const unions = tables.map((t) => `SELECT DISTINCT "${safeColumn}" AS v FROM ${qualifiedTable(schema, t)} WHERE "${safeColumn}" IS NOT NULL AND "${safeColumn}" <> '' ${filterSql}`).join(" UNION ");
|
|
14593
|
+
const unions = tables.map((t) => `SELECT DISTINCT "${safeColumn}" AS v FROM ${qualifiedTable(schema, t)} WHERE "${safeColumn}" IS NOT NULL AND "${safeColumn}" <> '' ${filterSql} ${lookbackPredicate(t, lookbackSeconds)}`).join(" UNION ");
|
|
14511
14594
|
return (await client.manyOrNone(`SELECT v FROM (${unions}) sub ORDER BY v`, filterParams)).map((r) => r.v);
|
|
14512
14595
|
}
|
|
14513
14596
|
async function getEntityTypes(client, schema, _args, config) {
|
|
14514
|
-
|
|
14597
|
+
const ttl = config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
14598
|
+
const lookback = config.lookbackSeconds ?? DEFAULT_LOOKBACK_SECONDS;
|
|
14599
|
+
return { entityTypes: await readWithRefresh(client, schema, "entity_types", () => distinctAcrossTables(client, schema, "entityType", ENTITY_DISCOVERY_TABLES, lookback), ttl, config.logger) };
|
|
14515
14600
|
}
|
|
14516
14601
|
async function getEntityNames(client, schema, args, config) {
|
|
14517
14602
|
const ttl = config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
14603
|
+
const lookback = config.lookbackSeconds ?? DEFAULT_LOOKBACK_SECONDS;
|
|
14518
14604
|
const cacheKey = args.entityType ? `entity_names:${args.entityType}` : "entity_names";
|
|
14519
14605
|
const filterSql = args.entityType ? `AND "entityType" = $1` : "";
|
|
14520
14606
|
const filterParams = args.entityType ? [args.entityType] : [];
|
|
14521
|
-
return { names: await readWithRefresh(client, schema, cacheKey, () => distinctAcrossTables(client, schema, "entityName", ENTITY_DISCOVERY_TABLES, filterSql, filterParams), ttl, config.logger) };
|
|
14607
|
+
return { names: await readWithRefresh(client, schema, cacheKey, () => distinctAcrossTables(client, schema, "entityName", ENTITY_DISCOVERY_TABLES, lookback, filterSql, filterParams), ttl, config.logger) };
|
|
14522
14608
|
}
|
|
14523
14609
|
async function getServiceNames(client, schema, _args, config) {
|
|
14524
|
-
|
|
14610
|
+
const ttl = config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
14611
|
+
const lookback = config.lookbackSeconds ?? DEFAULT_LOOKBACK_SECONDS;
|
|
14612
|
+
return { serviceNames: await readWithRefresh(client, schema, "service_names", () => distinctAcrossTables(client, schema, "serviceName", SIGNAL_TABLES_WITH_CONTEXT, lookback), ttl, config.logger) };
|
|
14525
14613
|
}
|
|
14526
14614
|
async function getEnvironments(client, schema, _args, config) {
|
|
14527
|
-
|
|
14615
|
+
const ttl = config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
14616
|
+
const lookback = config.lookbackSeconds ?? DEFAULT_LOOKBACK_SECONDS;
|
|
14617
|
+
return { environments: await readWithRefresh(client, schema, "environments", () => distinctAcrossTables(client, schema, "environment", SIGNAL_TABLES_WITH_CONTEXT, lookback), ttl, config.logger) };
|
|
14528
14618
|
}
|
|
14529
14619
|
async function getTags(client, schema, args, config) {
|
|
14530
14620
|
const ttl = config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
14621
|
+
const lookback = config.lookbackSeconds ?? DEFAULT_LOOKBACK_SECONDS;
|
|
14531
14622
|
const cacheKey = args.entityType ? `tags:${args.entityType}` : "tags";
|
|
14532
14623
|
const refresh = async () => {
|
|
14533
14624
|
const filter = args.entityType ? `AND "entityType" = $1` : "";
|
|
14534
14625
|
const params = args.entityType ? [args.entityType] : [];
|
|
14535
|
-
const unions = ENTITY_DISCOVERY_TABLES.map((t) => `SELECT DISTINCT UNNEST("tags") AS v FROM ${qualifiedTable(schema, t)} WHERE array_length("tags", 1) > 0 ${filter}`).join(" UNION ");
|
|
14626
|
+
const unions = ENTITY_DISCOVERY_TABLES.map((t) => `SELECT DISTINCT UNNEST("tags") AS v FROM ${qualifiedTable(schema, t)} WHERE array_length("tags", 1) > 0 ${filter} ${lookbackPredicate(t, lookback)}`).join(" UNION ");
|
|
14536
14627
|
return (await client.manyOrNone(`SELECT v FROM (${unions}) sub WHERE v IS NOT NULL AND v <> '' ORDER BY v`, params)).map((r) => r.v);
|
|
14537
14628
|
};
|
|
14538
14629
|
return { tags: await readWithRefresh(client, schema, cacheKey, refresh, ttl, config.logger) };
|
|
14539
14630
|
}
|
|
14540
14631
|
async function getMetricNames(client, schema, args, config) {
|
|
14632
|
+
const ttl = config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
14633
|
+
const lookback = config.lookbackSeconds ?? DEFAULT_LOOKBACK_SECONDS;
|
|
14541
14634
|
let filtered = await readWithRefresh(client, schema, "metric_names", async () => {
|
|
14542
14635
|
return (await client.manyOrNone(`SELECT DISTINCT "name" AS v FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)}
|
|
14543
|
-
WHERE "name" IS NOT NULL AND "name" <> '' ORDER BY "name"`)).map((r) => r.v);
|
|
14544
|
-
},
|
|
14636
|
+
WHERE "name" IS NOT NULL AND "name" <> '' ${lookbackPredicate(TABLE_METRIC_EVENTS, lookback)} ORDER BY "name"`)).map((r) => r.v);
|
|
14637
|
+
}, ttl, config.logger);
|
|
14545
14638
|
if (args.prefix) filtered = filtered.filter((v) => v.startsWith(args.prefix));
|
|
14546
14639
|
if (args.limit) filtered = filtered.slice(0, args.limit);
|
|
14547
14640
|
return { names: filtered };
|
|
14548
14641
|
}
|
|
14549
14642
|
async function getMetricLabelKeys(client, schema, args, config) {
|
|
14550
14643
|
const ttl = config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
14644
|
+
const lookback = config.lookbackSeconds ?? DEFAULT_LOOKBACK_SECONDS;
|
|
14551
14645
|
return { keys: await readWithRefresh(client, schema, `metric_label_keys:${args.metricName}`, async () => {
|
|
14552
14646
|
return (await client.manyOrNone(`SELECT DISTINCT k AS v
|
|
14553
14647
|
FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)}, jsonb_object_keys("labels") k
|
|
14554
|
-
WHERE "name" = $1 ORDER BY k`, [args.metricName])).map((r) => r.v);
|
|
14648
|
+
WHERE "name" = $1 ${lookbackPredicate(TABLE_METRIC_EVENTS, lookback)} ORDER BY k`, [args.metricName])).map((r) => r.v);
|
|
14555
14649
|
}, ttl, config.logger) };
|
|
14556
14650
|
}
|
|
14557
14651
|
async function getMetricLabelValues(client, schema, args, config) {
|
|
14558
14652
|
const ttl = config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
14653
|
+
const lookback = config.lookbackSeconds ?? DEFAULT_LOOKBACK_SECONDS;
|
|
14559
14654
|
let filtered = await readWithRefresh(client, schema, `metric_label_values:${args.metricName}:${args.labelKey}`, async () => {
|
|
14560
14655
|
return (await client.manyOrNone(`SELECT DISTINCT "labels" ->> $2 AS v
|
|
14561
14656
|
FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)}
|
|
14562
|
-
WHERE "name" = $1 AND "labels" ? $2
|
|
14657
|
+
WHERE "name" = $1 AND "labels" ? $2 ${lookbackPredicate(TABLE_METRIC_EVENTS, lookback)}
|
|
14563
14658
|
ORDER BY v`, [args.metricName, args.labelKey])).map((r) => r.v).filter((v) => v != null && v !== "");
|
|
14564
14659
|
}, ttl, config.logger);
|
|
14565
14660
|
if (args.prefix) filtered = filtered.filter((v) => v.startsWith(args.prefix));
|
|
@@ -21907,7 +22002,7 @@ var PgFactoryStorageOps = class {
|
|
|
21907
22002
|
row[name] = Boolean(value);
|
|
21908
22003
|
break;
|
|
21909
22004
|
case "json":
|
|
21910
|
-
row[name] =
|
|
22005
|
+
row[name] = value;
|
|
21911
22006
|
break;
|
|
21912
22007
|
case "bigint":
|
|
21913
22008
|
case "integer":
|