Skip to content

Commit

Permalink
Add network_status metric and canonical_name labels
Browse files Browse the repository at this point in the history
* canonical_name is the preffered method of linking stuff to chains
* network_status is a (WIP) metric to determine network "tier" or
  status, meaning: live (production, users) or preview (working on it)
  so you can drive your alerting needs based on it
  • Loading branch information
zytek committed Oct 28, 2024
1 parent a272dd6 commit 751e3b1
Show file tree
Hide file tree
Showing 23 changed files with 110 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ local*
# Python
venv
__pycache__
.coverage
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

prometheus-client==0.13.1
pyyaml==6.0
pyyaml==6.0.1
schema==0.7.5
websockets==10.4
structlog==22.1.0
Expand Down
28 changes: 20 additions & 8 deletions src/collectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
class EvmCollector():
"""A collector to fetch information about evm compatible RPC endpoints."""

def __init__(self, url, labels, chain_id, **client_parameters):
def __init__(self, url, labels, chain_id, network_status, **client_parameters):
self.labels = labels
self.chain_id = chain_id
self.network_status = network_status

sub_payload = {
"method": 'eth_subscribe',
Expand Down Expand Up @@ -58,9 +59,10 @@ def client_version(self):
class ConfluxCollector():
"""A collector to fetch information about conflux RPC endpoints."""

def __init__(self, url, labels, chain_id, **client_parameters):
def __init__(self, url, labels, chain_id, network_status, **client_parameters):
self.labels = labels
self.chain_id = chain_id
self.network_status = network_status

sub_payload = {
"method": 'cfx_subscribe',
Expand Down Expand Up @@ -111,9 +113,10 @@ def client_version(self):
class CardanoCollector():
"""A collector to fetch information about cardano RPC endpoints."""

def __init__(self, url, labels, chain_id, **client_parameters):
def __init__(self, url, labels, chain_id, network_status, **client_parameters):
self.labels = labels
self.chain_id = chain_id
self.network_status = network_status
self.block_height_payload = {
"id": "exporter",
"jsonrpc": "2.0",
Expand All @@ -140,10 +143,11 @@ def latency(self):
class BitcoinCollector():
"""A collector to fetch information about Bitcoin RPC endpoints."""

def __init__(self, url, labels, chain_id, **client_parameters):
def __init__(self, url, labels, chain_id, network_status, **client_parameters):

self.labels = labels
self.chain_id = chain_id
self.network_status = network_status
self.interface = HttpsInterface(url, client_parameters.get('open_timeout'),
client_parameters.get('ping_timeout'))
self._logger_metadata = {
Expand Down Expand Up @@ -209,10 +213,11 @@ def latency(self):
class FilecoinCollector():
"""A collector to fetch information about filecoin RPC endpoints."""

def __init__(self, url, labels, chain_id, **client_parameters):
def __init__(self, url, labels, chain_id, network_status, **client_parameters):

self.labels = labels
self.chain_id = chain_id
self.network_status = network_status
self.interface = HttpsInterface(url, client_parameters.get('open_timeout'),
client_parameters.get('ping_timeout'))
self._logger_metadata = {
Expand Down Expand Up @@ -264,14 +269,19 @@ def latency(self):
"""Returns connection latency."""
return self.interface.latest_query_latency

def network_status(self):
"""Returns network status."""
return self.interface.network_status


class SolanaCollector():
"""A collector to fetch information about solana RPC endpoints."""

def __init__(self, url, labels, chain_id, **client_parameters):
def __init__(self, url, labels, chain_id, network_status, **client_parameters):

self.labels = labels
self.chain_id = chain_id
self.network_status = network_status
self.interface = HttpsInterface(url, client_parameters.get('open_timeout'),
client_parameters.get('ping_timeout'))
self._logger_metadata = {
Expand Down Expand Up @@ -321,10 +331,11 @@ def latency(self):
class StarknetCollector():
"""A collector to fetch information about starknet RPC endpoints."""

def __init__(self, url, labels, chain_id, **client_parameters):
def __init__(self, url, labels, chain_id, network_status, **client_parameters):

self.labels = labels
self.chain_id = chain_id
self.network_status = network_status
self.interface = HttpsInterface(url, client_parameters.get('open_timeout'),
client_parameters.get('ping_timeout'))

Expand Down Expand Up @@ -356,10 +367,11 @@ def latency(self):
class AptosCollector():
"""A collector to fetch information about Aptos endpoints."""

def __init__(self, url, labels, chain_id, **client_parameters):
def __init__(self, url, labels, chain_id, network_status, **client_parameters):

self.labels = labels
self.chain_id = chain_id
self.network_status = network_status
self.interface = HttpsInterface(url, client_parameters.get('open_timeout'),
client_parameters.get('ping_timeout'))

Expand Down
4 changes: 4 additions & 0 deletions src/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ def _load_configuration(self):
And(int),
'network_name':
And(str),
'canonical_name':
And(str),
'network_status':
And(str),
'network_type':
And(str, lambda s: s in ('Testnet', 'Mainnet')),
'collector':
Expand Down
13 changes: 12 additions & 1 deletion src/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class MetricsLoader():
def __init__(self):
self._labels = [
'url', 'provider', 'blockchain', 'network_name', 'network_type',
'evmChainID'
'evmChainID', 'canonical_name'
]

@property
Expand Down Expand Up @@ -51,6 +51,14 @@ def client_version_metric(self):
'brpc_client_version',
'Client version for the particular RPC endpoint.',
labels=self._labels)

@property
def network_status_metric(self):
"""Returns instantiated network status metric."""
return InfoMetricFamily(
'brpc_network_status',
'Network status - live, preview, degraded',
labels=['canonical_name', 'status'])

@property
def total_difficulty_metric(self):
Expand Down Expand Up @@ -126,6 +134,7 @@ def collect(self):
disconnects_metric = self._metrics_loader.disconnects_metric
block_height_metric = self._metrics_loader.block_height_metric
client_version_metric = self._metrics_loader.client_version_metric
network_status_metric = self._metrics_loader.network_status_metric
total_difficulty_metric = self._metrics_loader.total_difficulty_metric
latency_metric = self._metrics_loader.latency_metric
block_height_delta_metric = self._metrics_loader.block_height_delta_metric
Expand All @@ -149,6 +158,7 @@ def collect(self):
total_difficulty_metric, 'total_difficulty')
for collector in self._collector_registry:
self._write_metric(collector, latency_metric, 'latency')
self._write_metric(collector, network_status_metric, 'network_status')
self.delta_compared_to_max(
block_height_metric, block_height_delta_metric)
self.delta_compared_to_max(
Expand All @@ -161,5 +171,6 @@ def collect(self):
yield client_version_metric
yield total_difficulty_metric
yield latency_metric
yield network_status_metric
yield block_height_delta_metric
yield difficulty_delta_metric
9 changes: 7 additions & 2 deletions src/registries.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ class Endpoint(): # pylint: disable=too-few-public-methods
"""RPC Endpoint class, to store metadata."""

def __init__( # pylint: disable=too-many-arguments
self, url, provider, blockchain, network_name, network_type,
self, url, provider, blockchain, network_name, canonical_name, network_type, network_status,
chain_id, **client_parameters):
self.url = url
self.chain_id = chain_id
self.canonical_name = canonical_name
self.network_status = network_status
self.labels = [
url, provider, blockchain, network_name, network_type,
url, provider, blockchain, network_name, network_type, canonical_name,
str(chain_id)
]
self.client_parameters = client_parameters
Expand Down Expand Up @@ -50,6 +52,8 @@ def get_endpoint_registry(self) -> list:
self.blockchain,
self.get_property('network_name'),
self.get_property('network_type'),
self.get_property('network_status'),
self.get_property('canonical_name'),
self.get_property('chain_id'),
**self.client_parameters))
return endpoints_list
Expand Down Expand Up @@ -96,5 +100,6 @@ def get_collector_registry(self) -> list:
else:
collectors_list.append(collector(item.url,
item.labels, item.chain_id,
item.network_status,
**self.client_parameters))
return collectors_list
24 changes: 16 additions & 8 deletions src/test_collectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def setUp(self):
self.url = "wss://test.com"
self.labels = ["dummy", "labels"]
self.chain_id = 123
self.network_status = "live"
self.client_params = {"param1": "dummy", "param2": "data"}
self.sub_payload = {
"method": 'eth_subscribe',
Expand All @@ -21,7 +22,7 @@ def setUp(self):
}
with mock.patch('collectors.WebsocketInterface') as mocked_websocket:
self.evm_collector = collectors.EvmCollector(
self.url, self.labels, self.chain_id, **self.client_params)
self.url, self.labels, self.chain_id, self.network_status, **self.client_params)
self.mocked_websocket = mocked_websocket

def test_websocket_interface_created(self):
Expand Down Expand Up @@ -99,6 +100,7 @@ def setUp(self):
self.url = "wss://test.com"
self.labels = ["dummy", "labels"]
self.chain_id = 123
self.network_status = "live"
self.client_params = {"param1": "dummy", "param2": "data"}
self.sub_payload = {
"method": 'cfx_subscribe',
Expand All @@ -108,7 +110,7 @@ def setUp(self):
}
with mock.patch('collectors.WebsocketInterface') as mocked_websocket:
self.conflux_collector = collectors.ConfluxCollector(
self.url, self.labels, self.chain_id, **self.client_params)
self.url, self.labels, self.chain_id, self.network_status, **self.client_params)
self.mocked_websocket = mocked_websocket

def test_websocket_interface_created(self):
Expand Down Expand Up @@ -186,6 +188,7 @@ def setUp(self):
self.url = "wss://test.com"
self.labels = ["dummy", "labels"]
self.chain_id = 123
self.network_status = "live"
self.client_params = {"param1": "dummy", "param2": "data"}
self.block_height_payload = {
"id": "exporter",
Expand All @@ -194,7 +197,7 @@ def setUp(self):
}
with mock.patch('collectors.WebsocketInterface') as mocked_websocket:
self.cardano_collector = collectors.CardanoCollector(
self.url, self.labels, self.chain_id, **self.client_params)
self.url, self.labels, self.chain_id, self.network_status, **self.client_params)
self.mocked_websocket = mocked_websocket

