Files
Aether/_deprecated_py_src/plugins/monitor/base.py
fawney19 1d9c77522a refactor: 移除 Python 后端源码,全面迁移至 Rust gateway 架构
- 删除全部 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)
2026-04-03 16:26:16 +08:00

251 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
监控插件基类
定义监控和指标收集的接口
"""
from __future__ import annotations
from abc import abstractmethod
from datetime import datetime, timezone
from enum import Enum
from typing import Any
from src.plugins.common import BasePlugin
class MetricType(Enum):
"""指标类型"""
COUNTER = "counter" # 计数器(只增不减)
GAUGE = "gauge" # 仪表(可增可减)
HISTOGRAM = "histogram" # 直方图(分布)
SUMMARY = "summary" # 摘要(分位数)
class Metric:
"""指标数据"""
def __init__(
self,
name: str,
value: float,
metric_type: MetricType,
labels: dict[str, str] | None = None,
timestamp: datetime | None = None,
description: str | None = None,
):
self.name = name
self.value = value
self.metric_type = metric_type
self.labels = labels or {}
self.timestamp = timestamp or datetime.now(timezone.utc)
self.description = description
class MonitorPlugin(BasePlugin):
"""
监控插件基类
所有监控插件必须继承此类并实现相关方法
"""
def __init__(self, name: str, config: dict[str, Any] | None = None):
"""
初始化监控插件
Args:
name: 插件名称
config: 配置字典
"""
# 调用父类初始化设置metadata
super().__init__(name=name, config=config, description="Monitor Plugin", version="1.0.0")
self.flush_interval = self.config.get("flush_interval", 60)
self.batch_size = self.config.get("batch_size", 100)
@abstractmethod
async def record_metric(self, metric: Metric) -> None:
"""
记录单个指标
Args:
metric: 指标数据
"""
pass
@abstractmethod
async def record_batch(self, metrics: list[Metric]) -> None:
"""
批量记录指标
Args:
metrics: 指标列表
"""
pass
@abstractmethod
async def increment(
self, name: str, value: float = 1, labels: dict[str, str] | None = None
) -> Any:
"""
增加计数器
Args:
name: 指标名称
value: 增加的值
labels: 标签字典
"""
pass
@abstractmethod
async def gauge(self, name: str, value: float, labels: dict[str, str] | None = None) -> Any:
"""
设置仪表值
Args:
name: 指标名称
value: 仪表值
labels: 标签字典
"""
pass
@abstractmethod
async def histogram(
self,
name: str,
value: float,
labels: dict[str, str] | None = None,
buckets: list[float] | None = None,
) -> Any:
"""
记录直方图数据
Args:
name: 指标名称
value: 观测值
labels: 标签字典
buckets: 桶边界
"""
pass
@abstractmethod
async def timing(self, name: str, duration: float, labels: dict[str, str] | None = None) -> Any:
"""
记录时间指标
Args:
name: 指标名称
duration: 持续时间(秒)
labels: 标签字典
"""
pass
@abstractmethod
async def flush(self) -> Any:
"""
刷新缓冲的指标到后端
"""
pass
@abstractmethod
async def get_stats(self) -> dict[str, Any]:
"""
获取插件统计信息
Returns:
统计信息字典
"""
pass
def record_request(
self,
method: str,
endpoint: str,
status_code: int,
duration: float,
provider: str | None = None,
model: str | None = None,
) -> Any:
"""
记录API请求指标便捷方法
Args:
method: HTTP方法
endpoint: 端点路径
status_code: 状态码
duration: 请求时长
provider: 提供商名称
model: 模型名称
"""
labels = {
"method": method,
"endpoint": endpoint,
"status": str(status_code),
"status_class": f"{status_code // 100}xx",
}
if provider:
labels["provider"] = provider
if model:
labels["model"] = model
# 异步记录指标
from src.utils.async_utils import safe_create_task
# 请求计数
safe_create_task(self.increment("http_requests_total", labels=labels))
# 请求延迟
safe_create_task(self.histogram("http_request_duration_seconds", duration, labels=labels))
# 错误计数
if status_code >= 400:
safe_create_task(self.increment("http_errors_total", labels=labels))
def record_token_usage(
self,
provider: str,
model: str, # noqa: ARG002 - 保留签名兼容性,不再用于 Prometheus 标签
input_tokens: int,
output_tokens: int,
cost: float | None = None,
) -> Any:
"""
记录Token使用指标便捷方法
Args:
provider: 提供商名称
model: 模型名称(保留签名兼容性,不再作为 Prometheus 标签)
input_tokens: 输入token数
output_tokens: 输出token数
cost: 费用
"""
labels = {"provider": provider}
from src.utils.async_utils import safe_create_task
# Token计数
safe_create_task(self.increment("tokens_input_total", input_tokens, labels=labels))
safe_create_task(self.increment("tokens_output_total", output_tokens, labels=labels))
safe_create_task(
self.increment("tokens_total", input_tokens + output_tokens, labels=labels)
)
# 费用
if cost is not None:
safe_create_task(self.increment("usage_cost_total", cost, labels=labels))
def configure(self, config: dict[str, Any]) -> Any:
"""
配置插件
Args:
config: 配置字典
"""
self.config.update(config)
self.enabled = config.get("enabled", True)
self.flush_interval = config.get("flush_interval", self.flush_interval)
self.batch_size = config.get("batch_size", self.batch_size)
def __repr__(self) -> None:
return f"<{self.__class__.__name__}(name={self.name}, enabled={self.enabled})>"