from decimal import Decimal from sanic import Blueprint, response bp = Blueprint(__name__) 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 calc_uptime(manager): res = {} for name, worker in manager.workers.items(): cur = manager.conn.cursor() # get total period we've been polling the service cur.execute(f""" SELECT min(timestamp), max(timestamp) from {name} """) row = cur.fetchone() min_tstamp, max_tstamp = row[0], row[1] t_period = max_tstamp - min_tstamp # get all polls that failed cur.execute(f""" SELECT COUNT(*) FROM {name} WHERE status = false """) row = cur.fetchone() down_hits = row[0] # total downtime in seconds downtime = down_hits * worker.service['poll'] # calculate total downtime in percentage percent = Decimal(downtime) / Decimal(t_period) # uptime - downtime = real uptime res[name] = str(Decimal(100) - percent) return res @bp.get('/api/current_status') async def get_cur_status(request): manager = request.app.manager return response.json({ **get_status(manager), **{ 'uptime': calc_uptime(manager) } }) @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': calc_uptime(manager) })