@@ -274,7 +274,7 @@ def generate_a004_cluster_report(self, cluster: str = "local", node_name: str =
274274 'active_connections' : f'sum(last_over_time(pgwatch_pg_stat_activity_count{{cluster="{ cluster } ", node_name="{ node_name } ", state="active"}}[3h]))' ,
275275 'idle_connections' : f'sum(last_over_time(pgwatch_pg_stat_activity_count{{cluster="{ cluster } ", node_name="{ node_name } ", state="idle"}}[3h]))' ,
276276 'total_connections' : f'sum(last_over_time(pgwatch_pg_stat_activity_count{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h]))' ,
277- 'database_sizes' : f'sum(last_over_time(pgwatch_pg_database_size_bytes {{cluster="{ cluster } ", node_name="{ node_name } "}}[3h]))' ,
277+ 'database_sizes' : f'sum(last_over_time(pgwatch_db_size_size_b {{cluster="{ cluster } ", node_name="{ node_name } "}}[3h]))' ,
278278 'cache_hit_ratio' : f'sum(last_over_time(pgwatch_db_stats_blks_hit{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])) / clamp_min(sum(last_over_time(pgwatch_db_stats_blks_hit{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])) + sum(last_over_time(pgwatch_db_stats_blks_read{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])), 1) * 100' ,
279279 'transactions_per_sec' : f'sum(rate(pgwatch_db_stats_xact_commit{{cluster="{ cluster } ", node_name="{ node_name } "}}[5m])) + sum(rate(pgwatch_db_stats_xact_rollback{{cluster="{ cluster } ", node_name="{ node_name } "}}[5m]))' ,
280280 'checkpoints_per_sec' : f'sum(rate(pgwatch_pg_stat_bgwriter_checkpoints_timed{{cluster="{ cluster } ", node_name="{ node_name } "}}[5m])) + sum(rate(pgwatch_pg_stat_bgwriter_checkpoints_req{{cluster="{ cluster } ", node_name="{ node_name } "}}[5m]))' ,
@@ -297,7 +297,7 @@ def generate_a004_cluster_report(self, cluster: str = "local", node_name: str =
297297 }
298298
299299 # Get database sizes
300- db_sizes_query = f'last_over_time(pgwatch_pg_database_size_bytes {{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])'
300+ db_sizes_query = f'last_over_time(pgwatch_db_size_size_b {{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])'
301301 db_sizes_result = self .query_instant (db_sizes_query )
302302 database_sizes = {}
303303
@@ -374,6 +374,17 @@ def generate_h001_invalid_indexes_report(self, cluster: str = "local", node_name
374374 # Get all databases
375375 databases = self .get_all_databases (cluster , node_name )
376376
377+ # Get database sizes
378+ db_sizes_query = f'last_over_time(pgwatch_db_size_size_b{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])'
379+ db_sizes_result = self .query_instant (db_sizes_query )
380+ database_sizes = {}
381+
382+ if db_sizes_result .get ('status' ) == 'success' and db_sizes_result .get ('data' , {}).get ('result' ):
383+ for result in db_sizes_result ['data' ]['result' ]:
384+ db_name = result ['metric' ].get ('datname' , 'unknown' )
385+ size_bytes = float (result ['value' ][1 ])
386+ database_sizes [db_name ] = size_bytes
387+
377388 invalid_indexes_by_db = {}
378389 for db_name in databases :
379390 # Query invalid indexes for each database
@@ -408,11 +419,14 @@ def generate_h001_invalid_indexes_report(self, cluster: str = "local", node_name
408419 invalid_indexes .append (invalid_index )
409420 total_size += index_size_bytes
410421
422+ db_size_bytes = database_sizes .get (db_name , 0 )
411423 invalid_indexes_by_db [db_name ] = {
412424 "invalid_indexes" : invalid_indexes ,
413425 "total_count" : len (invalid_indexes ),
414426 "total_size_bytes" : total_size ,
415- "total_size_pretty" : self .format_bytes (total_size )
427+ "total_size_pretty" : self .format_bytes (total_size ),
428+ "database_size_bytes" : db_size_bytes ,
429+ "database_size_pretty" : self .format_bytes (db_size_bytes )
416430 }
417431
418432 return self .format_report_data ("H001" , invalid_indexes_by_db , node_name )
@@ -433,6 +447,17 @@ def generate_h002_unused_indexes_report(self, cluster: str = "local", node_name:
433447 # Get all databases
434448 databases = self .get_all_databases (cluster , node_name )
435449
450+ # Get database sizes
451+ db_sizes_query = f'last_over_time(pgwatch_db_size_size_b{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])'
452+ db_sizes_result = self .query_instant (db_sizes_query )
453+ database_sizes = {}
454+
455+ if db_sizes_result .get ('status' ) == 'success' and db_sizes_result .get ('data' , {}).get ('result' ):
456+ for result in db_sizes_result ['data' ]['result' ]:
457+ db_name = result ['metric' ].get ('datname' , 'unknown' )
458+ size_bytes = float (result ['value' ][1 ])
459+ database_sizes [db_name ] = size_bytes
460+
436461 # Query postmaster uptime to get startup time
437462 postmaster_uptime_query = f'last_over_time(pgwatch_db_stats_postmaster_uptime_s{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])'
438463 postmaster_uptime_result = self .query_instant (postmaster_uptime_query )
@@ -509,11 +534,14 @@ def generate_h002_unused_indexes_report(self, cluster: str = "local", node_name:
509534
510535 total_unused_size = sum (idx ['index_size_bytes' ] for idx in unused_indexes )
511536
537+ db_size_bytes = database_sizes .get (db_name , 0 )
512538 unused_indexes_by_db [db_name ] = {
513539 "unused_indexes" : unused_indexes ,
514540 "total_count" : len (unused_indexes ),
515541 "total_size_bytes" : total_unused_size ,
516542 "total_size_pretty" : self .format_bytes (total_unused_size ),
543+ "database_size_bytes" : db_size_bytes ,
544+ "database_size_pretty" : self .format_bytes (db_size_bytes ),
517545 "stats_reset" : {
518546 "stats_reset_epoch" : stats_reset_epoch ,
519547 "stats_reset_time" : stats_reset_time ,
@@ -542,6 +570,17 @@ def generate_h004_redundant_indexes_report(self, cluster: str = "local", node_na
542570 # Get all databases
543571 databases = self .get_all_databases (cluster , node_name )
544572
573+ # Get database sizes
574+ db_sizes_query = f'last_over_time(pgwatch_db_size_size_b{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])'
575+ db_sizes_result = self .query_instant (db_sizes_query )
576+ database_sizes = {}
577+
578+ if db_sizes_result .get ('status' ) == 'success' and db_sizes_result .get ('data' , {}).get ('result' ):
579+ for result in db_sizes_result ['data' ]['result' ]:
580+ db_name = result ['metric' ].get ('datname' , 'unknown' )
581+ size_bytes = float (result ['value' ][1 ])
582+ database_sizes [db_name ] = size_bytes
583+
545584 redundant_indexes_by_db = {}
546585 for db_name in databases :
547586 # Fetch index definitions from the sink for this database (used to aid remediation)
@@ -606,11 +645,14 @@ def generate_h004_redundant_indexes_report(self, cluster: str = "local", node_na
606645 # Sort by index size descending
607646 redundant_indexes .sort (key = lambda x : x ['index_size_bytes' ], reverse = True )
608647
648+ db_size_bytes = database_sizes .get (db_name , 0 )
609649 redundant_indexes_by_db [db_name ] = {
610650 "redundant_indexes" : redundant_indexes ,
611651 "total_count" : len (redundant_indexes ),
612652 "total_size_bytes" : total_size ,
613- "total_size_pretty" : self .format_bytes (total_size )
653+ "total_size_pretty" : self .format_bytes (total_size ),
654+ "database_size_bytes" : db_size_bytes ,
655+ "database_size_pretty" : self .format_bytes (db_size_bytes )
614656 }
615657
616658 return self .format_report_data ("H004" , redundant_indexes_by_db , node_name )
@@ -872,6 +914,17 @@ def generate_f005_btree_bloat_report(self, cluster: str = "local", node_name: st
872914 # Get all databases
873915 databases = self .get_all_databases (cluster , node_name )
874916
917+ # Get database sizes
918+ db_sizes_query = f'last_over_time(pgwatch_db_size_size_b{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])'
919+ db_sizes_result = self .query_instant (db_sizes_query )
920+ database_sizes = {}
921+
922+ if db_sizes_result .get ('status' ) == 'success' and db_sizes_result .get ('data' , {}).get ('result' ):
923+ for result in db_sizes_result ['data' ]['result' ]:
924+ db_name = result ['metric' ].get ('datname' , 'unknown' )
925+ size_bytes = float (result ['value' ][1 ])
926+ database_sizes [db_name ] = size_bytes
927+
875928 bloated_indexes_by_db = {}
876929 for db_name in databases :
877930 # Query btree bloat using multiple metrics for each database with last_over_time [1d]
@@ -922,11 +975,14 @@ def generate_f005_btree_bloat_report(self, cluster: str = "local", node_name: st
922975 # Sort by bloat percentage descending
923976 bloated_indexes_list .sort (key = lambda x : x ['bloat_pct' ], reverse = True )
924977
978+ db_size_bytes = database_sizes .get (db_name , 0 )
925979 bloated_indexes_by_db [db_name ] = {
926980 "bloated_indexes" : bloated_indexes_list ,
927981 "total_count" : len (bloated_indexes_list ),
928982 "total_bloat_size_bytes" : total_bloat_size ,
929- "total_bloat_size_pretty" : self .format_bytes (total_bloat_size )
983+ "total_bloat_size_pretty" : self .format_bytes (total_bloat_size ),
984+ "database_size_bytes" : db_size_bytes ,
985+ "database_size_pretty" : self .format_bytes (db_size_bytes )
930986 }
931987
932988 return self .format_report_data ("F005" , bloated_indexes_by_db , node_name )
@@ -1120,6 +1176,17 @@ def generate_f004_heap_bloat_report(self, cluster: str = "local", node_name: str
11201176 if not databases :
11211177 print ("Warning: F004 - No databases found" )
11221178
1179+ # Get database sizes
1180+ db_sizes_query = f'last_over_time(pgwatch_db_size_size_b{{cluster="{ cluster } ", node_name="{ node_name } "}}[3h])'
1181+ db_sizes_result = self .query_instant (db_sizes_query )
1182+ database_sizes = {}
1183+
1184+ if db_sizes_result .get ('status' ) == 'success' and db_sizes_result .get ('data' , {}).get ('result' ):
1185+ for result in db_sizes_result ['data' ]['result' ]:
1186+ db_name = result ['metric' ].get ('datname' , 'unknown' )
1187+ size_bytes = float (result ['value' ][1 ])
1188+ database_sizes [db_name ] = size_bytes
1189+
11231190 bloated_tables_by_db = {}
11241191 for db_name in databases :
11251192 # Query table bloat using multiple metrics for each database
@@ -1174,11 +1241,14 @@ def generate_f004_heap_bloat_report(self, cluster: str = "local", node_name: str
11741241 # Sort by bloat percentage descending
11751242 bloated_tables_list .sort (key = lambda x : x ['bloat_pct' ], reverse = True )
11761243
1244+ db_size_bytes = database_sizes .get (db_name , 0 )
11771245 bloated_tables_by_db [db_name ] = {
11781246 "bloated_tables" : bloated_tables_list ,
11791247 "total_count" : len (bloated_tables_list ),
11801248 "total_bloat_size_bytes" : total_bloat_size ,
1181- "total_bloat_size_pretty" : self .format_bytes (total_bloat_size )
1249+ "total_bloat_size_pretty" : self .format_bytes (total_bloat_size ),
1250+ "database_size_bytes" : db_size_bytes ,
1251+ "database_size_pretty" : self .format_bytes (db_size_bytes )
11821252 }
11831253
11841254 return self .format_report_data ("F004" , bloated_tables_by_db , node_name )
0 commit comments