115 lines
2.6 KiB
Python
115 lines
2.6 KiB
Python
import time
|
|
from decimal import Decimal
|
|
|
|
from sanic import Blueprint, response
|
|
|
|
bp = Blueprint(__name__)
|
|
|
|
# a day, 7 days and 30 days in milliseconds
|
|
DAY_MSEC = 86400000
|
|
WEEK_MSEC = 604800000
|
|
MONTH_MSEC = 2592000000
|
|
|
|
|
|
def get_status(manager):
|
|
res = {}
|
|
|
|
for name, state in manager.state.items():
|
|
# ignore unitialized workers
|
|
if state is None:
|
|
continue
|
|
|
|
res[name] = state
|
|
|
|
worker = manager.workers[name]
|
|
res[name]['description'] = worker.service['description']
|
|
|
|
return res
|
|
|
|
|
|
def get_graphs(manager):
|
|
res = {}
|
|
|
|
for name, worker in manager.workers.items():
|
|
# skip adapters without latency
|
|
if 'latency' not in worker.adapter.spec['db']:
|
|
continue
|
|
|
|
cur = manager.conn.cursor()
|
|
|
|
cur.execute(f"""
|
|
SELECT timestamp, latency FROM {name}
|
|
ORDER BY timestamp DESC
|
|
LIMIT 50
|
|
""")
|
|
|
|
qres = cur.fetchall()
|
|
|
|
res[name] = qres
|
|
|
|
return res
|
|
|
|
|
|
def _raw_uptime(cur, service_name: str, worker, time_period: int) -> str:
|
|
"""Calculate uptime for a service given a timeframe."""
|
|
max_tstamp = time.time() * 1000
|
|
min_tstamp = max_tstamp - time_period
|
|
|
|
t_period = max_tstamp - min_tstamp
|
|
|
|
# get all polls that failed
|
|
cur.execute(f"""
|
|
SELECT COUNT(*) FROM {service_name}
|
|
WHERE status = 0 AND timestamp > ?
|
|
""", (min_tstamp, ))
|
|
|
|
row = cur.fetchone()
|
|
down_hits = row[0]
|
|
|
|
# total downtime in milliseconds
|
|
downtime = down_hits * worker.service['poll'] * 1000
|
|
|
|
# calculate total downtime in percentage
|
|
percent = Decimal(downtime) / Decimal(t_period)
|
|
return str(Decimal(100) - percent)
|
|
|
|
|
|
def calc_uptime(manager, time_frame):
|
|
res = {}
|
|
|
|
for name, worker in manager.workers.items():
|
|
cur = manager.conn.cursor()
|
|
res[name] = _raw_uptime(cur, name, worker, time_frame)
|
|
|
|
return res
|
|
|
|
|
|
@bp.get('/api/status')
|
|
async def get_full_status(request):
|
|
manager = request.app.manager
|
|
|
|
return response.json({
|
|
'status': get_status(manager),
|
|
'graph': get_graphs(manager),
|
|
|
|
# uptime stuff
|
|
'uptime': calc_uptime(manager, DAY_MSEC),
|
|
'week_uptime': calc_uptime(manager, WEEK_MSEC),
|
|
'month_uptime': calc_uptime(manager, MONTH_MSEC),
|
|
})
|
|
|
|
|
|
@bp.get('/api/quick')
|
|
async def quick_status(request):
|
|
"""basically /api/status without the graphs"""
|
|
manager = request.app.manager
|
|
|
|
return response.json({
|
|
'status': get_status(manager),
|
|
|
|
# uptime stuff
|
|
'uptime': calc_uptime(manager, DAY_MSEC),
|
|
'week_uptime': calc_uptime(manager, WEEK_MSEC),
|
|
'month_uptime': calc_uptime(manager, MONTH_MSEC),
|
|
})
|