import fastapi import re import numpy import subprocess import fastapi.responses import pydantic_settings import logging logger = logging.getLogger(__name__) from online.fxreader.pr34.commands_typed import metrics as pr34_metrics from typing import Optional, Any, ClassVar class Settings(pydantic_settings.BaseSettings): checks_hosts: list[str] _singleton: ClassVar[Optional['Settings']] = None @classmethod def singleton(cls) -> 'Settings': if cls._singleton is None: cls._singleton = Settings.model_validate({}) return cls._singleton def ping_stats(host: str) -> Optional[float]: try: ping_output = subprocess.check_output( [ 'ping', '-i', '0.1', '-c', '3', '-w', '1', host, ] ).decode('utf-8') except: logger.exception('') ping_output = '' r1 = re.compile(r'time=(\d+\.\d+)\sms') spend_time = [float(o[1]) for o in r1.finditer(ping_output)] if len(spend_time) == 0: return None else: return float(numpy.mean(spend_time)) async def metrics_get() -> fastapi.responses.Response: ping_res = {h: ping_stats(h) for h in Settings.singleton().checks_hosts} metrics = [ pr34_metrics.Metric.model_validate( dict( name='ping_mean', type='gauge', help='ping to host, 3 counts, up to 1 second', samples=[ dict( value=str(v), parameters=dict( host=k, ), ) ], ) ) for k, v in ping_res.items() if not v is None ] serialize_res = pr34_metrics.serialize(metrics) return fastapi.responses.Response( content=serialize_res.json2, headers={ 'Content-Type': serialize_res.content_type, }, ) def get_router() -> fastapi.APIRouter: router = fastapi.APIRouter() router.get('/metrics')(metrics_get) return router