postgresai 0.14.0-beta.14 → 0.14.0-beta.15
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/bin/postgres-ai.ts +12 -6
- package/dist/bin/postgres-ai.js +686 -33
- package/lib/checkup-dictionary.ts +114 -0
- package/lib/checkup.ts +130 -14
- package/package.json +9 -7
- package/scripts/embed-checkup-dictionary.ts +106 -0
- package/test/checkup.test.ts +17 -18
- package/lib/metrics-embedded.ts +0 -79
package/dist/bin/postgres-ai.js
CHANGED
|
@@ -13064,7 +13064,7 @@ var {
|
|
|
13064
13064
|
// package.json
|
|
13065
13065
|
var package_default = {
|
|
13066
13066
|
name: "postgresai",
|
|
13067
|
-
version: "0.14.0-beta.
|
|
13067
|
+
version: "0.14.0-beta.15",
|
|
13068
13068
|
description: "postgres_ai CLI",
|
|
13069
13069
|
license: "Apache-2.0",
|
|
13070
13070
|
private: false,
|
|
@@ -13090,15 +13090,17 @@ var package_default = {
|
|
|
13090
13090
|
},
|
|
13091
13091
|
scripts: {
|
|
13092
13092
|
"embed-metrics": "bun run scripts/embed-metrics.ts",
|
|
13093
|
-
|
|
13093
|
+
"embed-checkup-dictionary": "bun run scripts/embed-checkup-dictionary.ts",
|
|
13094
|
+
"embed-all": "bun run embed-metrics && bun run embed-checkup-dictionary",
|
|
13095
|
+
build: `bun run embed-all && bun build ./bin/postgres-ai.ts --outdir ./dist/bin --target node && node -e "const fs=require('fs');const f='./dist/bin/postgres-ai.js';fs.writeFileSync(f,fs.readFileSync(f,'utf8').replace('#!/usr/bin/env bun','#!/usr/bin/env node'))" && cp -r ./sql ./dist/sql`,
|
|
13094
13096
|
prepublishOnly: "npm run build",
|
|
13095
13097
|
start: "bun ./bin/postgres-ai.ts --help",
|
|
13096
13098
|
"start:node": "node ./dist/bin/postgres-ai.js --help",
|
|
13097
|
-
dev: "bun run embed-
|
|
13098
|
-
test: "bun run embed-
|
|
13099
|
-
"test:fast": "bun run embed-
|
|
13100
|
-
"test:coverage": "bun run embed-
|
|
13101
|
-
typecheck: "bun run embed-
|
|
13099
|
+
dev: "bun run embed-all && bun --watch ./bin/postgres-ai.ts",
|
|
13100
|
+
test: "bun run embed-all && bun test",
|
|
13101
|
+
"test:fast": "bun run embed-all && bun test --coverage=false",
|
|
13102
|
+
"test:coverage": "bun run embed-all && bun test --coverage && echo 'Coverage report: cli/coverage/lcov-report/index.html'",
|
|
13103
|
+
typecheck: "bun run embed-all && bunx tsc --noEmit"
|
|
13102
13104
|
},
|
|
13103
13105
|
dependencies: {
|
|
13104
13106
|
"@modelcontextprotocol/sdk": "^1.20.2",
|
|
@@ -15887,7 +15889,7 @@ var Result = import_lib.default.Result;
|
|
|
15887
15889
|
var TypeOverrides = import_lib.default.TypeOverrides;
|
|
15888
15890
|
var defaults = import_lib.default.defaults;
|
|
15889
15891
|
// package.json
|
|
15890
|
-
var version = "0.14.0-beta.
|
|
15892
|
+
var version = "0.14.0-beta.15";
|
|
15891
15893
|
var package_default2 = {
|
|
15892
15894
|
name: "postgresai",
|
|
15893
15895
|
version,
|
|
@@ -15916,15 +15918,17 @@ var package_default2 = {
|
|
|
15916
15918
|
},
|
|
15917
15919
|
scripts: {
|
|
15918
15920
|
"embed-metrics": "bun run scripts/embed-metrics.ts",
|
|
15919
|
-
|
|
15921
|
+
"embed-checkup-dictionary": "bun run scripts/embed-checkup-dictionary.ts",
|
|
15922
|
+
"embed-all": "bun run embed-metrics && bun run embed-checkup-dictionary",
|
|
15923
|
+
build: `bun run embed-all && bun build ./bin/postgres-ai.ts --outdir ./dist/bin --target node && node -e "const fs=require('fs');const f='./dist/bin/postgres-ai.js';fs.writeFileSync(f,fs.readFileSync(f,'utf8').replace('#!/usr/bin/env bun','#!/usr/bin/env node'))" && cp -r ./sql ./dist/sql`,
|
|
15920
15924
|
prepublishOnly: "npm run build",
|
|
15921
15925
|
start: "bun ./bin/postgres-ai.ts --help",
|
|
15922
15926
|
"start:node": "node ./dist/bin/postgres-ai.js --help",
|
|
15923
|
-
dev: "bun run embed-
|
|
15924
|
-
test: "bun run embed-
|
|
15925
|
-
"test:fast": "bun run embed-
|
|
15926
|
-
"test:coverage": "bun run embed-
|
|
15927
|
-
typecheck: "bun run embed-
|
|
15927
|
+
dev: "bun run embed-all && bun --watch ./bin/postgres-ai.ts",
|
|
15928
|
+
test: "bun run embed-all && bun test",
|
|
15929
|
+
"test:fast": "bun run embed-all && bun test --coverage=false",
|
|
15930
|
+
"test:coverage": "bun run embed-all && bun test --coverage && echo 'Coverage report: cli/coverage/lcov-report/index.html'",
|
|
15931
|
+
typecheck: "bun run embed-all && bunx tsc --noEmit"
|
|
15928
15932
|
},
|
|
15929
15933
|
dependencies: {
|
|
15930
15934
|
"@modelcontextprotocol/sdk": "^1.20.2",
|
|
@@ -26542,6 +26546,572 @@ function transformMetricRow(row) {
|
|
|
26542
26546
|
return result;
|
|
26543
26547
|
}
|
|
26544
26548
|
|
|
26549
|
+
// lib/checkup-dictionary-embedded.ts
|
|
26550
|
+
var CHECKUP_DICTIONARY_DATA = [
|
|
26551
|
+
{
|
|
26552
|
+
code: "A001",
|
|
26553
|
+
title: "System information",
|
|
26554
|
+
description: "OS, kernel, hardware details",
|
|
26555
|
+
category: "system",
|
|
26556
|
+
sort_order: null,
|
|
26557
|
+
is_system_report: false
|
|
26558
|
+
},
|
|
26559
|
+
{
|
|
26560
|
+
code: "A002",
|
|
26561
|
+
title: "Postgres major version",
|
|
26562
|
+
description: "Major version and end-of-life status",
|
|
26563
|
+
category: "system",
|
|
26564
|
+
sort_order: null,
|
|
26565
|
+
is_system_report: false
|
|
26566
|
+
},
|
|
26567
|
+
{
|
|
26568
|
+
code: "A003",
|
|
26569
|
+
title: "Postgres settings",
|
|
26570
|
+
description: "Full list of current settings",
|
|
26571
|
+
category: "system",
|
|
26572
|
+
sort_order: null,
|
|
26573
|
+
is_system_report: false
|
|
26574
|
+
},
|
|
26575
|
+
{
|
|
26576
|
+
code: "A004",
|
|
26577
|
+
title: "Cluster information",
|
|
26578
|
+
description: "Data directory, cluster name, system identifier",
|
|
26579
|
+
category: "system",
|
|
26580
|
+
sort_order: null,
|
|
26581
|
+
is_system_report: false
|
|
26582
|
+
},
|
|
26583
|
+
{
|
|
26584
|
+
code: "A005",
|
|
26585
|
+
title: "Extensions",
|
|
26586
|
+
description: "Installed and available extensions",
|
|
26587
|
+
category: "system",
|
|
26588
|
+
sort_order: null,
|
|
26589
|
+
is_system_report: false
|
|
26590
|
+
},
|
|
26591
|
+
{
|
|
26592
|
+
code: "A006",
|
|
26593
|
+
title: "Postgres setting deviations",
|
|
26594
|
+
description: "Settings that differ from defaults",
|
|
26595
|
+
category: "system",
|
|
26596
|
+
sort_order: null,
|
|
26597
|
+
is_system_report: false
|
|
26598
|
+
},
|
|
26599
|
+
{
|
|
26600
|
+
code: "A007",
|
|
26601
|
+
title: "Altered settings",
|
|
26602
|
+
description: "Settings changed via ALTER SYSTEM or per-user/database",
|
|
26603
|
+
category: "system",
|
|
26604
|
+
sort_order: null,
|
|
26605
|
+
is_system_report: false
|
|
26606
|
+
},
|
|
26607
|
+
{
|
|
26608
|
+
code: "A008",
|
|
26609
|
+
title: "Disk usage and file system type",
|
|
26610
|
+
description: "Disk space, mount points, filesystem types",
|
|
26611
|
+
category: "system",
|
|
26612
|
+
sort_order: null,
|
|
26613
|
+
is_system_report: false
|
|
26614
|
+
},
|
|
26615
|
+
{
|
|
26616
|
+
code: "A009",
|
|
26617
|
+
title: "Tablespaces",
|
|
26618
|
+
description: "Tablespace locations and usage",
|
|
26619
|
+
category: "system",
|
|
26620
|
+
sort_order: null,
|
|
26621
|
+
is_system_report: false
|
|
26622
|
+
},
|
|
26623
|
+
{
|
|
26624
|
+
code: "A010",
|
|
26625
|
+
title: "Corruption control",
|
|
26626
|
+
description: "Checksums, wal_log_hints, backup safety",
|
|
26627
|
+
category: "system",
|
|
26628
|
+
sort_order: null,
|
|
26629
|
+
is_system_report: false
|
|
26630
|
+
},
|
|
26631
|
+
{
|
|
26632
|
+
code: "A011",
|
|
26633
|
+
title: "Connection management and pooling",
|
|
26634
|
+
description: "Connection limits and pooler detection",
|
|
26635
|
+
category: "system",
|
|
26636
|
+
sort_order: null,
|
|
26637
|
+
is_system_report: false
|
|
26638
|
+
},
|
|
26639
|
+
{
|
|
26640
|
+
code: "A012",
|
|
26641
|
+
title: "Anti-crash checks",
|
|
26642
|
+
description: "fsync, full_page_writes, synchronous_commit",
|
|
26643
|
+
category: "system",
|
|
26644
|
+
sort_order: null,
|
|
26645
|
+
is_system_report: false
|
|
26646
|
+
},
|
|
26647
|
+
{
|
|
26648
|
+
code: "A013",
|
|
26649
|
+
title: "Postgres minor version",
|
|
26650
|
+
description: "Minor version and available updates",
|
|
26651
|
+
category: "system",
|
|
26652
|
+
sort_order: null,
|
|
26653
|
+
is_system_report: false
|
|
26654
|
+
},
|
|
26655
|
+
{
|
|
26656
|
+
code: "B001",
|
|
26657
|
+
title: "SLO/SLA, RPO, RTO",
|
|
26658
|
+
description: "Recovery objectives and current capabilities",
|
|
26659
|
+
category: "backup",
|
|
26660
|
+
sort_order: null,
|
|
26661
|
+
is_system_report: false
|
|
26662
|
+
},
|
|
26663
|
+
{
|
|
26664
|
+
code: "B002",
|
|
26665
|
+
title: "File system and mount flags",
|
|
26666
|
+
description: "Mount options affecting durability",
|
|
26667
|
+
category: "backup",
|
|
26668
|
+
sort_order: null,
|
|
26669
|
+
is_system_report: false
|
|
26670
|
+
},
|
|
26671
|
+
{
|
|
26672
|
+
code: "B003",
|
|
26673
|
+
title: "Full and incremental backups",
|
|
26674
|
+
description: "Backup tooling and schedule",
|
|
26675
|
+
category: "backup",
|
|
26676
|
+
sort_order: null,
|
|
26677
|
+
is_system_report: false
|
|
26678
|
+
},
|
|
26679
|
+
{
|
|
26680
|
+
code: "B004",
|
|
26681
|
+
title: "WAL archiving",
|
|
26682
|
+
description: "Archive configuration and status",
|
|
26683
|
+
category: "backup",
|
|
26684
|
+
sort_order: null,
|
|
26685
|
+
is_system_report: false
|
|
26686
|
+
},
|
|
26687
|
+
{
|
|
26688
|
+
code: "B005",
|
|
26689
|
+
title: "Backup restore testing and monitoring",
|
|
26690
|
+
description: "Restore testing practices and alerting",
|
|
26691
|
+
category: "backup",
|
|
26692
|
+
sort_order: null,
|
|
26693
|
+
is_system_report: false
|
|
26694
|
+
},
|
|
26695
|
+
{
|
|
26696
|
+
code: "C001",
|
|
26697
|
+
title: "SLO/SLA",
|
|
26698
|
+
description: "Availability objectives",
|
|
26699
|
+
category: "replication",
|
|
26700
|
+
sort_order: null,
|
|
26701
|
+
is_system_report: false
|
|
26702
|
+
},
|
|
26703
|
+
{
|
|
26704
|
+
code: "C002",
|
|
26705
|
+
title: "Replication mode and method",
|
|
26706
|
+
description: "Sync/async, streaming/WAL shipping",
|
|
26707
|
+
category: "replication",
|
|
26708
|
+
sort_order: null,
|
|
26709
|
+
is_system_report: false
|
|
26710
|
+
},
|
|
26711
|
+
{
|
|
26712
|
+
code: "C003",
|
|
26713
|
+
title: "Single points of failure",
|
|
26714
|
+
description: "SPOF analysis",
|
|
26715
|
+
category: "replication",
|
|
26716
|
+
sort_order: null,
|
|
26717
|
+
is_system_report: false
|
|
26718
|
+
},
|
|
26719
|
+
{
|
|
26720
|
+
code: "C004",
|
|
26721
|
+
title: "Failover",
|
|
26722
|
+
description: "Failover mechanism and automation",
|
|
26723
|
+
category: "replication",
|
|
26724
|
+
sort_order: null,
|
|
26725
|
+
is_system_report: false
|
|
26726
|
+
},
|
|
26727
|
+
{
|
|
26728
|
+
code: "C005",
|
|
26729
|
+
title: "Switchover",
|
|
26730
|
+
description: "Planned switchover procedures",
|
|
26731
|
+
category: "replication",
|
|
26732
|
+
sort_order: null,
|
|
26733
|
+
is_system_report: false
|
|
26734
|
+
},
|
|
26735
|
+
{
|
|
26736
|
+
code: "C006",
|
|
26737
|
+
title: "Delayed replica",
|
|
26738
|
+
description: "Delayed standby configuration",
|
|
26739
|
+
category: "replication",
|
|
26740
|
+
sort_order: null,
|
|
26741
|
+
is_system_report: false
|
|
26742
|
+
},
|
|
26743
|
+
{
|
|
26744
|
+
code: "C007",
|
|
26745
|
+
title: "Replication slots and lag",
|
|
26746
|
+
description: "Slot status, lag, standby feedback",
|
|
26747
|
+
category: "replication",
|
|
26748
|
+
sort_order: null,
|
|
26749
|
+
is_system_report: false
|
|
26750
|
+
},
|
|
26751
|
+
{
|
|
26752
|
+
code: "D001",
|
|
26753
|
+
title: "Logging settings",
|
|
26754
|
+
description: "Log destination, verbosity, rotation",
|
|
26755
|
+
category: "monitoring",
|
|
26756
|
+
sort_order: null,
|
|
26757
|
+
is_system_report: false
|
|
26758
|
+
},
|
|
26759
|
+
{
|
|
26760
|
+
code: "D002",
|
|
26761
|
+
title: "Useful Linux tools",
|
|
26762
|
+
description: "Recommended OS-level tooling",
|
|
26763
|
+
category: "monitoring",
|
|
26764
|
+
sort_order: null,
|
|
26765
|
+
is_system_report: false
|
|
26766
|
+
},
|
|
26767
|
+
{
|
|
26768
|
+
code: "D003",
|
|
26769
|
+
title: "Monitoring metrics",
|
|
26770
|
+
description: "Key metrics to track",
|
|
26771
|
+
category: "monitoring",
|
|
26772
|
+
sort_order: null,
|
|
26773
|
+
is_system_report: false
|
|
26774
|
+
},
|
|
26775
|
+
{
|
|
26776
|
+
code: "D004",
|
|
26777
|
+
title: "pg_stat_statements and pg_stat_kcache",
|
|
26778
|
+
description: "Query stats extension settings",
|
|
26779
|
+
category: "monitoring",
|
|
26780
|
+
sort_order: null,
|
|
26781
|
+
is_system_report: false
|
|
26782
|
+
},
|
|
26783
|
+
{
|
|
26784
|
+
code: "D005",
|
|
26785
|
+
title: "track_io_timing and auto_explain",
|
|
26786
|
+
description: "I/O timing and plan logging",
|
|
26787
|
+
category: "monitoring",
|
|
26788
|
+
sort_order: null,
|
|
26789
|
+
is_system_report: false
|
|
26790
|
+
},
|
|
26791
|
+
{
|
|
26792
|
+
code: "D006",
|
|
26793
|
+
title: "Recommended DBA toolsets",
|
|
26794
|
+
description: "Useful third-party tools",
|
|
26795
|
+
category: "monitoring",
|
|
26796
|
+
sort_order: null,
|
|
26797
|
+
is_system_report: false
|
|
26798
|
+
},
|
|
26799
|
+
{
|
|
26800
|
+
code: "D007",
|
|
26801
|
+
title: "Postgres troubleshooting tools",
|
|
26802
|
+
description: "Built-in and ecosystem diagnostic tools",
|
|
26803
|
+
category: "monitoring",
|
|
26804
|
+
sort_order: null,
|
|
26805
|
+
is_system_report: false
|
|
26806
|
+
},
|
|
26807
|
+
{
|
|
26808
|
+
code: "E001",
|
|
26809
|
+
title: "WAL and checkpoint settings",
|
|
26810
|
+
description: "WAL size, checkpoint timing, I/O limits",
|
|
26811
|
+
category: "wal",
|
|
26812
|
+
sort_order: null,
|
|
26813
|
+
is_system_report: false
|
|
26814
|
+
},
|
|
26815
|
+
{
|
|
26816
|
+
code: "E002",
|
|
26817
|
+
title: "Checkpoint and bgwriter activity",
|
|
26818
|
+
description: "Checkpoint frequency, bgwriter stats",
|
|
26819
|
+
category: "wal",
|
|
26820
|
+
sort_order: null,
|
|
26821
|
+
is_system_report: false
|
|
26822
|
+
},
|
|
26823
|
+
{
|
|
26824
|
+
code: "F001",
|
|
26825
|
+
title: "Autovacuum: current settings",
|
|
26826
|
+
description: "Autovacuum configuration",
|
|
26827
|
+
category: "vacuum",
|
|
26828
|
+
sort_order: null,
|
|
26829
|
+
is_system_report: false
|
|
26830
|
+
},
|
|
26831
|
+
{
|
|
26832
|
+
code: "F002",
|
|
26833
|
+
title: "Autovacuum: transaction ID wraparound",
|
|
26834
|
+
description: "XID age and wraparound risk",
|
|
26835
|
+
category: "vacuum",
|
|
26836
|
+
sort_order: null,
|
|
26837
|
+
is_system_report: false
|
|
26838
|
+
},
|
|
26839
|
+
{
|
|
26840
|
+
code: "F003",
|
|
26841
|
+
title: "Autovacuum: dead tuples",
|
|
26842
|
+
description: "Dead tuple counts and cleanup status",
|
|
26843
|
+
category: "vacuum",
|
|
26844
|
+
sort_order: null,
|
|
26845
|
+
is_system_report: false
|
|
26846
|
+
},
|
|
26847
|
+
{
|
|
26848
|
+
code: "F004",
|
|
26849
|
+
title: "Autovacuum: heap bloat estimate",
|
|
26850
|
+
description: "Estimated table bloat",
|
|
26851
|
+
category: "vacuum",
|
|
26852
|
+
sort_order: null,
|
|
26853
|
+
is_system_report: false
|
|
26854
|
+
},
|
|
26855
|
+
{
|
|
26856
|
+
code: "F005",
|
|
26857
|
+
title: "Autovacuum: index bloat estimate",
|
|
26858
|
+
description: "Estimated index bloat",
|
|
26859
|
+
category: "vacuum",
|
|
26860
|
+
sort_order: null,
|
|
26861
|
+
is_system_report: false
|
|
26862
|
+
},
|
|
26863
|
+
{
|
|
26864
|
+
code: "F006",
|
|
26865
|
+
title: "Precise heap bloat analysis",
|
|
26866
|
+
description: "Detailed table bloat measurement",
|
|
26867
|
+
category: "vacuum",
|
|
26868
|
+
sort_order: null,
|
|
26869
|
+
is_system_report: false
|
|
26870
|
+
},
|
|
26871
|
+
{
|
|
26872
|
+
code: "F007",
|
|
26873
|
+
title: "Precise index bloat analysis",
|
|
26874
|
+
description: "Detailed index bloat measurement",
|
|
26875
|
+
category: "vacuum",
|
|
26876
|
+
sort_order: null,
|
|
26877
|
+
is_system_report: false
|
|
26878
|
+
},
|
|
26879
|
+
{
|
|
26880
|
+
code: "F008",
|
|
26881
|
+
title: "Autovacuum: resource usage",
|
|
26882
|
+
description: "Autovacuum I/O and CPU impact",
|
|
26883
|
+
category: "vacuum",
|
|
26884
|
+
sort_order: null,
|
|
26885
|
+
is_system_report: false
|
|
26886
|
+
},
|
|
26887
|
+
{
|
|
26888
|
+
code: "G001",
|
|
26889
|
+
title: "Memory-related settings",
|
|
26890
|
+
description: "shared_buffers, work_mem, maintenance_work_mem",
|
|
26891
|
+
category: "tuning",
|
|
26892
|
+
sort_order: null,
|
|
26893
|
+
is_system_report: false
|
|
26894
|
+
},
|
|
26895
|
+
{
|
|
26896
|
+
code: "G002",
|
|
26897
|
+
title: "Connections and current activity",
|
|
26898
|
+
description: "Connection usage and active sessions",
|
|
26899
|
+
category: "tuning",
|
|
26900
|
+
sort_order: null,
|
|
26901
|
+
is_system_report: false
|
|
26902
|
+
},
|
|
26903
|
+
{
|
|
26904
|
+
code: "G003",
|
|
26905
|
+
title: "Timeouts, locks, deadlocks",
|
|
26906
|
+
description: "Lock settings and deadlock stats",
|
|
26907
|
+
category: "tuning",
|
|
26908
|
+
sort_order: null,
|
|
26909
|
+
is_system_report: false
|
|
26910
|
+
},
|
|
26911
|
+
{
|
|
26912
|
+
code: "G004",
|
|
26913
|
+
title: "Query planner settings",
|
|
26914
|
+
description: "Planner cost and behavior settings",
|
|
26915
|
+
category: "tuning",
|
|
26916
|
+
sort_order: null,
|
|
26917
|
+
is_system_report: false
|
|
26918
|
+
},
|
|
26919
|
+
{
|
|
26920
|
+
code: "G005",
|
|
26921
|
+
title: "I/O settings",
|
|
26922
|
+
description: "effective_io_concurrency, random_page_cost",
|
|
26923
|
+
category: "tuning",
|
|
26924
|
+
sort_order: null,
|
|
26925
|
+
is_system_report: false
|
|
26926
|
+
},
|
|
26927
|
+
{
|
|
26928
|
+
code: "G006",
|
|
26929
|
+
title: "Statistics target settings",
|
|
26930
|
+
description: "default_statistics_target and per-column targets",
|
|
26931
|
+
category: "tuning",
|
|
26932
|
+
sort_order: null,
|
|
26933
|
+
is_system_report: false
|
|
26934
|
+
},
|
|
26935
|
+
{
|
|
26936
|
+
code: "H001",
|
|
26937
|
+
title: "Invalid indexes",
|
|
26938
|
+
description: "Indexes that failed to build",
|
|
26939
|
+
category: "indexes",
|
|
26940
|
+
sort_order: null,
|
|
26941
|
+
is_system_report: false
|
|
26942
|
+
},
|
|
26943
|
+
{
|
|
26944
|
+
code: "H002",
|
|
26945
|
+
title: "Unused indexes",
|
|
26946
|
+
description: "Indexes with no scans",
|
|
26947
|
+
category: "indexes",
|
|
26948
|
+
sort_order: null,
|
|
26949
|
+
is_system_report: false
|
|
26950
|
+
},
|
|
26951
|
+
{
|
|
26952
|
+
code: "H003",
|
|
26953
|
+
title: "Non-indexed foreign keys",
|
|
26954
|
+
description: "FKs missing supporting indexes",
|
|
26955
|
+
category: "indexes",
|
|
26956
|
+
sort_order: null,
|
|
26957
|
+
is_system_report: false
|
|
26958
|
+
},
|
|
26959
|
+
{
|
|
26960
|
+
code: "H004",
|
|
26961
|
+
title: "Redundant indexes",
|
|
26962
|
+
description: "Indexes covered by other indexes",
|
|
26963
|
+
category: "indexes",
|
|
26964
|
+
sort_order: null,
|
|
26965
|
+
is_system_report: false
|
|
26966
|
+
},
|
|
26967
|
+
{
|
|
26968
|
+
code: "J001",
|
|
26969
|
+
title: "Capacity planning",
|
|
26970
|
+
description: "Growth trends and resource projections",
|
|
26971
|
+
category: "capacity",
|
|
26972
|
+
sort_order: null,
|
|
26973
|
+
is_system_report: false
|
|
26974
|
+
},
|
|
26975
|
+
{
|
|
26976
|
+
code: "K001",
|
|
26977
|
+
title: "Globally aggregated query metrics",
|
|
26978
|
+
description: "Overall query stats summary",
|
|
26979
|
+
category: "queries",
|
|
26980
|
+
sort_order: null,
|
|
26981
|
+
is_system_report: false
|
|
26982
|
+
},
|
|
26983
|
+
{
|
|
26984
|
+
code: "K002",
|
|
26985
|
+
title: "Workload type",
|
|
26986
|
+
description: "Read/write/mixed workload classification",
|
|
26987
|
+
category: "queries",
|
|
26988
|
+
sort_order: null,
|
|
26989
|
+
is_system_report: false
|
|
26990
|
+
},
|
|
26991
|
+
{
|
|
26992
|
+
code: "K003",
|
|
26993
|
+
title: "Top queries by total time",
|
|
26994
|
+
description: "Highest total execution + planning time",
|
|
26995
|
+
category: "queries",
|
|
26996
|
+
sort_order: null,
|
|
26997
|
+
is_system_report: false
|
|
26998
|
+
},
|
|
26999
|
+
{
|
|
27000
|
+
code: "K004",
|
|
27001
|
+
title: "Top queries by temp bytes written",
|
|
27002
|
+
description: "Queries spilling to disk",
|
|
27003
|
+
category: "queries",
|
|
27004
|
+
sort_order: null,
|
|
27005
|
+
is_system_report: false
|
|
27006
|
+
},
|
|
27007
|
+
{
|
|
27008
|
+
code: "K005",
|
|
27009
|
+
title: "Top queries by WAL generation",
|
|
27010
|
+
description: "Queries generating most WAL",
|
|
27011
|
+
category: "queries",
|
|
27012
|
+
sort_order: null,
|
|
27013
|
+
is_system_report: false
|
|
27014
|
+
},
|
|
27015
|
+
{
|
|
27016
|
+
code: "K006",
|
|
27017
|
+
title: "Top queries by shared blocks read",
|
|
27018
|
+
description: "Queries with most disk reads",
|
|
27019
|
+
category: "queries",
|
|
27020
|
+
sort_order: null,
|
|
27021
|
+
is_system_report: false
|
|
27022
|
+
},
|
|
27023
|
+
{
|
|
27024
|
+
code: "K007",
|
|
27025
|
+
title: "Top queries by shared blocks hit",
|
|
27026
|
+
description: "Queries with most buffer hits",
|
|
27027
|
+
category: "queries",
|
|
27028
|
+
sort_order: null,
|
|
27029
|
+
is_system_report: false
|
|
27030
|
+
},
|
|
27031
|
+
{
|
|
27032
|
+
code: "K008",
|
|
27033
|
+
title: "Top queries by shared blocks accessed",
|
|
27034
|
+
description: "Queries touching most data",
|
|
27035
|
+
category: "queries",
|
|
27036
|
+
sort_order: null,
|
|
27037
|
+
is_system_report: false
|
|
27038
|
+
},
|
|
27039
|
+
{
|
|
27040
|
+
code: "L001",
|
|
27041
|
+
title: "Table sizes",
|
|
27042
|
+
description: "Table and toast sizes",
|
|
27043
|
+
category: "schema",
|
|
27044
|
+
sort_order: null,
|
|
27045
|
+
is_system_report: false
|
|
27046
|
+
},
|
|
27047
|
+
{
|
|
27048
|
+
code: "L002",
|
|
27049
|
+
title: "Data types being used",
|
|
27050
|
+
description: "Column type distribution",
|
|
27051
|
+
category: "schema",
|
|
27052
|
+
sort_order: null,
|
|
27053
|
+
is_system_report: false
|
|
27054
|
+
},
|
|
27055
|
+
{
|
|
27056
|
+
code: "L003",
|
|
27057
|
+
title: "Integer overflow risks in primary keys",
|
|
27058
|
+
description: "PKs approaching integer limits",
|
|
27059
|
+
category: "schema",
|
|
27060
|
+
sort_order: null,
|
|
27061
|
+
is_system_report: false
|
|
27062
|
+
},
|
|
27063
|
+
{
|
|
27064
|
+
code: "L004",
|
|
27065
|
+
title: "Tables without primary key",
|
|
27066
|
+
description: "Tables missing PK or unique constraint",
|
|
27067
|
+
category: "schema",
|
|
27068
|
+
sort_order: null,
|
|
27069
|
+
is_system_report: false
|
|
27070
|
+
},
|
|
27071
|
+
{
|
|
27072
|
+
code: "M001",
|
|
27073
|
+
title: "Top queries by mean execution time",
|
|
27074
|
+
description: "Slowest queries on average",
|
|
27075
|
+
category: "queries",
|
|
27076
|
+
sort_order: null,
|
|
27077
|
+
is_system_report: false
|
|
27078
|
+
},
|
|
27079
|
+
{
|
|
27080
|
+
code: "M002",
|
|
27081
|
+
title: "Top queries by rows processed",
|
|
27082
|
+
description: "Queries touching most rows",
|
|
27083
|
+
category: "queries",
|
|
27084
|
+
sort_order: null,
|
|
27085
|
+
is_system_report: false
|
|
27086
|
+
},
|
|
27087
|
+
{
|
|
27088
|
+
code: "M003",
|
|
27089
|
+
title: "Top queries by I/O time",
|
|
27090
|
+
description: "Queries with highest I/O wait",
|
|
27091
|
+
category: "queries",
|
|
27092
|
+
sort_order: null,
|
|
27093
|
+
is_system_report: false
|
|
27094
|
+
},
|
|
27095
|
+
{
|
|
27096
|
+
code: "N001",
|
|
27097
|
+
title: "Wait events by type and query",
|
|
27098
|
+
description: "Wait event analysis",
|
|
27099
|
+
category: "waits",
|
|
27100
|
+
sort_order: null,
|
|
27101
|
+
is_system_report: false
|
|
27102
|
+
}
|
|
27103
|
+
];
|
|
27104
|
+
|
|
27105
|
+
// lib/checkup-dictionary.ts
|
|
27106
|
+
var dictionaryByCode = new Map(CHECKUP_DICTIONARY_DATA.map((entry) => [entry.code.toUpperCase(), entry]));
|
|
27107
|
+
function buildCheckInfoMap() {
|
|
27108
|
+
const result = {};
|
|
27109
|
+
for (const entry of CHECKUP_DICTIONARY_DATA) {
|
|
27110
|
+
result[entry.code] = entry.title;
|
|
27111
|
+
}
|
|
27112
|
+
return result;
|
|
27113
|
+
}
|
|
27114
|
+
|
|
26545
27115
|
// lib/checkup.ts
|
|
26546
27116
|
var __dirname = "/builds/postgres-ai/postgres_ai/cli/lib";
|
|
26547
27117
|
var SECONDS_PER_DAY = 86400;
|
|
@@ -27185,6 +27755,23 @@ async function generateD004(client, nodeName) {
|
|
|
27185
27755
|
};
|
|
27186
27756
|
return report;
|
|
27187
27757
|
}
|
|
27758
|
+
async function generateD001(client, nodeName) {
|
|
27759
|
+
const report = createBaseReport("D001", "Logging settings", nodeName);
|
|
27760
|
+
const postgresVersion = await getPostgresVersion(client);
|
|
27761
|
+
const pgMajorVersion = parseInt(postgresVersion.server_major_ver, 10) || 16;
|
|
27762
|
+
const allSettings = await getSettings(client, pgMajorVersion);
|
|
27763
|
+
const loggingSettings = {};
|
|
27764
|
+
for (const [name, setting] of Object.entries(allSettings)) {
|
|
27765
|
+
if (name.startsWith("log_") || name.startsWith("logging_")) {
|
|
27766
|
+
loggingSettings[name] = setting;
|
|
27767
|
+
}
|
|
27768
|
+
}
|
|
27769
|
+
report.results[nodeName] = {
|
|
27770
|
+
data: loggingSettings,
|
|
27771
|
+
postgres_version: postgresVersion
|
|
27772
|
+
};
|
|
27773
|
+
return report;
|
|
27774
|
+
}
|
|
27188
27775
|
async function generateF001(client, nodeName) {
|
|
27189
27776
|
const report = createBaseReport("F001", "Autovacuum: current settings", nodeName);
|
|
27190
27777
|
const postgresVersion = await getPostgresVersion(client);
|
|
@@ -27285,32 +27872,88 @@ async function generateG001(client, nodeName) {
|
|
|
27285
27872
|
};
|
|
27286
27873
|
return report;
|
|
27287
27874
|
}
|
|
27875
|
+
async function generateG003(client, nodeName) {
|
|
27876
|
+
const report = createBaseReport("G003", "Timeouts, locks, deadlocks", nodeName);
|
|
27877
|
+
const postgresVersion = await getPostgresVersion(client);
|
|
27878
|
+
const pgMajorVersion = parseInt(postgresVersion.server_major_ver, 10) || 16;
|
|
27879
|
+
const allSettings = await getSettings(client, pgMajorVersion);
|
|
27880
|
+
const lockTimeoutSettingNames = [
|
|
27881
|
+
"lock_timeout",
|
|
27882
|
+
"statement_timeout",
|
|
27883
|
+
"idle_in_transaction_session_timeout",
|
|
27884
|
+
"idle_session_timeout",
|
|
27885
|
+
"deadlock_timeout",
|
|
27886
|
+
"max_locks_per_transaction",
|
|
27887
|
+
"max_pred_locks_per_transaction",
|
|
27888
|
+
"max_pred_locks_per_relation",
|
|
27889
|
+
"max_pred_locks_per_page",
|
|
27890
|
+
"log_lock_waits",
|
|
27891
|
+
"transaction_timeout"
|
|
27892
|
+
];
|
|
27893
|
+
const lockSettings = {};
|
|
27894
|
+
for (const name of lockTimeoutSettingNames) {
|
|
27895
|
+
if (allSettings[name]) {
|
|
27896
|
+
lockSettings[name] = allSettings[name];
|
|
27897
|
+
}
|
|
27898
|
+
}
|
|
27899
|
+
let deadlockStats = null;
|
|
27900
|
+
let deadlockError = null;
|
|
27901
|
+
try {
|
|
27902
|
+
const statsResult = await client.query(`
|
|
27903
|
+
select
|
|
27904
|
+
coalesce(sum(deadlocks), 0)::bigint as deadlocks,
|
|
27905
|
+
coalesce(sum(conflicts), 0)::bigint as conflicts,
|
|
27906
|
+
min(stats_reset)::text as stats_reset
|
|
27907
|
+
from pg_stat_database
|
|
27908
|
+
where datname = current_database()
|
|
27909
|
+
`);
|
|
27910
|
+
if (statsResult.rows.length > 0) {
|
|
27911
|
+
const row = statsResult.rows[0];
|
|
27912
|
+
deadlockStats = {
|
|
27913
|
+
deadlocks: parseInt(row.deadlocks, 10),
|
|
27914
|
+
conflicts: parseInt(row.conflicts, 10),
|
|
27915
|
+
stats_reset: row.stats_reset || null
|
|
27916
|
+
};
|
|
27917
|
+
}
|
|
27918
|
+
} catch (err) {
|
|
27919
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
27920
|
+
console.log(`[G003] Error querying deadlock stats: ${errorMsg}`);
|
|
27921
|
+
deadlockError = errorMsg;
|
|
27922
|
+
}
|
|
27923
|
+
report.results[nodeName] = {
|
|
27924
|
+
data: {
|
|
27925
|
+
settings: lockSettings,
|
|
27926
|
+
deadlock_stats: deadlockStats,
|
|
27927
|
+
...deadlockError && { deadlock_stats_error: deadlockError }
|
|
27928
|
+
},
|
|
27929
|
+
postgres_version: postgresVersion
|
|
27930
|
+
};
|
|
27931
|
+
return report;
|
|
27932
|
+
}
|
|
27288
27933
|
var REPORT_GENERATORS = {
|
|
27289
27934
|
A002: generateA002,
|
|
27290
27935
|
A003: generateA003,
|
|
27291
27936
|
A004: generateA004,
|
|
27292
27937
|
A007: generateA007,
|
|
27293
27938
|
A013: generateA013,
|
|
27939
|
+
D001: generateD001,
|
|
27294
27940
|
D004: generateD004,
|
|
27295
27941
|
F001: generateF001,
|
|
27296
27942
|
G001: generateG001,
|
|
27943
|
+
G003: generateG003,
|
|
27297
27944
|
H001: generateH001,
|
|
27298
27945
|
H002: generateH002,
|
|
27299
27946
|
H004: generateH004
|
|
27300
27947
|
};
|
|
27301
|
-
var CHECK_INFO = {
|
|
27302
|
-
|
|
27303
|
-
|
|
27304
|
-
|
|
27305
|
-
|
|
27306
|
-
|
|
27307
|
-
|
|
27308
|
-
|
|
27309
|
-
|
|
27310
|
-
H001: "Invalid indexes",
|
|
27311
|
-
H002: "Unused indexes",
|
|
27312
|
-
H004: "Redundant indexes"
|
|
27313
|
-
};
|
|
27948
|
+
var CHECK_INFO = (() => {
|
|
27949
|
+
const fullMap = buildCheckInfoMap();
|
|
27950
|
+
const expressCheckIds = Object.keys(REPORT_GENERATORS);
|
|
27951
|
+
const filtered = {};
|
|
27952
|
+
for (const checkId of expressCheckIds) {
|
|
27953
|
+
filtered[checkId] = fullMap[checkId] || checkId;
|
|
27954
|
+
}
|
|
27955
|
+
return filtered;
|
|
27956
|
+
})();
|
|
27314
27957
|
async function generateAllReports(client, nodeName = "node-01", onProgress) {
|
|
27315
27958
|
const reports = {};
|
|
27316
27959
|
const entries = Object.entries(REPORT_GENERATORS);
|
|
@@ -27329,6 +27972,12 @@ async function generateAllReports(client, nodeName = "node-01", onProgress) {
|
|
|
27329
27972
|
return reports;
|
|
27330
27973
|
}
|
|
27331
27974
|
|
|
27975
|
+
// lib/checkup-dictionary.ts
|
|
27976
|
+
var dictionaryByCode2 = new Map(CHECKUP_DICTIONARY_DATA.map((entry) => [entry.code.toUpperCase(), entry]));
|
|
27977
|
+
function getCheckupEntry(code) {
|
|
27978
|
+
return dictionaryByCode2.get(code.toUpperCase()) ?? null;
|
|
27979
|
+
}
|
|
27980
|
+
|
|
27332
27981
|
// lib/checkup-api.ts
|
|
27333
27982
|
import * as https from "https";
|
|
27334
27983
|
import { URL as URL3 } from "url";
|
|
@@ -28835,18 +29484,16 @@ program2.command("unprepare-db [conn]").description("remove monitoring setup: dr
|
|
|
28835
29484
|
closeReadline();
|
|
28836
29485
|
}
|
|
28837
29486
|
});
|
|
28838
|
-
program2.command("checkup [conn]").description("generate health check reports directly from PostgreSQL (express mode)").option("--check-id <id>", `specific check to run
|
|
29487
|
+
program2.command("checkup [conn]").description("generate health check reports directly from PostgreSQL (express mode)").option("--check-id <id>", `specific check to run (see list below), or ALL`, "ALL").option("--node-name <name>", "node name for reports", "node-01").option("--output <path>", "output directory for JSON files").option("--[no-]upload", "upload JSON results to PostgresAI (default: enabled; requires API key)", undefined).option("--project <project>", "project name or ID for remote upload (used with --upload; defaults to config defaultProject; auto-generated on first run)").option("--json", "output JSON to stdout (implies --no-upload)").addHelpText("after", [
|
|
28839
29488
|
"",
|
|
28840
29489
|
"Available checks:",
|
|
28841
29490
|
...Object.entries(CHECK_INFO).map(([id, title]) => ` ${id}: ${title}`),
|
|
28842
29491
|
"",
|
|
28843
29492
|
"Examples:",
|
|
28844
29493
|
" postgresai checkup postgresql://user:pass@host:5432/db",
|
|
28845
|
-
" postgresai checkup postgresql://user:pass@host:5432/db --check-id
|
|
29494
|
+
" postgresai checkup postgresql://user:pass@host:5432/db --check-id D001",
|
|
28846
29495
|
" postgresai checkup postgresql://user:pass@host:5432/db --output ./reports",
|
|
28847
29496
|
" postgresai checkup postgresql://user:pass@host:5432/db --project my_project",
|
|
28848
|
-
" postgresai set-default-project my_project",
|
|
28849
|
-
" postgresai checkup postgresql://user:pass@host:5432/db",
|
|
28850
29497
|
" postgresai checkup postgresql://user:pass@host:5432/db --no-upload --json"
|
|
28851
29498
|
].join(`
|
|
28852
29499
|
`)).action(async (conn, opts, cmd) => {
|
|
@@ -28894,8 +29541,14 @@ program2.command("checkup [conn]").description("generate health check reports di
|
|
|
28894
29541
|
const generator = REPORT_GENERATORS[checkId];
|
|
28895
29542
|
if (!generator) {
|
|
28896
29543
|
spinner.stop();
|
|
28897
|
-
|
|
28898
|
-
|
|
29544
|
+
const dictEntry = getCheckupEntry(checkId);
|
|
29545
|
+
if (dictEntry) {
|
|
29546
|
+
console.error(`Check ${checkId} (${dictEntry.title}) is not yet available in express mode.`);
|
|
29547
|
+
console.error(`Express-mode checks: ${Object.keys(CHECK_INFO).join(", ")}`);
|
|
29548
|
+
} else {
|
|
29549
|
+
console.error(`Unknown check ID: ${opts.checkId}`);
|
|
29550
|
+
console.error(`See 'postgresai checkup --help' for available checks.`);
|
|
29551
|
+
}
|
|
28899
29552
|
process.exitCode = 1;
|
|
28900
29553
|
return;
|
|
28901
29554
|
}
|