diff --git a/httpd.py b/httpd.py index 6a77bde..0a75807 100644 --- a/httpd.py +++ b/httpd.py @@ -992,6 +992,12 @@ class ProxyAPIHandler(BaseHTTPServer.BaseHTTPRequestHandler): db = mysqlite.mysqlite(self.database, str) stats = {} + # Total counts + row = db.execute('SELECT COUNT(*) FROM proxylist WHERE failed=0').fetchone() + stats['working'] = row[0] if row else 0 + row = db.execute('SELECT COUNT(*) FROM proxylist').fetchone() + stats['total'] = row[0] if row else 0 + # By protocol rows = db.execute( 'SELECT proto, COUNT(*) FROM proxylist WHERE failed=0 GROUP BY proto' @@ -1003,7 +1009,7 @@ class ProxyAPIHandler(BaseHTTPServer.BaseHTTPRequestHandler): 'SELECT country, COUNT(*) as c FROM proxylist WHERE failed=0 AND country IS NOT NULL ' 'GROUP BY country ORDER BY c DESC LIMIT 10' ).fetchall() - stats['top_countries'] = [(r[0], r[1]) for r in rows] + stats['top_countries'] = [{'code': r[0], 'count': r[1]} for r in rows] # Top ASNs rows = db.execute( @@ -1012,74 +1018,12 @@ class ProxyAPIHandler(BaseHTTPServer.BaseHTTPRequestHandler): ).fetchall() stats['top_asns'] = [(r[0], r[1]) for r in rows] - # Age distribution (when added) - now = int(time.time()) - rows = db.execute( - 'SELECT ' - 'SUM(CASE WHEN added > ? THEN 1 ELSE 0 END) as hour, ' - 'SUM(CASE WHEN added > ? THEN 1 ELSE 0 END) as day, ' - 'SUM(CASE WHEN added > ? THEN 1 ELSE 0 END) as week, ' - 'COUNT(*) as total ' - 'FROM proxylist WHERE failed=0', - (now - 3600, now - 86400, now - 604800) - ).fetchone() - if rows: - stats['age'] = { - 'last_hour': rows[0] or 0, - 'last_day': rows[1] or 0, - 'last_week': rows[2] or 0, - 'total': rows[3] or 0, - } - return stats except Exception as e: return {'error': str(e)} def handle_stats(self): - stats = { - 'working_proxies': 0, - 'total_proxies': 0, - 'tested': 0, - 'passed': 0, - 'failed': 0, - 'success_rate': 0, - 'rate': 0, - 'pass_rate': 0, - 'recent_rate': 0, - 'recent_success_rate': 0, - 'peak_rate': 0, - 'avg_latency': 0, - 'min_latency': 0, - 'max_latency': 0, - 'latency_percentiles': {'p50': 0, 'p90': 0, 'p99': 0}, - 'latency_histogram': [], - 'uptime_seconds': 0, - 'threads': 0, - 'min_threads': 0, - 'max_threads': 0, - 'queue_size': 0, - 'checktype': '', - 'by_proto': {}, - 'proto_stats': {}, - 'rate_history': [], - 'success_rate_history': [], - 'failures': {}, - 'top_countries': [], - 'top_asns': [], - 'tor_pool': {'hosts': [], 'total_requests': 0, 'success_rate': 0}, - 'judges': None, - 'db_stats': {}, - } - - # Database counts - try: - db = mysqlite.mysqlite(self.database, str) - row = db.execute('SELECT COUNT(*) FROM proxylist WHERE failed=0').fetchone() - stats['working_proxies'] = row[0] if row else 0 - row = db.execute('SELECT COUNT(*) FROM proxylist').fetchone() - stats['total_proxies'] = row[0] if row else 0 - except Exception: - pass + stats = {} # Runtime stats from provider if self.stats_provider: @@ -1088,8 +1032,16 @@ class ProxyAPIHandler(BaseHTTPServer.BaseHTTPRequestHandler): except Exception as e: _log('stats_provider error: %s' % str(e), 'error') - # Database-level stats - stats['db_stats'] = self.get_db_stats() + # Add system stats + stats['system'] = get_system_stats() + + # Add database stats + try: + db = mysqlite.mysqlite(self.database, str) + stats['db'] = self.get_db_stats() + stats['db_health'] = get_db_health(db) + except Exception: + pass self.send_json(stats) diff --git a/proxywatchd.py b/proxywatchd.py index 8e22820..babccde 100644 --- a/proxywatchd.py +++ b/proxywatchd.py @@ -1680,21 +1680,38 @@ class Proxywatchd(): pool = connection_pool.get_pool() if pool: pool_stats = pool.get_stats() - pool_info = { - 'hosts': [], - 'total_requests': pool_stats.get('total_requests', 0), - 'success_rate': pool_stats.get('success_rate', 0) - } + hosts_list = [] + healthy_count = 0 + latency_sum = 0.0 + latency_count = 0 for h in pool_stats.get('hosts', []): - pool_info['hosts'].append({ + is_healthy = h.get('available', False) + lat_ms = h.get('avg_latency', 0) * 1000 if h.get('avg_latency') else None + hosts_list.append({ 'address': h.get('host', ''), - 'healthy': h.get('available', False), - 'latency_ms': h.get('avg_latency', 0) * 1000 if h.get('avg_latency') else None, + 'healthy': is_healthy, + 'latency_ms': lat_ms, 'success_rate': h.get('success_rate', 0), }) + if is_healthy: + healthy_count += 1 + if lat_ms and lat_ms > 0: + latency_sum += lat_ms + latency_count += 1 + pool_info = { + 'hosts': hosts_list, + 'total_requests': pool_stats.get('total_requests', 0), + 'success_rate': pool_stats.get('success_rate', 0), + 'healthy_count': healthy_count, + 'total_count': len(hosts_list), + 'avg_latency': latency_sum / latency_count if latency_count > 0 else 0, + } stats_data['tor_pool'] = pool_info else: - stats_data['tor_pool'] = {'hosts': [], 'total_requests': 0, 'success_rate': 0} + stats_data['tor_pool'] = { + 'hosts': [], 'total_requests': 0, 'success_rate': 0, + 'healthy_count': 0, 'total_count': 0, 'avg_latency': 0 + } # Judge stats (when using judges checktype) if config.watchd.checktype == 'judges':