4343 metric_replication_delay_bytes ,
4444 metric_wal_file_amount ,
4545 metric_incoming_replication_running ,
46+ metric_multixact_members_per_mxid ,
47+ metric_multixact_remaining_ratio ,
48+ metric_xid_remaining_ratio ,
49+ metric_multixact_members_remaining_ratio ,
4650)
4751
48- from postgresql_metrics .localhost_postgres_stats import get_amount_of_wal_files
52+ from postgresql_metrics .localhost_postgres_stats import get_amount_of_wal_files , get_multixact_member_files
4953
5054from postgresql_metrics .postgres_queries import (
5155 get_client_connections_amount ,
6064 get_replication_delays ,
6165 get_tables_with_oids_for_current_db ,
6266 get_wal_receiver_status ,
67+ get_max_mxid_age ,
68+ get_max_xid_age ,
6369)
6470
71+ MEMBERS_PER_MEMBER_FILE = 52352
72+ MAX_MULTIXACT_MEMBERS = 2 ** 32
73+ WRAPAROUND_LIMIT = (2 ** 32 / 2 ) - 1
6574
6675# Notice that all functions here are expected to return a list of metrics.
6776# Notice also that the names of these functions should match the configuration.
6877
69- def get_stats_client_connections (db_connection ):
78+
79+ def get_stats_client_connections (_data_dir , db_connection ):
7080 client_amount = get_client_connections_amount (db_connection )
7181 return [metric_client_connections (client_amount )]
7282
7383
74- def get_stats_disk_usage_for_database (db_connection ):
84+ def get_stats_disk_usage_for_database (_data_dir , db_connection ):
7585 db_size = get_disk_usage_for_database (db_connection )
7686 return [metric_database_size (db_size [0 ], db_size [1 ])]
7787
7888
79- def get_stats_tx_rate_for_database (db_connection ):
89+ def get_stats_tx_rate_for_database (_data_dir , db_connection ):
8090 db_name , tx_rate , tx_rollbacks = get_transaction_rate_for_database (db_connection )
8191 if tx_rate is not None :
8292 return [metric_transaction_rate (db_name , tx_rate ),
@@ -85,15 +95,15 @@ def get_stats_tx_rate_for_database(db_connection):
8595 return []
8696
8797
88- def get_stats_seconds_since_last_vacuum_per_table (db_connection ):
98+ def get_stats_seconds_since_last_vacuum_per_table (_data_dir , db_connection ):
8999 last_vacuums_data = get_seconds_since_last_vacuum_per_table (db_connection )
90100 metrics = []
91101 for db_name , table_name , seconds_since in last_vacuums_data :
92102 metrics .append (metric_seconds_since_last_vacuum (db_name , table_name , seconds_since ))
93103 return metrics
94104
95105
96- def get_stats_heap_hit_statistics (db_connection ):
106+ def get_stats_heap_hit_statistics (_data_dir , db_connection ):
97107 db_name , heap_read , heap_hit , heap_hit_ratio = get_heap_hit_statistics (db_connection )
98108 metrics = []
99109 if heap_hit_ratio is not None :
@@ -103,7 +113,7 @@ def get_stats_heap_hit_statistics(db_connection):
103113 return metrics
104114
105115
106- def get_stats_lock_statistics (db_connection ):
116+ def get_stats_lock_statistics (_data_dir , db_connection ):
107117 locks_by_type , [total_locks_waiting , total_locks_granted ] = get_lock_statistics (db_connection )
108118 metrics = []
109119 for lock_type , [locks_waiting , locks_granted ] in locks_by_type .items ():
@@ -114,15 +124,15 @@ def get_stats_lock_statistics(db_connection):
114124 return metrics
115125
116126
117- def get_stats_oldest_transaction_timestamp (db_connection ):
127+ def get_stats_oldest_transaction_timestamp (_data_dir , db_connection ):
118128 db_name , sec_since_oldest_xact_start = get_oldest_transaction_timestamp (db_connection )
119129 metrics = []
120130 if sec_since_oldest_xact_start is not None :
121131 metrics .append (metric_sec_since_oldest_xact_start (db_name , sec_since_oldest_xact_start ))
122132 return metrics
123133
124134
125- def get_stats_table_bloat (db_connection ):
135+ def get_stats_table_bloat (_data_dir , db_connection ):
126136 tables_with_oids = get_tables_with_oids_for_current_db (db_connection )
127137 metrics = []
128138 for table_oid , table_name in tables_with_oids :
@@ -132,7 +142,7 @@ def get_stats_table_bloat(db_connection):
132142 return metrics
133143
134144
135- def get_stats_index_hit_rates (db_connection ):
145+ def get_stats_index_hit_rates (_data_dir , db_connection ):
136146 index_hit_rates = get_index_hit_rates (db_connection )
137147 metrics = []
138148 for db_name , table_name , index_hit_ratio in index_hit_rates :
@@ -141,18 +151,56 @@ def get_stats_index_hit_rates(db_connection):
141151 return metrics
142152
143153
144- def get_stats_replication_delays (db_connection ):
154+ def get_stats_replication_delays (_data_dir , db_connection ):
145155 replication_delays = get_replication_delays (db_connection )
146156 metrics = []
147157 for client_addr , delay_in_bytes in replication_delays :
148158 metrics .append (metric_replication_delay_bytes (client_addr , delay_in_bytes ))
149159 return metrics
150160
151161
152- def get_stats_wal_file_amount (data_dir ):
162+ def _get_multixact_members (data_dir ):
163+ return get_multixact_member_files (data_dir ) * MEMBERS_PER_MEMBER_FILE
164+
165+
166+ def get_multixact_members_per_mxid (data_dir , db_connection ):
167+ members = _get_multixact_members (data_dir )
168+ mxid_age = get_max_mxid_age (db_connection )
169+ if not mxid_age :
170+ return []
171+ members_per_id = round (members / mxid_age , 2 )
172+ return [metric_multixact_members_per_mxid (members_per_id )]
173+
174+
175+ def get_multixact_members_remaining_ratio (data_dir , _db_connection ):
176+ members = _get_multixact_members (data_dir )
177+ ratio = round (members / MAX_MULTIXACT_MEMBERS , 2 )
178+ percentage_remaining = (1.0 - ratio ) * 100
179+ return [metric_multixact_members_remaining_ratio (percentage_remaining )]
180+
181+
182+ def get_multixact_remaining_ratio (_data_dir , db_connection ):
183+ mxid_age = get_max_mxid_age (db_connection )
184+ if not mxid_age :
185+ return []
186+ ratio = round (mxid_age / WRAPAROUND_LIMIT , 2 )
187+ percentage_remaining = (1.0 - ratio ) * 100
188+ return [metric_multixact_remaining_ratio (percentage_remaining )]
189+
190+
191+ def get_xid_remaining_ratio (_data_dir , db_connection ):
192+ xid_age = get_max_xid_age (db_connection )
193+ if not xid_age :
194+ return []
195+ ratio = round (xid_age / WRAPAROUND_LIMIT , 2 )
196+ percentage_remaining = (1.0 - ratio ) * 100
197+ return [metric_xid_remaining_ratio (percentage_remaining )]
198+
199+
200+ def get_stats_wal_file_amount (data_dir , _db_connection ):
153201 return [metric_wal_file_amount (get_amount_of_wal_files (data_dir ))]
154202
155203
156- def get_stats_incoming_replication_status (db_connection ):
204+ def get_stats_incoming_replication_status (_data_dir , db_connection ):
157205 return [metric_incoming_replication_running (host , is_streaming )
158206 for host , is_streaming in get_wal_receiver_status (db_connection )]
0 commit comments