def test_websocket_interface_created(self):
Expand Down Expand Up @@ -242,6 +245,7 @@ def setUp(self):
self.url = "wss://test.com"
self.labels = ["dummy", "labels"]
self.chain_id = 123
self.network_status = "live"
self.open_timeout = 8
self.ping_timeout = 9
self.client_params = {
Expand All @@ -259,7 +263,7 @@ def setUp(self):
}
with mock.patch('collectors.HttpsInterface') as mocked_connection:
self.bitcoin_collector = collectors.BitcoinCollector(
self.url, self.labels, self.chain_id, **self.client_params)
self.url, self.labels, self.chain_id, self.network_status, **self.client_params)
self.mocked_connection = mocked_connection

def test_logger_metadata(self):
Expand Down Expand Up @@ -384,6 +388,7 @@ def setUp(self):
self.url = "wss://test.com"
self.labels = ["dummy", "labels"]
self.chain_id = 123
self.network_status = "live"
self.open_timeout = 8
self.ping_timeout = 9
self.client_params = {
Expand All @@ -400,7 +405,7 @@ def setUp(self):
}
with mock.patch('collectors.HttpsInterface') as mocked_connection:
self.filecoin_collector = collectors.FilecoinCollector(
self.url, self.labels, self.chain_id, **self.client_params)
self.url, self.labels, self.chain_id, self.network_status, **self.client_params)
self.mocked_connection = mocked_connection

