@neverinfamous/postgres-mcp 2.1.0 → 2.2.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 +58 -52
- package/dist/__tests__/benchmarks/codemode.bench.js +3 -3
- package/dist/__tests__/benchmarks/codemode.bench.js.map +1 -1
- package/dist/__tests__/benchmarks/connection-pool.bench.js +3 -3
- package/dist/__tests__/benchmarks/connection-pool.bench.js.map +1 -1
- package/dist/__tests__/benchmarks/introspection-migration.bench.d.ts +11 -0
- package/dist/__tests__/benchmarks/introspection-migration.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/introspection-migration.bench.js +143 -0
- package/dist/__tests__/benchmarks/introspection-migration.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/resource-prompts.bench.js +0 -64
- package/dist/__tests__/benchmarks/resource-prompts.bench.js.map +1 -1
- package/dist/__tests__/benchmarks/schema-parsing.bench.js +4 -4
- package/dist/__tests__/benchmarks/schema-parsing.bench.js.map +1 -1
- package/dist/__tests__/benchmarks/tool-filtering.bench.js +17 -8
- package/dist/__tests__/benchmarks/tool-filtering.bench.js.map +1 -1
- package/dist/adapters/DatabaseAdapter.d.ts +0 -4
- package/dist/adapters/DatabaseAdapter.d.ts.map +1 -1
- package/dist/adapters/DatabaseAdapter.js +0 -13
- package/dist/adapters/DatabaseAdapter.js.map +1 -1
- package/dist/adapters/postgresql/PostgresAdapter.d.ts +0 -4
- package/dist/adapters/postgresql/PostgresAdapter.d.ts.map +1 -1
- package/dist/adapters/postgresql/PostgresAdapter.js +3 -6
- package/dist/adapters/postgresql/PostgresAdapter.js.map +1 -1
- package/dist/adapters/postgresql/schemas/core/queries.d.ts +4 -4
- package/dist/adapters/postgresql/schemas/introspection.d.ts +14 -37
- package/dist/adapters/postgresql/schemas/introspection.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/introspection.js +71 -29
- package/dist/adapters/postgresql/schemas/introspection.js.map +1 -1
- package/dist/adapters/postgresql/schemas/vector.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/vector.js +2 -4
- package/dist/adapters/postgresql/schemas/vector.js.map +1 -1
- package/dist/adapters/postgresql/tools/introspection/analysis.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/introspection/analysis.js +158 -127
- package/dist/adapters/postgresql/tools/introspection/analysis.js.map +1 -1
- package/dist/adapters/postgresql/tools/introspection/graph.d.ts +1 -1
- package/dist/adapters/postgresql/tools/introspection/graph.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/introspection/graph.js +12 -29
- package/dist/adapters/postgresql/tools/introspection/graph.js.map +1 -1
- package/dist/adapters/postgresql/tools/introspection/index.d.ts +9 -7
- package/dist/adapters/postgresql/tools/introspection/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/introspection/index.js +9 -14
- package/dist/adapters/postgresql/tools/introspection/index.js.map +1 -1
- package/dist/adapters/postgresql/tools/introspection/migration.d.ts +1 -1
- package/dist/adapters/postgresql/tools/introspection/migration.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/introspection/migration.js +62 -86
- package/dist/adapters/postgresql/tools/introspection/migration.js.map +1 -1
- package/dist/adapters/postgresql/tools/migration/index.d.ts +15 -0
- package/dist/adapters/postgresql/tools/migration/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/migration/index.js +23 -0
- package/dist/adapters/postgresql/tools/migration/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/performance/anomaly-detection.d.ts +18 -0
- package/dist/adapters/postgresql/tools/performance/anomaly-detection.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/performance/anomaly-detection.js +533 -0
- package/dist/adapters/postgresql/tools/performance/anomaly-detection.js.map +1 -0
- package/dist/adapters/postgresql/tools/performance/diagnostics.d.ts +11 -0
- package/dist/adapters/postgresql/tools/performance/diagnostics.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/performance/diagnostics.js +332 -0
- package/dist/adapters/postgresql/tools/performance/diagnostics.js.map +1 -0
- package/dist/adapters/postgresql/tools/performance/index.d.ts +1 -1
- package/dist/adapters/postgresql/tools/performance/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/index.js +7 -1
- package/dist/adapters/postgresql/tools/performance/index.js.map +1 -1
- package/dist/auth/scopes.d.ts.map +1 -1
- package/dist/auth/scopes.js +2 -0
- package/dist/auth/scopes.js.map +1 -1
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/dist/codemode/api/index.d.ts +1 -0
- package/dist/codemode/api/index.d.ts.map +1 -1
- package/dist/codemode/api/index.js +3 -0
- package/dist/codemode/api/index.js.map +1 -1
- package/dist/codemode/api/maps.d.ts.map +1 -1
- package/dist/codemode/api/maps.js +18 -12
- package/dist/codemode/api/maps.js.map +1 -1
- package/dist/filtering/ToolConstants.d.ts +11 -11
- package/dist/filtering/ToolConstants.d.ts.map +1 -1
- package/dist/filtering/ToolConstants.js +28 -15
- package/dist/filtering/ToolConstants.js.map +1 -1
- package/dist/filtering/ToolFilter.d.ts +0 -32
- package/dist/filtering/ToolFilter.d.ts.map +1 -1
- package/dist/filtering/ToolFilter.js +0 -43
- package/dist/filtering/ToolFilter.js.map +1 -1
- package/dist/transports/http.d.ts +12 -0
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +19 -1
- package/dist/transports/http.js.map +1 -1
- package/dist/types/filtering.d.ts +1 -1
- package/dist/types/filtering.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/mcp.d.ts +0 -21
- package/dist/types/mcp.d.ts.map +1 -1
- package/dist/types/schema.d.ts +0 -79
- package/dist/types/schema.d.ts.map +1 -1
- package/dist/utils/fts-config.d.ts +0 -6
- package/dist/utils/fts-config.d.ts.map +1 -1
- package/dist/utils/fts-config.js +1 -1
- package/dist/utils/fts-config.js.map +1 -1
- package/dist/utils/icons.d.ts.map +1 -1
- package/dist/utils/icons.js +5 -0
- package/dist/utils/icons.js.map +1 -1
- package/dist/utils/identifiers.d.ts.map +1 -1
- package/dist/utils/identifiers.js +6 -6
- package/dist/utils/identifiers.js.map +1 -1
- package/dist/utils/progress-utils.d.ts +1 -12
- package/dist/utils/progress-utils.d.ts.map +1 -1
- package/dist/utils/progress-utils.js +0 -18
- package/dist/utils/progress-utils.js.map +1 -1
- package/package.json +1 -1
- package/dist/utils/promptGenerator.d.ts +0 -20
- package/dist/utils/promptGenerator.d.ts.map +0 -1
- package/dist/utils/promptGenerator.js +0 -81
- package/dist/utils/promptGenerator.js.map +0 -1
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL Performance Tools - Anomaly Detection
|
|
3
|
+
*
|
|
4
|
+
* Lightweight anomaly detectors that compare current state against
|
|
5
|
+
* historical baselines using PostgreSQL system views. Returns risk
|
|
6
|
+
* scores, trend analysis, and actionable recommendations.
|
|
7
|
+
*
|
|
8
|
+
* Tools:
|
|
9
|
+
* - pg_detect_query_anomalies: z-score analysis via pg_stat_statements
|
|
10
|
+
* - pg_detect_bloat_risk: multi-factor bloat risk scoring
|
|
11
|
+
* - pg_detect_connection_spike: connection concentration detection
|
|
12
|
+
*/
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import { readOnly } from "../../../../utils/annotations.js";
|
|
15
|
+
import { getToolIcons } from "../../../../utils/icons.js";
|
|
16
|
+
import { formatPostgresError } from "../core/error-helpers.js";
|
|
17
|
+
const toNum = (val) => val === null || val === undefined ? 0 : Number(val);
|
|
18
|
+
const toStr = (val, fallback = "") => typeof val === "string" ? val : fallback;
|
|
19
|
+
function riskFromScore(score) {
|
|
20
|
+
if (score >= 80)
|
|
21
|
+
return "critical";
|
|
22
|
+
if (score >= 60)
|
|
23
|
+
return "high";
|
|
24
|
+
if (score >= 40)
|
|
25
|
+
return "moderate";
|
|
26
|
+
return "low";
|
|
27
|
+
}
|
|
28
|
+
// =============================================================================
|
|
29
|
+
// 1. pg_detect_query_anomalies
|
|
30
|
+
// =============================================================================
|
|
31
|
+
const QueryAnomaliesInputBase = z.object({
|
|
32
|
+
threshold: z
|
|
33
|
+
.any()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("Standard deviation multiplier for anomaly detection (default: 2.0)"),
|
|
36
|
+
minCalls: z
|
|
37
|
+
.any()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe("Minimum call count to filter noise (default: 10)"),
|
|
40
|
+
});
|
|
41
|
+
const QueryAnomaliesInput = QueryAnomaliesInputBase.transform((data) => ({
|
|
42
|
+
threshold: Math.max(0.5, Math.min(10, Number(data.threshold) || 2.0)),
|
|
43
|
+
minCalls: Math.max(1, Math.min(10000, Number(data.minCalls) || 10)),
|
|
44
|
+
}));
|
|
45
|
+
export function createDetectQueryAnomaliesTool(adapter) {
|
|
46
|
+
return {
|
|
47
|
+
name: "pg_detect_query_anomalies",
|
|
48
|
+
description: "Detects queries deviating from their historical execution time norms " +
|
|
49
|
+
"using z-score analysis. Requires pg_stat_statements extension. " +
|
|
50
|
+
"Returns anomalous queries ranked by deviation severity with risk level.",
|
|
51
|
+
inputSchema: QueryAnomaliesInputBase.shape,
|
|
52
|
+
outputSchema: z.object({
|
|
53
|
+
anomalies: z.array(z.any()),
|
|
54
|
+
riskLevel: z.enum(["low", "moderate", "high", "critical"]),
|
|
55
|
+
totalAnalyzed: z.number(),
|
|
56
|
+
anomalyCount: z.number(),
|
|
57
|
+
summary: z.string(),
|
|
58
|
+
}),
|
|
59
|
+
group: "performance",
|
|
60
|
+
annotations: readOnly("Detect query anomalies"),
|
|
61
|
+
icons: getToolIcons("performance", readOnly("Detect query anomalies")),
|
|
62
|
+
handler: async (params, _context) => {
|
|
63
|
+
try {
|
|
64
|
+
const parsed = QueryAnomaliesInput.safeParse(params);
|
|
65
|
+
if (!parsed.success) {
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
error: `Validation error: ${parsed.error.issues.map((i) => i.message).join(", ")}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const { threshold, minCalls } = parsed.data;
|
|
72
|
+
// Check if pg_stat_statements is available
|
|
73
|
+
const extCheck = await adapter.executeQuery(`SELECT 1 FROM pg_extension WHERE extname = 'pg_stat_statements'`);
|
|
74
|
+
if (!extCheck.rows || extCheck.rows.length === 0) {
|
|
75
|
+
return {
|
|
76
|
+
success: false,
|
|
77
|
+
error: "pg_stat_statements extension is not installed. " +
|
|
78
|
+
"Install with: CREATE EXTENSION pg_stat_statements; " +
|
|
79
|
+
"(requires shared_preload_libraries configuration)",
|
|
80
|
+
suggestion: "Use pg_diagnose_database_performance for baseline-free health checks",
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// Count total analyzed queries
|
|
84
|
+
const countResult = await adapter.executeQuery(`SELECT COUNT(*) AS total FROM pg_stat_statements WHERE calls >= ${String(minCalls)}`);
|
|
85
|
+
const totalAnalyzed = toNum(countResult.rows?.[0]?.["total"]);
|
|
86
|
+
// Find anomalous queries using z-score
|
|
87
|
+
const result = await adapter.executeQuery(`
|
|
88
|
+
SELECT
|
|
89
|
+
LEFT(query, 200) AS query_preview,
|
|
90
|
+
calls,
|
|
91
|
+
round(mean_exec_time::numeric, 3) AS mean_exec_time_ms,
|
|
92
|
+
round(stddev_exec_time::numeric, 3) AS stddev_exec_time_ms,
|
|
93
|
+
round((mean_exec_time / NULLIF(stddev_exec_time, 0))::numeric, 2) AS z_score,
|
|
94
|
+
round(total_exec_time::numeric, 2) AS total_exec_time_ms,
|
|
95
|
+
rows
|
|
96
|
+
FROM pg_stat_statements
|
|
97
|
+
WHERE calls >= ${String(minCalls)}
|
|
98
|
+
AND stddev_exec_time > 0
|
|
99
|
+
AND mean_exec_time > (stddev_exec_time * ${String(threshold)})
|
|
100
|
+
ORDER BY (mean_exec_time / NULLIF(stddev_exec_time, 0)) DESC
|
|
101
|
+
LIMIT 20
|
|
102
|
+
`);
|
|
103
|
+
const anomalies = (result.rows ?? []).map((row) => ({
|
|
104
|
+
queryPreview: toStr(row["query_preview"]),
|
|
105
|
+
calls: toNum(row["calls"]),
|
|
106
|
+
meanExecTimeMs: toNum(row["mean_exec_time_ms"]),
|
|
107
|
+
stddevExecTimeMs: toNum(row["stddev_exec_time_ms"]),
|
|
108
|
+
zScore: toNum(row["z_score"]),
|
|
109
|
+
totalExecTimeMs: toNum(row["total_exec_time_ms"]),
|
|
110
|
+
rows: toNum(row["rows"]),
|
|
111
|
+
}));
|
|
112
|
+
const anomalyCount = anomalies.length;
|
|
113
|
+
const maxZScore = anomalies.length > 0 ? (anomalies[0]?.zScore ?? 0) : 0;
|
|
114
|
+
// Risk based on count and severity
|
|
115
|
+
let riskScore = 0;
|
|
116
|
+
if (anomalyCount >= 10)
|
|
117
|
+
riskScore += 40;
|
|
118
|
+
else if (anomalyCount >= 5)
|
|
119
|
+
riskScore += 25;
|
|
120
|
+
else if (anomalyCount >= 1)
|
|
121
|
+
riskScore += 10;
|
|
122
|
+
if (maxZScore >= 10)
|
|
123
|
+
riskScore += 50;
|
|
124
|
+
else if (maxZScore >= 5)
|
|
125
|
+
riskScore += 30;
|
|
126
|
+
else if (maxZScore >= 3)
|
|
127
|
+
riskScore += 15;
|
|
128
|
+
const riskLevel = riskFromScore(riskScore);
|
|
129
|
+
const summary = anomalyCount === 0
|
|
130
|
+
? `No query anomalies detected (analyzed ${String(totalAnalyzed)} queries with threshold ${String(threshold)}σ)`
|
|
131
|
+
: `${String(anomalyCount)} anomalous queries detected out of ${String(totalAnalyzed)} analyzed (threshold: ${String(threshold)}σ, max z-score: ${String(maxZScore)})`;
|
|
132
|
+
return {
|
|
133
|
+
anomalies,
|
|
134
|
+
riskLevel,
|
|
135
|
+
totalAnalyzed,
|
|
136
|
+
anomalyCount,
|
|
137
|
+
summary,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
return {
|
|
142
|
+
success: false,
|
|
143
|
+
error: formatPostgresError(error, {
|
|
144
|
+
tool: "pg_detect_query_anomalies",
|
|
145
|
+
}),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
// =============================================================================
|
|
152
|
+
// 2. pg_detect_bloat_risk
|
|
153
|
+
// =============================================================================
|
|
154
|
+
const BloatRiskInputBase = z.object({
|
|
155
|
+
schema: z
|
|
156
|
+
.string()
|
|
157
|
+
.optional()
|
|
158
|
+
.describe("Filter to a specific schema (default: all user schemas)"),
|
|
159
|
+
minRows: z
|
|
160
|
+
.any()
|
|
161
|
+
.optional()
|
|
162
|
+
.describe("Minimum live rows to include (default: 1000)"),
|
|
163
|
+
});
|
|
164
|
+
const BloatRiskInput = BloatRiskInputBase.transform((data) => ({
|
|
165
|
+
schema: data.schema,
|
|
166
|
+
minRows: Math.max(0, Math.min(1000000, Number(data.minRows) || 1000)),
|
|
167
|
+
}));
|
|
168
|
+
export function createDetectBloatRiskTool(adapter) {
|
|
169
|
+
return {
|
|
170
|
+
name: "pg_detect_bloat_risk",
|
|
171
|
+
description: "Scores tables by bloat risk using multiple factors: dead tuple ratio, " +
|
|
172
|
+
"vacuum staleness, table size, and autovacuum effectiveness. " +
|
|
173
|
+
"Returns per-table risk scores (0-100) with actionable recommendations.",
|
|
174
|
+
inputSchema: BloatRiskInputBase.shape,
|
|
175
|
+
outputSchema: z.object({
|
|
176
|
+
tables: z.array(z.any()),
|
|
177
|
+
highRiskCount: z.number(),
|
|
178
|
+
totalAnalyzed: z.number(),
|
|
179
|
+
summary: z.string(),
|
|
180
|
+
}),
|
|
181
|
+
group: "performance",
|
|
182
|
+
annotations: readOnly("Detect bloat risk"),
|
|
183
|
+
icons: getToolIcons("performance", readOnly("Detect bloat risk")),
|
|
184
|
+
handler: async (params, _context) => {
|
|
185
|
+
try {
|
|
186
|
+
const parsed = BloatRiskInput.safeParse(params);
|
|
187
|
+
if (!parsed.success) {
|
|
188
|
+
return {
|
|
189
|
+
success: false,
|
|
190
|
+
error: `Validation error: ${parsed.error.issues.map((i) => i.message).join(", ")}`,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const { schema, minRows } = parsed.data;
|
|
194
|
+
const schemaFilter = schema
|
|
195
|
+
? `AND schemaname = '${schema.replace(/'/g, "''")}'`
|
|
196
|
+
: `AND schemaname NOT IN ('pg_catalog', 'information_schema', 'cron', 'topology', 'tiger', 'tiger_data')`;
|
|
197
|
+
const result = await adapter.executeQuery(`
|
|
198
|
+
SELECT
|
|
199
|
+
schemaname AS schema,
|
|
200
|
+
relname AS table_name,
|
|
201
|
+
n_live_tup AS live_tuples,
|
|
202
|
+
n_dead_tup AS dead_tuples,
|
|
203
|
+
CASE WHEN n_live_tup + n_dead_tup > 0
|
|
204
|
+
THEN round((100.0 * n_dead_tup / (n_live_tup + n_dead_tup))::numeric, 2)
|
|
205
|
+
ELSE 0
|
|
206
|
+
END AS dead_pct,
|
|
207
|
+
pg_size_pretty(pg_total_relation_size(schemaname || '.' || relname)) AS total_size,
|
|
208
|
+
pg_total_relation_size(schemaname || '.' || relname) AS total_bytes,
|
|
209
|
+
last_vacuum,
|
|
210
|
+
last_autovacuum,
|
|
211
|
+
last_analyze,
|
|
212
|
+
last_autoanalyze,
|
|
213
|
+
vacuum_count,
|
|
214
|
+
autovacuum_count,
|
|
215
|
+
autoanalyze_count,
|
|
216
|
+
EXTRACT(EPOCH FROM (now() - COALESCE(last_autovacuum, last_vacuum)))::int AS seconds_since_vacuum
|
|
217
|
+
FROM pg_stat_user_tables
|
|
218
|
+
WHERE n_live_tup >= ${String(minRows)}
|
|
219
|
+
${schemaFilter}
|
|
220
|
+
ORDER BY n_dead_tup DESC
|
|
221
|
+
LIMIT 50
|
|
222
|
+
`);
|
|
223
|
+
const rows = result.rows ?? [];
|
|
224
|
+
const tables = rows.map((row) => {
|
|
225
|
+
const liveTuples = toNum(row["live_tuples"]);
|
|
226
|
+
const deadTuples = toNum(row["dead_tuples"]);
|
|
227
|
+
const totalTuples = liveTuples + deadTuples;
|
|
228
|
+
const deadPct = toNum(row["dead_pct"]);
|
|
229
|
+
const totalBytes = toNum(row["total_bytes"]);
|
|
230
|
+
const secondsSinceVacuum = toNum(row["seconds_since_vacuum"]);
|
|
231
|
+
const autovacuumCount = toNum(row["autovacuum_count"]);
|
|
232
|
+
const autoanalyzeCount = toNum(row["autoanalyze_count"]);
|
|
233
|
+
// Risk scoring (0-100)
|
|
234
|
+
// Factor 1: Dead tuple ratio (35% weight)
|
|
235
|
+
let deadTupleScore = 0;
|
|
236
|
+
if (totalTuples > 0) {
|
|
237
|
+
const ratio = deadTuples / totalTuples;
|
|
238
|
+
if (ratio >= 0.5)
|
|
239
|
+
deadTupleScore = 100;
|
|
240
|
+
else if (ratio >= 0.3)
|
|
241
|
+
deadTupleScore = 80;
|
|
242
|
+
else if (ratio >= 0.1)
|
|
243
|
+
deadTupleScore = 50;
|
|
244
|
+
else if (ratio >= 0.05)
|
|
245
|
+
deadTupleScore = 25;
|
|
246
|
+
}
|
|
247
|
+
// Factor 2: Vacuum staleness (25% weight)
|
|
248
|
+
let vacuumStalenessScore = 0;
|
|
249
|
+
const hoursSinceVacuum = secondsSinceVacuum / 3600;
|
|
250
|
+
if (secondsSinceVacuum === 0 && deadTuples > 0) {
|
|
251
|
+
vacuumStalenessScore = 80; // Never vacuumed but has dead tuples
|
|
252
|
+
}
|
|
253
|
+
else if (hoursSinceVacuum >= 168) {
|
|
254
|
+
vacuumStalenessScore = 100; // > 7 days
|
|
255
|
+
}
|
|
256
|
+
else if (hoursSinceVacuum >= 72) {
|
|
257
|
+
vacuumStalenessScore = 70; // > 3 days
|
|
258
|
+
}
|
|
259
|
+
else if (hoursSinceVacuum >= 24) {
|
|
260
|
+
vacuumStalenessScore = 40; // > 1 day
|
|
261
|
+
}
|
|
262
|
+
// Factor 3: Table size blast radius (15% weight)
|
|
263
|
+
let sizeScore = 0;
|
|
264
|
+
const sizeMB = totalBytes / (1024 * 1024);
|
|
265
|
+
if (sizeMB >= 10000)
|
|
266
|
+
sizeScore = 100; // > 10 GB
|
|
267
|
+
else if (sizeMB >= 1000)
|
|
268
|
+
sizeScore = 70; // > 1 GB
|
|
269
|
+
else if (sizeMB >= 100)
|
|
270
|
+
sizeScore = 40; // > 100 MB
|
|
271
|
+
// Factor 4: Autovacuum effectiveness (25% weight)
|
|
272
|
+
let autovacuumScore = 0;
|
|
273
|
+
if (autovacuumCount === 0 && deadTuples > 0) {
|
|
274
|
+
autovacuumScore = 90; // Autovacuum never ran but has dead tuples
|
|
275
|
+
}
|
|
276
|
+
else if (autoanalyzeCount === 0 && liveTuples > 10000) {
|
|
277
|
+
autovacuumScore = 60; // Autoanalyze never ran on large table
|
|
278
|
+
}
|
|
279
|
+
const riskScore = Math.round(deadTupleScore * 0.35 +
|
|
280
|
+
vacuumStalenessScore * 0.25 +
|
|
281
|
+
sizeScore * 0.15 +
|
|
282
|
+
autovacuumScore * 0.25);
|
|
283
|
+
const recommendations = [];
|
|
284
|
+
if (deadPct >= 10) {
|
|
285
|
+
recommendations.push(`Run VACUUM ANALYZE on ${toStr(row["schema"])}.${toStr(row["table_name"])}`);
|
|
286
|
+
}
|
|
287
|
+
if (secondsSinceVacuum === 0 && deadTuples > 0) {
|
|
288
|
+
recommendations.push("Table has never been vacuumed — run VACUUM");
|
|
289
|
+
}
|
|
290
|
+
if (autovacuumCount === 0 && deadTuples > 1000) {
|
|
291
|
+
recommendations.push("Autovacuum has never run — check autovacuum settings");
|
|
292
|
+
}
|
|
293
|
+
if (hoursSinceVacuum >= 72 && deadTuples > 0) {
|
|
294
|
+
recommendations.push(`Last vacuum was ${String(Math.round(hoursSinceVacuum))}h ago — schedule more frequent vacuuming`);
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
schema: toStr(row["schema"]),
|
|
298
|
+
tableName: toStr(row["table_name"]),
|
|
299
|
+
liveTuples,
|
|
300
|
+
deadTuples,
|
|
301
|
+
deadPct,
|
|
302
|
+
totalSize: toStr(row["total_size"], "0 bytes"),
|
|
303
|
+
lastVacuum: row["last_vacuum"],
|
|
304
|
+
lastAutovacuum: row["last_autovacuum"],
|
|
305
|
+
hoursSinceVacuum: Math.round(hoursSinceVacuum),
|
|
306
|
+
autovacuumCount,
|
|
307
|
+
riskScore,
|
|
308
|
+
riskLevel: riskFromScore(riskScore),
|
|
309
|
+
factors: {
|
|
310
|
+
deadTupleRatio: Math.round(deadTupleScore * 0.35),
|
|
311
|
+
vacuumStaleness: Math.round(vacuumStalenessScore * 0.25),
|
|
312
|
+
tableSizeImpact: Math.round(sizeScore * 0.15),
|
|
313
|
+
autovacuumEffectiveness: Math.round(autovacuumScore * 0.25),
|
|
314
|
+
},
|
|
315
|
+
recommendations,
|
|
316
|
+
};
|
|
317
|
+
});
|
|
318
|
+
// Sort by risk score descending
|
|
319
|
+
tables.sort((a, b) => b.riskScore - a.riskScore);
|
|
320
|
+
const highRiskCount = tables.filter((t) => t.riskScore >= 60).length;
|
|
321
|
+
const summary = highRiskCount === 0
|
|
322
|
+
? `No high-risk bloat detected across ${String(tables.length)} tables`
|
|
323
|
+
: `${String(highRiskCount)} table(s) at high bloat risk out of ${String(tables.length)} analyzed`;
|
|
324
|
+
return {
|
|
325
|
+
tables,
|
|
326
|
+
highRiskCount,
|
|
327
|
+
totalAnalyzed: tables.length,
|
|
328
|
+
summary,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
return {
|
|
333
|
+
success: false,
|
|
334
|
+
error: formatPostgresError(error, {
|
|
335
|
+
tool: "pg_detect_bloat_risk",
|
|
336
|
+
}),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
// =============================================================================
|
|
343
|
+
// 3. pg_detect_connection_spike
|
|
344
|
+
// =============================================================================
|
|
345
|
+
const ConnectionSpikeInputBase = z.object({
|
|
346
|
+
warningPercent: z
|
|
347
|
+
.any()
|
|
348
|
+
.optional()
|
|
349
|
+
.describe("Percentage threshold for flagging concentration (default: 70)"),
|
|
350
|
+
});
|
|
351
|
+
const ConnectionSpikeInput = ConnectionSpikeInputBase.transform((data) => ({
|
|
352
|
+
warningPercent: Math.max(10, Math.min(100, Number(data.warningPercent) || 70)),
|
|
353
|
+
}));
|
|
354
|
+
export function createDetectConnectionSpikeTool(adapter) {
|
|
355
|
+
return {
|
|
356
|
+
name: "pg_detect_connection_spike",
|
|
357
|
+
description: "Detects unusual connection patterns by analyzing concentration " +
|
|
358
|
+
"by user, application, state, and wait events. Flags when a single " +
|
|
359
|
+
"user or application monopolizes the connection pool, or when " +
|
|
360
|
+
"idle-in-transaction connections accumulate.",
|
|
361
|
+
inputSchema: ConnectionSpikeInputBase.shape,
|
|
362
|
+
outputSchema: z.object({
|
|
363
|
+
totalConnections: z.number(),
|
|
364
|
+
maxConnections: z.number(),
|
|
365
|
+
usagePercent: z.number(),
|
|
366
|
+
byState: z.array(z.any()),
|
|
367
|
+
concentrations: z.array(z.any()),
|
|
368
|
+
warnings: z.array(z.string()),
|
|
369
|
+
riskLevel: z.enum(["low", "moderate", "high", "critical"]),
|
|
370
|
+
summary: z.string(),
|
|
371
|
+
}),
|
|
372
|
+
group: "performance",
|
|
373
|
+
annotations: readOnly("Detect connection spike"),
|
|
374
|
+
icons: getToolIcons("performance", readOnly("Detect connection spike")),
|
|
375
|
+
handler: async (params, _context) => {
|
|
376
|
+
try {
|
|
377
|
+
const parsed = ConnectionSpikeInput.safeParse(params);
|
|
378
|
+
if (!parsed.success) {
|
|
379
|
+
return {
|
|
380
|
+
success: false,
|
|
381
|
+
error: `Validation error: ${parsed.error.issues.map((i) => i.message).join(", ")}`,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
const { warningPercent } = parsed.data;
|
|
385
|
+
// Gather connection data in parallel
|
|
386
|
+
const [stateResult, userResult, appResult, maxResult, idleTxResult] = await Promise.all([
|
|
387
|
+
// By state
|
|
388
|
+
adapter.executeQuery(`
|
|
389
|
+
SELECT state, count(*) AS count
|
|
390
|
+
FROM pg_stat_activity
|
|
391
|
+
WHERE pid != pg_backend_pid()
|
|
392
|
+
GROUP BY state
|
|
393
|
+
ORDER BY count DESC
|
|
394
|
+
`),
|
|
395
|
+
// By user
|
|
396
|
+
adapter.executeQuery(`
|
|
397
|
+
SELECT usename, count(*) AS count
|
|
398
|
+
FROM pg_stat_activity
|
|
399
|
+
WHERE pid != pg_backend_pid()
|
|
400
|
+
GROUP BY usename
|
|
401
|
+
ORDER BY count DESC
|
|
402
|
+
`),
|
|
403
|
+
// By application
|
|
404
|
+
adapter.executeQuery(`
|
|
405
|
+
SELECT COALESCE(application_name, '') AS app_name, count(*) AS count
|
|
406
|
+
FROM pg_stat_activity
|
|
407
|
+
WHERE pid != pg_backend_pid()
|
|
408
|
+
GROUP BY application_name
|
|
409
|
+
ORDER BY count DESC
|
|
410
|
+
`),
|
|
411
|
+
// Max connections
|
|
412
|
+
adapter.executeQuery(`SHOW max_connections`),
|
|
413
|
+
// Idle-in-transaction details
|
|
414
|
+
adapter.executeQuery(`
|
|
415
|
+
SELECT pid, usename,
|
|
416
|
+
COALESCE(application_name, '') AS app_name,
|
|
417
|
+
now() - state_change AS idle_duration,
|
|
418
|
+
EXTRACT(EPOCH FROM (now() - state_change))::int AS idle_seconds
|
|
419
|
+
FROM pg_stat_activity
|
|
420
|
+
WHERE state = 'idle in transaction'
|
|
421
|
+
AND pid != pg_backend_pid()
|
|
422
|
+
ORDER BY state_change ASC
|
|
423
|
+
LIMIT 20
|
|
424
|
+
`),
|
|
425
|
+
]);
|
|
426
|
+
const byState = stateResult.rows ?? [];
|
|
427
|
+
const totalConnections = byState.reduce((sum, r) => sum + toNum(r["count"]), 0);
|
|
428
|
+
const maxConnections = toNum(maxResult.rows?.[0]?.["max_connections"]);
|
|
429
|
+
const usagePercent = maxConnections > 0
|
|
430
|
+
? Math.round((totalConnections / maxConnections) * 100 * 10) / 10
|
|
431
|
+
: 0;
|
|
432
|
+
const concentrations = [];
|
|
433
|
+
const warnings = [];
|
|
434
|
+
// Check user concentration
|
|
435
|
+
for (const row of userResult.rows ?? []) {
|
|
436
|
+
const count = toNum(row["count"]);
|
|
437
|
+
const percent = totalConnections > 0
|
|
438
|
+
? Math.round((count / totalConnections) * 100 * 10) / 10
|
|
439
|
+
: 0;
|
|
440
|
+
if (percent >= warningPercent) {
|
|
441
|
+
const user = toStr(row["usename"], "unknown");
|
|
442
|
+
concentrations.push({
|
|
443
|
+
dimension: "user",
|
|
444
|
+
value: user,
|
|
445
|
+
count,
|
|
446
|
+
percent,
|
|
447
|
+
});
|
|
448
|
+
warnings.push(`User '${user}' holds ${String(percent)}% of connections (${String(count)}/${String(totalConnections)})`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
// Check application concentration
|
|
452
|
+
for (const row of appResult.rows ?? []) {
|
|
453
|
+
const count = toNum(row["count"]);
|
|
454
|
+
const percent = totalConnections > 0
|
|
455
|
+
? Math.round((count / totalConnections) * 100 * 10) / 10
|
|
456
|
+
: 0;
|
|
457
|
+
if (percent >= warningPercent) {
|
|
458
|
+
const app = toStr(row["app_name"]);
|
|
459
|
+
if (app) {
|
|
460
|
+
concentrations.push({
|
|
461
|
+
dimension: "application",
|
|
462
|
+
value: app,
|
|
463
|
+
count,
|
|
464
|
+
percent,
|
|
465
|
+
});
|
|
466
|
+
warnings.push(`Application '${app}' holds ${String(percent)}% of connections (${String(count)}/${String(totalConnections)})`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
// Check idle-in-transaction buildup
|
|
471
|
+
const idleTxRows = idleTxResult.rows ?? [];
|
|
472
|
+
if (idleTxRows.length > 0) {
|
|
473
|
+
const longIdleTx = idleTxRows.filter((r) => toNum(r["idle_seconds"]) > 300);
|
|
474
|
+
if (longIdleTx.length > 0) {
|
|
475
|
+
warnings.push(`${String(longIdleTx.length)} connection(s) idle in transaction for >5 minutes — these hold locks and block autovacuum`);
|
|
476
|
+
}
|
|
477
|
+
if (idleTxRows.length >= 5) {
|
|
478
|
+
warnings.push(`${String(idleTxRows.length)} total idle-in-transaction connections — check for uncommitted transactions`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
// Check overall pressure
|
|
482
|
+
if (usagePercent >= 90) {
|
|
483
|
+
warnings.push(`Critical connection pressure: ${String(usagePercent)}% of max_connections in use`);
|
|
484
|
+
}
|
|
485
|
+
else if (usagePercent >= 80) {
|
|
486
|
+
warnings.push(`High connection pressure: ${String(usagePercent)}% of max_connections in use`);
|
|
487
|
+
}
|
|
488
|
+
// Calculate risk level
|
|
489
|
+
let riskScore = 0;
|
|
490
|
+
if (usagePercent >= 90)
|
|
491
|
+
riskScore += 40;
|
|
492
|
+
else if (usagePercent >= 80)
|
|
493
|
+
riskScore += 25;
|
|
494
|
+
else if (usagePercent >= 70)
|
|
495
|
+
riskScore += 10;
|
|
496
|
+
if (concentrations.length >= 2)
|
|
497
|
+
riskScore += 30;
|
|
498
|
+
else if (concentrations.length >= 1)
|
|
499
|
+
riskScore += 15;
|
|
500
|
+
if (idleTxRows.length >= 5)
|
|
501
|
+
riskScore += 25;
|
|
502
|
+
else if (idleTxRows.length >= 1)
|
|
503
|
+
riskScore += 10;
|
|
504
|
+
const riskLevel = riskFromScore(riskScore);
|
|
505
|
+
const summary = warnings.length === 0
|
|
506
|
+
? `No connection anomalies detected (${String(totalConnections)}/${String(maxConnections)} connections, ${String(usagePercent)}% usage)`
|
|
507
|
+
: `${String(warnings.length)} warning(s) detected: ${String(totalConnections)}/${String(maxConnections)} connections (${String(usagePercent)}% usage)`;
|
|
508
|
+
return {
|
|
509
|
+
totalConnections,
|
|
510
|
+
maxConnections,
|
|
511
|
+
usagePercent,
|
|
512
|
+
byState: byState.map((r) => ({
|
|
513
|
+
state: toStr(r["state"], "null"),
|
|
514
|
+
count: toNum(r["count"]),
|
|
515
|
+
})),
|
|
516
|
+
concentrations,
|
|
517
|
+
warnings,
|
|
518
|
+
riskLevel,
|
|
519
|
+
summary,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
catch (error) {
|
|
523
|
+
return {
|
|
524
|
+
success: false,
|
|
525
|
+
error: formatPostgresError(error, {
|
|
526
|
+
tool: "pg_detect_connection_spike",
|
|
527
|
+
}),
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
//# sourceMappingURL=anomaly-detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anomaly-detection.js","sourceRoot":"","sources":["../../../../../src/adapters/postgresql/tools/performance/anomaly-detection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL Performance Tools - Database Diagnostics
|
|
3
|
+
*
|
|
4
|
+
* Consolidates key performance metrics into a single actionable report:
|
|
5
|
+
* slow queries, blocking locks, connection pressure, cache hit ratio,
|
|
6
|
+
* disk usage, and top tables by size/activity.
|
|
7
|
+
*/
|
|
8
|
+
import type { PostgresAdapter } from "../../PostgresAdapter.js";
|
|
9
|
+
import type { ToolDefinition } from "../../../../types/index.js";
|
|
10
|
+
export declare function createDiagnoseTool(adapter: PostgresAdapter): ToolDefinition;
|
|
11
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/postgresql/tools/performance/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EACV,cAAc,EAEf,MAAM,4BAA4B,CAAC;AA0VpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,CAwG3E"}
|