Skip to content

Instantly share code, notes, and snippets.

@sasa-tomic
Created July 9, 2024 12:25
Show Gist options
  • Save sasa-tomic/04d9217e5b8847caa0566b619495bb02 to your computer and use it in GitHub Desktop.
Save sasa-tomic/04d9217e5b8847caa0566b619495bb02 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import requests
import ipaddress
import urllib3
import math
import multiprocessing
urllib3.disable_warnings()
IC_API_URL = "https://ic-api.internetcomputer.org/api/v3/nodes"
def get_nodes_list():
response = requests.get(IC_API_URL, timeout=5)
response_json = response.json()["nodes"]
return response_json
def get_node_power_usage(node):
try:
host_metrics = requests.get(
f"https://[{node['host_ipv6']}]:42372/metrics/hostos_node_exporter", verify=False, timeout=10
).text
power_usage_watts = [line for line in host_metrics.splitlines() if line.startswith("power_average_watts ")]
if power_usage_watts:
power_usage_watts = float(power_usage_watts[0].split(" ")[1])
if power_usage_watts > 0:
return (node, power_usage_watts)
except requests.exceptions.SSLError as err:
print("SSL Error while fetching metrics from", node["host_ipv6"], err)
except requests.exceptions.ConnectTimeout as err:
print("Connection Timeout while fetching metrics from", node["host_ipv6"], err)
except requests.exceptions.ConnectionError as err:
print("Connection Error while fetching metrics from", node["host_ipv6"], err)
return (node, float("nan"))
def main():
nodes = []
for node in get_nodes_list():
addr = ipaddress.IPv6Address(node["ip_address"]).exploded.split(":")
if addr[4] != "6801":
print("Skipping", addr, "as it is not a regular GuestOS node")
continue
node["guest_ipv6"] = ipaddress.IPv6Address(":".join(addr))
node["host_ipv6"] = ipaddress.IPv6Address(":".join(addr[:4] + ["6800"] + addr[5:]))
nodes.append(node)
with multiprocessing.Pool(64) as pool:
power_usages = pool.map(get_node_power_usage, nodes)
power_usages_invalid = [p for p in power_usages if math.isnan(p[1])]
power_usages_valid = [p for p in power_usages if not math.isnan(p[1])]
power_usages_valid = sorted(power_usages_valid, key=lambda x: x[1], reverse=True)
for node, power_usage_watts in power_usages_invalid:
print(
f"Node {node['guest_ipv6'].exploded} ({node['status']} {node['alertname']}) has power usage of {power_usage_watts} W. "
f"Node Provider {node['node_provider_name']}, DC: {node['dc_name']}"
)
for node, power_usage_watts in power_usages_valid:
print(
f"Node {node['guest_ipv6'].exploded} has power usage of {power_usage_watts} W. "
f"Node Provider {node['node_provider_name']}, DC: {node['dc_name']}"
)
print("Total nodes with invalid power usage metrics:", len(power_usages_invalid))
print("Total nodes with valid power usage metrics:", len(power_usages_valid))
avg_power_usage = sum([p[1] for p in power_usages_valid]) / len(power_usages_valid)
print("Average power usage per node: %.2f W" % avg_power_usage)
if __name__ == "__main__":
main()
@sasa-tomic
Copy link
Author

Example output:

$ python3 ic-public-node-metrics.py
[...]
Node 2604:7e00:0030:0003:6801:e3ff:fe6b:eebb has power usage of 256.0 W. Node Provider Bigger Capital, DC: Allentown
Node 2001:0ed0:000a:0101:6801:92ff:fe25:6c55 has power usage of 250.0 W. Node Provider Neptune Partners, DC: Seoul 1
Node 2600:3000:6100:0200:6801:f0ff:fe97:47ac has power usage of 242.0 W. Node Provider 87m Neuron, LLC, DC: Dallas
Node 2606:f180:0009:001a:6801:caff:fe3f:05e5 has power usage of 242.0 W. Node Provider Bianca-Martina Rohner, DC: Panama City 1
Node 2401:3f00:1000:0024:6801:11ff:fe40:221e has power usage of 242.0 W. Node Provider OneSixtyTwo Digital Capital, DC: Singapore
Node 2a0a:5000:0000:0003:6801:9dff:feca:c43a has power usage of 242.0 W. Node Provider George Bassadone, DC: Tbilisi 1
Node 2600:3006:1400:1500:6801:a5ff:fe3e:8081 has power usage of 238.0 W. Node Provider 87m Neuron, LLC, DC: Las Vegas
[...]
Total nodes with invalid power usage metrics: 150
Total nodes with valid power usage metrics: 1278
Average power usage per node: 254.63 W

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment