Source code for harp_apps.dashboard.controllers.system

from copy import deepcopy
from typing import cast

from sqlalchemy import func, select
from sqlalchemy.orm import aliased, joinedload

from harp import Config, __revision__, __version__, get_logger
from harp.controllers import GetHandler, RouterPrefix, RoutingController
from harp.http import HttpRequest
from harp.typing import Storage
from harp.typing.global_settings import GlobalSettings
from harp.views.json import json
from harp_apps.sqlalchemy_storage.models import MetricValue
from harp_apps.sqlalchemy_storage.storage import SqlAlchemyStorage

from ..utils.dependencies import get_python_dependencies, parse_dependencies

logger = get_logger(__name__)


[docs] @RouterPrefix("/api/system") class SystemController(RoutingController):
[docs] def __init__(self, *, storage: Storage, settings: GlobalSettings, handle_errors=True, router=None): self.settings = Config(deepcopy(dict(settings))).validate(secure=True) self.storage: SqlAlchemyStorage = cast(SqlAlchemyStorage, storage) self._dependencies = None super().__init__(handle_errors=handle_errors, router=router)
[docs] @GetHandler("/") async def get(self, request: HttpRequest): context = getattr(request, "context", {}) return json( { "version": __version__, "revision": __revision__, "user": context.get("user"), } )
[docs] @GetHandler("/settings") async def get_settings(self): return json(self.settings)
[docs] @GetHandler("/dependencies") async def get_dependencies(self): return json({"python": await self.__get_cached_python_dependencies()})
[docs] @GetHandler("/storage") async def get_storage(self): subquery = select( func.rank().over(order_by=MetricValue.created_at.desc(), partition_by=MetricValue.metric_id).label("rank"), MetricValue, ).subquery() v = aliased(MetricValue, subquery) query = select(v).where(subquery.c.rank == 1).options(joinedload(v.metric)) async with self.storage.session_factory() as session: result = (await session.execute(query)).scalars().all() return json( { "settings": self.settings.get("storage", {}), "counts": {value.metric.name.split(".", 1)[-1]: value.value for value in result}, } )
async def __get_cached_python_dependencies(self): if self._dependencies is None: self._dependencies = parse_dependencies(await get_python_dependencies()) return self._dependencies