Files
spothole/server/handlers/api/dxstats.py
T

71 lines
2.4 KiB
Python

import json
import logging
from collections import Counter
from datetime import datetime, timedelta
from typing import Any
import pytz
import tornado
from tornado import httputil
from tornado.web import Application
from core.enums import Continent
from core.prometheus_metrics_handler import api_requests_counter
from core.utils import safe_json_dumps
logger = logging.getLogger(__name__)
CONTINENTS = [c.value for c in Continent]
BANDS = ["160m", "80m", "60m", "40m", "30m", "20m", "17m", "15m", "12m", "10m", "6m"]
class APIDxStatsHandler(tornado.web.RequestHandler):
"""API request handler for /api/v2/dxstats"""
def __init__(
self,
application: "Application",
request: httputil.HTTPServerRequest,
**kwargs: Any,
):
self._spots = None
self._web_server_metrics = None
super().__init__(application, request, **kwargs)
def initialize(self, spots, web_server_metrics):
self._spots = spots
self._web_server_metrics = web_server_metrics
def get(self):
try:
self._web_server_metrics["last_api_access_time"] = datetime.now(pytz.UTC)
self._web_server_metrics["api_access_counter"] += 1
self._web_server_metrics["status"] = "OK"
api_requests_counter.inc()
one_hour_ago = (datetime.now(pytz.UTC) - timedelta(hours=1)).timestamp()
counts = Counter()
for key in self._spots.keys(): # noqa: SIM118
spot = self._spots.get(key)
if spot is None:
continue
if not spot.time or spot.time < one_hour_ago:
continue
if spot.de_continent in CONTINENTS and spot.dx_continent in CONTINENTS and spot.band in BANDS:
counts[spot.de_continent, spot.dx_continent, spot.band] += 1
result = {
de: {dx: {band: counts[de, dx, band] for band in BANDS} for dx in CONTINENTS} for de in CONTINENTS
}
self.write(json.dumps(result))
self.set_status(200)
self.set_header("Cache-Control", "no-store")
self.set_header("Content-Type", "application/json")
except Exception:
logger.exception("Exception when handling client request to dx stats API")
self.write(safe_json_dumps("Error - an internal server error occurred."))
self.set_status(500)