Source code for harp_apps.dashboard.controllers.overview

from datetime import UTC, datetime, timedelta
from decimal import Decimal
from statistics import StatisticsError, mean

from harp.controllers import GetHandler, RouterPrefix, RoutingController
from harp.http import HttpRequest
from harp.typing.storage import Storage
from harp.views import json
from harp_apps.sqlalchemy_storage.constants import TimeBucket

from ..utils.dates import generate_continuous_time_range, get_start_datetime_from_range

time_bucket_for_range = {
    "1h": TimeBucket.HOUR.value,
    "24h": TimeBucket.HOUR.value,
    "7d": TimeBucket.DAY.value,
    "1m": TimeBucket.DAY.value,
    "1y": TimeBucket.DAY.value,
}


def _format_aggregate(items, count, key, *, default=None):
    if count >= 86400:
        period = "sec"
        divider = 86400

    elif count >= 1440:
        period = "min"
        divider = 1440

    elif count >= 24:
        period = "hour"
        divider = 24

    else:
        period = "day"
        divider = 1

    return {
        "rate": Decimal(int(10 * (count / divider))) / 10,
        "period": period,
        "data": [
            {
                "datetime": t["datetime"],
                "value": int(t[key]) if t[key] is not None else default,
            }
            for t in items
        ],
    }


[docs] @RouterPrefix("/api/overview") class OverviewController(RoutingController):
[docs] def __init__(self, *, storage: Storage, handle_errors=True, router=None): self.storage = storage super().__init__(handle_errors=handle_errors, router=router)
[docs] @GetHandler("/summary") async def get_summary_data(self, request: HttpRequest): time_span = "24h" time_bucket = time_bucket_for_range[time_span] now = datetime.now(UTC) start_datetime = get_start_datetime_from_range(time_span, now=now + timedelta(hours=1)) transactions_by_date_list = await self.storage.transactions_grouped_by_time_bucket( start_datetime=start_datetime, time_bucket=time_bucket ) errors_count = sum([t["errors"] for t in transactions_by_date_list]) transactions_count = sum([t["count"] for t in transactions_by_date_list]) transactions_by_date_list = generate_continuous_time_range( discontinuous_transactions=transactions_by_date_list, time_bucket=time_bucket, start_datetime=start_datetime, ) try: mean_tpdex = mean(filter(None, [t["meanTpdex"] for t in transactions_by_date_list])) except StatisticsError: mean_tpdex = 100 return json( { "tpdex": { "mean": int(mean_tpdex), "data": [ { "datetime": t["datetime"], "value": int(t["meanTpdex"]) if t["meanTpdex"] is not None else 100, } for t in transactions_by_date_list ], }, "transactions": _format_aggregate(transactions_by_date_list, transactions_count, "count", default=0), "errors": _format_aggregate(transactions_by_date_list, errors_count, "errors", default=0), } )
[docs] @GetHandler("/") async def get_overview_data(self, request: HttpRequest): # endpoint and range from request endpoint = request.query.get("endpoint") range = request.query.get("timeRange", "24h") # time buckets and start_datetime accordingly time_bucket = time_bucket_for_range.get(range, "day") start_datetime = get_start_datetime_from_range(range) transactions_by_date_list = await self.storage.transactions_grouped_by_time_bucket( endpoint=endpoint, start_datetime=start_datetime, time_bucket=time_bucket ) errors_count = sum([t["errors"] for t in transactions_by_date_list]) transactions_count = sum([t["count"] for t in transactions_by_date_list]) errors_rate = errors_count / transactions_count if transactions_count else 0 mean_duration = ( sum([t["meanDuration"] * t["count"] for t in transactions_by_date_list]) / transactions_count if transactions_count else 0 ) transactions_by_date_list = generate_continuous_time_range( discontinuous_transactions=transactions_by_date_list, time_bucket=time_bucket, start_datetime=start_datetime ) try: mean_tpdex = mean(filter(None, [t["meanTpdex"] for t in transactions_by_date_list])) except StatisticsError: mean_tpdex = 100 return json( { "transactions": transactions_by_date_list, "errors": {"count": errors_count, "rate": errors_rate}, "count": transactions_count, "meanDuration": mean_duration, "meanTpdex": mean_tpdex, "timeRange": range, } )