增加服务首页celery相关监控
This commit is contained in:
+145
-1
@@ -560,6 +560,150 @@ def create_app() -> FastAPI:
|
||||
async def health():
|
||||
return {"status": "ok"}
|
||||
|
||||
@application.get("/internal/status", response_class=HTMLResponse)
|
||||
async def status_page():
|
||||
from app.tasks.celery_app import celery_app
|
||||
from app.config import settings
|
||||
|
||||
celery_status = "unknown"
|
||||
celery_error = ""
|
||||
redis_status = "unknown"
|
||||
redis_error = ""
|
||||
|
||||
try:
|
||||
if celery_app:
|
||||
inspect = celery_app.control.inspect()
|
||||
try:
|
||||
workers = inspect.stats()
|
||||
if workers:
|
||||
celery_status = "running"
|
||||
else:
|
||||
celery_status = "no_workers"
|
||||
except Exception as e:
|
||||
celery_status = "error"
|
||||
celery_error = str(e)
|
||||
else:
|
||||
celery_status = "disabled"
|
||||
except Exception as e:
|
||||
celery_status = "error"
|
||||
celery_error = str(e)
|
||||
|
||||
try:
|
||||
if settings.REDIS_URL:
|
||||
import redis
|
||||
r = redis.from_url(settings.REDIS_URL)
|
||||
r.ping()
|
||||
redis_status = "connected"
|
||||
else:
|
||||
redis_status = "disabled"
|
||||
except Exception as e:
|
||||
redis_status = "disconnected"
|
||||
redis_error = str(e)
|
||||
|
||||
def get_celery_text(status):
|
||||
if status == 'running':
|
||||
return '运行中'
|
||||
elif status == 'no_workers':
|
||||
return '无可用 Worker'
|
||||
elif status == 'disabled':
|
||||
return '已禁用'
|
||||
elif status == 'error':
|
||||
return '连接失败'
|
||||
else:
|
||||
return '未知'
|
||||
|
||||
def get_redis_text(status):
|
||||
if status == 'connected':
|
||||
return '已连接'
|
||||
elif status == 'disabled':
|
||||
return '已禁用'
|
||||
elif status == 'disconnected':
|
||||
return '未连接'
|
||||
else:
|
||||
return '未知'
|
||||
|
||||
celery_text = get_celery_text(celery_status)
|
||||
redis_text = get_redis_text(redis_status)
|
||||
|
||||
celery_error_html = f'<div class="error-message">错误: {celery_error}</div>' if celery_error else ''
|
||||
redis_error_html = f'<div class="error-message">错误: {redis_error}</div>' if redis_error else ''
|
||||
|
||||
html_content = f"""<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>服务状态监控</title>
|
||||
<style>
|
||||
body {{ font-family: system-ui, -apple-system, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; background: #f5f6fa; }}
|
||||
h1 {{ color: #1a1a2e; font-size: 28px; margin-bottom: 8px; }}
|
||||
h1 span {{ color: #6366f1; }}
|
||||
.status-card {{ background: #fff; border: 1px solid #e2e8f0; border-radius: 12px; padding: 20px; margin-bottom: 16px; }}
|
||||
.status-card h3 {{ margin: 0 0 12px; font-size: 16px; color: #1e293b; }}
|
||||
.status-indicator {{ display: inline-flex; align-items: center; gap: 8px; }}
|
||||
.status-dot {{ width: 10px; height: 10px; border-radius: 50%; }}
|
||||
.status-dot.running {{ background: #22c55e; box-shadow: 0 0 8px rgba(34, 197, 94, 0.5); }}
|
||||
.status-dot.connected {{ background: #22c55e; box-shadow: 0 0 8px rgba(34, 197, 94, 0.5); }}
|
||||
.status-dot.error {{ background: #dc2626; box-shadow: 0 0 8px rgba(220, 38, 38, 0.5); }}
|
||||
.status-dot.disabled {{ background: #94a3b8; }}
|
||||
.status-dot.unknown {{ background: #f59e0b; }}
|
||||
.status-dot.no_workers {{ background: #f59e0b; }}
|
||||
.status-dot.disconnected {{ background: #dc2626; }}
|
||||
.status-text {{ font-weight: 600; }}
|
||||
.status-text.running, .status-text.connected {{ color: #16a34a; }}
|
||||
.status-text.error, .status-text.disconnected {{ color: #dc2626; }}
|
||||
.status-text.disabled {{ color: #64748b; }}
|
||||
.status-text.unknown, .status-text.no_workers {{ color: #d97706; }}
|
||||
.error-message {{ margin-top: 8px; padding: 8px 12px; background: #fef2f2; border-radius: 6px; font-size: 13px; color: #dc2626; word-break: break-all; }}
|
||||
.info-box {{ margin-top: 12px; padding: 12px; background: #f1f5f9; border-radius: 8px; font-size: 13px; color: #64748b; }}
|
||||
.back-link {{ display: inline-block; margin-top: 20px; color: #6366f1; text-decoration: none; font-weight: 600; }}
|
||||
.back-link:hover {{ text-decoration: underline; }}
|
||||
.version {{ font-size: 13px; color: #94a3b8; margin-top: 4px; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>服务状态<span>.</span></h1>
|
||||
<p class="version">版本 v{settings.APP_VERSION}</p>
|
||||
|
||||
<div class="status-card">
|
||||
<h3>Celery 任务队列</h3>
|
||||
<div class="status-indicator">
|
||||
<div class="status-dot {celery_status}"></div>
|
||||
<span class="status-text {celery_status}">{celery_text}</span>
|
||||
</div>
|
||||
{celery_error_html}
|
||||
<div class="info-box">
|
||||
<strong>说明:</strong> Celery 用于异步处理 AI 生成任务、轮询任务和下载任务。如果显示"无可用 Worker",请启动 Celery worker。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="status-card">
|
||||
<h3>Redis 缓存</h3>
|
||||
<div class="status-indicator">
|
||||
<div class="status-dot {redis_status}"></div>
|
||||
<span class="status-text {redis_status}">{redis_text}</span>
|
||||
</div>
|
||||
{redis_error_html}
|
||||
<div class="info-box">
|
||||
<strong>说明:</strong> Redis 用于 Celery 消息队列、任务状态存储和缓存。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="status-card">
|
||||
<h3>数据库连接</h3>
|
||||
<div class="status-indicator">
|
||||
<div class="status-dot connected"></div>
|
||||
<span class="status-text connected">已连接</span>
|
||||
</div>
|
||||
<div class="info-box">
|
||||
<strong>说明:</strong> PostgreSQL 数据库已连接。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="/internal/" class="back-link">← 返回首页</a>
|
||||
</body>
|
||||
</html>"""
|
||||
return HTMLResponse(content=html_content)
|
||||
|
||||
@application.get("/internal/decrypt-data", response_class=HTMLResponse)
|
||||
async def decrypt_data_page():
|
||||
html_content = """
|
||||
@@ -701,7 +845,7 @@ a:hover{text-decoration:underline}
|
||||
<div class="cards">
|
||||
<div class="card"><h3><a href="/internal/api-docs">API 文档</a></h3><p>Swagger UI 交互式文档</p></div>
|
||||
<div class="card"><h3><a href="/internal/api-redoc">ReDoc</a></h3><p>ReDoc 格式文档</p></div>
|
||||
<div class="card"><h3><a href="/internal/health">健康检查</a></h3><p>服务状态</p></div>
|
||||
<div class="card"><h3><a href="/internal/status">服务状态</a></h3><p>Celery/Redis 监控</p></div>
|
||||
<div class="card"><h3><a href="/internal/decrypt-data">解密数据</a></h3><p>数据解密</p></div>
|
||||
</div>
|
||||
</body></html>"""
|
||||
|
||||
Reference in New Issue
Block a user