#!/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)