@neverinfamous/postgres-mcp 1.1.0 → 1.3.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.
- package/README.md +95 -81
- package/dist/__tests__/mocks/adapter.d.ts.map +1 -1
- package/dist/__tests__/mocks/adapter.js +0 -1
- package/dist/__tests__/mocks/adapter.js.map +1 -1
- package/dist/__tests__/mocks/pool.d.ts.map +1 -1
- package/dist/__tests__/mocks/pool.js +0 -1
- package/dist/__tests__/mocks/pool.js.map +1 -1
- package/dist/adapters/DatabaseAdapter.js +1 -1
- package/dist/adapters/DatabaseAdapter.js.map +1 -1
- package/dist/adapters/postgresql/PostgresAdapter.d.ts.map +1 -1
- package/dist/adapters/postgresql/PostgresAdapter.js +78 -8
- package/dist/adapters/postgresql/PostgresAdapter.js.map +1 -1
- package/dist/adapters/postgresql/prompts/backup.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/backup.js +2 -3
- package/dist/adapters/postgresql/prompts/backup.js.map +1 -1
- package/dist/adapters/postgresql/prompts/citext.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/citext.js +3 -4
- package/dist/adapters/postgresql/prompts/citext.js.map +1 -1
- package/dist/adapters/postgresql/prompts/extensionSetup.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/extensionSetup.js +2 -3
- package/dist/adapters/postgresql/prompts/extensionSetup.js.map +1 -1
- package/dist/adapters/postgresql/prompts/health.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/health.js +2 -3
- package/dist/adapters/postgresql/prompts/health.js.map +1 -1
- package/dist/adapters/postgresql/prompts/index.js +20 -27
- package/dist/adapters/postgresql/prompts/index.js.map +1 -1
- package/dist/adapters/postgresql/prompts/indexTuning.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/indexTuning.js +2 -3
- package/dist/adapters/postgresql/prompts/indexTuning.js.map +1 -1
- package/dist/adapters/postgresql/prompts/kcache.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/kcache.js +3 -4
- package/dist/adapters/postgresql/prompts/kcache.js.map +1 -1
- package/dist/adapters/postgresql/prompts/ltree.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/ltree.js +5 -6
- package/dist/adapters/postgresql/prompts/ltree.js.map +1 -1
- package/dist/adapters/postgresql/prompts/partman.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/partman.js +2 -3
- package/dist/adapters/postgresql/prompts/partman.js.map +1 -1
- package/dist/adapters/postgresql/prompts/pgcron.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/pgcron.js +2 -3
- package/dist/adapters/postgresql/prompts/pgcron.js.map +1 -1
- package/dist/adapters/postgresql/prompts/pgcrypto.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/pgcrypto.js +3 -4
- package/dist/adapters/postgresql/prompts/pgcrypto.js.map +1 -1
- package/dist/adapters/postgresql/prompts/pgvector.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/pgvector.js +3 -4
- package/dist/adapters/postgresql/prompts/pgvector.js.map +1 -1
- package/dist/adapters/postgresql/prompts/postgis.d.ts.map +1 -1
- package/dist/adapters/postgresql/prompts/postgis.js +2 -3
- package/dist/adapters/postgresql/prompts/postgis.js.map +1 -1
- package/dist/adapters/postgresql/schemas/admin.d.ts +10 -5
- package/dist/adapters/postgresql/schemas/admin.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/admin.js +10 -5
- package/dist/adapters/postgresql/schemas/admin.js.map +1 -1
- package/dist/adapters/postgresql/schemas/backup.d.ts +8 -4
- package/dist/adapters/postgresql/schemas/backup.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/backup.js +11 -4
- package/dist/adapters/postgresql/schemas/backup.js.map +1 -1
- package/dist/adapters/postgresql/schemas/core.d.ts +54 -19
- package/dist/adapters/postgresql/schemas/core.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/core.js +65 -17
- package/dist/adapters/postgresql/schemas/core.js.map +1 -1
- package/dist/adapters/postgresql/schemas/cron.d.ts +51 -32
- package/dist/adapters/postgresql/schemas/cron.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/cron.js +64 -44
- package/dist/adapters/postgresql/schemas/cron.js.map +1 -1
- package/dist/adapters/postgresql/schemas/extensions.d.ts +168 -73
- package/dist/adapters/postgresql/schemas/extensions.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/extensions.js +179 -62
- package/dist/adapters/postgresql/schemas/extensions.js.map +1 -1
- package/dist/adapters/postgresql/schemas/index.d.ts +5 -5
- package/dist/adapters/postgresql/schemas/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/index.js +9 -7
- package/dist/adapters/postgresql/schemas/index.js.map +1 -1
- package/dist/adapters/postgresql/schemas/jsonb.d.ts +94 -42
- package/dist/adapters/postgresql/schemas/jsonb.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/jsonb.js +101 -30
- package/dist/adapters/postgresql/schemas/jsonb.js.map +1 -1
- package/dist/adapters/postgresql/schemas/monitoring.d.ts +28 -11
- package/dist/adapters/postgresql/schemas/monitoring.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/monitoring.js +49 -24
- package/dist/adapters/postgresql/schemas/monitoring.js.map +1 -1
- package/dist/adapters/postgresql/schemas/partitioning.d.ts +15 -11
- package/dist/adapters/postgresql/schemas/partitioning.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/partitioning.js +17 -13
- package/dist/adapters/postgresql/schemas/partitioning.js.map +1 -1
- package/dist/adapters/postgresql/schemas/performance.d.ts +62 -31
- package/dist/adapters/postgresql/schemas/performance.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/performance.js +86 -24
- package/dist/adapters/postgresql/schemas/performance.js.map +1 -1
- package/dist/adapters/postgresql/schemas/postgis.d.ts +20 -0
- package/dist/adapters/postgresql/schemas/postgis.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/postgis.js +20 -3
- package/dist/adapters/postgresql/schemas/postgis.js.map +1 -1
- package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts +35 -23
- package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/schema-mgmt.js +69 -26
- package/dist/adapters/postgresql/schemas/schema-mgmt.js.map +1 -1
- package/dist/adapters/postgresql/schemas/stats.d.ts +33 -20
- package/dist/adapters/postgresql/schemas/stats.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/stats.js +36 -20
- package/dist/adapters/postgresql/schemas/stats.js.map +1 -1
- package/dist/adapters/postgresql/schemas/text-search.d.ts +8 -5
- package/dist/adapters/postgresql/schemas/text-search.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/text-search.js +15 -5
- package/dist/adapters/postgresql/schemas/text-search.js.map +1 -1
- package/dist/adapters/postgresql/tools/admin.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/admin.js +211 -140
- package/dist/adapters/postgresql/tools/admin.js.map +1 -1
- package/dist/adapters/postgresql/tools/backup/dump.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/backup/dump.js +410 -387
- package/dist/adapters/postgresql/tools/backup/dump.js.map +1 -1
- package/dist/adapters/postgresql/tools/backup/planning.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/backup/planning.js +175 -172
- package/dist/adapters/postgresql/tools/backup/planning.js.map +1 -1
- package/dist/adapters/postgresql/tools/citext.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/citext.js +221 -163
- package/dist/adapters/postgresql/tools/citext.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/convenience.d.ts +9 -1
- package/dist/adapters/postgresql/tools/core/convenience.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/convenience.js +96 -9
- package/dist/adapters/postgresql/tools/core/convenience.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/error-helpers.d.ts +48 -0
- package/dist/adapters/postgresql/tools/core/error-helpers.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/error-helpers.js +256 -0
- package/dist/adapters/postgresql/tools/core/error-helpers.js.map +1 -0
- package/dist/adapters/postgresql/tools/core/health.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/health.js +23 -6
- package/dist/adapters/postgresql/tools/core/health.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/indexes.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/indexes.js +45 -4
- package/dist/adapters/postgresql/tools/core/indexes.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/objects.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/objects.js +104 -85
- package/dist/adapters/postgresql/tools/core/objects.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/query.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/query.js +100 -42
- package/dist/adapters/postgresql/tools/core/query.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/schemas.d.ts +52 -25
- package/dist/adapters/postgresql/tools/core/schemas.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/schemas.js +55 -25
- package/dist/adapters/postgresql/tools/core/schemas.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/tables.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/tables.js +74 -30
- package/dist/adapters/postgresql/tools/core/tables.js.map +1 -1
- package/dist/adapters/postgresql/tools/cron.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/cron.js +274 -179
- package/dist/adapters/postgresql/tools/cron.js.map +1 -1
- package/dist/adapters/postgresql/tools/jsonb/advanced.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/jsonb/advanced.js +372 -284
- package/dist/adapters/postgresql/tools/jsonb/advanced.js.map +1 -1
- package/dist/adapters/postgresql/tools/jsonb/basic.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/jsonb/basic.js +617 -398
- package/dist/adapters/postgresql/tools/jsonb/basic.js.map +1 -1
- package/dist/adapters/postgresql/tools/kcache.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/kcache.js +282 -220
- package/dist/adapters/postgresql/tools/kcache.js.map +1 -1
- package/dist/adapters/postgresql/tools/ltree.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/ltree.js +126 -35
- package/dist/adapters/postgresql/tools/ltree.js.map +1 -1
- package/dist/adapters/postgresql/tools/monitoring.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/monitoring.js +59 -40
- package/dist/adapters/postgresql/tools/monitoring.js.map +1 -1
- package/dist/adapters/postgresql/tools/partitioning.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/partitioning.js +150 -15
- package/dist/adapters/postgresql/tools/partitioning.js.map +1 -1
- package/dist/adapters/postgresql/tools/partman/management.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/partman/management.js +12 -5
- package/dist/adapters/postgresql/tools/partman/management.js.map +1 -1
- package/dist/adapters/postgresql/tools/partman/operations.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/partman/operations.js +135 -22
- package/dist/adapters/postgresql/tools/partman/operations.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/analysis.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/analysis.js +264 -160
- package/dist/adapters/postgresql/tools/performance/analysis.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/explain.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/explain.js +61 -21
- package/dist/adapters/postgresql/tools/performance/explain.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/monitoring.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/monitoring.js +44 -7
- package/dist/adapters/postgresql/tools/performance/monitoring.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/optimization.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/optimization.js +92 -81
- package/dist/adapters/postgresql/tools/performance/optimization.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/stats.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/stats.js +128 -37
- package/dist/adapters/postgresql/tools/performance/stats.js.map +1 -1
- package/dist/adapters/postgresql/tools/pgcrypto.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/pgcrypto.js +242 -87
- package/dist/adapters/postgresql/tools/pgcrypto.js.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/advanced.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/advanced.js +293 -201
- package/dist/adapters/postgresql/tools/postgis/advanced.js.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/basic.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/basic.js +359 -249
- package/dist/adapters/postgresql/tools/postgis/basic.js.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/standalone.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/standalone.js +135 -51
- package/dist/adapters/postgresql/tools/postgis/standalone.js.map +1 -1
- package/dist/adapters/postgresql/tools/schema.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/schema.js +515 -226
- package/dist/adapters/postgresql/tools/schema.js.map +1 -1
- package/dist/adapters/postgresql/tools/stats/advanced.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/stats/advanced.js +515 -476
- package/dist/adapters/postgresql/tools/stats/advanced.js.map +1 -1
- package/dist/adapters/postgresql/tools/stats/basic.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/stats/basic.js +302 -293
- package/dist/adapters/postgresql/tools/stats/basic.js.map +1 -1
- package/dist/adapters/postgresql/tools/text.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/text.js +398 -220
- package/dist/adapters/postgresql/tools/text.js.map +1 -1
- package/dist/adapters/postgresql/tools/transactions.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/transactions.js +157 -50
- package/dist/adapters/postgresql/tools/transactions.js.map +1 -1
- package/dist/adapters/postgresql/tools/vector/advanced.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/vector/advanced.js +70 -38
- package/dist/adapters/postgresql/tools/vector/advanced.js.map +1 -1
- package/dist/adapters/postgresql/tools/vector/basic.d.ts +8 -0
- package/dist/adapters/postgresql/tools/vector/basic.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/vector/basic.js +194 -82
- package/dist/adapters/postgresql/tools/vector/basic.js.map +1 -1
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +15 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli.js +7 -6
- package/dist/cli.js.map +1 -1
- package/dist/codemode/api.d.ts.map +1 -1
- package/dist/codemode/api.js +4 -3
- package/dist/codemode/api.js.map +1 -1
- package/dist/constants/ServerInstructions.d.ts +1 -1
- package/dist/constants/ServerInstructions.d.ts.map +1 -1
- package/dist/constants/ServerInstructions.js +76 -34
- package/dist/constants/ServerInstructions.js.map +1 -1
- package/dist/filtering/ToolConstants.d.ts +29 -13
- package/dist/filtering/ToolConstants.d.ts.map +1 -1
- package/dist/filtering/ToolConstants.js +44 -27
- package/dist/filtering/ToolConstants.js.map +1 -1
- package/dist/utils/logger.js +2 -2
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/progress-utils.js +1 -1
- package/dist/utils/progress-utils.js.map +1 -1
- package/package.json +13 -9
|
@@ -14,11 +14,10 @@
|
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
import { readOnly, write, destructive } from "../../../utils/annotations.js";
|
|
16
16
|
import { getToolIcons } from "../../../utils/icons.js";
|
|
17
|
-
import {
|
|
17
|
+
import { formatPostgresError } from "./core/error-helpers.js";
|
|
18
|
+
import { KcacheQueryStatsSchemaBase, KcacheQueryStatsSchema, KcacheTopCpuSchemaBase, KcacheTopIoSchemaBase, KcacheDatabaseStatsSchemaBase, KcacheDatabaseStatsSchema, KcacheResourceAnalysisSchemaBase, KcacheResourceAnalysisSchema,
|
|
18
19
|
// Output schemas
|
|
19
20
|
KcacheCreateExtensionOutputSchema, KcacheQueryStatsOutputSchema, KcacheTopCpuOutputSchema, KcacheTopIoOutputSchema, KcacheDatabaseStatsOutputSchema, KcacheResourceAnalysisOutputSchema, KcacheResetOutputSchema, } from "../schemas/index.js";
|
|
20
|
-
// Helper to handle undefined params (allows tools to be called without {})
|
|
21
|
-
const defaultToEmpty = (val) => val ?? {};
|
|
22
21
|
async function getKcacheColumnNames(adapter) {
|
|
23
22
|
const result = await adapter.executeQuery(`
|
|
24
23
|
SELECT column_name FROM information_schema.columns
|
|
@@ -105,37 +104,52 @@ Joins pg_stat_statements with pg_stat_kcache to show what SQL did AND what syste
|
|
|
105
104
|
|
|
106
105
|
orderBy options: 'total_time' (default), 'cpu_time', 'reads', 'writes'. Use minCalls parameter to filter by call count.`,
|
|
107
106
|
group: "kcache",
|
|
108
|
-
inputSchema:
|
|
107
|
+
inputSchema: KcacheQueryStatsSchemaBase,
|
|
109
108
|
outputSchema: KcacheQueryStatsOutputSchema,
|
|
110
109
|
annotations: readOnly("Kcache Query Stats"),
|
|
111
110
|
icons: getToolIcons("kcache", readOnly("Kcache Query Stats")),
|
|
112
111
|
handler: async (params, _context) => {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
112
|
+
try {
|
|
113
|
+
const { limit, orderBy, minCalls, queryPreviewLength } = KcacheQueryStatsSchema.parse(params);
|
|
114
|
+
// Validate orderBy inside handler for structured error response
|
|
115
|
+
const VALID_ORDER_BY = [
|
|
116
|
+
"total_time",
|
|
117
|
+
"cpu_time",
|
|
118
|
+
"reads",
|
|
119
|
+
"writes",
|
|
120
|
+
];
|
|
121
|
+
if (orderBy !== undefined &&
|
|
122
|
+
!VALID_ORDER_BY.includes(orderBy)) {
|
|
123
|
+
return {
|
|
124
|
+
success: false,
|
|
125
|
+
error: `Invalid orderBy value "${orderBy}". Valid options: ${VALID_ORDER_BY.join(", ")}`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const cols = await getKcacheColumnNames(adapter);
|
|
129
|
+
const DEFAULT_LIMIT = 20;
|
|
130
|
+
// limit: 0 means "no limit" (return all rows), undefined means use default
|
|
131
|
+
const limitVal = limit === 0 ? null : (limit ?? DEFAULT_LIMIT);
|
|
132
|
+
// Bound queryPreviewLength: 0 = full query, default 100, max 500
|
|
133
|
+
const previewLen = queryPreviewLength === 0
|
|
134
|
+
? 10000
|
|
135
|
+
: Math.min(queryPreviewLength ?? 100, 500);
|
|
136
|
+
const orderColumn = orderBy === "cpu_time"
|
|
137
|
+
? `(k.${cols.userTime} + k.${cols.systemTime})`
|
|
138
|
+
: orderBy === "reads"
|
|
139
|
+
? `k.${cols.reads}`
|
|
140
|
+
: orderBy === "writes"
|
|
141
|
+
? `k.${cols.writes}`
|
|
142
|
+
: "s.total_exec_time";
|
|
143
|
+
const conditions = [];
|
|
144
|
+
const queryParams = [];
|
|
145
|
+
const paramIndex = 1;
|
|
146
|
+
if (minCalls !== undefined) {
|
|
147
|
+
conditions.push(`s.calls >= $${String(paramIndex)}`);
|
|
148
|
+
queryParams.push(minCalls);
|
|
149
|
+
}
|
|
150
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
151
|
+
// Get total count first for truncation indicator
|
|
152
|
+
const countSql = `
|
|
139
153
|
SELECT COUNT(*) as total
|
|
140
154
|
FROM pg_stat_statements s
|
|
141
155
|
JOIN pg_stat_kcache() k ON s.queryid = k.queryid
|
|
@@ -143,10 +157,10 @@ orderBy options: 'total_time' (default), 'cpu_time', 'reads', 'writes'. Use minC
|
|
|
143
157
|
AND s.dbid = k.dbid
|
|
144
158
|
${whereClause}
|
|
145
159
|
`;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
160
|
+
const countResult = await adapter.executeQuery(countSql, queryParams);
|
|
161
|
+
const totalRaw = countResult.rows?.[0]?.["total"];
|
|
162
|
+
const totalCount = Number(totalRaw) || 0;
|
|
163
|
+
const sql = `
|
|
150
164
|
SELECT
|
|
151
165
|
s.queryid,
|
|
152
166
|
LEFT(s.query, ${String(previewLen)}) as query_preview,
|
|
@@ -170,17 +184,25 @@ orderBy options: 'total_time' (default), 'cpu_time', 'reads', 'writes'. Use minC
|
|
|
170
184
|
ORDER BY ${orderColumn} DESC
|
|
171
185
|
${limitVal !== null ? `LIMIT ${String(limitVal)}` : ""}
|
|
172
186
|
`;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
187
|
+
const result = await adapter.executeQuery(sql, queryParams);
|
|
188
|
+
const rowCount = result.rows?.length ?? 0;
|
|
189
|
+
const effectiveTotalCount = Math.max(totalCount, rowCount);
|
|
190
|
+
const truncated = rowCount < effectiveTotalCount;
|
|
191
|
+
const response = {
|
|
192
|
+
queries: result.rows ?? [],
|
|
193
|
+
count: rowCount,
|
|
194
|
+
orderBy: orderBy ?? "total_time",
|
|
195
|
+
truncated,
|
|
196
|
+
totalCount: effectiveTotalCount,
|
|
197
|
+
};
|
|
198
|
+
return response;
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
return {
|
|
202
|
+
success: false,
|
|
203
|
+
error: formatPostgresError(error, { tool: "pg_kcache_query_stats" }),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
184
206
|
},
|
|
185
207
|
};
|
|
186
208
|
}
|
|
@@ -193,25 +215,28 @@ function createKcacheTopCpuTool(adapter) {
|
|
|
193
215
|
description: `Get top CPU-consuming queries. Shows which queries spend the most time
|
|
194
216
|
in user CPU (application code) vs system CPU (kernel operations).`,
|
|
195
217
|
group: "kcache",
|
|
196
|
-
inputSchema:
|
|
197
|
-
limit: z
|
|
198
|
-
.number()
|
|
199
|
-
.optional()
|
|
200
|
-
.describe("Number of top queries to return (default: 10)"),
|
|
201
|
-
})),
|
|
218
|
+
inputSchema: KcacheTopCpuSchemaBase,
|
|
202
219
|
outputSchema: KcacheTopCpuOutputSchema,
|
|
203
220
|
annotations: readOnly("Kcache Top CPU"),
|
|
204
221
|
icons: getToolIcons("kcache", readOnly("Kcache Top CPU")),
|
|
205
222
|
handler: async (params, _context) => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
223
|
+
try {
|
|
224
|
+
const parsed = z
|
|
225
|
+
.object({
|
|
226
|
+
limit: z.number().optional(),
|
|
227
|
+
queryPreviewLength: z.number().optional(),
|
|
228
|
+
})
|
|
229
|
+
.parse(params ?? {});
|
|
230
|
+
const DEFAULT_LIMIT = 10;
|
|
231
|
+
// limit: 0 means "no limit" (return all rows), undefined means use default
|
|
232
|
+
const limitVal = parsed.limit === 0 ? null : (parsed.limit ?? DEFAULT_LIMIT);
|
|
233
|
+
// Bound queryPreviewLength: 0 = full query, default 100, max 500
|
|
234
|
+
const previewLen = parsed.queryPreviewLength === 0
|
|
235
|
+
? 10000
|
|
236
|
+
: Math.min(parsed.queryPreviewLength ?? 100, 500);
|
|
237
|
+
const cols = await getKcacheColumnNames(adapter);
|
|
238
|
+
// Get total count first for truncation indicator
|
|
239
|
+
const countSql = `
|
|
215
240
|
SELECT COUNT(*) as total
|
|
216
241
|
FROM pg_stat_statements s
|
|
217
242
|
JOIN pg_stat_kcache() k ON s.queryid = k.queryid
|
|
@@ -219,13 +244,13 @@ in user CPU (application code) vs system CPU (kernel operations).`,
|
|
|
219
244
|
AND s.dbid = k.dbid
|
|
220
245
|
WHERE (k.${cols.userTime} + k.${cols.systemTime}) > 0
|
|
221
246
|
`;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
247
|
+
const countResult = await adapter.executeQuery(countSql);
|
|
248
|
+
const totalRaw = countResult.rows?.[0]?.["total"];
|
|
249
|
+
const totalCount = Number(totalRaw) || 0;
|
|
250
|
+
const sql = `
|
|
226
251
|
SELECT
|
|
227
252
|
s.queryid,
|
|
228
|
-
LEFT(s.query,
|
|
253
|
+
LEFT(s.query, ${String(previewLen)}) as query_preview,
|
|
229
254
|
s.calls,
|
|
230
255
|
k.${cols.userTime} as user_time,
|
|
231
256
|
k.${cols.systemTime} as system_time,
|
|
@@ -249,17 +274,25 @@ in user CPU (application code) vs system CPU (kernel operations).`,
|
|
|
249
274
|
ORDER BY (k.${cols.userTime} + k.${cols.systemTime}) DESC
|
|
250
275
|
${limitVal !== null ? `LIMIT ${String(limitVal)}` : ""}
|
|
251
276
|
`;
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
277
|
+
const result = await adapter.executeQuery(sql);
|
|
278
|
+
const rowCount = result.rows?.length ?? 0;
|
|
279
|
+
const effectiveTotalCount = Math.max(totalCount, rowCount);
|
|
280
|
+
const truncated = rowCount < effectiveTotalCount;
|
|
281
|
+
const response = {
|
|
282
|
+
topCpuQueries: result.rows ?? [],
|
|
283
|
+
count: rowCount,
|
|
284
|
+
description: "Queries ranked by total CPU time (user + system)",
|
|
285
|
+
truncated,
|
|
286
|
+
totalCount: effectiveTotalCount,
|
|
287
|
+
};
|
|
288
|
+
return response;
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
return {
|
|
292
|
+
success: false,
|
|
293
|
+
error: formatPostgresError(error, { tool: "pg_kcache_top_cpu" }),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
263
296
|
},
|
|
264
297
|
};
|
|
265
298
|
}
|
|
@@ -272,71 +305,63 @@ function createKcacheTopIoTool(adapter) {
|
|
|
272
305
|
description: `Get top I/O-consuming queries. Shows filesystem-level reads and writes,
|
|
273
306
|
which represent actual disk access (not just shared buffer hits).`,
|
|
274
307
|
group: "kcache",
|
|
275
|
-
inputSchema:
|
|
276
|
-
const obj = defaultToEmpty(input);
|
|
277
|
-
// Alias: ioType -> type
|
|
278
|
-
if (obj["ioType"] !== undefined && obj["type"] === undefined) {
|
|
279
|
-
obj["type"] = obj["ioType"];
|
|
280
|
-
}
|
|
281
|
-
return obj;
|
|
282
|
-
}, z.object({
|
|
283
|
-
type: z
|
|
284
|
-
.enum(["reads", "writes", "both"])
|
|
285
|
-
.optional()
|
|
286
|
-
.describe("I/O type to rank by (default: both)"),
|
|
287
|
-
ioType: z
|
|
288
|
-
.enum(["reads", "writes", "both"])
|
|
289
|
-
.optional()
|
|
290
|
-
.describe("Alias for type"),
|
|
291
|
-
limit: z
|
|
292
|
-
.number()
|
|
293
|
-
.optional()
|
|
294
|
-
.describe("Number of top queries to return (default: 10)"),
|
|
295
|
-
})),
|
|
308
|
+
inputSchema: KcacheTopIoSchemaBase,
|
|
296
309
|
outputSchema: KcacheTopIoOutputSchema,
|
|
297
310
|
annotations: readOnly("Kcache Top IO"),
|
|
298
311
|
icons: getToolIcons("kcache", readOnly("Kcache Top IO")),
|
|
299
312
|
handler: async (params, _context) => {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
?
|
|
323
|
-
:
|
|
324
|
-
|
|
325
|
-
|
|
313
|
+
try {
|
|
314
|
+
// Apply the same preprocessing as inputSchema
|
|
315
|
+
const preprocessed = (() => {
|
|
316
|
+
const obj = (params ?? {});
|
|
317
|
+
if (obj["ioType"] !== undefined && obj["type"] === undefined) {
|
|
318
|
+
return { ...obj, type: obj["ioType"] };
|
|
319
|
+
}
|
|
320
|
+
return obj;
|
|
321
|
+
})();
|
|
322
|
+
const parsed = z
|
|
323
|
+
.object({
|
|
324
|
+
type: z.enum(["reads", "writes", "both"]).optional(),
|
|
325
|
+
limit: z.number().optional(),
|
|
326
|
+
queryPreviewLength: z.number().optional(),
|
|
327
|
+
})
|
|
328
|
+
.parse(preprocessed);
|
|
329
|
+
const ioType = parsed.type ?? "both";
|
|
330
|
+
const DEFAULT_LIMIT = 10;
|
|
331
|
+
// limit: 0 means "no limit" (return all rows), undefined means use default
|
|
332
|
+
const limitVal = parsed.limit === 0 ? null : (parsed.limit ?? DEFAULT_LIMIT);
|
|
333
|
+
// Bound queryPreviewLength: 0 = full query, default 100, max 500
|
|
334
|
+
const previewLen = parsed.queryPreviewLength === 0
|
|
335
|
+
? 10000
|
|
336
|
+
: Math.min(parsed.queryPreviewLength ?? 100, 500);
|
|
337
|
+
const cols = await getKcacheColumnNames(adapter);
|
|
338
|
+
const orderColumn = ioType === "reads"
|
|
339
|
+
? `k.${cols.reads}`
|
|
340
|
+
: ioType === "writes"
|
|
341
|
+
? `k.${cols.writes}`
|
|
342
|
+
: `(k.${cols.reads} + k.${cols.writes})`;
|
|
343
|
+
// Filter by the type-specific IO column so 'reads' excludes write-only queries
|
|
344
|
+
const ioFilter = ioType === "reads"
|
|
345
|
+
? `k.${cols.reads} > 0`
|
|
346
|
+
: ioType === "writes"
|
|
347
|
+
? `k.${cols.writes} > 0`
|
|
348
|
+
: `(k.${cols.reads} + k.${cols.writes}) > 0`;
|
|
349
|
+
// Get total count first for truncation indicator
|
|
350
|
+
const countSql = `
|
|
326
351
|
SELECT COUNT(*) as total
|
|
327
352
|
FROM pg_stat_statements s
|
|
328
353
|
JOIN pg_stat_kcache() k ON s.queryid = k.queryid
|
|
329
354
|
AND s.userid = k.userid
|
|
330
355
|
AND s.dbid = k.dbid
|
|
331
|
-
WHERE
|
|
356
|
+
WHERE ${ioFilter}
|
|
332
357
|
`;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
358
|
+
const countResult = await adapter.executeQuery(countSql);
|
|
359
|
+
const totalRaw = countResult.rows?.[0]?.["total"];
|
|
360
|
+
const totalCount = Number(totalRaw) || 0;
|
|
361
|
+
const sql = `
|
|
337
362
|
SELECT
|
|
338
363
|
s.queryid,
|
|
339
|
-
LEFT(s.query,
|
|
364
|
+
LEFT(s.query, ${String(previewLen)}) as query_preview,
|
|
340
365
|
s.calls,
|
|
341
366
|
k.${cols.reads} as read_bytes,
|
|
342
367
|
k.${cols.writes} as write_bytes,
|
|
@@ -348,22 +373,30 @@ which represent actual disk access (not just shared buffer hits).`,
|
|
|
348
373
|
JOIN pg_stat_kcache() k ON s.queryid = k.queryid
|
|
349
374
|
AND s.userid = k.userid
|
|
350
375
|
AND s.dbid = k.dbid
|
|
351
|
-
WHERE
|
|
376
|
+
WHERE ${ioFilter}
|
|
352
377
|
ORDER BY ${orderColumn} DESC
|
|
353
378
|
${limitVal !== null ? `LIMIT ${String(limitVal)}` : ""}
|
|
354
379
|
`;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
380
|
+
const result = await adapter.executeQuery(sql);
|
|
381
|
+
const rowCount = result.rows?.length ?? 0;
|
|
382
|
+
const effectiveTotalCount = Math.max(totalCount, rowCount);
|
|
383
|
+
const truncated = rowCount < effectiveTotalCount;
|
|
384
|
+
const response = {
|
|
385
|
+
topIoQueries: result.rows ?? [],
|
|
386
|
+
count: rowCount,
|
|
387
|
+
ioType,
|
|
388
|
+
description: `Queries ranked by ${ioType === "both" ? "total I/O" : ioType}`,
|
|
389
|
+
truncated,
|
|
390
|
+
totalCount: effectiveTotalCount,
|
|
391
|
+
};
|
|
392
|
+
return response;
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
return {
|
|
396
|
+
success: false,
|
|
397
|
+
error: formatPostgresError(error, { tool: "pg_kcache_top_io" }),
|
|
398
|
+
};
|
|
399
|
+
}
|
|
367
400
|
},
|
|
368
401
|
};
|
|
369
402
|
}
|
|
@@ -376,17 +409,18 @@ function createKcacheDatabaseStatsTool(adapter) {
|
|
|
376
409
|
description: `Get aggregated OS-level statistics for a database.
|
|
377
410
|
Shows total CPU time, I/O, and page faults across all queries.`,
|
|
378
411
|
group: "kcache",
|
|
379
|
-
inputSchema:
|
|
412
|
+
inputSchema: KcacheDatabaseStatsSchemaBase,
|
|
380
413
|
outputSchema: KcacheDatabaseStatsOutputSchema,
|
|
381
414
|
annotations: readOnly("Kcache Database Stats"),
|
|
382
415
|
icons: getToolIcons("kcache", readOnly("Kcache Database Stats")),
|
|
383
416
|
handler: async (params, _context) => {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
417
|
+
try {
|
|
418
|
+
const { database } = KcacheDatabaseStatsSchema.parse(params);
|
|
419
|
+
const cols = await getKcacheColumnNames(adapter);
|
|
420
|
+
let sql;
|
|
421
|
+
const queryParams = [];
|
|
422
|
+
if (database !== undefined) {
|
|
423
|
+
sql = `
|
|
390
424
|
SELECT
|
|
391
425
|
d.datname as database,
|
|
392
426
|
SUM(k.${cols.userTime}) as total_user_time,
|
|
@@ -404,10 +438,10 @@ Shows total CPU time, I/O, and page faults across all queries.`,
|
|
|
404
438
|
WHERE d.datname = $1
|
|
405
439
|
GROUP BY d.datname
|
|
406
440
|
`;
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
441
|
+
queryParams.push(database);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
sql = `
|
|
411
445
|
SELECT
|
|
412
446
|
datname as database,
|
|
413
447
|
SUM(${cols.userTime}) as total_user_time,
|
|
@@ -424,12 +458,21 @@ Shows total CPU time, I/O, and page faults across all queries.`,
|
|
|
424
458
|
GROUP BY datname
|
|
425
459
|
ORDER BY SUM(${cols.userTime} + ${cols.systemTime}) DESC
|
|
426
460
|
`;
|
|
461
|
+
}
|
|
462
|
+
const result = await adapter.executeQuery(sql, queryParams);
|
|
463
|
+
return {
|
|
464
|
+
databaseStats: result.rows ?? [],
|
|
465
|
+
count: result.rows?.length ?? 0,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
catch (error) {
|
|
469
|
+
return {
|
|
470
|
+
success: false,
|
|
471
|
+
error: formatPostgresError(error, {
|
|
472
|
+
tool: "pg_kcache_database_stats",
|
|
473
|
+
}),
|
|
474
|
+
};
|
|
427
475
|
}
|
|
428
|
-
const result = await adapter.executeQuery(sql, queryParams);
|
|
429
|
-
return {
|
|
430
|
-
databaseStats: result.rows ?? [],
|
|
431
|
-
count: result.rows?.length ?? 0,
|
|
432
|
-
};
|
|
433
476
|
},
|
|
434
477
|
};
|
|
435
478
|
}
|
|
@@ -442,36 +485,37 @@ function createKcacheResourceAnalysisTool(adapter) {
|
|
|
442
485
|
description: `Analyze queries to classify them as CPU-bound, I/O-bound, or balanced.
|
|
443
486
|
Helps identify the root cause of performance issues - is the query computation-heavy or disk-heavy?`,
|
|
444
487
|
group: "kcache",
|
|
445
|
-
inputSchema:
|
|
488
|
+
inputSchema: KcacheResourceAnalysisSchemaBase,
|
|
446
489
|
outputSchema: KcacheResourceAnalysisOutputSchema,
|
|
447
490
|
annotations: readOnly("Kcache Resource Analysis"),
|
|
448
491
|
icons: getToolIcons("kcache", readOnly("Kcache Resource Analysis")),
|
|
449
492
|
handler: async (params, _context) => {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
493
|
+
try {
|
|
494
|
+
const { queryId, threshold, limit, minCalls, queryPreviewLength } = KcacheResourceAnalysisSchema.parse(params);
|
|
495
|
+
const thresholdVal = threshold ?? 0.5;
|
|
496
|
+
const DEFAULT_LIMIT = 20;
|
|
497
|
+
// limit: 0 means "no limit" (return all rows), undefined means use default
|
|
498
|
+
const limitVal = limit === 0 ? null : (limit ?? DEFAULT_LIMIT);
|
|
499
|
+
// Bound queryPreviewLength: 0 = full query, default 100, max 500
|
|
500
|
+
const previewLen = queryPreviewLength === 0
|
|
501
|
+
? 10000
|
|
502
|
+
: Math.min(queryPreviewLength ?? 100, 500);
|
|
503
|
+
const cols = await getKcacheColumnNames(adapter);
|
|
504
|
+
const conditions = [];
|
|
505
|
+
const queryParams = [];
|
|
506
|
+
let paramIndex = 1;
|
|
507
|
+
if (queryId !== undefined) {
|
|
508
|
+
conditions.push(`s.queryid::text = $${String(paramIndex++)}`);
|
|
509
|
+
queryParams.push(queryId);
|
|
510
|
+
}
|
|
511
|
+
if (minCalls !== undefined) {
|
|
512
|
+
conditions.push(`s.calls >= $${String(paramIndex)}`);
|
|
513
|
+
queryParams.push(minCalls);
|
|
514
|
+
}
|
|
515
|
+
conditions.push(`(k.${cols.userTime} + k.${cols.systemTime} + k.${cols.reads} + k.${cols.writes}) > 0`);
|
|
516
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
517
|
+
// Get total count first for truncation indicator
|
|
518
|
+
const countSql = `
|
|
475
519
|
SELECT COUNT(*) as total
|
|
476
520
|
FROM pg_stat_statements s
|
|
477
521
|
JOIN pg_stat_kcache() k ON s.queryid = k.queryid
|
|
@@ -479,10 +523,10 @@ Helps identify the root cause of performance issues - is the query computation-h
|
|
|
479
523
|
AND s.dbid = k.dbid
|
|
480
524
|
${whereClause}
|
|
481
525
|
`;
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
526
|
+
const countResult = await adapter.executeQuery(countSql, queryParams);
|
|
527
|
+
const totalRaw = countResult.rows?.[0]?.["total"];
|
|
528
|
+
const totalCount = Number(totalRaw) || 0;
|
|
529
|
+
const sql = `
|
|
486
530
|
WITH query_metrics AS (
|
|
487
531
|
SELECT
|
|
488
532
|
s.queryid,
|
|
@@ -528,32 +572,42 @@ Helps identify the root cause of performance issues - is the query computation-h
|
|
|
528
572
|
ORDER BY total_time_ms DESC
|
|
529
573
|
${limitVal !== null ? `LIMIT ${String(limitVal)}` : ""}
|
|
530
574
|
`;
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
575
|
+
const result = await adapter.executeQuery(sql, queryParams);
|
|
576
|
+
const rows = result.rows ?? [];
|
|
577
|
+
const effectiveTotalCount = Math.max(totalCount, rows.length);
|
|
578
|
+
const truncated = rows.length < effectiveTotalCount;
|
|
579
|
+
const cpuBound = rows.filter((r) => r["resource_classification"] === "CPU-bound").length;
|
|
580
|
+
const ioBound = rows.filter((r) => r["resource_classification"] === "I/O-bound").length;
|
|
581
|
+
const balanced = rows.filter((r) => r["resource_classification"] === "Balanced").length;
|
|
582
|
+
const response = {
|
|
583
|
+
queries: rows,
|
|
584
|
+
count: rows.length,
|
|
585
|
+
summary: {
|
|
586
|
+
cpuBound,
|
|
587
|
+
ioBound,
|
|
588
|
+
balanced,
|
|
589
|
+
threshold: thresholdVal,
|
|
590
|
+
},
|
|
591
|
+
recommendations: [
|
|
592
|
+
cpuBound > ioBound
|
|
593
|
+
? "Most resource-intensive queries are CPU-bound. Consider query optimization or more CPU resources."
|
|
594
|
+
: ioBound > cpuBound
|
|
595
|
+
? "Most resource-intensive queries are I/O-bound. Consider more memory, faster storage, or better indexing."
|
|
596
|
+
: "Resource usage is balanced between CPU and I/O.",
|
|
597
|
+
],
|
|
598
|
+
truncated,
|
|
599
|
+
totalCount: effectiveTotalCount,
|
|
600
|
+
};
|
|
601
|
+
return response;
|
|
602
|
+
}
|
|
603
|
+
catch (error) {
|
|
604
|
+
return {
|
|
605
|
+
success: false,
|
|
606
|
+
error: formatPostgresError(error, {
|
|
607
|
+
tool: "pg_kcache_resource_analysis",
|
|
608
|
+
}),
|
|
609
|
+
};
|
|
610
|
+
}
|
|
557
611
|
},
|
|
558
612
|
};
|
|
559
613
|
}
|
|
@@ -571,12 +625,20 @@ Note: This also resets pg_stat_statements statistics.`,
|
|
|
571
625
|
annotations: destructive("Reset Kcache Stats"),
|
|
572
626
|
icons: getToolIcons("kcache", destructive("Reset Kcache Stats")),
|
|
573
627
|
handler: async (_params, _context) => {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
628
|
+
try {
|
|
629
|
+
await adapter.executeQuery("SELECT pg_stat_kcache_reset()");
|
|
630
|
+
return {
|
|
631
|
+
success: true,
|
|
632
|
+
message: "pg_stat_kcache statistics reset",
|
|
633
|
+
note: "pg_stat_statements statistics were also reset",
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
catch (error) {
|
|
637
|
+
return {
|
|
638
|
+
success: false,
|
|
639
|
+
error: formatPostgresError(error, { tool: "pg_kcache_reset" }),
|
|
640
|
+
};
|
|
641
|
+
}
|
|
580
642
|
},
|
|
581
643
|
};
|
|
582
644
|
}
|