diff --git a/docs/rest_api.rst b/docs/rest_api.rst index be8249fb..e5323b82 100644 --- a/docs/rest_api.rst +++ b/docs/rest_api.rst @@ -139,6 +139,9 @@ Retrieve the Patroni metrics in Prometheus format through the ``GET /metrics`` e # HELP patroni_replica Value is 1 if this node is a replica, 0 otherwise. # TYPE patroni_replica gauge patroni_replica{scope="batman"} 0 + # HELP patroni_sync_standby Value is 1 if this node is a sync standby replica, 0 otherwise. + # TYPE patroni_sync_standby gauge + patroni_sync_standby{scope="batman"} 0 # HELP patroni_xlog_received_location Current location of the received Postgres transaction log, 0 if this node is not a replica. # TYPE patroni_xlog_received_location counter patroni_xlog_received_location{scope="batman"} 0 diff --git a/patroni/api.py b/patroni/api.py index 7a049bae..ebbdee9a 100644 --- a/patroni/api.py +++ b/patroni/api.py @@ -269,6 +269,10 @@ class RestApiHandler(BaseHTTPRequestHandler): metrics.append("# TYPE patroni_replica gauge") metrics.append("patroni_replica{0} {1}".format(scope_label, int(postgres['role'] == 'replica'))) + metrics.append("# HELP patroni_sync_standby Value is 1 if this node is a sync standby replica, 0 otherwise.") + metrics.append("# TYPE patroni_sync_standby gauge") + metrics.append("patroni_sync_standby{0} {1}".format(scope_label, int(postgres.get('sync_standby', False)))) + metrics.append("# HELP patroni_xlog_received_location Current location of the received" " Postgres transaction log, 0 if this node is not a replica.") metrics.append("# TYPE patroni_xlog_received_location counter") @@ -686,6 +690,10 @@ class RestApiHandler(BaseHTTPRequestHandler): if result['role'] == 'replica' and self.server.patroni.ha.is_standby_cluster(): result['role'] = postgresql.role + if result['role'] == 'replica' and cluster and cluster.is_synchronous_mode()\ + and cluster.sync and postgresql.name in cluster.sync.members: + result['sync_standby'] = True + if row[1] > 0: result['timeline'] = row[1] else: diff --git a/tests/test_api.py b/tests/test_api.py index ab2e8f04..43e185f9 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -184,6 +184,7 @@ class TestRestApiHandler(unittest.TestCase): def test_do_GET(self): MockPatroni.dcs.cluster.last_lsn = 20 + MockPatroni.dcs.cluster.sync.members = [MockPostgresql.name] MockRestApiServer(RestApiHandler, 'GET /replica') MockRestApiServer(RestApiHandler, 'GET /replica?lag=1M') MockRestApiServer(RestApiHandler, 'GET /replica?lag=10MB') @@ -196,7 +197,6 @@ class TestRestApiHandler(unittest.TestCase): with patch.object(RestApiHandler, 'get_postgresql_status', Mock(return_value={'state': 'running'})): MockRestApiServer(RestApiHandler, 'GET /health') MockRestApiServer(RestApiHandler, 'GET /leader') - MockPatroni.dcs.cluster.sync.members = [MockPostgresql.name] MockPatroni.dcs.cluster.is_synchronous_mode = Mock(return_value=True) with patch.object(RestApiHandler, 'get_postgresql_status', Mock(return_value={'role': 'replica'})): MockRestApiServer(RestApiHandler, 'GET /synchronous')