From a5a51e75f834ae0640047ee9efd9d449a2a85a97 Mon Sep 17 00:00:00 2001 From: Andrew Boudreau Date: Fri, 18 Jun 2021 21:44:19 -0500 Subject: [PATCH 1/6] added docker compose from tedder's gist --- docker-compose.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f09a4c1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,33 @@ +# launch: docker-compose up -d +version: "3.7" +services: + validator: + image: quay.io/team-helium/validator:latest-val-amd64 + container_name: validator + init: true + ports: + - "2154:2154" + - "127.0.0.1:4467:4467" # jsonrpc + volumes: + - "${HOME}/validator_data/:/var/data" + labels: + "com.centurylinklabs.watchtower.lifecycle.pre-update": > + sh -c 'while [ "$$(miner info in_consensus)" == "true" ]; do echo "in consensus, loop-waiting"; sleep 30; done' + "com.centurylinklabs.watchtower.lifecycle.pre-update-timeout": 43200 # 12hrs should be longer than a validator is in the consensus group. + val_watchtower: + image: containrrr/watchtower:latest + container_name: val_watchtower + volumes: + - /var/run/docker.sock:/var/run/docker.sock + command: validator miner_exporter # the container name(s) to monitor + environment: + - WATCHTOWER_POLL_INTERVAL=21600 # check for new image every 6 hrs + - WATCHTOWER_LIFECYCLE_HOOKS=true + #- WATCHTOWER_DEBUG=true # uncomment to see watchtower waiting for consensus + miner_exporter: + image: ghcr.io/tedder/miner_exporter:latest + container_name: miner_exporter + volumes: + - /var/run/docker.sock:/var/run/docker.sock + ports: + - "127.0.0.1:9825:9825" \ No newline at end of file From 5be165f9a0d21e4cf0561dfdc3de5bd57c0fd23a Mon Sep 17 00:00:00 2001 From: Andrew Boudreau Date: Fri, 18 Jun 2021 21:45:04 -0500 Subject: [PATCH 2/6] added ref to full docker-compose in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a80398d..9ae6ba4 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ docker run -p 9825:9825 --name miner_exporter -v /var/run/docker.sock:/var/run/d ``` ### Docker-Compose -Using your existing docker-compose file, add the section for the exporter (below). When you're done, run `docker-compose up -d` as usual. That's it! +Using your existing docker-compose file, add the section for the exporter (below). When you're done, run `docker-compose up -d` as usual. That's it! Here is the full [docker-compose.yml](docker-compose.yml) example. ``` version: "3" services: From 7441cf587ca284eab1e4b1f072acf70965a4f157 Mon Sep 17 00:00:00 2001 From: Andrew Boudreau Date: Tue, 13 Jul 2021 01:35:39 -0500 Subject: [PATCH 3/6] use the miner's json rpc interface --- miner_exporter.py | 292 +++++++++++++--------------------------------- 1 file changed, 82 insertions(+), 210 deletions(-) diff --git a/miner_exporter.py b/miner_exporter.py index e025f58..61b19a2 100755 --- a/miner_exporter.py +++ b/miner_exporter.py @@ -7,6 +7,9 @@ import requests import dateutil.parser +# I just copied the python script from https://github.com/andrewboudreau/miner_httpclient into the folder for easy testing. +from miner_client import MinerClient + # internal packages import datetime import time @@ -58,92 +61,41 @@ UPTIME = prometheus_client.Gauge('validator_container_uptime', 'Time container has been at a given state', ['state_type','validator_name']) -miner_facts = {} -def try_int(v): - if re.match(r"^\-?\d+$", v): - return int(v) - return v +# create a client for the miner's json rpc interface +jsonRpcClient = MinerClient() def try_float(v): if re.match(r"^\-?[\d\.]+$", v): return float(v) return v -def get_facts(docker_container_obj): - if miner_facts: - return miner_facts - #miner_facts = { - # 'name': None, - # 'address': None - #} - out = docker_container_obj.exec_run('miner print_keys') - # sample output: - # {pubkey,"1YBkf..."}. - # {onboarding_key,"1YBkf..."}. - # {animal_name,"one-two-three"}. - - log.debug(out.output) - printkeys = {} - for line in out.output.split(b"\n"): - strline = line.decode('utf-8') - - # := requires py3.8 - if m := re.match(r'{([^,]+),"([^"]+)"}.', strline): - log.debug(m) - k = m.group(1) - v = m.group(2) - log.debug(k,v) - printkeys[k] = v - - if v := printkeys.get('pubkey'): - miner_facts['address'] = v - if printkeys.get('animal_name'): - miner_facts['name'] = v - #$ docker exec validator miner print_keys - return miner_facts - - # Decorate function with metric. @SCRAPE_TIME.time() def stats(): + miner_name = "wild-brunette-monkey"# jsonRpcClient.info_name() + try: dc = docker.DockerClient() docker_container = dc.containers.get(VALIDATOR_CONTAINER_NAME) - miner_facts = get_facts(docker_container) - hotspot_name_str = get_miner_name(docker_container) except docker.errors.NotFound as ex: log.error(f"docker failed while bootstrapping. Not exporting anything. Error: {ex}") - return - + return + # collect total cpu and memory usage. Might want to consider just the docker # container with something like cadvisor instead - SYSTEM_USAGE.labels('CPU', hotspot_name_str).set(psutil.cpu_percent()) - SYSTEM_USAGE.labels('Memory', hotspot_name_str).set(psutil.virtual_memory()[2]) - - collect_container_run_time(docker_container, hotspot_name_str) - collect_miner_version(docker_container, hotspot_name_str) - collect_block_age(docker_container, hotspot_name_str) - collect_miner_height(docker_container, hotspot_name_str) - collect_in_consensus(docker_container, hotspot_name_str) - collect_ledger_validators(docker_container, hotspot_name_str) - collect_peer_book(docker_container, hotspot_name_str) - collect_hbbft_performance(docker_container, hotspot_name_str) - collect_balance(docker_container,miner_facts['address'],hotspot_name_str) - -def safe_get_json(url): - try: - ret = requests.get(url) - if not ret.status_code == requests.codes.ok: - log.error(f"bad status code ({ret.status_code}) from url: {url}") - return - retj = ret.json() - return retj + SYSTEM_USAGE.labels('CPU', miner_name).set(psutil.cpu_percent()) + SYSTEM_USAGE.labels('Memory', miner_name).set(psutil.virtual_memory()[2]) + collect_container_run_time(docker_container, miner_name) + collect_hbbft_performance(docker_container, miner_name) - except (requests.exceptions.SSLError, requests.exceptions.ConnectionError) as ex: - log.error(f"error fetching {url}: {ex}") - return + collect_block_age(miner_name) + collect_miner_height(miner_name) + collect_in_consensus(miner_name) + collect_ledger_validators(miner_name) + collect_peer_book(miner_name) + collect_balance(miner_name) def collect_container_run_time(docker_container, miner_name): attrs = docker_container.attrs @@ -177,68 +129,11 @@ def collect_container_run_time(docker_container, miner_name): start_delta = (now-start_dt).total_seconds() UPTIME.labels('start', miner_name).set(start_delta) -def collect_balance(docker_container, addr, miner_name): - # should move pubkey to getfacts and then pass it in here - #out = docker_container.exec_run('miner print_keys') - #for line in out.output.decode('utf-8').split("\n"): - # if 'pubkey' in line: - # addr=line[9:60] - api_validators = safe_get_json(f'https://testnet-api.helium.wtf/v1/validators/{addr}') - if not api_validators: - log.error("validator fetch returned empty JSON") - return - elif not api_validators.get('data') or not api_validators['data'].get('owner'): - log.error("could not find validator data owner in json") - return - owner = api_validators['data']['owner'] - - api_accounts = safe_get_json(f'https://testnet-api.helium.wtf/v1/accounts/{owner}') - if not api_accounts: - return - if not api_accounts.get('data') or not api_accounts['data'].get('balance'): - return - balance = float(api_accounts['data']['balance'])/1E8 - #print(api_accounts) - #print('balance',balance) - BALANCE.labels(miner_name).set(balance) - - -def get_miner_name(docker_container): - # need to fix this. hotspot name really should only be queried once - out = docker_container.exec_run('miner info name') - log.debug(out.output) - hotspot_name = out.output.decode('utf-8').rstrip("\n") - return hotspot_name - -def collect_miner_height(docker_container, miner_name): - # grab the local blockchain height - out = docker_container.exec_run('miner info height') - log.debug(out.output) - txt = out.output.decode('utf-8').rstrip("\n") - VAL.labels('Height', miner_name).set(out.output.split()[1]) - -def collect_in_consensus(docker_container, miner_name): - # check if currently in consensus group - out = docker_container.exec_run('miner info in_consensus') - incon_txt = out.output.decode('utf-8').rstrip("\n") - incon = 0 - if incon_txt == 'true': - incon = 1 - log.info(f"in consensus? {incon} / {incon_txt}") - INCON.labels(miner_name).set(incon) - -def collect_block_age(docker_container, miner_name): - # collect current block age - out = docker_container.exec_run('miner info block_age') - ## transform into a number - age_val = try_int(out.output.decode('utf-8').rstrip("\n")) - - BLOCKAGE.labels('BlockAge', miner_name).set(age_val) - log.debug(f"age: {age_val}") - # persist these between calls hval = {} -def collect_hbbft_performance(docker_container, miner_name): +def collect_hbbft_performance(docker_container, miner_name): + + # parse the hbbft performance table for the penalty field out = docker_container.exec_run('miner hbbft perf --format csv') #print(out.output) @@ -290,96 +185,74 @@ def collect_hbbft_performance(docker_container, miner_name): HBBFT_PERF.labels('hbbft_perf','Seen_Last', miner_name).set(hval.get('seen_last_val', 0)) HBBFT_PERF.labels('hbbft_perf','Tenure', miner_name).set(hval.get('tenure', 0)) -def collect_peer_book(docker_container, miner_name): - # peer book -s output - out = docker_container.exec_run('miner peer book -s --format csv') - # parse the peer book output - - # samples - # address,name,listen_addrs,connections,nat,last_updated - # /p2p/1YBkfTYH8iCvchuTevbCAbdni54geDjH95yopRRznZtAur3iPrM,bright-fuchsia-sidewinder,1,6,none,203.072s - # listen_addrs (prioritized) - # /ip4/174.140.164.130/tcp/2154 - # local,remote,p2p,name - # /ip4/192.168.0.4/tcp/2154,/ip4/72.224.176.69/tcp/2154,/p2p/1YU2cE9FNrwkTr8RjSBT7KLvxwPF9i6mAx8GoaHB9G3tou37jCM,clever-sepia-bull - - sessions = 0 - for line in out.output.decode('utf-8').split("\r\n"): - c = line.split(',') - if len(c) == 6: - log.debug(f"peerbook entry6: {c}") - (address,peer_name,listen_add,connections,nat,last_update) = c - conns_num = try_int(connections) - - if miner_name == peer_name and isinstance(conns_num, int): - CONNECTIONS.labels('connections', miner_name).set(conns_num) - - elif len(c) == 4: - # local,remote,p2p,name - log.debug(f"peerbook entry4: {c}") - if c[0] != 'local': - sessions += 1 - elif len(c) == 1: - log.debug(f"peerbook entry1: {c}") - # listen_addrs - pass - else: - log.warning(f"could not understand peer book line: {c}") - log.debug(f"sess: {sessions}") - SESSIONS.labels('sessions', miner_name).set(sessions) +def collect_balance(miner_name): + validator = get_validator_ledger(miner_name) + + if validator is None: + log.warning(f"failed to find validator {miner_name}") + return + + owner_address = validator['owner_address'] + bones = jsonRpcClient.ledger_balance(owner_address)["balance"] + balance = float(bones)/1E8 + BALANCE.labels(miner_name).set(balance) -def collect_ledger_validators(docker_container, miner_name): - # ledger validators output - out = docker_container.exec_run('miner ledger validators --format csv') - results = out.output.decode('utf-8').split("\n") - # parse the ledger validators output - for line in [x.rstrip("\r\n") for x in results]: - c = line.split(',') - #print(f"{len(c)} {c}") - if len(c) == 10: - if c[0] == 'name' and c[1] == 'owner_address': - # header line - continue - - (val_name,address,last_heartbeat,stake,status,version,tenure_penalty,dkg_penalty,performance_penalty,total_penalty) = c - if miner_name == val_name: - log.debug(f"have pen line: {c}") - tenure_penalty_val = try_float(tenure_penalty) - dkg_penalty_val = try_float(dkg_penalty) - performance_penalty_val = try_float(performance_penalty) - total_penalty_val = try_float(total_penalty) - least_heartbeat=try_float(last_heartbeat) - - log.info(f"L penalty: {total_penalty_val}") - LEDGER_PENALTY.labels('ledger_penalties', 'tenure', miner_name).set(tenure_penalty_val) - LEDGER_PENALTY.labels('ledger_penalties', 'dkg', miner_name).set(dkg_penalty_val) - LEDGER_PENALTY.labels('ledger_penalties', 'performance', miner_name).set(performance_penalty_val) - LEDGER_PENALTY.labels('ledger_penalties', 'total', miner_name).set(total_penalty_val) - BLOCKAGE.labels('last_heartbeat', miner_name).set(last_heartbeat) +def collect_miner_height(miner_name): + # grab the local blockchain height + height = jsonRpcClient.info_height()["height"] + VAL.labels('Height', miner_name).set(height) - elif len(line) == 0: - # empty lines are fine - pass - else: - log.warning(f"failed to grok line: {c}; section count: {len(c)}") +def collect_in_consensus(miner_name): + # check if currently in consensus group + in_consensus = (1,0)[jsonRpcClient.info_in_consensus()] + INCON.labels(miner_name).set(in_consensus) +def collect_block_age(miner_name): + block_age = jsonRpcClient.info_block_age() + BLOCKAGE.labels('BlockAge', miner_name).set(block_age) + log.debug(f"block age: {block_age}") -def collect_miner_version(docker_container, miner_name): - out = docker_container.exec_run('miner versions') - results = out.output.decode('utf-8').split("\n") - # sample output - # $ docker exec validator miner versions - # Installed versions: - # * 0.1.48 permanent - for line in results: - if m := re.match('^\*\s+([\d\.]+)(.*)', line): - miner_version = m.group(1) - log.info(f"found miner version: {miner_version}") - VALIDATOR_VERSION.labels(miner_name).info({'version': miner_version}) +def collect_peer_book(miner_name): + book = jsonRpcClient.peer_book("self")[0] + connections = book["connection_count"] + CONNECTIONS.labels('connections', miner_name).set(connections) + sessions = len(book["sessions"]) + SESSIONS.labels('sessions', miner_name).set(sessions) + +def collect_ledger_validators(miner_name): + validator = get_validator_ledger(miner_name) + + if validator is None: + log.warning(f"failed to find validator {miner_name}") + return + + tenure_penalty = float(validator['tenure_penalty']) + dkg_penalty = float(validator['dkg_penalty']) + performance_penalty = float(validator['performance_penalty']) + total_penalty = float(validator['total_penalty']) + + log.info(f"L penalty: {total_penalty}") + LEDGER_PENALTY.labels('ledger_penalties', 'tenure', miner_name).set(tenure_penalty) + LEDGER_PENALTY.labels('ledger_penalties', 'dkg', miner_name).set(dkg_penalty) + LEDGER_PENALTY.labels('ledger_penalties', 'performance', miner_name).set(performance_penalty) + LEDGER_PENALTY.labels('ledger_penalties', 'total', miner_name).set(total_penalty) + + last_heartbeat = validator['last_heartbeat'] + BLOCKAGE.labels('last_heartbeat', miner_name).set(last_heartbeat) + + miner_version = validator["version"] + VALIDATOR_VERSION.labels(miner_name).info({'version': miner_version}) + +def get_validator_ledger(miner_name): + validators = jsonRpcClient.ledger_validators() + validator = next((v for v in validators if v["name"] == miner_name), None) + return validator if __name__ == '__main__': + print(f"collecting metrics for: {jsonRpcClient.info_name()}") + prometheus_client.start_http_server(9825) # 9-VAL on your phone while True: #log.warning("starting loop.") @@ -393,4 +266,3 @@ def collect_miner_version(docker_container, miner_name): # sleep 30 seconds time.sleep(UPDATE_PERIOD) - From 7ead28ee89044de4b7aefde6b9ab7ac2e42c8197 Mon Sep 17 00:00:00 2001 From: Andrew Boudreau Date: Tue, 13 Jul 2021 01:43:05 -0500 Subject: [PATCH 4/6] no readme changes --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9ae6ba4..1b581d9 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Prometheus exporter for the [Helium miner (validator)](https://github.com/helium This is only the exporter, which still requires a **prometheus server** for data and **grafana** for the dashboard. Prometheus and Grafana servers can run on an external machine, the same machine as the miner, or possibly using a cloud service. The [helium\_miner\_grafana\_dashboard](https://github.com/tedder/helium_miner_grafana_dashboard) can be imported to Grafana. -Note [port 9825 is the 'reserved' port for this specific exporter](https://github.com/prometheus/prometheus/wiki/Default-port-allocations). Feel free to use whatever you like, of course, but you won't be able to dial 9VAL on your phone. +Note [port 9825 is the 'reserved' port for this specific exporter](https://github.com/prometheus/prometheus/wiki/Default-port-allocations). Feel free to use whatever you like, of course, but you won't be able to [dial 9VAL on your phone](https://en.wikipedia.org/wiki/E.161). ## Running via Docker @@ -15,7 +15,7 @@ docker run -p 9825:9825 --name miner_exporter -v /var/run/docker.sock:/var/run/d ``` ### Docker-Compose -Using your existing docker-compose file, add the section for the exporter (below). When you're done, run `docker-compose up -d` as usual. That's it! Here is the full [docker-compose.yml](docker-compose.yml) example. +Using your existing docker-compose file, add the section for the exporter (below). When you're done, run `docker-compose up -d` as usual. That's it! ``` version: "3" services: @@ -45,3 +45,12 @@ Details on the libraries: * [docker](https://pypi.org/project/docker/) +## Configuration + +The following have valid defaults, but you can change them: +``` +UPDATE_PERIOD # seconds between scrapes, int +VALIDATOR_CONTAINER_NAME # eg 'validator', string +API_BASE_URL # URL for api access, string. For testnet, set to "https://testnet-api.helium.wtf/v1" +ENABLE_RPC # opt in to using the RPC API with a truthy value (defaults to falsey value until `exec` calls are fully replaced). +``` \ No newline at end of file From 9884a87ae3fb7959914dd3398e1e5d1f5e8c8929 Mon Sep 17 00:00:00 2001 From: Andrew Boudreau Date: Tue, 13 Jul 2021 01:46:23 -0500 Subject: [PATCH 5/6] remove compose file --- docker-compose.yml | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index f09a4c1..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,33 +0,0 @@ -# launch: docker-compose up -d -version: "3.7" -services: - validator: - image: quay.io/team-helium/validator:latest-val-amd64 - container_name: validator - init: true - ports: - - "2154:2154" - - "127.0.0.1:4467:4467" # jsonrpc - volumes: - - "${HOME}/validator_data/:/var/data" - labels: - "com.centurylinklabs.watchtower.lifecycle.pre-update": > - sh -c 'while [ "$$(miner info in_consensus)" == "true" ]; do echo "in consensus, loop-waiting"; sleep 30; done' - "com.centurylinklabs.watchtower.lifecycle.pre-update-timeout": 43200 # 12hrs should be longer than a validator is in the consensus group. - val_watchtower: - image: containrrr/watchtower:latest - container_name: val_watchtower - volumes: - - /var/run/docker.sock:/var/run/docker.sock - command: validator miner_exporter # the container name(s) to monitor - environment: - - WATCHTOWER_POLL_INTERVAL=21600 # check for new image every 6 hrs - - WATCHTOWER_LIFECYCLE_HOOKS=true - #- WATCHTOWER_DEBUG=true # uncomment to see watchtower waiting for consensus - miner_exporter: - image: ghcr.io/tedder/miner_exporter:latest - container_name: miner_exporter - volumes: - - /var/run/docker.sock:/var/run/docker.sock - ports: - - "127.0.0.1:9825:9825" \ No newline at end of file From ac207be505bd316be20d4255dab5eaec0f1bfba4 Mon Sep 17 00:00:00 2001 From: Andrew Boudreau Date: Sun, 18 Jul 2021 01:46:53 -0500 Subject: [PATCH 6/6] convert hbbft perf to use json rpc --- miner_exporter.py | 87 ++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 53 deletions(-) diff --git a/miner_exporter.py b/miner_exporter.py index aedc4bb..21716fd 100755 --- a/miner_exporter.py +++ b/miner_exporter.py @@ -104,10 +104,14 @@ def stats(): # container with something like cadvisor instead SYSTEM_USAGE.labels('CPU', miner_name).set(psutil.cpu_percent()) SYSTEM_USAGE.labels('Memory', miner_name).set(psutil.virtual_memory()[2]) + SYSTEM_USAGE.labels('CPU-Steal', miner_name).set(psutil.cpu_times_percent().steal) + SYSTEM_USAGE.labels('Disk Used', miner_name).set(float(psutil.disk_usage('/').used) / float(psutil.disk_usage('/').total)) + SYSTEM_USAGE.labels('Disk Free', miner_name).set(float(psutil.disk_usage('/').free) / float(psutil.disk_usage('/').total)) + collect_container_run_time(docker_container, miner_name) - collect_hbbft_performance(docker_container, miner_name) + collect_hbbft_performance(miner_name) collect_block_age(miner_name) collect_miner_height(miner_name) collect_in_consensus(miner_name) @@ -177,59 +181,36 @@ def collect_chain_stats(): CHAIN_STATS.labels('staked_validators').set(count_val) # persist these between calls -hval = {} -def collect_hbbft_performance(docker_container, miner_name): - # parse the hbbft performance table for the penalty field - out = docker_container.exec_run('miner hbbft perf --format csv') - #print(out.output) - - for line in out.output.decode('utf-8').split("\n"): - c = [x.strip() for x in line.split(',')] - # samples: - - have_data = False - - if len(c) == 7 and miner_name == c[0]: - # name,bba_completions,seen_votes,last_bba,last_seen,tenure,penalty - # great-clear-chinchilla,5/5,237/237,0,0,2.91,2.91 - log.debug(f"resl7: {c}; {miner_name}/{c[0]}") - - (hval['bba_votes'],hval['bba_tot'])=c[1].split("/") - (hval['seen_votes'],hval['seen_tot'])=c[2].split("/") - hval['bba_last_val']=try_float(c[3]) - hval['seen_last_val']=try_float(c[4]) - hval['tenure'] = try_float(c[5]) - hval['pen_val'] = try_float(c[6]) - elif len(c) == 6 and miner_name == c[0]: - # name,bba_completions,seen_votes,last_bba,last_seen,penalty - # curly-peach-owl,11/11,368/368,0,0,1.86 - log.debug(f"resl6: {c}; {miner_name}/{c[0]}") - - (hval['bba_votes'],hval['bba_tot'])=c[1].split("/") - (hval['seen_votes'],hval['seen_tot'])=c[2].split("/") - hval['bba_last_val']=try_float(c[3]) - hval['seen_last_val']=try_float(c[4]) - hval['pen_val'] = try_float(c[5]) - - elif len(c) == 6: - # not our line - pass - elif len(line) == 0: - # empty line - pass - else: - log.debug(f"wrong len ({len(c)}) for hbbft: {c}") - - # always set these, that way they get reset when out of CG - HBBFT_PERF.labels('hbbft_perf','Penalty', miner_name).set(hval.get('pen_val', 0)) - HBBFT_PERF.labels('hbbft_perf','BBA_Total', miner_name).set(hval.get('bba_tot', 0)) - HBBFT_PERF.labels('hbbft_perf','BBA_Votes', miner_name).set(hval.get('bba_votes', 0)) - HBBFT_PERF.labels('hbbft_perf','Seen_Total', miner_name).set(hval.get('seen_tot', 0)) - HBBFT_PERF.labels('hbbft_perf','Seen_Votes', miner_name).set(hval.get('seen_votes', 0)) - HBBFT_PERF.labels('hbbft_perf','BBA_Last', miner_name).set(hval.get('bba_last_val', 0)) - HBBFT_PERF.labels('hbbft_perf','Seen_Last', miner_name).set(hval.get('seen_last_val', 0)) - HBBFT_PERF.labels('hbbft_perf','Tenure', miner_name).set(hval.get('tenure', 0)) +def collect_hbbft_performance(miner_name): + #{'address': '1126bQkTLZGXtt3Dx4kWUs4JufeBfsdnWTgNV3fptEmAYM2YPkzo', + # 'bba_completions': [10, 18], + # 'last_bba': 0, + # 'last_seen': 0, + # 'name': 'mythical-coconut-horse', + # 'penalty': [4.7695473020038905], + # 'seen_votes': [661, 661], + # 'tenure': [2.071502976190476]} + perf = jsonRpcClient.hbbft_perf(miner_name) + if perf is None: + HBBFT_PERF.labels('hbbft_perf','Penalty', miner_name).set(0) + HBBFT_PERF.labels('hbbft_perf','Tenure', miner_name).set(0) + HBBFT_PERF.labels('hbbft_perf','BBA_Total', miner_name).set(0) + HBBFT_PERF.labels('hbbft_perf','BBA_Votes', miner_name).set(0) + HBBFT_PERF.labels('hbbft_perf','BBA_Last', miner_name).set(0) + HBBFT_PERF.labels('hbbft_perf','Seen_Total', miner_name).set(0) + HBBFT_PERF.labels('hbbft_perf','Seen_Votes', miner_name).set(0) + HBBFT_PERF.labels('hbbft_perf','Seen_Last', miner_name).set(0) + else: + HBBFT_PERF.labels('hbbft_perf','Penalty', miner_name).set(float(perf.get('penalty')[0])) + HBBFT_PERF.labels('hbbft_perf','Tenure', miner_name).set(float(perf.get('tenure')[0])) + + HBBFT_PERF.labels('hbbft_perf','BBA_Votes', miner_name).set(perf.get('bba_completions')[0]) + HBBFT_PERF.labels('hbbft_perf','BBA_Total', miner_name).set(perf.get('bba_completions')[1]) + HBBFT_PERF.labels('hbbft_perf','BBA_Last', miner_name).set(perf.get('last_bba')) + HBBFT_PERF.labels('hbbft_perf','Seen_Votes', miner_name).set(perf.get('seen_votes')[0]) + HBBFT_PERF.labels('hbbft_perf','Seen_Total', miner_name).set(perf.get('seen_votes')[1]) + HBBFT_PERF.labels('hbbft_perf','Seen_Last', miner_name).set(perf.get('last_seen')) def collect_balance(miner_name): validator = get_validator_ledger(miner_name)