临时保存1
This commit is contained in:
@@ -11,6 +11,7 @@ from datetime import datetime, timedelta
|
||||
import plotly.graph_objs as go
|
||||
import plotly.utils
|
||||
import json
|
||||
from src.flask_prompt_master.utils.performance_monitor import monitor_performance
|
||||
|
||||
class AnalyticsAdminView(BaseView):
|
||||
"""数据分析管理视图"""
|
||||
@@ -39,50 +40,53 @@ class AnalyticsAdminView(BaseView):
|
||||
|
||||
return self.render('admin/analytics_charts.html', charts_data=charts_data)
|
||||
|
||||
@monitor_performance
|
||||
def _get_analytics_data(self):
|
||||
"""获取分析数据"""
|
||||
"""获取分析数据 - 优化版本"""
|
||||
try:
|
||||
# 用户统计
|
||||
total_users = User.query.count()
|
||||
active_users = User.query.filter_by(status=1).count()
|
||||
new_users_today = User.query.filter(
|
||||
User.created_time >= datetime.now().date()
|
||||
).count()
|
||||
new_users_week = User.query.filter(
|
||||
User.created_time >= datetime.now() - timedelta(days=7)
|
||||
).count()
|
||||
today = datetime.now().date()
|
||||
week_ago = datetime.now() - timedelta(days=7)
|
||||
|
||||
# 提示词统计
|
||||
total_prompts = Prompt.query.count()
|
||||
today_prompts = Prompt.query.filter(
|
||||
Prompt.created_at >= datetime.now().date()
|
||||
).count()
|
||||
week_prompts = Prompt.query.filter(
|
||||
Prompt.created_at >= datetime.now() - timedelta(days=7)
|
||||
).count()
|
||||
# 使用单个查询获取所有用户统计
|
||||
user_stats = db.session.query(
|
||||
func.count(User.uid).label('total_users'),
|
||||
func.sum(func.case([(User.status == 1, 1)], else_=0)).label('active_users'),
|
||||
func.sum(func.case([(User.created_time >= today, 1)], else_=0)).label('new_users_today'),
|
||||
func.sum(func.case([(User.created_time >= week_ago, 1)], else_=0)).label('new_users_week')
|
||||
).first()
|
||||
|
||||
# 使用单个查询获取所有提示词统计
|
||||
prompt_stats = db.session.query(
|
||||
func.count(Prompt.id).label('total_prompts'),
|
||||
func.sum(func.case([(Prompt.created_at >= today, 1)], else_=0)).label('today_prompts'),
|
||||
func.sum(func.case([(Prompt.created_at >= week_ago, 1)], else_=0)).label('week_prompts')
|
||||
).first()
|
||||
|
||||
# 模板统计
|
||||
total_templates = PromptTemplate.query.count()
|
||||
default_templates = PromptTemplate.query.filter_by(is_default=True).count()
|
||||
template_stats = db.session.query(
|
||||
func.count(PromptTemplate.id).label('total_templates'),
|
||||
func.sum(func.case([(PromptTemplate.is_default == True, 1)], else_=0)).label('default_templates')
|
||||
).first()
|
||||
|
||||
# 用户活跃度
|
||||
active_users_week = db.session.query(func.count(func.distinct(Prompt.user_id))).filter(
|
||||
Prompt.created_at >= datetime.now() - timedelta(days=7)
|
||||
).scalar()
|
||||
# 用户活跃度 - 优化查询
|
||||
active_users_week = db.session.query(
|
||||
func.count(func.distinct(Prompt.user_id))
|
||||
).filter(Prompt.created_at >= week_ago).scalar() or 0
|
||||
|
||||
return {
|
||||
'total_users': total_users,
|
||||
'active_users': active_users,
|
||||
'new_users_today': new_users_today,
|
||||
'new_users_week': new_users_week,
|
||||
'total_prompts': total_prompts,
|
||||
'today_prompts': today_prompts,
|
||||
'week_prompts': week_prompts,
|
||||
'total_templates': total_templates,
|
||||
'default_templates': default_templates,
|
||||
'active_users_week': active_users_week or 0
|
||||
'total_users': user_stats.total_users or 0,
|
||||
'active_users': user_stats.active_users or 0,
|
||||
'new_users_today': user_stats.new_users_today or 0,
|
||||
'new_users_week': user_stats.new_users_week or 0,
|
||||
'total_prompts': prompt_stats.total_prompts or 0,
|
||||
'today_prompts': prompt_stats.today_prompts or 0,
|
||||
'week_prompts': prompt_stats.week_prompts or 0,
|
||||
'total_templates': template_stats.total_templates or 0,
|
||||
'default_templates': template_stats.default_templates or 0,
|
||||
'active_users_week': active_users_week
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"获取分析数据失败: {str(e)}")
|
||||
return {
|
||||
'total_users': 0,
|
||||
'active_users': 0,
|
||||
|
||||
@@ -110,18 +110,26 @@ class ApiAdminView(BaseView):
|
||||
# 成功率(模拟数据)
|
||||
success_rate = 98.5 # 百分比
|
||||
|
||||
# 最近7天的调用趋势
|
||||
# 最近7天的调用趋势 - 优化版本
|
||||
week_ago = datetime.now() - timedelta(days=7)
|
||||
daily_calls_data = db.session.query(
|
||||
func.date(Prompt.created_at).label('date'),
|
||||
func.count(Prompt.id).label('count')
|
||||
).filter(
|
||||
Prompt.created_at >= week_ago
|
||||
).group_by(
|
||||
func.date(Prompt.created_at)
|
||||
).order_by(func.date(Prompt.created_at)).all()
|
||||
|
||||
# 构建完整的7天数据
|
||||
daily_calls = []
|
||||
for i in range(7):
|
||||
date = datetime.now() - timedelta(days=i)
|
||||
count = Prompt.query.filter(
|
||||
func.date(Prompt.created_at) == date.date()
|
||||
).count()
|
||||
date = (datetime.now() - timedelta(days=6-i)).date()
|
||||
count = next((item.count for item in daily_calls_data if item.date == date), 0)
|
||||
daily_calls.append({
|
||||
'date': date.strftime('%Y-%m-%d'),
|
||||
'count': count
|
||||
})
|
||||
daily_calls.reverse()
|
||||
|
||||
return {
|
||||
'today_calls': today_calls,
|
||||
|
||||
@@ -269,8 +269,11 @@
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 初始化图表
|
||||
initCharts();
|
||||
// 延迟初始化,避免阻塞页面渲染
|
||||
setTimeout(function() {
|
||||
// 初始化图表
|
||||
initCharts();
|
||||
}, 100);
|
||||
|
||||
// 数字动画
|
||||
const statsNumbers = document.querySelectorAll('.stats-number');
|
||||
|
||||
67
src/flask_prompt_master/utils/cache_utils.py
Normal file
67
src/flask_prompt_master/utils/cache_utils.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
缓存工具类
|
||||
用于缓存频繁查询的数据,提升页面加载性能
|
||||
"""
|
||||
import json
|
||||
import hashlib
|
||||
from datetime import datetime, timedelta
|
||||
from functools import wraps
|
||||
from flask import current_app
|
||||
|
||||
# 简单的内存缓存实现
|
||||
_cache = {}
|
||||
_cache_expiry = {}
|
||||
|
||||
def cache_key(*args, **kwargs):
|
||||
"""生成缓存键"""
|
||||
key_str = json.dumps({'args': args, 'kwargs': kwargs}, sort_keys=True)
|
||||
return hashlib.md5(key_str.encode()).hexdigest()
|
||||
|
||||
def cached(expiry_seconds=300):
|
||||
"""
|
||||
缓存装饰器
|
||||
:param expiry_seconds: 缓存过期时间(秒)
|
||||
"""
|
||||
def decorator(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
key = f"{func.__name__}:{cache_key(*args, **kwargs)}"
|
||||
|
||||
# 检查缓存是否有效
|
||||
if key in _cache and key in _cache_expiry:
|
||||
if datetime.now() < _cache_expiry[key]:
|
||||
return _cache[key]
|
||||
|
||||
# 执行函数并缓存结果
|
||||
result = func(*args, **kwargs)
|
||||
_cache[key] = result
|
||||
_cache_expiry[key] = datetime.now() + timedelta(seconds=expiry_seconds)
|
||||
|
||||
return result
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
def clear_cache(pattern=None):
|
||||
"""
|
||||
清除缓存
|
||||
:param pattern: 缓存键模式,如果为None则清除所有缓存
|
||||
"""
|
||||
global _cache, _cache_expiry
|
||||
|
||||
if pattern is None:
|
||||
_cache.clear()
|
||||
_cache_expiry.clear()
|
||||
else:
|
||||
keys_to_remove = [key for key in _cache.keys() if pattern in key]
|
||||
for key in keys_to_remove:
|
||||
_cache.pop(key, None)
|
||||
_cache_expiry.pop(key, None)
|
||||
|
||||
def get_cache_stats():
|
||||
"""获取缓存统计信息"""
|
||||
return {
|
||||
'total_keys': len(_cache),
|
||||
'expired_keys': len([k for k, v in _cache_expiry.items() if datetime.now() > v]),
|
||||
'cache_size': sum(len(str(v)) for v in _cache.values())
|
||||
}
|
||||
88
src/flask_prompt_master/utils/performance_monitor.py
Normal file
88
src/flask_prompt_master/utils/performance_monitor.py
Normal file
@@ -0,0 +1,88 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
性能监控工具
|
||||
用于监控页面加载时间和数据库查询性能
|
||||
"""
|
||||
import time
|
||||
import functools
|
||||
from flask import request, g
|
||||
from sqlalchemy import event
|
||||
from sqlalchemy.engine import Engine
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 查询时间统计
|
||||
query_times = []
|
||||
|
||||
@event.listens_for(Engine, "before_cursor_execute")
|
||||
def receive_before_cursor_execute(conn, cursor, statement, parameters, context, executemany):
|
||||
"""记录SQL查询开始时间"""
|
||||
context._query_start_time = time.time()
|
||||
|
||||
@event.listens_for(Engine, "after_cursor_execute")
|
||||
def receive_after_cursor_execute(conn, cursor, statement, parameters, context, executemany):
|
||||
"""记录SQL查询结束时间"""
|
||||
total = time.time() - context._query_start_time
|
||||
query_times.append({
|
||||
'statement': statement,
|
||||
'duration': total,
|
||||
'timestamp': time.time()
|
||||
})
|
||||
|
||||
# 记录慢查询
|
||||
if total > 1.0: # 超过1秒的查询
|
||||
logger.warning(f"慢查询检测: {total:.2f}s - {statement[:100]}...")
|
||||
|
||||
def monitor_performance(func):
|
||||
"""性能监控装饰器"""
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
start_time = time.time()
|
||||
|
||||
# 清空查询时间记录
|
||||
global query_times
|
||||
query_times.clear()
|
||||
|
||||
try:
|
||||
result = func(*args, **kwargs)
|
||||
return result
|
||||
finally:
|
||||
end_time = time.time()
|
||||
duration = end_time - start_time
|
||||
|
||||
# 记录性能数据
|
||||
performance_data = {
|
||||
'function': func.__name__,
|
||||
'duration': duration,
|
||||
'query_count': len(query_times),
|
||||
'total_query_time': sum(q['duration'] for q in query_times),
|
||||
'slow_queries': [q for q in query_times if q['duration'] > 0.5]
|
||||
}
|
||||
|
||||
# 记录到日志
|
||||
logger.info(f"性能监控 - {func.__name__}: {duration:.2f}s, 查询数: {len(query_times)}")
|
||||
|
||||
# 如果性能较差,记录详细信息
|
||||
if duration > 2.0 or len(query_times) > 10:
|
||||
logger.warning(f"性能警告 - {func.__name__}: {performance_data}")
|
||||
|
||||
return wrapper
|
||||
|
||||
def get_performance_stats():
|
||||
"""获取性能统计信息"""
|
||||
if not query_times:
|
||||
return {'message': '暂无查询数据'}
|
||||
|
||||
total_queries = len(query_times)
|
||||
total_time = sum(q['duration'] for q in query_times)
|
||||
avg_time = total_time / total_queries if total_queries > 0 else 0
|
||||
slow_queries = [q for q in query_times if q['duration'] > 0.5]
|
||||
|
||||
return {
|
||||
'total_queries': total_queries,
|
||||
'total_time': round(total_time, 2),
|
||||
'average_time': round(avg_time, 2),
|
||||
'slow_queries_count': len(slow_queries),
|
||||
'slow_queries': slow_queries[:5] # 只返回前5个慢查询
|
||||
}
|
||||
Reference in New Issue
Block a user