183 lines
6.9 KiB
Python
183 lines
6.9 KiB
Python
from __future__ import annotations
|
||
|
||
import json
|
||
from pathlib import Path
|
||
from typing import Any
|
||
|
||
from .env import env_float, env_int, env_int_list, env_str, load_env_file
|
||
|
||
|
||
# 项目根目录。
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
# 静态资源目录。
|
||
STATIC_DIR = ROOT / "static"
|
||
# 默认 .env 路径。
|
||
DEFAULT_ENV_PATH = ROOT / ".env"
|
||
|
||
# 先加载项目根目录的 .env。
|
||
load_env_file(Path(env_str("APP_ENV_FILE", str(DEFAULT_ENV_PATH))).expanduser())
|
||
|
||
# 监控目标配置文件路径。
|
||
CONFIG_PATH = Path(env_str("TARGETS_FILE", str(ROOT / "config" / "targets.json"))).expanduser()
|
||
# HTTP 服务监听地址。
|
||
APP_BIND = env_str("APP_BIND", "0.0.0.0") or "0.0.0.0"
|
||
# HTTP 服务监听端口。
|
||
APP_PORT = env_int("APP_PORT", 2026)
|
||
|
||
# 服务健康检查超时时间。
|
||
PROBE_TIMEOUT_SECONDS = env_float("PROBE_TIMEOUT_SECONDS", 3.0)
|
||
# 服务健康检查缓存秒数。
|
||
PROBE_CACHE_TTL_SECONDS = env_float("PROBE_CACHE_TTL_SECONDS", 5.0)
|
||
# 服务健康检查并发数。
|
||
PROBE_MAX_WORKERS = env_int("PROBE_MAX_WORKERS", 12)
|
||
|
||
# TAT 主机指标缓存秒数。
|
||
HOST_METRIC_CACHE_TTL_SECONDS = env_float("HOST_METRIC_CACHE_TTL_SECONDS", 25.0)
|
||
# TAT 远端命令超时时间。
|
||
TAT_METRIC_TIMEOUT_SECONDS = env_int("TAT_METRIC_TIMEOUT_SECONDS", 30)
|
||
# TAT CPU 采样间隔。
|
||
TAT_CPU_SAMPLE_SECONDS = env_float("TAT_CPU_SAMPLE_SECONDS", 1.0)
|
||
|
||
# TAT 所在区域。
|
||
DEPLOY_REGION = env_str("DEPLOY_REGION", "me-saudi-arabia")
|
||
# 腾讯云 SecretId。
|
||
TENCENT_SECRET_ID = env_str("TENCENT_SECRET_ID", "")
|
||
# 腾讯云 SecretKey。
|
||
TENCENT_SECRET_KEY = env_str("TENCENT_SECRET_KEY", "")
|
||
|
||
# 页面默认刷新间隔。
|
||
DEFAULT_REFRESH_INTERVAL_SECONDS = env_int("DEFAULT_REFRESH_INTERVAL_SECONDS", 10)
|
||
# 页面可选刷新间隔。
|
||
REFRESH_INTERVAL_OPTIONS = env_int_list("REFRESH_INTERVAL_OPTIONS", [5, 10, 15, 30, 60])
|
||
|
||
# Nacos API 基础地址。
|
||
NACOS_BASE_URL = env_str("NACOS_BASE_URL", "http://10.2.1.17:8848").removesuffix("/nacos").rstrip("/")
|
||
# Nacos 目标命名空间 ID。
|
||
NACOS_NAMESPACE_ID = env_str("NACOS_NAMESPACE_ID", "f7a8594e-090c-4830-a3ad-b5c0f9afcc07")
|
||
# Nacos 目标命名空间名。
|
||
NACOS_NAMESPACE_NAME = env_str("NACOS_NAMESPACE_NAME", "RedCircleServiceProd")
|
||
# Nacos 默认注册分组。
|
||
NACOS_DISCOVERY_GROUP = env_str("NACOS_DISCOVERY_GROUP", "DEFAULT_GROUP")
|
||
# Nacos 默认注册集群。
|
||
NACOS_DISCOVERY_CLUSTER_NAME = env_str("NACOS_DISCOVERY_CLUSTER_NAME", "DEFAULT")
|
||
# Nacos 请求超时。
|
||
NACOS_TIMEOUT_SECONDS = env_float("NACOS_TIMEOUT_SECONDS", 6.0)
|
||
# Nacos 结果缓存秒数。
|
||
NACOS_CACHE_TTL_SECONDS = env_float("NACOS_CACHE_TTL_SECONDS", 15.0)
|
||
# Nacos service list 单页大小。
|
||
NACOS_PAGE_SIZE = env_int("NACOS_PAGE_SIZE", 200)
|
||
# Nacos 可选用户名。
|
||
NACOS_USERNAME = env_str("NACOS_USERNAME", "")
|
||
# Nacos 可选密码。
|
||
NACOS_PASSWORD = env_str("NACOS_PASSWORD", "")
|
||
|
||
# Mongo 连接串。
|
||
MONGO_URI = env_str("MONGO_URI", "")
|
||
# Mongo 默认关注的业务库名。
|
||
MONGO_DB_NAME = env_str("MONGO_DB_NAME", "tarab_all")
|
||
# Mongo 机器实例 ID,主要用于和主机指标联动显示。
|
||
MONGO_INSTANCE_ID = env_str("MONGO_INSTANCE_ID", "ins-o9mmob66")
|
||
# Mongo 结果缓存秒数。
|
||
MONGO_CACHE_TTL_SECONDS = env_float("MONGO_CACHE_TTL_SECONDS", 20.0)
|
||
# Mongo 建连超时。
|
||
MONGO_CONNECT_TIMEOUT_MS = env_int("MONGO_CONNECT_TIMEOUT_MS", 3000)
|
||
# Mongo server selection 超时。
|
||
MONGO_SERVER_SELECTION_TIMEOUT_MS = env_int("MONGO_SERVER_SELECTION_TIMEOUT_MS", 3000)
|
||
# Mongo socket 超时。
|
||
MONGO_SOCKET_TIMEOUT_MS = env_int("MONGO_SOCKET_TIMEOUT_MS", 5000)
|
||
|
||
# CPU 告警阈值。
|
||
CPU_WARN_PERCENT = env_float("CPU_WARN_PERCENT", 60.0)
|
||
# CPU 严重阈值。
|
||
CPU_BAD_PERCENT = env_float("CPU_BAD_PERCENT", 85.0)
|
||
# 内存告警阈值。
|
||
MEMORY_WARN_PERCENT = env_float("MEMORY_WARN_PERCENT", 70.0)
|
||
# 内存严重阈值。
|
||
MEMORY_BAD_PERCENT = env_float("MEMORY_BAD_PERCENT", 90.0)
|
||
# 磁盘告警阈值。
|
||
DISK_WARN_PERCENT = env_float("DISK_WARN_PERCENT", 75.0)
|
||
# 磁盘严重阈值。
|
||
DISK_BAD_PERCENT = env_float("DISK_BAD_PERCENT", 90.0)
|
||
# 进程数告警阈值。
|
||
PROCESS_WARN_COUNT = env_int("PROCESS_WARN_COUNT", 180)
|
||
# 进程数严重阈值。
|
||
PROCESS_BAD_COUNT = env_int("PROCESS_BAD_COUNT", 260)
|
||
# 服务耗时告警阈值。
|
||
SERVICE_LATENCY_WARN_MS = env_int("SERVICE_LATENCY_WARN_MS", 1000)
|
||
# 服务耗时严重阈值。
|
||
SERVICE_LATENCY_BAD_MS = env_int("SERVICE_LATENCY_BAD_MS", 3000)
|
||
|
||
# 统一暴露给前端的阈值定义。
|
||
THRESHOLDS = {
|
||
"cpuPercent": {"warn": CPU_WARN_PERCENT, "bad": CPU_BAD_PERCENT},
|
||
"memoryPercent": {"warn": MEMORY_WARN_PERCENT, "bad": MEMORY_BAD_PERCENT},
|
||
"diskPercent": {"warn": DISK_WARN_PERCENT, "bad": DISK_BAD_PERCENT},
|
||
"processCount": {"warn": PROCESS_WARN_COUNT, "bad": PROCESS_BAD_COUNT},
|
||
"latencyMs": {"warn": SERVICE_LATENCY_WARN_MS, "bad": SERVICE_LATENCY_BAD_MS},
|
||
}
|
||
|
||
|
||
def utc_now() -> str:
|
||
# 时间函数延迟导入,避免这里堆太多全局依赖。
|
||
from datetime import datetime, timezone
|
||
|
||
# 统一输出无微秒的 UTC ISO 字符串。
|
||
return datetime.now(timezone.utc).replace(microsecond=0).isoformat()
|
||
|
||
|
||
def settings_payload() -> dict[str, Any]:
|
||
# 把页面需要的动态设置统一打包返回。
|
||
return {
|
||
"refreshIntervalSeconds": DEFAULT_REFRESH_INTERVAL_SECONDS,
|
||
"refreshIntervalOptions": list(REFRESH_INTERVAL_OPTIONS),
|
||
"thresholds": THRESHOLDS,
|
||
}
|
||
|
||
|
||
def load_hosts() -> list[dict[str, Any]]:
|
||
# 读取监控目标配置。
|
||
payload = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
|
||
# 没有 hosts 时回退为空列表。
|
||
hosts = payload.get("hosts") or []
|
||
# 规范化后的主机列表。
|
||
normalized: list[dict[str, Any]] = []
|
||
|
||
# 逐台主机做结构清洗。
|
||
for host in hosts:
|
||
normalized.append(
|
||
{
|
||
"host": str(host.get("name") or "").strip(),
|
||
"group": str(host.get("group") or "").strip(),
|
||
"ip": str(host.get("ip") or "").strip(),
|
||
"instanceId": str(host.get("instanceId") or "").strip(),
|
||
"services": host.get("services") or [],
|
||
}
|
||
)
|
||
|
||
# 返回可供各模块复用的主机列表。
|
||
return normalized
|
||
|
||
|
||
def flatten_services(hosts: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||
# 这里把主机结构拍平成服务列表,方便并发探测。
|
||
services: list[dict[str, Any]] = []
|
||
|
||
# 逐台主机展开服务。
|
||
for host in hosts:
|
||
for service in host.get("services") or []:
|
||
services.append(
|
||
{
|
||
"host": host["host"],
|
||
"group": host["group"],
|
||
"ip": host["ip"],
|
||
"instanceId": host["instanceId"],
|
||
"service": str(service.get("name") or "").strip(),
|
||
"kind": str(service.get("kind") or "java").strip(),
|
||
"port": int(service.get("port")),
|
||
"path": str(service.get("path") or "/").strip(),
|
||
}
|
||
)
|
||
|
||
# 返回扁平服务列表。
|
||
return services
|