@indiekitai/pg-dash 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -117,6 +117,13 @@ The Dashboard is there when you need it. But the real power is in the CLI, MCP,
117
117
  - `--health` flag adds health score comparison and unique issues per environment
118
118
  - `pg_dash_compare_env` MCP tool: ask your AI "what's different between local and staging?"
119
119
 
120
+ ### 🔧 Production Readiness Audit
121
+ - **Unused indexes** — Find indexes with 0 scans since last stats reset; suggests safe `DROP INDEX CONCURRENTLY` SQL
122
+ - **Table bloat** — Dead tuple ratio per table (≥10%); surfaces both `last_autovacuum` and `last_vacuum` timestamps
123
+ - **Autovacuum health** — Classifies each table as `ok` / `stale` / `overdue` / `never`; shows autovacuum settings with units
124
+ - **Lock monitoring** — Active lock-wait chains (who is blocking whom) + long-running queries >5s
125
+ - **Config recommendations** — Audits `shared_buffers`, `work_mem`, `checkpoint_completion_target`, `random_page_cost`, `idle_in_transaction_session_timeout`, and 5 more settings with severity-tagged recommendations
126
+
120
127
  ### 🤖 MCP Server
121
128
  - 23 tools for AI agent integration
122
129
  - `pg-dash-mcp postgres://...` — works with Claude, Cursor, etc.
package/README.zh-CN.md CHANGED
@@ -117,6 +117,13 @@ Dashboard 需要时可以用。但真正的核心能力在 CLI、MCP 和 CI。
117
117
  - `--health` 参数额外对比健康分和各环境独有的问题
118
118
  - `pg_dash_compare_env` MCP 工具:直接问 AI "本地和预发有什么差异?"
119
119
 
120
+ ### 🔧 生产就绪审计
121
+ - **废弃索引检测** — 找出从未被使用(0 次扫描)的索引,自动生成带引号的 `DROP INDEX CONCURRENTLY` SQL
122
+ - **表膨胀检测** — 统计每张表的 dead tuple 比例(≥10% 才展示),同时显示 `last_autovacuum` 和 `last_vacuum` 时间戳
123
+ - **Autovacuum 健康** — 将每张表分类为 `ok` / `stale` / `overdue` / `never`,展示带单位的 autovacuum 配置
124
+ - **锁监控** — 活跃的锁等待链(谁在阻塞谁)+ 超过 5 秒的长查询
125
+ - **配置建议** — 审计 `shared_buffers`、`work_mem`、`checkpoint_completion_target`、`random_page_cost`、`idle_in_transaction_session_timeout` 等 10 项配置,给出带严重级别的调优建议
126
+
120
127
  ### 🤖 MCP Server
121
128
  - 23 个工具,支持 AI Agent 集成
122
129
  - `pg-dash-mcp postgres://...` —— 可配合 Claude、Cursor 等使用
package/dist/mcp.js CHANGED
@@ -1933,7 +1933,18 @@ async function getUnusedIndexes(pool2) {
1933
1933
  pool2.query(`SELECT stats_reset FROM pg_stat_bgwriter`)
1934
1934
  ]);
1935
1935
  const statsReset = bgwriterResult.rows[0]?.stats_reset ? new Date(bgwriterResult.rows[0].stats_reset).toISOString() : null;
1936
- const indexes = indexResult.rows.map((row) => {
1936
+ const filteredRows = indexResult.rows.filter((row) => {
1937
+ const def = row.indexdef ?? "";
1938
+ if (def.includes(" WHERE ")) return false;
1939
+ const colStart = def.indexOf("(");
1940
+ const colEnd = def.lastIndexOf(")");
1941
+ if (colStart !== -1 && colEnd !== -1) {
1942
+ const cols = def.slice(colStart + 1, colEnd);
1943
+ if (cols.includes("(")) return false;
1944
+ }
1945
+ return true;
1946
+ });
1947
+ const indexes = filteredRows.map((row) => {
1937
1948
  const sizeBytes = parseInt(row.index_size_bytes, 10) || 0;
1938
1949
  const index = row.index_name;
1939
1950
  const table = row.table_name;
@@ -2236,7 +2247,7 @@ async function getConfigReport(pool2) {
2236
2247
  if (mb <= 4) {
2237
2248
  recommendations.push({
2238
2249
  setting: "work_mem",
2239
- currentValue: "4MB",
2250
+ currentValue: `${mb % 1 === 0 ? mb : mb.toFixed(1)}MB`,
2240
2251
  recommendedValue: "16MB",
2241
2252
  reason: "work_mem of 4MB is conservative; consider 16MB\u201364MB for analytical queries (but multiply by max_connections for total)",
2242
2253
  severity: "info",
@@ -2325,7 +2336,7 @@ async function getConfigReport(pool2) {
2325
2336
  if (mb <= 64) {
2326
2337
  recommendations.push({
2327
2338
  setting: "maintenance_work_mem",
2328
- currentValue: "64MB",
2339
+ currentValue: `${mb % 1 === 0 ? mb : mb.toFixed(1)}MB`,
2329
2340
  recommendedValue: "256MB",
2330
2341
  reason: "Consider 256MB for faster VACUUM and index builds",
2331
2342
  severity: "info",
@@ -2334,6 +2345,19 @@ async function getConfigReport(pool2) {
2334
2345
  }
2335
2346
  }
2336
2347
  const maxConnSetting = get("max_connections");
2348
+ if (maxConnSetting !== null) {
2349
+ const maxConn = parseInt(maxConnSetting, 10);
2350
+ if (maxConn > 200) {
2351
+ recommendations.push({
2352
+ setting: "max_connections",
2353
+ currentValue: String(maxConn),
2354
+ recommendedValue: "100",
2355
+ reason: `max_connections=${maxConn} is high. Each connection uses ~5\u201310MB RAM. Without a connection pooler (PgBouncer), this leads to memory pressure and context-switch overhead. Consider lowering to 100 and using a pooler.`,
2356
+ severity: "warning",
2357
+ docs: "https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-MAX-CONNECTIONS"
2358
+ });
2359
+ }
2360
+ }
2337
2361
  const serverInfo = {
2338
2362
  maxConnections: maxConnSetting !== null ? parseInt(maxConnSetting, 10) : 0,
2339
2363
  sharedBuffers: formatMemSetting(sharedBuffersSetting, getUnit("shared_buffers")),