from app.log import LOG from monitor.metric import UpcloudMetric, UpcloudMetrics, UpcloudRecord import base64 import requests from typing import Any BASE_URL = "https://api.upcloud.com" def get_metric(json: Any, metric: str) -> UpcloudMetric: records = [] if metric in json: metric_data = json[metric] data = metric_data["data"] cols = list(map(lambda x: x["label"], data["cols"][1:])) latest = data["rows"][-1] time = latest[0] for column_idx in range(len(cols)): value = latest[1 + column_idx] # If the latest value is None, try to fetch the second to last if value is None: value = data["rows"][-2][1 + column_idx] if value is not None: label = cols[column_idx] if "(master)" in label: db_role = "master" else: db_role = "standby" records.append( UpcloudRecord(time=time, db_role=db_role, label=label, value=value) ) else: LOG.warn(f"Could not get value for metric {metric}") return UpcloudMetric(metric_name=metric, records=records) def get_metrics(json: Any) -> UpcloudMetrics: return UpcloudMetrics( metrics=[ get_metric(json, "cpu_usage"), get_metric(json, "disk_usage"), get_metric(json, "diskio_reads"), get_metric(json, "diskio_writes"), get_metric(json, "load_average"), get_metric(json, "mem_usage"), get_metric(json, "net_receive"), get_metric(json, "net_send"), ] ) class UpcloudClient: def __init__(self, username: str, password: str): if not username: raise Exception("UpcloudClient username must be set") if not password: raise Exception("UpcloudClient password must be set") client = requests.Session() encoded_auth = base64.b64encode( f"{username}:{password}".encode("utf-8") ).decode("utf-8") client.headers = {"Authorization": f"Basic {encoded_auth}"} self.__client = client def get_metrics(self, db_uuid: str) -> UpcloudMetrics: url = f"{BASE_URL}/1.3/database/{db_uuid}/metrics?period=hour" LOG.d(f"Performing request to {url}") response = self.__client.get(url) LOG.d(f"Status code: {response.status_code}") if response.status_code != 200: return UpcloudMetrics(metrics=[]) as_json = response.json() return get_metrics(as_json)