def test_logger_metadata(self):
Expand Down Expand Up @@ -498,6 +503,7 @@ def setUp(self):
self.url = "wss://test.com"
self.labels = ["dummy", "labels"]
self.chain_id = 123
self.network_status = "live"
self.open_timeout = 8
self.ping_timeout = 9
self.client_params = {
Expand All @@ -514,7 +520,7 @@ def setUp(self):
}
with mock.patch('collectors.HttpsInterface') as mocked_connection:
self.solana_collector = collectors.SolanaCollector(
self.url, self.labels, self.chain_id, **self.client_params)
self.url, self.labels, self.chain_id, self.network_status, **self.client_params)
self.mocked_connection = mocked_connection

def test_logger_metadata(self):
Expand Down Expand Up @@ -598,6 +604,7 @@ def setUp(self):
self.url = "wss://test.com"
self.labels = ["dummy", "labels"]
self.chain_id = 123
self.network_status = "live"
self.open_timeout = 8
self.ping_timeout = 9
self.client_params = {
Expand All @@ -609,7 +616,7 @@ def setUp(self):
}
with mock.patch('collectors.HttpsInterface') as mocked_connection:
self.starknet_collector = collectors.StarknetCollector(
self.url, self.labels, self.chain_id, **self.client_params)
self.url, self.labels, self.chain_id, self.network_status, **self.client_params)
self.mocked_connection = mocked_connection

def test_https_interface_created(self):
Expand Down Expand Up @@ -658,13 +665,14 @@ def setUp(self):
self.url = "https://test.com"
self.labels = ["dummy", "labels"]
self.chain_id = 123
self.network_status = "live"
self.open_timeout = 8
self.ping_timeout = 9
self.client_params = {
"open_timeout": self.open_timeout, "ping_timeout": self.ping_timeout}
with mock.patch('collectors.HttpsInterface') as mocked_connection:
self.aptos_collector = collectors.AptosCollector(
self.url, self.labels, self.chain_id, **self.client_params)
self.url, self.labels, self.chain_id, self.network_status, **self.client_params)
self.mocked_connection = mocked_connection

def test_logger_metadata(self):
Expand Down
4 changes: 4 additions & 0 deletions src/test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ def test_configuration_attribute(self):
expected_configuration = {
"blockchain":
"TestChain",
"canonical_name":
"canonical_name",
"chain_id":
1234,
"network_name":
"TestNetwork",
"network_status":
"live",
"network_type":
"Mainnet",
"collector":
Expand Down
Loading

0 comments on commit 751e3b1

Please sign in to comment.