105 lines
2.8 KiB
Python
105 lines
2.8 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()
|
|
_INCLUDE_HEALTH_METRICS = str(os.environ.get("HEALTH_INCLUDE_METRICS", "0")).strip().lower() in {
|
|
"1",
|
|
"true",
|
|
"yes",
|
|
"on",
|
|
}
|
|
_EXPOSE_HEALTH_ERRORS = str(os.environ.get("HEALTH_EXPOSE_ERRORS", "0")).strip().lower() in {
|
|
"1",
|
|
"true",
|
|
"yes",
|
|
"on",
|
|
}
|
|
|
|
|
|
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
|
|
if _EXPOSE_HEALTH_ERRORS:
|
|
db_error = f"{type(e).__name__}: {e}"
|
|
else:
|
|
db_error = "db_unavailable"
|
|
|
|
payload = {
|
|
"ok": db_ok,
|
|
"time": get_beijing_now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
"db_ok": db_ok,
|
|
"db_error": db_error,
|
|
}
|
|
if _INCLUDE_HEALTH_METRICS:
|
|
payload["metrics"] = _build_runtime_metrics()
|
|
|
|
return jsonify(payload), (200 if db_ok else 500)
|