Files
zsglpt/routes/health.py

88 lines
2.4 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
import os
import time
from flask import Blueprint, jsonify
import database
import db_pool
from services.request_metrics import get_request_metrics_snapshot
from services.time_utils import get_beijing_now
health_bp = Blueprint("health", __name__)
_PROCESS_START_TS = time.time()
def _build_runtime_metrics() -> dict:
metrics = {
"uptime_seconds": max(0, int(time.time() - _PROCESS_START_TS)),
}
try:
pool_stats = db_pool.get_pool_stats() or {}
metrics["db_pool"] = {
"pool_size": int(pool_stats.get("pool_size", 0) or 0),
"available": int(pool_stats.get("available", 0) or 0),
"in_use": int(pool_stats.get("in_use", 0) or 0),
}
except Exception:
pass
try:
import psutil
proc = psutil.Process(os.getpid())
with proc.oneshot():
mem_info = proc.memory_info()
metrics["process"] = {
"rss_mb": round(float(mem_info.rss) / 1024 / 1024, 2),
"cpu_percent": round(float(proc.cpu_percent(interval=None)), 2),
"threads": int(proc.num_threads()),
}
except Exception:
pass
try:
from services import tasks as tasks_module
scheduler = getattr(tasks_module, "_task_scheduler", None)
if scheduler is not None:
queue_snapshot = scheduler.get_queue_state_snapshot() or {}
metrics["task_queue"] = {
"pending_total": int(queue_snapshot.get("pending_total", 0) or 0),
"running_total": int(queue_snapshot.get("running_total", 0) or 0),
}
except Exception:
pass
try:
metrics["requests"] = get_request_metrics_snapshot()
except Exception:
pass
return metrics
@health_bp.route("/health", methods=["GET"])
def health_check():
"""轻量健康检查:用于宿主机/负载均衡探活。"""
db_ok = True
db_error = ""
try:
database.get_system_config()
except Exception as e:
db_ok = False
db_error = f"{type(e).__name__}: {e}"
payload = {
"ok": db_ok,
"time": get_beijing_now().strftime("%Y-%m-%d %H:%M:%S"),
"db_ok": db_ok,
"db_error": db_error,
"metrics": _build_runtime_metrics(),
}
return jsonify(payload), (200 if db_ok else 500)