|
1 | | -from settings import cfg, logger |
2 | | -from conflux_web3 import Web3 |
3 | | -import asyncio |
4 | | -from helpers import strip_url, check_protocol, generate_labels_from_metadata |
5 | | -from collectors.ws import websocket_collector |
| 1 | +from settings import logger, cfg |
| 2 | +from helpers import strip_url, generate_labels_from_metadata, hex_to_int, key_from_json_str |
6 | 3 | from metrics_processor import results |
7 | 4 |
|
| 5 | +from collectors.ws import subscription, fetch_latency |
| 6 | +import websockets |
| 7 | +import asyncio |
| 8 | +import json |
| 9 | + |
8 | 10 |
|
9 | 11 | class conflux_collector(): |
10 | 12 |
|
11 | 13 | def __init__(self, rpc_metadata): |
12 | | - self.url = rpc_metadata['url'] |
13 | | - if check_protocol(self.url, "wss") or check_protocol(self.url, 'ws'): |
14 | | - self.labels, self.labels_values = generate_labels_from_metadata(rpc_metadata) |
15 | | - self.labels, self.labels_values = generate_labels_from_metadata(rpc_metadata) |
16 | | - self.client = Web3(Web3.WebsocketProvider(self.url, websocket_timeout=cfg.response_timeout)) |
17 | | - self.labels, self.labels_values = generate_labels_from_metadata(rpc_metadata) |
18 | | - |
19 | | - self.ws_collector = websocket_collector(self.url, |
20 | | - sub_payload={ |
21 | | - "method": "cfx_subscribe", |
22 | | - "jsonrpc": "2.0", |
23 | | - "id": 1, |
24 | | - "params": ["newHeads"] |
25 | | - }) |
26 | | - self.ws_collector.setDaemon(True) |
27 | | - self.ws_collector.start() |
28 | | - else: |
29 | | - logger.error("Please provide wss/ws endpoint for {}".format(strip_url(self.url))) |
30 | | - exit(1) |
31 | | - |
32 | | - def probe(self) -> results: |
| 14 | + self.url, self.chain_id, self.stripped_url = rpc_metadata['url'], rpc_metadata['chain_id'], strip_url( |
| 15 | + rpc_metadata['url']) |
| 16 | + self.labels, self.labels_values = generate_labels_from_metadata(rpc_metadata) |
| 17 | + |
| 18 | + sub_payload = {"method": "cfx_subscribe", "jsonrpc": "2.0", "id": 1, "params": ["newHeads"]} |
| 19 | + self.sub = subscription(self.url, sub_payload) |
| 20 | + self.sub.isDaemon() |
| 21 | + self.sub.start() |
| 22 | + |
| 23 | + async def _cfx_clientVersion(self, websocket): |
| 24 | + payload = {"jsonrpc": "2.0", "method": "cfx_clientVersion", "params": [], "id": 1} |
| 25 | + await websocket.send(json.dumps(payload)) |
| 26 | + result = await websocket.recv() |
| 27 | + return key_from_json_str(result, "result") |
| 28 | + |
| 29 | + async def _cfx_epochNumber(self, websocket): |
| 30 | + payload = {"jsonrpc": "2.0", "method": "cfx_epochNumber", "params": [], "id": 1} |
| 31 | + await websocket.send(json.dumps(payload)) |
| 32 | + result = await websocket.recv() |
| 33 | + return hex_to_int(key_from_json_str(result, "result")) |
| 34 | + |
| 35 | + async def _probe(self) -> results: |
33 | 36 | results.register(self.url, self.labels_values) |
34 | 37 | try: |
35 | | - if self.client.isConnected(): |
| 38 | + async with websockets.connect(self.url, |
| 39 | + open_timeout=cfg.open_timeout, |
| 40 | + close_timeout=cfg.close_timeout, |
| 41 | + ping_interval=cfg.ping_interval, |
| 42 | + ping_timeout=cfg.ping_timeout) as websocket: |
| 43 | + results.record_latency(self.url, await fetch_latency(websocket)) |
36 | 44 | results.record_health(self.url, True) |
37 | | - results.record_head_count(self.url, self.ws_collector.message_counter) |
38 | | - results.record_disconnects(self.url, self.ws_collector.disconnects_counter) |
39 | | - results.record_latency(self.url, self.ws_collector.get_latency()) |
40 | | - results.record_block_height(self.url, self.client.cfx.epoch_number) |
41 | | - try: |
42 | | - difficulty = self.client.cfx.get_block_by_hash(self.client.cfx.get_best_block_hash())['difficulty'] |
43 | | - results.record_difficulty(self.url, difficulty) |
44 | | - except TypeError: |
45 | | - logger.error( |
46 | | - "RPC Endpoint sent faulty response type when querying for difficulty. This is most likely issue with RPC endpoint." |
47 | | - ) |
48 | | - results.record_gas_price(self.url, self.client.cfx.gas_price) |
49 | | - results.record_client_version(self.url, self.client.clientVersion) |
50 | | - else: |
51 | | - logger.info("Client is not connected to {}".format(strip_url(self.url))) |
52 | | - results.record_health(self.url, False) |
53 | | - except asyncio.exceptions.TimeoutError: |
54 | | - logger.info("Client timed out for {}".format(strip_url(self.url))) |
55 | | - results.record_health(self.url, False) |
| 45 | + results.record_block_height(self.url, await self._cfx_epochNumber(websocket)) |
| 46 | + results.record_client_version(self.url, await self._cfx_clientVersion(websocket)) |
| 47 | + results.record_head_count(self.url, self.sub.head_counter) |
| 48 | + results.record_disconnects(self.url, self.sub.disconnects) |
56 | 49 | except Exception as exc: |
57 | | - logger.error("Failed probing {} with error: {}".format(strip_url(self.url), exc)) |
58 | 50 | results.record_health(self.url, False) |
| 51 | + logger.error(f"{exc}", url=self.stripped_url) |
| 52 | + |
| 53 | + def probe(self): |
| 54 | + asyncio.run(self._probe()) |
0 commit comments