expose more prisma metrics
This commit is contained in:
@@ -56,6 +56,7 @@ import { logger } from "~/services/logger.server";
|
||||
import { flattenAttributes } from "@trigger.dev/core/v3";
|
||||
import { prisma } from "~/db.server";
|
||||
import { metricsRegister } from "~/metrics.server";
|
||||
import type { Prisma } from "@trigger.dev/database";
|
||||
|
||||
export const SEMINTATTRS_FORCE_RECORDING = "forceRecording";
|
||||
|
||||
@@ -336,6 +337,33 @@ function setupMetrics() {
|
||||
}
|
||||
|
||||
function configurePrismaMetrics({ meter }: { meter: Meter }) {
|
||||
// Counters
|
||||
const queriesTotal = meter.createObservableCounter("db.client.queries.total", {
|
||||
description: "Total number of Prisma Client queries executed",
|
||||
unit: "queries",
|
||||
});
|
||||
const datasourceQueriesTotal = meter.createObservableCounter("db.datasource.queries.total", {
|
||||
description: "Total number of datasource queries executed",
|
||||
unit: "queries",
|
||||
});
|
||||
const connectionsOpenedTotal = meter.createObservableCounter("db.pool.connections.opened.total", {
|
||||
description: "Total number of pool connections opened",
|
||||
unit: "connections",
|
||||
});
|
||||
const connectionsClosedTotal = meter.createObservableCounter("db.pool.connections.closed.total", {
|
||||
description: "Total number of pool connections closed",
|
||||
unit: "connections",
|
||||
});
|
||||
|
||||
// Gauges
|
||||
const queriesActive = meter.createObservableGauge("db.client.queries.active", {
|
||||
description: "Number of currently active Prisma Client queries",
|
||||
unit: "queries",
|
||||
});
|
||||
const queriesWait = meter.createObservableGauge("db.client.queries.wait", {
|
||||
description: "Number of queries currently waiting for a connection",
|
||||
unit: "queries",
|
||||
});
|
||||
const totalGauge = meter.createObservableGauge("db.pool.connections.total", {
|
||||
description: "Open Prisma-pool connections",
|
||||
unit: "connections",
|
||||
@@ -349,26 +377,170 @@ function configurePrismaMetrics({ meter }: { meter: Meter }) {
|
||||
unit: "connections",
|
||||
});
|
||||
|
||||
// Histogram statistics as gauges
|
||||
const queriesWaitTimeCount = meter.createObservableGauge("db.client.queries.wait_time.count", {
|
||||
description: "Number of wait time observations",
|
||||
unit: "observations",
|
||||
});
|
||||
const queriesWaitTimeSum = meter.createObservableGauge("db.client.queries.wait_time.sum", {
|
||||
description: "Total wait time across all observations",
|
||||
unit: "ms",
|
||||
});
|
||||
const queriesWaitTimeMean = meter.createObservableGauge("db.client.queries.wait_time.mean", {
|
||||
description: "Average wait time for a connection",
|
||||
unit: "ms",
|
||||
});
|
||||
|
||||
const queriesDurationCount = meter.createObservableGauge("db.client.queries.duration.count", {
|
||||
description: "Number of query duration observations",
|
||||
unit: "observations",
|
||||
});
|
||||
const queriesDurationSum = meter.createObservableGauge("db.client.queries.duration.sum", {
|
||||
description: "Total query duration across all observations",
|
||||
unit: "ms",
|
||||
});
|
||||
const queriesDurationMean = meter.createObservableGauge("db.client.queries.duration.mean", {
|
||||
description: "Average duration of Prisma Client queries",
|
||||
unit: "ms",
|
||||
});
|
||||
|
||||
const datasourceQueriesDurationCount = meter.createObservableGauge(
|
||||
"db.datasource.queries.duration.count",
|
||||
{
|
||||
description: "Number of datasource query duration observations",
|
||||
unit: "observations",
|
||||
}
|
||||
);
|
||||
const datasourceQueriesDurationSum = meter.createObservableGauge(
|
||||
"db.datasource.queries.duration.sum",
|
||||
{
|
||||
description: "Total datasource query duration across all observations",
|
||||
unit: "ms",
|
||||
}
|
||||
);
|
||||
const datasourceQueriesDurationMean = meter.createObservableGauge(
|
||||
"db.datasource.queries.duration.mean",
|
||||
{
|
||||
description: "Average duration of datasource queries",
|
||||
unit: "ms",
|
||||
}
|
||||
);
|
||||
|
||||
// Single helper so we hit Prisma only once per scrape ---------------------
|
||||
async function readPoolCounters() {
|
||||
const { gauges } = await prisma.$metrics.json();
|
||||
async function readPrismaMetrics() {
|
||||
const metrics = await prisma.$metrics.json();
|
||||
|
||||
const busy = gauges.find((g) => g.key === "prisma_pool_connections_busy")?.value ?? 0;
|
||||
const free = gauges.find((g) => g.key === "prisma_pool_connections_idle")?.value ?? 0;
|
||||
const total =
|
||||
gauges.find((g) => g.key === "prisma_pool_connections_open")?.value ?? busy + free; // fallback compute
|
||||
// Extract counter values
|
||||
const counters: Record<string, number> = {};
|
||||
for (const counter of metrics.counters) {
|
||||
counters[counter.key] = counter.value;
|
||||
}
|
||||
|
||||
return { total, busy, free };
|
||||
// Extract gauge values
|
||||
const gauges: Record<string, number> = {};
|
||||
for (const gauge of metrics.gauges) {
|
||||
gauges[gauge.key] = gauge.value;
|
||||
}
|
||||
|
||||
// Extract histogram values
|
||||
const histograms: Record<string, Prisma.MetricHistogram> = {};
|
||||
for (const histogram of metrics.histograms) {
|
||||
histograms[histogram.key] = histogram.value;
|
||||
}
|
||||
|
||||
return {
|
||||
counters: {
|
||||
queriesTotal: counters["prisma_client_queries_total"] ?? 0,
|
||||
datasourceQueriesTotal: counters["prisma_datasource_queries_total"] ?? 0,
|
||||
connectionsOpenedTotal: counters["prisma_pool_connections_opened_total"] ?? 0,
|
||||
connectionsClosedTotal: counters["prisma_pool_connections_closed_total"] ?? 0,
|
||||
},
|
||||
gauges: {
|
||||
queriesActive: gauges["prisma_client_queries_active"] ?? 0,
|
||||
queriesWait: gauges["prisma_client_queries_wait"] ?? 0,
|
||||
connectionsOpen: gauges["prisma_pool_connections_open"] ?? 0,
|
||||
connectionsBusy: gauges["prisma_pool_connections_busy"] ?? 0,
|
||||
connectionsIdle: gauges["prisma_pool_connections_idle"] ?? 0,
|
||||
},
|
||||
histograms: {
|
||||
queriesWait: histograms["prisma_client_queries_wait_histogram_ms"],
|
||||
queriesDuration: histograms["prisma_client_queries_duration_histogram_ms"],
|
||||
datasourceQueriesDuration: histograms["prisma_datasource_queries_duration_histogram_ms"],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
meter.addBatchObservableCallback(
|
||||
async (res) => {
|
||||
const { total, busy, free } = await readPoolCounters();
|
||||
res.observe(totalGauge, total);
|
||||
res.observe(busyGauge, busy);
|
||||
res.observe(freeGauge, free);
|
||||
const { counters, gauges, histograms } = await readPrismaMetrics();
|
||||
|
||||
// Observe counters
|
||||
res.observe(queriesTotal, counters.queriesTotal);
|
||||
res.observe(datasourceQueriesTotal, counters.datasourceQueriesTotal);
|
||||
res.observe(connectionsOpenedTotal, counters.connectionsOpenedTotal);
|
||||
res.observe(connectionsClosedTotal, counters.connectionsClosedTotal);
|
||||
|
||||
// Observe gauges
|
||||
res.observe(queriesActive, gauges.queriesActive);
|
||||
res.observe(queriesWait, gauges.queriesWait);
|
||||
res.observe(totalGauge, gauges.connectionsOpen);
|
||||
res.observe(busyGauge, gauges.connectionsBusy);
|
||||
res.observe(freeGauge, gauges.connectionsIdle);
|
||||
|
||||
// Observe histogram statistics as gauges
|
||||
if (histograms.queriesWait) {
|
||||
res.observe(queriesWaitTimeCount, histograms.queriesWait.count);
|
||||
res.observe(queriesWaitTimeSum, histograms.queriesWait.sum);
|
||||
res.observe(
|
||||
queriesWaitTimeMean,
|
||||
histograms.queriesWait.count > 0
|
||||
? histograms.queriesWait.sum / histograms.queriesWait.count
|
||||
: 0
|
||||
);
|
||||
}
|
||||
|
||||
if (histograms.queriesDuration) {
|
||||
res.observe(queriesDurationCount, histograms.queriesDuration.count);
|
||||
res.observe(queriesDurationSum, histograms.queriesDuration.sum);
|
||||
res.observe(
|
||||
queriesDurationMean,
|
||||
histograms.queriesDuration.count > 0
|
||||
? histograms.queriesDuration.sum / histograms.queriesDuration.count
|
||||
: 0
|
||||
);
|
||||
}
|
||||
|
||||
if (histograms.datasourceQueriesDuration) {
|
||||
res.observe(datasourceQueriesDurationCount, histograms.datasourceQueriesDuration.count);
|
||||
res.observe(datasourceQueriesDurationSum, histograms.datasourceQueriesDuration.sum);
|
||||
res.observe(
|
||||
datasourceQueriesDurationMean,
|
||||
histograms.datasourceQueriesDuration.count > 0
|
||||
? histograms.datasourceQueriesDuration.sum / histograms.datasourceQueriesDuration.count
|
||||
: 0
|
||||
);
|
||||
}
|
||||
},
|
||||
[totalGauge, busyGauge, freeGauge]
|
||||
[
|
||||
queriesTotal,
|
||||
datasourceQueriesTotal,
|
||||
connectionsOpenedTotal,
|
||||
connectionsClosedTotal,
|
||||
queriesActive,
|
||||
queriesWait,
|
||||
totalGauge,
|
||||
busyGauge,
|
||||
freeGauge,
|
||||
queriesWaitTimeCount,
|
||||
queriesWaitTimeSum,
|
||||
queriesWaitTimeMean,
|
||||
queriesDurationCount,
|
||||
queriesDurationSum,
|
||||
queriesDurationMean,
|
||||
datasourceQueriesDurationCount,
|
||||
datasourceQueriesDurationSum,
|
||||
datasourceQueriesDurationMean,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user