#!/usr/bin/python import requests import threading import time import re from http.server import BaseHTTPRequestHandler, HTTPServer HOST = '127.0.0.1' PORT = 10080 base_ip_prefix = "192.42.6." base_ip_start = 31 update_interval = 30 expected_backends = [f"http://{base_ip_prefix}{base_ip_start + i}:8282/metrics" for i in range(10)] expected_container_names = [f"invidious-companion-{i:02d}" for i in range(1, 11)] aggregated_metrics = {} def fetch_metrics(): global aggregated_metrics while True: sums = {} backend_down = 0 backend_down_list = [] backend_up_list = [] for url, container_name in zip(expected_backends, expected_container_names): try: resp = requests.get(url, timeout=5) if resp.status_code != 200: backend_down += 1 backend_down_list.append(container_name) continue backend_up_list.append(container_name) lines = resp.text.strip().split('\n') for line in lines: if line.startswith('#'): continue parts = line.split() if len(parts) != 2: continue name, value = parts name = name.lower() if not re.match(r'^[a-z0-9_]+$', name): continue if not re.match(r'^[0-9]+(\.[0-9]+)?$', value): continue sums[name] = sums.get(name, 0) + float(value) except Exception as e: backend_down += 1 backend_down_list.append(container_name) print(f"Fehler beim Abruf von {url}: {e}") backend_total = len(expected_backends) backend_up = backend_total - backend_down metrics = {} for k, v in sums.items(): metrics[k] = v metrics["invidious_companion_total"] = backend_total metrics["invidious_companion_healthy_total"] = backend_up metrics["invidious_companion_unhealthy_total"] = backend_down try: with open('/var/log/inv_network_load.log', 'r') as file: network_load = file.read().replace('\n', '') metrics["invidious_companion_network_load_percent"] = network_load except Exception as e: metrics["invidious_companion_network_load_percent"] = 0 labeled_metrics = [] for ep in backend_up_list: labeled_metrics.append((f'invidious_companion_healthy{{container="{ep}"}}', 1)) for ep in backend_down_list: labeled_metrics.append((f'invidious_companion_unhealthy{{container="{ep}"}}', 1)) aggregated_metrics = (metrics, labeled_metrics) time.sleep(update_interval) class MetricsHandler(BaseHTTPRequestHandler): def do_GET(self): if self.path == '/metrics': metrics, labeled_metrics = aggregated_metrics response = '' for name, value in metrics.items(): response += f"# TYPE {name} gauge\n{name} {value}\n" for labeled_name, value in labeled_metrics: # labeled_name enthält schon Label-String, TYPE nicht nötig hier response += f"{labeled_name} {value}\n" self.send_response(200) self.send_header('Content-Type', 'text/plain; version=0.0.4') self.end_headers() self.wfile.write(response.encode('utf-8')) else: self.send_response(404) self.end_headers() def run_server(): server = HTTPServer((HOST, PORT), MetricsHandler) print(f'Starte HTTP-Server auf http://{HOST}:{PORT}/metrics') server.serve_forever() if __name__ == '__main__': thread = threading.Thread(target=fetch_metrics, daemon=True) thread.start() run_server()