Files
abot/plugins/stats_dashboard/dashboard_server.py
2025-03-19 13:24:00 +08:00

141 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import logging
from typing import Dict, Any, Optional
import threading
import time
import os
from flask import Flask, render_template, request, jsonify, redirect, url_for, session, send_from_directory
from db.connection import DBConnectionManager
from db.stats_db import StatsDBOperator
class DashboardServer:
"""统计看板服务器"""
def __init__(self, host: str = "127.0.0.1", port: int = 8080,
username: str = "admin", password: str = "admin123"):
self.host = host
self.port = port
self.username = username
self.password = password
self.logger = logging.getLogger("DashboardServer")
# 修正:使用单例模式获取数据库连接
self.db_manager = DBConnectionManager.get_instance()
self.stats_db = StatsDBOperator(self.db_manager)
self.app = self._create_app()
self._stop_event = threading.Event()
self._server = None # 添加:存储服务器实例
def _create_app(self) -> Flask:
"""创建Flask应用"""
app = Flask(__name__)
app.secret_key = "stats_dashboard_secret_key"
# 添加:实现基本的身份验证
def check_auth():
auth = request.authorization
if not auth or auth.username != self.username or auth.password != self.password:
return False
return True
# 静态文件目录
static_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static')
@app.route('/static/<path:filename>')
def serve_static(filename):
return send_from_directory(static_folder, filename)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/plugins')
def plugins():
return render_template('plugins.html')
@app.route('/users')
def users_page():
return render_template('users.html')
@app.route('/groups')
def groups():
return render_template('groups.html')
@app.route('/api/plugin_stats')
def api_plugin_stats():
days = request.args.get('days', 7, type=int)
stats = self.stats_db.get_plugin_stats(days)
return jsonify({"success": True, "data": stats})
@app.route('/api/user_stats')
def api_user_stats():
days = request.args.get('days', 7, type=int)
limit = request.args.get('limit', 10, type=int)
stats = self.stats_db.get_user_stats(days, limit)
return jsonify({"success": True, "data": stats})
@app.route('/api/group_stats')
def api_group_stats():
days = request.args.get('days', 7, type=int)
limit = request.args.get('limit', 10, type=int)
stats = self.stats_db.get_group_stats(days, limit)
return jsonify({"success": True, "data": stats})
@app.route('/api/error_logs')
def api_error_logs():
days = request.args.get('days', 7, type=int)
limit = request.args.get('limit', 50, type=int)
logs = self.stats_db.get_error_logs(days, limit)
return jsonify({"success": True, "data": logs})
@app.route('/api/error_detail/<int:error_id>')
def api_error_detail(error_id):
detail = self.stats_db.get_error_detail(error_id)
return jsonify({"success": True, "data": detail})
# 修改添加错误处理的API路由示例
@app.route('/api/dashboard_summary')
def api_dashboard_summary():
try:
days = request.args.get('days', 7, type=int)
summary = self.stats_db.get_dashboard_summary(days)
self.logger.info(f"看板主页统计数据: {summary}")
return jsonify({"success": True, "data": summary})
except Exception as e:
self.logger.error(f"获取仪表盘摘要数据出错: {e}")
return jsonify({"success": False, "error": str(e)}), 500
@app.route('/api/plugin_trend')
def api_plugin_trend():
days = request.args.get('days', 7, type=int)
plugin_name = request.args.get('plugin_name', '')
trend = self.stats_db.get_plugin_trend(plugin_name, days)
self.logger.info(f"看板主页/api/plugin_trend: {trend}")
return jsonify({"success": True, "data": trend})
return app
def run(self) -> None:
"""运行服务器"""
try:
self.logger.info(f"启动统计看板服务器,地址: {self.host}:{self.port}")
# 修改:使用线程安全的方式运行服务器
from werkzeug.serving import make_server
self._server = make_server(self.host, self.port, self.app)
self._server.serve_forever()
except Exception as e:
self.logger.error(f"运行统计看板服务器出错: {e}")
def stop(self) -> None:
"""停止服务器"""
try:
self._stop_event.set()
# 修改:使用更可靠的方式停止服务器
if self._server:
self._server.shutdown()
self.logger.info("统计看板服务器已停止")
except Exception as e:
self.logger.error(f"停止统计看板服务器出错: {e}")
raise