mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
- 删除全部 Python 源码 (src/) 及 Alembic 迁移脚本,归档至 _deprecated_py_src/ - 重构 Rust gateway ai_pipeline: 拆分 planner/finalize 模块,新增 contracts/adaptation 层 - 重组 handlers 模块为 admin/public/proxy/internal/shared 子模块结构 - 新增 executor 模块,引入 Rust 原生数据库迁移 (aether-data/migrations) - 简化 CI/Docker 构建流程,移除 base image 二级构建,统一为单一 app image - 移除 Python 相关基础设施文件 (entrypoint.sh, gunicorn_conf.py, Dockerfile.base)
136 lines
3.9 KiB
Python
136 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
import random
|
|
import time
|
|
from typing import Any
|
|
|
|
from src.config.settings import config
|
|
from src.core.logger import logger
|
|
|
|
|
|
class PerfRecorder:
|
|
"""轻量性能记录器(可选启用)"""
|
|
|
|
@staticmethod
|
|
def enabled() -> bool:
|
|
return bool(config.perf_metrics_enabled or config.perf_log_slow_ms > 0)
|
|
|
|
@staticmethod
|
|
def start(force: bool = False) -> float | None:
|
|
if not force and not PerfRecorder.enabled():
|
|
return None
|
|
return time.perf_counter()
|
|
|
|
@staticmethod
|
|
def stop(
|
|
start: float | None,
|
|
name: str,
|
|
labels: dict[str, str] | None = None,
|
|
*,
|
|
sample_rate: float | None = None,
|
|
log_hint: str | None = None,
|
|
) -> float | None:
|
|
if start is None:
|
|
return None
|
|
duration = time.perf_counter() - start
|
|
PerfRecorder.record_timing(
|
|
name,
|
|
duration,
|
|
labels=labels,
|
|
sample_rate=sample_rate,
|
|
log_hint=log_hint,
|
|
)
|
|
return duration
|
|
|
|
@staticmethod
|
|
def record_timing(
|
|
name: str,
|
|
duration: float,
|
|
labels: dict[str, str] | None = None,
|
|
*,
|
|
sample_rate: float | None = None,
|
|
log_hint: str | None = None,
|
|
) -> None:
|
|
if not PerfRecorder.enabled():
|
|
return
|
|
if not PerfRecorder._should_sample(sample_rate):
|
|
return
|
|
|
|
duration_ms = duration * 1000.0
|
|
if config.perf_log_slow_ms > 0 and duration_ms >= float(config.perf_log_slow_ms):
|
|
hint = f" | {log_hint}" if log_hint else ""
|
|
logger.info("[PERF] {} took {:.2f}ms{}", name, duration_ms, hint)
|
|
|
|
if not config.perf_metrics_enabled:
|
|
return
|
|
|
|
plugin = PerfRecorder._get_monitor_plugin()
|
|
if not plugin:
|
|
return
|
|
PerfRecorder._create_task(plugin.timing(PerfRecorder._metric_name(name), duration, labels))
|
|
|
|
@staticmethod
|
|
def record_counter(
|
|
name: str,
|
|
value: float = 1,
|
|
labels: dict[str, str] | None = None,
|
|
*,
|
|
sample_rate: float | None = None,
|
|
) -> None:
|
|
if not config.perf_metrics_enabled:
|
|
return
|
|
if not PerfRecorder._should_sample(sample_rate):
|
|
return
|
|
|
|
plugin = PerfRecorder._get_monitor_plugin()
|
|
if not plugin:
|
|
return
|
|
PerfRecorder._create_task(
|
|
plugin.increment(PerfRecorder._metric_name(name), value=value, labels=labels)
|
|
)
|
|
|
|
@staticmethod
|
|
def should_store() -> bool:
|
|
return bool(getattr(config, "perf_store_enabled", False))
|
|
|
|
@staticmethod
|
|
def should_store_sample() -> bool:
|
|
if not PerfRecorder.should_store():
|
|
return False
|
|
rate = float(getattr(config, "perf_store_sample_rate", 1.0))
|
|
return PerfRecorder._should_sample(rate)
|
|
|
|
@staticmethod
|
|
def _should_sample(sample_rate: float | None) -> bool:
|
|
rate = float(sample_rate if sample_rate is not None else config.perf_sample_rate)
|
|
if rate >= 1:
|
|
return True
|
|
if rate <= 0:
|
|
return False
|
|
return random.random() < rate
|
|
|
|
@staticmethod
|
|
def _get_monitor_plugin() -> Any | None:
|
|
# Lazy import to avoid circular deps during app startup.
|
|
try:
|
|
from src.plugins.manager import get_plugin_manager
|
|
except Exception:
|
|
return None
|
|
try:
|
|
plugin = get_plugin_manager().get_plugin("monitor")
|
|
except Exception:
|
|
return None
|
|
if plugin and getattr(plugin, "enabled", True):
|
|
return plugin
|
|
return None
|
|
|
|
@staticmethod
|
|
def _metric_name(name: str) -> str:
|
|
return name if name.startswith("perf_") else f"perf_{name}"
|
|
|
|
@staticmethod
|
|
def _create_task(coro: Any) -> None:
|
|
from src.utils.async_utils import safe_create_task
|
|
|
|
safe_create_task(coro)
|