Files
darkproxy/monitor/exporter.py
T
auto-ci e4fd2074e2
Configuration validation / lint (push) Has been cancelled
Configuration validation / smoke (push) Has been cancelled
Add monitoring stack files and finalize ARM build cleanups
2026-03-05 20:57:01 -05:00

85 lines
2.5 KiB
Python

import os
import re
import socket
from http.server import BaseHTTPRequestHandler, HTTPServer
MONITOR_HOST = os.getenv("MONITOR_HOST", "dark3proxy")
MONITOR_PORT = int(os.getenv("MONITOR_PORT", "6800"))
SOCKET_TIMEOUT = float(os.getenv("SOCKET_TIMEOUT", "2"))
EXPORTER_PORT = int(os.getenv("EXPORTER_PORT", "9100"))
def fetch_monitor_data() -> str:
with socket.create_connection((MONITOR_HOST, MONITOR_PORT), timeout=SOCKET_TIMEOUT) as sock:
sock.settimeout(SOCKET_TIMEOUT)
chunks = []
while True:
data = sock.recv(4096)
if not data:
break
chunks.append(data)
return b"".join(chunks).decode("utf-8", errors="replace")
def metric_name(raw_parts: list[str]) -> str:
name = "_".join(raw_parts).lower()
name = re.sub(r"[^a-z0-9_]", "_", name)
name = re.sub(r"_+", "_", name).strip("_")
if not name or not name[0].isalpha():
name = f"m_{name}" if name else "m_value"
return f"proxy_{name}"
def parse_metrics(text: str) -> dict[str, float]:
metrics: dict[str, float] = {}
for line in text.splitlines():
parts = line.strip().split()
if len(parts) < 2:
continue
value_token = parts[-1].replace(",", ".")
try:
value = float(value_token)
except ValueError:
continue
name = metric_name(parts[:-1])
metrics[name] = value
return metrics
def render_metrics() -> bytes:
body_lines = []
try:
raw = fetch_monitor_data()
metrics = parse_metrics(raw)
body_lines.append("proxy_exporter_up 1")
for name in sorted(metrics):
body_lines.append(f"{name} {metrics[name]}")
except Exception:
body_lines.append("proxy_exporter_up 0")
body = "\n".join(body_lines) + "\n"
return body.encode("utf-8")
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path not in ("/metrics", "/"):
self.send_response(404)
self.end_headers()
return
payload = render_metrics()
self.send_response(200)
self.send_header("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
self.send_header("Content-Length", str(len(payload)))
self.end_headers()
self.wfile.write(payload)
def log_message(self, format, *args):
return
if __name__ == "__main__":
server = HTTPServer(("0.0.0.0", EXPORTER_PORT), Handler)
server.serve_forever()