fix: auto-fix code issues (cron)

- 修复重复导入/字段
- 修复异常处理
- 修复PEP8格式问题
- 添加类型注解
This commit is contained in:
OpenClaw Bot
2026-02-27 18:09:24 +08:00
parent 646b64daf7
commit 17bda3dbce
38 changed files with 1993 additions and 1972 deletions

View File

@@ -10,26 +10,27 @@ InsightFlow Operations & Monitoring Manager - Phase 8 Task 8
作者: InsightFlow Team
"""
import os
import json
import sqlite3
import httpx
import asyncio
import hashlib
import uuid
import json
import os
import re
import time
import sqlite3
import statistics
from typing import List, Dict, Optional, Tuple, Callable
import time
import uuid
from collections.abc import Callable
from dataclasses import dataclass
from datetime import datetime, timedelta
from enum import Enum
from enum import StrEnum
import httpx
# Database path
DB_PATH = os.path.join(os.path.dirname(__file__), "insightflow.db")
class AlertSeverity(str, Enum):
class AlertSeverity(StrEnum):
"""告警严重级别 P0-P3"""
P0 = "p0" # 紧急 - 系统不可用,需要立即处理
@@ -38,7 +39,7 @@ class AlertSeverity(str, Enum):
P3 = "p3" # 轻微 - 非核心功能问题24小时内处理
class AlertStatus(str, Enum):
class AlertStatus(StrEnum):
"""告警状态"""
FIRING = "firing" # 正在告警
@@ -47,7 +48,7 @@ class AlertStatus(str, Enum):
SUPPRESSED = "suppressed" # 已抑制
class AlertChannelType(str, Enum):
class AlertChannelType(StrEnum):
"""告警渠道类型"""
PAGERDUTY = "pagerduty"
@@ -60,7 +61,7 @@ class AlertChannelType(str, Enum):
WEBHOOK = "webhook"
class AlertRuleType(str, Enum):
class AlertRuleType(StrEnum):
"""告警规则类型"""
THRESHOLD = "threshold" # 阈值告警
@@ -69,7 +70,7 @@ class AlertRuleType(str, Enum):
COMPOSITE = "composite" # 复合告警
class ResourceType(str, Enum):
class ResourceType(StrEnum):
"""资源类型"""
CPU = "cpu"
@@ -82,7 +83,7 @@ class ResourceType(str, Enum):
QUEUE = "queue"
class ScalingAction(str, Enum):
class ScalingAction(StrEnum):
"""扩缩容动作"""
SCALE_UP = "scale_up" # 扩容
@@ -90,7 +91,7 @@ class ScalingAction(str, Enum):
MAINTAIN = "maintain" # 保持
class HealthStatus(str, Enum):
class HealthStatus(StrEnum):
"""健康状态"""
HEALTHY = "healthy"
@@ -99,7 +100,7 @@ class HealthStatus(str, Enum):
UNKNOWN = "unknown"
class BackupStatus(str, Enum):
class BackupStatus(StrEnum):
"""备份状态"""
PENDING = "pending"
@@ -124,9 +125,9 @@ class AlertRule:
threshold: float
duration: int # 持续时间(秒)
evaluation_interval: int # 评估间隔(秒)
channels: List[str] # 告警渠道ID列表
labels: Dict[str, str] # 标签
annotations: Dict[str, str] # 注释
channels: list[str] # 告警渠道ID列表
labels: dict[str, str] # 标签
annotations: dict[str, str] # 注释
is_enabled: bool
created_at: str
updated_at: str
@@ -141,12 +142,12 @@ class AlertChannel:
tenant_id: str
name: str
channel_type: AlertChannelType
config: Dict # 渠道特定配置
severity_filter: List[str] # 过滤的告警级别
config: dict # 渠道特定配置
severity_filter: list[str] # 过滤的告警级别
is_enabled: bool
success_count: int
fail_count: int
last_used_at: Optional[str]
last_used_at: str | None
created_at: str
updated_at: str
@@ -165,13 +166,13 @@ class Alert:
metric: str
value: float
threshold: float
labels: Dict[str, str]
annotations: Dict[str, str]
labels: dict[str, str]
annotations: dict[str, str]
started_at: str
resolved_at: Optional[str]
acknowledged_by: Optional[str]
acknowledged_at: Optional[str]
notification_sent: Dict[str, bool] # 渠道发送状态
resolved_at: str | None
acknowledged_by: str | None
acknowledged_at: str | None
notification_sent: dict[str, bool] # 渠道发送状态
suppression_count: int # 抑制计数
@@ -182,11 +183,11 @@ class AlertSuppressionRule:
id: str
tenant_id: str
name: str
matchers: Dict[str, str] # 匹配条件
matchers: dict[str, str] # 匹配条件
duration: int # 抑制持续时间(秒)
is_regex: bool # 是否使用正则匹配
created_at: str
expires_at: Optional[str]
expires_at: str | None
@dataclass
@@ -196,7 +197,7 @@ class AlertGroup:
id: str
tenant_id: str
group_key: str # 聚合键
alerts: List[str] # 告警ID列表
alerts: list[str] # 告警ID列表
created_at: str
updated_at: str
@@ -213,7 +214,7 @@ class ResourceMetric:
metric_value: float
unit: str
timestamp: str
metadata: Dict
metadata: dict
@dataclass
@@ -267,8 +268,8 @@ class ScalingEvent:
triggered_by: str # 触发来源: manual, auto, scheduled
status: str # pending, in_progress, completed, failed
started_at: str
completed_at: Optional[str]
error_message: Optional[str]
completed_at: str | None
error_message: str | None
@dataclass
@@ -281,7 +282,7 @@ class HealthCheck:
target_type: str # service, database, api, etc.
target_id: str
check_type: str # http, tcp, ping, custom
check_config: Dict # 检查配置
check_config: dict # 检查配置
interval: int # 检查间隔(秒)
timeout: int # 超时时间(秒)
retry_count: int
@@ -302,7 +303,7 @@ class HealthCheckResult:
status: HealthStatus
response_time: float # 响应时间(毫秒)
message: str
details: Dict
details: dict
checked_at: str
@@ -314,7 +315,7 @@ class FailoverConfig:
tenant_id: str
name: str
primary_region: str
secondary_regions: List[str] # 备用区域列表
secondary_regions: list[str] # 备用区域列表
failover_trigger: str # 触发条件
auto_failover: bool
failover_timeout: int # 故障转移超时(秒)
@@ -336,8 +337,8 @@ class FailoverEvent:
reason: str
status: str # initiated, in_progress, completed, failed, rolled_back
started_at: str
completed_at: Optional[str]
rolled_back_at: Optional[str]
completed_at: str | None
rolled_back_at: str | None
@dataclass
@@ -371,9 +372,9 @@ class BackupRecord:
size_bytes: int
checksum: str
started_at: str
completed_at: Optional[str]
verified_at: Optional[str]
error_message: Optional[str]
completed_at: str | None
verified_at: str | None
error_message: str | None
storage_path: str
@@ -386,9 +387,9 @@ class CostReport:
report_period: str # YYYY-MM
total_cost: float
currency: str
breakdown: Dict[str, float] # 按资源类型分解
trends: Dict # 趋势数据
anomalies: List[Dict] # 异常检测
breakdown: dict[str, float] # 按资源类型分解
trends: dict # 趋势数据
anomalies: list[dict] # 异常检测
created_at: str
@@ -405,7 +406,7 @@ class ResourceUtilization:
avg_utilization: float
idle_time_percent: float
report_date: str
recommendations: List[str]
recommendations: list[str]
@dataclass
@@ -438,11 +439,11 @@ class CostOptimizationSuggestion:
currency: str
confidence: float
difficulty: str # easy, medium, hard
implementation_steps: List[str]
implementation_steps: list[str]
risk_level: str # low, medium, high
is_applied: bool
created_at: str
applied_at: Optional[str]
applied_at: str | None
class OpsManager:
@@ -450,7 +451,7 @@ class OpsManager:
def __init__(self, db_path: str = DB_PATH):
self.db_path = db_path
self._alert_evaluators: Dict[str, Callable] = {}
self._alert_evaluators: dict[str, Callable] = {}
self._running = False
self._evaluator_thread = None
self._register_default_evaluators()
@@ -481,9 +482,9 @@ class OpsManager:
threshold: float,
duration: int,
evaluation_interval: int,
channels: List[str],
labels: Dict,
annotations: Dict,
channels: list[str],
labels: dict,
annotations: dict,
created_by: str,
) -> AlertRule:
"""创建告警规则"""
@@ -545,7 +546,7 @@ class OpsManager:
return rule
def get_alert_rule(self, rule_id: str) -> Optional[AlertRule]:
def get_alert_rule(self, rule_id: str) -> AlertRule | None:
"""获取告警规则"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM alert_rules WHERE id = ?", (rule_id,)).fetchone()
@@ -554,7 +555,7 @@ class OpsManager:
return self._row_to_alert_rule(row)
return None
def list_alert_rules(self, tenant_id: str, is_enabled: Optional[bool] = None) -> List[AlertRule]:
def list_alert_rules(self, tenant_id: str, is_enabled: bool | None = None) -> list[AlertRule]:
"""列出租户的所有告警规则"""
query = "SELECT * FROM alert_rules WHERE tenant_id = ?"
params = [tenant_id]
@@ -569,7 +570,7 @@ class OpsManager:
rows = conn.execute(query, params).fetchall()
return [self._row_to_alert_rule(row) for row in rows]
def update_alert_rule(self, rule_id: str, **kwargs) -> Optional[AlertRule]:
def update_alert_rule(self, rule_id: str, **kwargs) -> AlertRule | None:
"""更新告警规则"""
allowed_fields = [
"name",
@@ -619,7 +620,7 @@ class OpsManager:
# ==================== 告警渠道管理 ====================
def create_alert_channel(
self, tenant_id: str, name: str, channel_type: AlertChannelType, config: Dict, severity_filter: List[str] = None
self, tenant_id: str, name: str, channel_type: AlertChannelType, config: dict, severity_filter: list[str] = None
) -> AlertChannel:
"""创建告警渠道"""
channel_id = f"ac_{uuid.uuid4().hex[:16]}"
@@ -667,7 +668,7 @@ class OpsManager:
return channel
def get_alert_channel(self, channel_id: str) -> Optional[AlertChannel]:
def get_alert_channel(self, channel_id: str) -> AlertChannel | None:
"""获取告警渠道"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM alert_channels WHERE id = ?", (channel_id,)).fetchone()
@@ -676,7 +677,7 @@ class OpsManager:
return self._row_to_alert_channel(row)
return None
def list_alert_channels(self, tenant_id: str) -> List[AlertChannel]:
def list_alert_channels(self, tenant_id: str) -> list[AlertChannel]:
"""列出租户的所有告警渠道"""
with self._get_db() as conn:
rows = conn.execute(
@@ -715,7 +716,7 @@ class OpsManager:
# ==================== 告警评估与触发 ====================
def _evaluate_threshold_rule(self, rule: AlertRule, metrics: List[ResourceMetric]) -> bool:
def _evaluate_threshold_rule(self, rule: AlertRule, metrics: list[ResourceMetric]) -> bool:
"""评估阈值告警规则"""
if not metrics:
return False
@@ -746,7 +747,7 @@ class OpsManager:
return False
def _evaluate_anomaly_rule(self, rule: AlertRule, metrics: List[ResourceMetric]) -> bool:
def _evaluate_anomaly_rule(self, rule: AlertRule, metrics: list[ResourceMetric]) -> bool:
"""评估异常检测规则(基于标准差)"""
if len(metrics) < 10:
return False
@@ -764,7 +765,7 @@ class OpsManager:
return z_score > 3.0
def _evaluate_predictive_rule(self, rule: AlertRule, metrics: List[ResourceMetric]) -> bool:
def _evaluate_predictive_rule(self, rule: AlertRule, metrics: list[ResourceMetric]) -> bool:
"""评估预测性告警规则(基于线性趋势)"""
if len(metrics) < 5:
return False
@@ -814,7 +815,7 @@ class OpsManager:
# 触发告警
await self._trigger_alert(rule, metrics[-1] if metrics else None)
async def _trigger_alert(self, rule: AlertRule, metric: Optional[ResourceMetric]):
async def _trigger_alert(self, rule: AlertRule, metric: ResourceMetric | None):
"""触发告警"""
# 检查是否已有相同告警在触发中
existing = self.get_active_alert_by_rule(rule.id)
@@ -1166,7 +1167,7 @@ class OpsManager:
# ==================== 告警查询与管理 ====================
def get_active_alert_by_rule(self, rule_id: str) -> Optional[Alert]:
def get_active_alert_by_rule(self, rule_id: str) -> Alert | None:
"""获取规则对应的活跃告警"""
with self._get_db() as conn:
row = conn.execute(
@@ -1180,7 +1181,7 @@ class OpsManager:
return self._row_to_alert(row)
return None
def get_alert(self, alert_id: str) -> Optional[Alert]:
def get_alert(self, alert_id: str) -> Alert | None:
"""获取告警详情"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM alerts WHERE id = ?", (alert_id,)).fetchone()
@@ -1192,10 +1193,10 @@ class OpsManager:
def list_alerts(
self,
tenant_id: str,
status: Optional[AlertStatus] = None,
severity: Optional[AlertSeverity] = None,
status: AlertStatus | None = None,
severity: AlertSeverity | None = None,
limit: int = 100,
) -> List[Alert]:
) -> list[Alert]:
"""列出租户的告警"""
query = "SELECT * FROM alerts WHERE tenant_id = ?"
params = [tenant_id]
@@ -1214,7 +1215,7 @@ class OpsManager:
rows = conn.execute(query, params).fetchall()
return [self._row_to_alert(row) for row in rows]
def acknowledge_alert(self, alert_id: str, user_id: str) -> Optional[Alert]:
def acknowledge_alert(self, alert_id: str, user_id: str) -> Alert | None:
"""确认告警"""
now = datetime.now().isoformat()
@@ -1231,7 +1232,7 @@ class OpsManager:
return self.get_alert(alert_id)
def resolve_alert(self, alert_id: str) -> Optional[Alert]:
def resolve_alert(self, alert_id: str) -> Alert | None:
"""解决告警"""
now = datetime.now().isoformat()
@@ -1306,10 +1307,10 @@ class OpsManager:
self,
tenant_id: str,
name: str,
matchers: Dict[str, str],
matchers: dict[str, str],
duration: int,
is_regex: bool = False,
expires_at: Optional[str] = None,
expires_at: str | None = None,
) -> AlertSuppressionRule:
"""创建告警抑制规则"""
rule_id = f"sr_{uuid.uuid4().hex[:16]}"
@@ -1394,7 +1395,7 @@ class OpsManager:
metric_name: str,
metric_value: float,
unit: str,
metadata: Dict = None,
metadata: dict = None,
) -> ResourceMetric:
"""记录资源指标"""
metric_id = f"rm_{uuid.uuid4().hex[:16]}"
@@ -1436,7 +1437,7 @@ class OpsManager:
return metric
def get_recent_metrics(self, tenant_id: str, metric_name: str, seconds: int = 3600) -> List[ResourceMetric]:
def get_recent_metrics(self, tenant_id: str, metric_name: str, seconds: int = 3600) -> list[ResourceMetric]:
"""获取最近的指标数据"""
cutoff_time = (datetime.now() - timedelta(seconds=seconds)).isoformat()
@@ -1458,7 +1459,7 @@ class OpsManager:
metric_name: str,
start_time: str,
end_time: str,
) -> List[ResourceMetric]:
) -> list[ResourceMetric]:
"""获取指定资源的指标数据"""
with self._get_db() as conn:
rows = conn.execute(
@@ -1549,7 +1550,7 @@ class OpsManager:
return plan
def _calculate_trend(self, values: List[float]) -> float:
def _calculate_trend(self, values: list[float]) -> float:
"""计算趋势(增长率)"""
if len(values) < 2:
return 0.0
@@ -1576,7 +1577,7 @@ class OpsManager:
return slope / mean_y
return 0.0
def get_capacity_plans(self, tenant_id: str) -> List[CapacityPlan]:
def get_capacity_plans(self, tenant_id: str) -> list[CapacityPlan]:
"""获取容量规划列表"""
with self._get_db() as conn:
rows = conn.execute(
@@ -1653,7 +1654,7 @@ class OpsManager:
return policy
def get_auto_scaling_policy(self, policy_id: str) -> Optional[AutoScalingPolicy]:
def get_auto_scaling_policy(self, policy_id: str) -> AutoScalingPolicy | None:
"""获取自动扩缩容策略"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM auto_scaling_policies WHERE id = ?", (policy_id,)).fetchone()
@@ -1662,7 +1663,7 @@ class OpsManager:
return self._row_to_auto_scaling_policy(row)
return None
def list_auto_scaling_policies(self, tenant_id: str) -> List[AutoScalingPolicy]:
def list_auto_scaling_policies(self, tenant_id: str) -> list[AutoScalingPolicy]:
"""列出租户的自动扩缩容策略"""
with self._get_db() as conn:
rows = conn.execute(
@@ -1672,7 +1673,7 @@ class OpsManager:
def evaluate_scaling_policy(
self, policy_id: str, current_instances: int, current_utilization: float
) -> Optional[ScalingEvent]:
) -> ScalingEvent | None:
"""评估扩缩容策略"""
policy = self.get_auto_scaling_policy(policy_id)
if not policy or not policy.is_enabled:
@@ -1754,7 +1755,7 @@ class OpsManager:
return event
def get_last_scaling_event(self, policy_id: str) -> Optional[ScalingEvent]:
def get_last_scaling_event(self, policy_id: str) -> ScalingEvent | None:
"""获取最近的扩缩容事件"""
with self._get_db() as conn:
row = conn.execute(
@@ -1770,7 +1771,7 @@ class OpsManager:
def update_scaling_event_status(
self, event_id: str, status: str, error_message: str = None
) -> Optional[ScalingEvent]:
) -> ScalingEvent | None:
"""更新扩缩容事件状态"""
now = datetime.now().isoformat()
@@ -1797,7 +1798,7 @@ class OpsManager:
return self.get_scaling_event(event_id)
def get_scaling_event(self, event_id: str) -> Optional[ScalingEvent]:
def get_scaling_event(self, event_id: str) -> ScalingEvent | None:
"""获取扩缩容事件"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM scaling_events WHERE id = ?", (event_id,)).fetchone()
@@ -1806,7 +1807,7 @@ class OpsManager:
return self._row_to_scaling_event(row)
return None
def list_scaling_events(self, tenant_id: str, policy_id: str = None, limit: int = 100) -> List[ScalingEvent]:
def list_scaling_events(self, tenant_id: str, policy_id: str = None, limit: int = 100) -> list[ScalingEvent]:
"""列出租户的扩缩容事件"""
query = "SELECT * FROM scaling_events WHERE tenant_id = ?"
params = [tenant_id]
@@ -1831,7 +1832,7 @@ class OpsManager:
target_type: str,
target_id: str,
check_type: str,
check_config: Dict,
check_config: dict,
interval: int = 60,
timeout: int = 10,
retry_count: int = 3,
@@ -1889,7 +1890,7 @@ class OpsManager:
return check
def get_health_check(self, check_id: str) -> Optional[HealthCheck]:
def get_health_check(self, check_id: str) -> HealthCheck | None:
"""获取健康检查配置"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM health_checks WHERE id = ?", (check_id,)).fetchone()
@@ -1898,7 +1899,7 @@ class OpsManager:
return self._row_to_health_check(row)
return None
def list_health_checks(self, tenant_id: str) -> List[HealthCheck]:
def list_health_checks(self, tenant_id: str) -> list[HealthCheck]:
"""列出租户的健康检查"""
with self._get_db() as conn:
rows = conn.execute(
@@ -1958,7 +1959,7 @@ class OpsManager:
return result
async def _check_http_health(self, check: HealthCheck) -> Tuple[HealthStatus, float, str]:
async def _check_http_health(self, check: HealthCheck) -> tuple[HealthStatus, float, str]:
"""HTTP 健康检查"""
config = check.check_config
url = config.get("url")
@@ -1980,7 +1981,7 @@ class OpsManager:
except Exception as e:
return HealthStatus.UNHEALTHY, (time.time() - start_time) * 1000, str(e)
async def _check_tcp_health(self, check: HealthCheck) -> Tuple[HealthStatus, float, str]:
async def _check_tcp_health(self, check: HealthCheck) -> tuple[HealthStatus, float, str]:
"""TCP 健康检查"""
config = check.check_config
host = config.get("host")
@@ -1996,12 +1997,12 @@ class OpsManager:
writer.close()
await writer.wait_closed()
return HealthStatus.HEALTHY, response_time, "TCP connection successful"
except asyncio.TimeoutError:
except TimeoutError:
return HealthStatus.UNHEALTHY, (time.time() - start_time) * 1000, "Connection timeout"
except Exception as e:
return HealthStatus.UNHEALTHY, (time.time() - start_time) * 1000, str(e)
async def _check_ping_health(self, check: HealthCheck) -> Tuple[HealthStatus, float, str]:
async def _check_ping_health(self, check: HealthCheck) -> tuple[HealthStatus, float, str]:
"""Ping 健康检查(模拟)"""
config = check.check_config
host = config.get("host")
@@ -2013,7 +2014,7 @@ class OpsManager:
# 这里模拟成功
return HealthStatus.HEALTHY, 10.0, "Ping successful"
def get_health_check_results(self, check_id: str, limit: int = 100) -> List[HealthCheckResult]:
def get_health_check_results(self, check_id: str, limit: int = 100) -> list[HealthCheckResult]:
"""获取健康检查历史结果"""
with self._get_db() as conn:
rows = conn.execute(
@@ -2031,7 +2032,7 @@ class OpsManager:
tenant_id: str,
name: str,
primary_region: str,
secondary_regions: List[str],
secondary_regions: list[str],
failover_trigger: str,
auto_failover: bool = False,
failover_timeout: int = 300,
@@ -2083,7 +2084,7 @@ class OpsManager:
return config
def get_failover_config(self, config_id: str) -> Optional[FailoverConfig]:
def get_failover_config(self, config_id: str) -> FailoverConfig | None:
"""获取故障转移配置"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM failover_configs WHERE id = ?", (config_id,)).fetchone()
@@ -2092,7 +2093,7 @@ class OpsManager:
return self._row_to_failover_config(row)
return None
def list_failover_configs(self, tenant_id: str) -> List[FailoverConfig]:
def list_failover_configs(self, tenant_id: str) -> list[FailoverConfig]:
"""列出租户的故障转移配置"""
with self._get_db() as conn:
rows = conn.execute(
@@ -2100,7 +2101,7 @@ class OpsManager:
).fetchall()
return [self._row_to_failover_config(row) for row in rows]
def initiate_failover(self, config_id: str, reason: str) -> Optional[FailoverEvent]:
def initiate_failover(self, config_id: str, reason: str) -> FailoverEvent | None:
"""发起故障转移"""
config = self.get_failover_config(config_id)
if not config or not config.is_enabled:
@@ -2150,7 +2151,7 @@ class OpsManager:
return event
def update_failover_status(self, event_id: str, status: str) -> Optional[FailoverEvent]:
def update_failover_status(self, event_id: str, status: str) -> FailoverEvent | None:
"""更新故障转移状态"""
now = datetime.now().isoformat()
@@ -2186,7 +2187,7 @@ class OpsManager:
return self.get_failover_event(event_id)
def get_failover_event(self, event_id: str) -> Optional[FailoverEvent]:
def get_failover_event(self, event_id: str) -> FailoverEvent | None:
"""获取故障转移事件"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM failover_events WHERE id = ?", (event_id,)).fetchone()
@@ -2195,7 +2196,7 @@ class OpsManager:
return self._row_to_failover_event(row)
return None
def list_failover_events(self, tenant_id: str, limit: int = 100) -> List[FailoverEvent]:
def list_failover_events(self, tenant_id: str, limit: int = 100) -> list[FailoverEvent]:
"""列出租户的故障转移事件"""
with self._get_db() as conn:
rows = conn.execute(
@@ -2272,7 +2273,7 @@ class OpsManager:
return job
def get_backup_job(self, job_id: str) -> Optional[BackupJob]:
def get_backup_job(self, job_id: str) -> BackupJob | None:
"""获取备份任务"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM backup_jobs WHERE id = ?", (job_id,)).fetchone()
@@ -2281,7 +2282,7 @@ class OpsManager:
return self._row_to_backup_job(row)
return None
def list_backup_jobs(self, tenant_id: str) -> List[BackupJob]:
def list_backup_jobs(self, tenant_id: str) -> list[BackupJob]:
"""列出租户的备份任务"""
with self._get_db() as conn:
rows = conn.execute(
@@ -2289,7 +2290,7 @@ class OpsManager:
).fetchall()
return [self._row_to_backup_job(row) for row in rows]
def execute_backup(self, job_id: str) -> Optional[BackupRecord]:
def execute_backup(self, job_id: str) -> BackupRecord | None:
"""执行备份"""
job = self.get_backup_job(job_id)
if not job or not job.is_enabled:
@@ -2354,7 +2355,7 @@ class OpsManager:
)
conn.commit()
def get_backup_record(self, record_id: str) -> Optional[BackupRecord]:
def get_backup_record(self, record_id: str) -> BackupRecord | None:
"""获取备份记录"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM backup_records WHERE id = ?", (record_id,)).fetchone()
@@ -2363,7 +2364,7 @@ class OpsManager:
return self._row_to_backup_record(row)
return None
def list_backup_records(self, tenant_id: str, job_id: str = None, limit: int = 100) -> List[BackupRecord]:
def list_backup_records(self, tenant_id: str, job_id: str = None, limit: int = 100) -> list[BackupRecord]:
"""列出租户的备份记录"""
query = "SELECT * FROM backup_records WHERE tenant_id = ?"
params = [tenant_id]
@@ -2452,7 +2453,7 @@ class OpsManager:
return report
def _detect_cost_anomalies(self, utilizations: List[ResourceUtilization]) -> List[Dict]:
def _detect_cost_anomalies(self, utilizations: list[ResourceUtilization]) -> list[dict]:
"""检测成本异常"""
anomalies = []
@@ -2483,7 +2484,7 @@ class OpsManager:
return anomalies
def _calculate_cost_trends(self, tenant_id: str, year: int, month: int) -> Dict:
def _calculate_cost_trends(self, tenant_id: str, year: int, month: int) -> dict:
"""计算成本趋势"""
# 简化实现:返回模拟趋势
return {"month_over_month": 0.05, "year_over_year": 0.15, "forecast_next_month": 1.05} # 5% 增长 # 15% 增长
@@ -2498,7 +2499,7 @@ class OpsManager:
avg_utilization: float,
idle_time_percent: float,
report_date: str,
recommendations: List[str] = None,
recommendations: list[str] = None,
) -> ResourceUtilization:
"""记录资源利用率"""
util_id = f"ru_{uuid.uuid4().hex[:16]}"
@@ -2541,7 +2542,7 @@ class OpsManager:
return util
def get_resource_utilizations(self, tenant_id: str, report_period: str) -> List[ResourceUtilization]:
def get_resource_utilizations(self, tenant_id: str, report_period: str) -> list[ResourceUtilization]:
"""获取资源利用率列表"""
with self._get_db() as conn:
rows = conn.execute(
@@ -2552,7 +2553,7 @@ class OpsManager:
).fetchall()
return [self._row_to_resource_utilization(row) for row in rows]
def detect_idle_resources(self, tenant_id: str) -> List[IdleResource]:
def detect_idle_resources(self, tenant_id: str) -> list[IdleResource]:
"""检测闲置资源"""
idle_resources = []
@@ -2615,7 +2616,7 @@ class OpsManager:
return idle_resources
def get_idle_resources(self, tenant_id: str) -> List[IdleResource]:
def get_idle_resources(self, tenant_id: str) -> list[IdleResource]:
"""获取闲置资源列表"""
with self._get_db() as conn:
rows = conn.execute(
@@ -2623,7 +2624,7 @@ class OpsManager:
).fetchall()
return [self._row_to_idle_resource(row) for row in rows]
def generate_cost_optimization_suggestions(self, tenant_id: str) -> List[CostOptimizationSuggestion]:
def generate_cost_optimization_suggestions(self, tenant_id: str) -> list[CostOptimizationSuggestion]:
"""生成成本优化建议"""
suggestions = []
@@ -2691,7 +2692,7 @@ class OpsManager:
def get_cost_optimization_suggestions(
self, tenant_id: str, is_applied: bool = None
) -> List[CostOptimizationSuggestion]:
) -> list[CostOptimizationSuggestion]:
"""获取成本优化建议"""
query = "SELECT * FROM cost_optimization_suggestions WHERE tenant_id = ?"
params = [tenant_id]
@@ -2706,7 +2707,7 @@ class OpsManager:
rows = conn.execute(query, params).fetchall()
return [self._row_to_cost_optimization_suggestion(row) for row in rows]
def apply_cost_optimization_suggestion(self, suggestion_id: str) -> Optional[CostOptimizationSuggestion]:
def apply_cost_optimization_suggestion(self, suggestion_id: str) -> CostOptimizationSuggestion | None:
"""应用成本优化建议"""
now = datetime.now().isoformat()
@@ -2723,7 +2724,7 @@ class OpsManager:
return self.get_cost_optimization_suggestion(suggestion_id)
def get_cost_optimization_suggestion(self, suggestion_id: str) -> Optional[CostOptimizationSuggestion]:
def get_cost_optimization_suggestion(self, suggestion_id: str) -> CostOptimizationSuggestion | None:
"""获取成本优化建议详情"""
with self._get_db() as conn:
row = conn.execute("SELECT * FROM cost_optimization_suggestions WHERE id = ?", (suggestion_id,)).fetchone()