Skip to content

Commit 960dbfc

Browse files
committed
Complete rewrite
1 parent 4e90dc9 commit 960dbfc

File tree

18 files changed

+553
-460
lines changed

18 files changed

+553
-460
lines changed

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
*.out
1313
local*
1414

15-
# Dependency directories (remove the comment below to include it)
16-
# vendor/
15+
# Python
16+
venv
17+
__pycache__

CHANGELOG.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# Changelog
22

33
## v1.0.0
4-
5-
Initial release
4+
- Initial release
65

76
## v1.0.1
8-
9-
Reworked logic for totalDifficulty to support chains that don't use it
7+
- Reworked logic for totalDifficulty to support chains that don't use it
108

119
## v1.0.2
10+
- Handling response of type `None` in JSON RPC response.
1211

13-
Handling response of type `None` in JSON RPC response.
12+
## v2.0.0
13+
- Complete rewrite of evm collector to use web3.py library.
14+
- Introducing limited support for Conflux, Solana and Cardano

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ COPY --from=build /usr/local/lib/python3.9/site-packages/ \
1010
ENV LC_ALL C.UTF-8
1111
WORKDIR /usr/src/app
1212
COPY src/*.py .
13-
13+
COPY src/collectors/* collectors/
1414
# https://github.com/GoogleContainerTools/distroless/blob/main/experimental/python3/BUILD#L77
1515
USER nonroot
1616
CMD ["exporter.py"]

README.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
# EVM RPC Websocket Exporter
2-
Simple exporter used to scrape different metrics from EVM compatible websocket RPCs.
3-
2+
The exporter is used to scrape metrics from blockchain RPC endpoints. The purpose of this exporter is to perform black-box testing on RPC endpoints.
3+
c
44
## Metrics
5-
For list of metrics and explanations please check [collect method](src/exporter.py#L42-L79) in exporter source-code.
6-
For available labels please see [metric_labels](src/exporter.py#L37-L40) list in exporter source-code.
5+
Exporter currently supports all EVM-compatible chains. In addition, there is limited support for the following chains:
6+
- Cardano
7+
- Conflux
8+
- Solana
79

810
# Disclaimer
9-
Please note that this tool is in early development stage, and as such should not be used to influence business crictical decisions.
10-
The project in it's current form suits our short-term needs and will receive limited support. We encourage you to fork the project, and extend it with additional functionality you might need.
11-
This project was inspired by [blackbox-websocket-exporter](https://github.com/smohsensh/blackbox-websocket-exporter)
11+
Please note that this tool is in the early development stage and should not be used to influence critical business decisions.
12+
The project in its current form suits our short-term needs and will receive limited support. We encourage you to fork the project and extend it with additional functionality you might need.
1213

1314
## Development
14-
It is recommended that you install [pre-commit](https://pre-commit.com/) so that automated linting and formatting checks are performed before each commit. Run:
15+
You should install [pre-commit](https://pre-commit.com/) so that automated linting and formatting checks are performed before each commit.
16+
17+
Run:
1518
```bash
1619
pip install pre-commit
1720
pre-commit install
1821
```
1922
### Running locally
2023
1. Make sure you have python3 installed (>3.9.10)
21-
2. Set-up your python environment
24+
2. Set up your python environment
2225
```bash
2326
pip3 install virtualenv
2427
virtualenv venv

config/exporter_example/config.yml

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1-
blockchain: "Example Chain" # Name of blockchain i.e "Ethereum"
2-
chain_id: 1 # Chain ID, can be found at https://chainlist.org/
3-
network_name: "Example" # Name of the blokckchain network i.e Rinkeby
4-
network_type: "Example" # Type of the blockchain network, only two values allowed (Mainnet|Testnet)
5-
connection_timeout_seconds : 5 # Amount in seconds before websocket client drops a connection that has not finished connection handshake and labels the RPC node as unhealhty.
6-
slo: # Metrics below 'slo' will only affect `ws_rpc_sla_compliant` metric. In case any of the threshold are breached, this metric will be set to 0 for that perticular RPC endpoint.
7-
max_pool_deviation_block_count: 10 # Threshold for max allowed deviation in block height, compared to the node with the highest block count in the pool.
8-
max_response_latency_miliseconds: 500 # Threshold for max allowed latency.
9-
endpoints: # List of endpoints with their metadata.
10-
- url: wss://example-rpc-1.com/ws # RPC Endpoint (Must start with wss://)
11-
provider: Provider1 # Provider (Must be present in allowed providers list. Please check src/settings.py line 24) The purpose is to make sure we do not have same providers spelled differently
12-
- url: wss://example-rpc-2.com/ws
1+
blockchain: "Example Chain" # Name of blockchain i.e "Ethereum"
2+
chain_id: 1 # Chain ID, can be found at https://chainlist.org/
3+
network_name: "Example" # Name of the blokckchain network i.e Rinkeby
4+
network_type: "Example" # Type of the blockchain network, only two values allowed (Mainnet|Testnet)
5+
connection_parameters:
6+
open_timeout: 6 # Timeout when opening websocket connection
7+
close_timeout: 1 # Timeout when closing websocket connection
8+
response_timeout: 5 # Timeout when waiting for a websocket message response
9+
ping_interval: 6 # Liveness ping intervals
10+
ping_timeout: 3 # Liveness ping timeout
11+
collector: "evm" # This will load different collectors based on what mode exporter will run with Supported modes are: "evm", "solana", "conflux", "cardano"
12+
endpoints: # List of endpoints with their metadata.
13+
- ws_url: wss://example-rpc-1.com/ws # RPC Endpoint websocket endpoint (Must start with wss://)
14+
https_url: https://example-rpc-1.com/rpc # RPC Endpoint https endpoint (Must be valid https:// domain)
15+
provider: Provider1 # Provider (Must be present in allowed providers list. Please check src/settings.py line 24) The purpose is to make sure we do not have same providers spelled differently
16+
- ws_url: wss://example-rpc-2.com/ws
17+
https_url: https://example-rpc-2.com/rpc
1318
provider: Provider2
14-
- url: wss://example-rpc-3.com/ws
19+
- ws_url: wss://example-rpc-3.com/ws
20+
https_url: https://example-rpc-3.com/rpc
1521
provider: Provider3
22+
23+
24+

config/exporter_example/validation.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,3 @@ allowed_providers: # When adding endpoints, these are the only values you will b
33
- Provider1
44
- Provider2
55
- Provider3
6-
allowed_blockchains: # When setting Blockchain key in your config file, it will be validate against this list.`
7-
- Example Chain
8-
- Example Chain2
9-
- Example Chain3

requirements.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
websockets==10.2
1+
22
prometheus-client==0.13.1
33
pyyaml==6.0
4-
schema==0.7.5
4+
schema==0.7.5
5+
websockets==10.3
6+
web3==v6.0.0-beta.4
7+
solana==0.25.1
8+
conflux-web3==1.0.0b1

src/__init__.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/collectors/__init__.py

Whitespace-only changes.

src/collectors/cardano.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from settings import cfg, logger
2+
import json
3+
from collectors.ws import websocket_collector
4+
from helpers import strip_url
5+
6+
7+
class cardano_collector():
8+
9+
def __init__(self, url, provider):
10+
self.labels = ['url', 'provider', 'blockchain', 'network_name', 'network_type', 'evmChainID']
11+
self.labels_values = [url, provider, cfg.blockchain, cfg.network_name, cfg.network_type]
12+
self.url = url
13+
self.ws_collector = websocket_collector(url, provider)
14+
15+
def _get_block_height(self):
16+
blk_height_payload = {
17+
"type": "jsonwsp/request",
18+
"version": "1.0",
19+
"servicename": "ogmios",
20+
"methodname": "Query",
21+
"args": {
22+
"query": "blockHeight"
23+
}
24+
}
25+
try:
26+
return json.loads(self.ws_collector.query(blk_height_payload))['result']
27+
except KeyError as err:
28+
logger.error("Failed to fetch block height for {}, error: {}".format(strip_url(self.url), err))
29+
30+
def probe(self, metrics):
31+
try:
32+
alive = self.ws_collector.get_liveliness()
33+
if alive:
34+
metrics['ws_rpc_health'].add_metric(self.labels_values, True)
35+
metrics['ws_rpc_latency'].add_metric(self.labels_values, self.ws_collector.get_latency())
36+
metrics['ws_rpc_block_height'].add_metric(self.labels_values, self._get_block_height())
37+
else:
38+
metrics['ws_rpc_health'].add_metric(self.labels_values, False)
39+
except Exception as exc:
40+
logger.error("Failed probing {} with error: {}".format(strip_url(self.url), exc))

0 commit comments

Comments
 (0)