#!/usr/bin/env python3 # -*- coding: UTF-8 -*- #------------------------------------------------------------------------------- # Name: check_providers_api.py # Purpose: Flask API to expose check_providers state and history # # Routes: # GET /status -> current state of all providers (from JSON state file) # GET /history -> event history from SQLite # ?provider=NAME -> filter by provider name # ?limit=N -> number of rows (default: 200) # ?transitions=true -> only show up<->down transitions # ?days=N -> limit to last N days (default: 7) #------------------------------------------------------------------------------- import os import json import sqlite3 from flask import Flask, jsonify, request, Response app = Flask(__name__) BASE_DIR = '/opt/check_providers' STATE_FILE = os.path.join(BASE_DIR, 'check-providers-state.json') DB_PATH = os.path.join(BASE_DIR, 'check-providers.db') def get_db(): conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row return conn # --------------------------------------------------------------------------- # Routes # --------------------------------------------------------------------------- @app.route('/status') def status(): """Return the current state of all providers from the JSON state file.""" try: with open(STATE_FILE) as f: content = f.read() return Response(content, mimetype='application/json') except FileNotFoundError: return jsonify({'error': 'No state file found — is the monitor running?'}), 503 except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/history') def history(): """ Return event history from SQLite. Query params: provider : filter by provider name limit : max rows returned (default 200, max 5000) transitions : if 'true', only return up<->down transitions days : only return events from the last N days (default 7) """ provider = request.args.get('provider') limit = min(int(request.args.get('limit', 200)), 5000) only_transitions = request.args.get('transitions', 'false').lower() == 'true' days = int(request.args.get('days', 7)) query = ''' SELECT id, ts, provider, available, rtt, loss, status, transition FROM events ''' where, params = [], [] where.append("ts >= datetime('now', '-{} days')".format(days)) if provider: where.append('provider = ?') params.append(provider) if only_transitions: where.append('transition = 1') if where: query += ' WHERE ' + ' AND '.join(where) query += ' ORDER BY id DESC LIMIT ?' params.append(limit) try: with get_db() as conn: rows = conn.execute(query, params).fetchall() return jsonify([dict(r) for r in rows]) except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/history/summary') def history_summary(): """ Return per-provider stats: total events, transitions, last seen, avg rtt. Query params: days : window in days (default 7) """ days = int(request.args.get('days', 7)) query = ''' SELECT provider, COUNT(*) AS total_events, SUM(transition) AS total_transitions, SUM(CASE WHEN available=1 THEN 1 ELSE 0 END) AS up_count, SUM(CASE WHEN available=0 THEN 1 ELSE 0 END) AS down_count, ROUND(AVG(rtt), 2) AS avg_rtt, MAX(ts) AS last_seen FROM events WHERE ts >= datetime('now', '-{} days') GROUP BY provider ORDER BY provider '''.format(days) try: with get_db() as conn: rows = conn.execute(query).fetchall() return jsonify([dict(r) for r in rows]) except Exception as e: return jsonify({'error': str(e)}), 500 # --------------------------------------------------------------------------- # Entry point # --------------------------------------------------------------------------- if __name__ == '__main__': app.run(host='0.0.0.0', port=5050, debug=False)