325 lines
9.0 KiB
Python
325 lines
9.0 KiB
Python
"""
|
||
套餐额度预警服务
|
||
|
||
监控用户的API调用额度、查询次数等使用情况,在接近限制时触发预警。
|
||
|
||
功能:
|
||
- 额度使用查询: 获取用户当前额度使用情况
|
||
- 使用率计算: 计算额度使用百分比
|
||
- 预警阈值检查: 80%警告、90%严重、100%限制
|
||
- 预警消息生成: 生成带建议操作的预警消息
|
||
- 额度重置: 支持额度重置功能
|
||
|
||
额度类型:
|
||
- api_calls: API调用次数
|
||
- queries: 查询次数
|
||
- content_generation: 内容生成次数
|
||
- storage: 存储空间(MB)
|
||
|
||
预警阈值:
|
||
- warning: 80% - 警告
|
||
- critical: 90% - 严重
|
||
- exhausted: 100% - 耗尽
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
from enum import Enum
|
||
|
||
|
||
class QuotaType(str, Enum):
|
||
"""额度类型枚举"""
|
||
API_CALLS = "api_calls"
|
||
QUERIES = "queries"
|
||
CONTENT_GENERATION = "content_generation"
|
||
STORAGE = "storage"
|
||
|
||
|
||
QUOTA_LIMITS = {
|
||
"free": {
|
||
"api_calls": 1000,
|
||
"queries": 50,
|
||
"content_generation": 10,
|
||
"storage": 100,
|
||
},
|
||
"basic": {
|
||
"api_calls": 10000,
|
||
"queries": 500,
|
||
"content_generation": 100,
|
||
"storage": 1000,
|
||
},
|
||
"pro": {
|
||
"api_calls": 100000,
|
||
"queries": 5000,
|
||
"content_generation": 1000,
|
||
"storage": 10000,
|
||
},
|
||
"unlimited": {
|
||
"api_calls": -1,
|
||
"queries": -1,
|
||
"content_generation": -1,
|
||
"storage": -1,
|
||
},
|
||
}
|
||
|
||
WARNING_THRESHOLDS = {
|
||
"warning": 0.80,
|
||
"critical": 0.90,
|
||
"exhausted": 1.00,
|
||
}
|
||
|
||
WARNING_MESSAGES = {
|
||
"warning": "{quota_type}额度已使用{percentage:.0f}%",
|
||
"critical": "{quota_type}额度已使用{percentage:.0f}%,即将耗尽",
|
||
"exhausted": "{quota_type}额度已使用{percentage:.0f}%,已耗尽",
|
||
}
|
||
|
||
RECOMMENDED_ACTIONS = {
|
||
"warning": "请关注使用情况,考虑升级套餐",
|
||
"critical": "额度即将耗尽,建议立即升级套餐",
|
||
"exhausted": "额度已耗尽,请升级套餐或等待重置",
|
||
}
|
||
|
||
|
||
@dataclass
|
||
class QuotaUsage:
|
||
"""额度使用数据结构
|
||
|
||
Attributes:
|
||
quota_type: 额度类型
|
||
used: 已使用量
|
||
limit: 额度限制(-1表示无限)
|
||
usage_percentage: 使用百分比(0-100,无限时为0)
|
||
status: 状态(ok/warning/critical/exhausted/unlimited)
|
||
remaining: 剩余额度(-1表示无限)
|
||
"""
|
||
quota_type: str
|
||
used: int
|
||
limit: int
|
||
usage_percentage: float
|
||
status: str
|
||
remaining: int
|
||
|
||
|
||
@dataclass
|
||
class QuotaWarning:
|
||
"""预警数据结构
|
||
|
||
Attributes:
|
||
quota_type: 额度类型
|
||
status: 预警状态
|
||
usage_percentage: 使用百分比
|
||
message: 预警消息
|
||
recommended_action: 建议操作
|
||
"""
|
||
quota_type: str
|
||
status: str
|
||
usage_percentage: float
|
||
message: str
|
||
recommended_action: str
|
||
|
||
|
||
class QuotaService:
|
||
"""套餐额度预警服务
|
||
|
||
提供额度查询、使用率计算、预警检查等功能。
|
||
"""
|
||
|
||
def calculate_usage_percentage(self, used: int, limit: int) -> float:
|
||
"""计算额度使用百分比
|
||
|
||
Args:
|
||
used: 已使用量
|
||
limit: 额度限制(-1表示无限)
|
||
|
||
Returns:
|
||
使用百分比(0-100),无限额度时返回0.0
|
||
"""
|
||
if limit == -1 or limit == 0:
|
||
return 0.0
|
||
return (used / limit) * 100.0
|
||
|
||
def get_quota_status(self, usage_percentage: float, limit: int = 0) -> str:
|
||
"""根据使用率获取额度状态
|
||
|
||
Args:
|
||
usage_percentage: 使用百分比
|
||
limit: 额度限制(-1表示无限)
|
||
|
||
Returns:
|
||
状态字符串: ok/warning/critical/exhausted/unlimited
|
||
"""
|
||
if limit == -1:
|
||
return "unlimited"
|
||
if usage_percentage >= 100.0:
|
||
return "exhausted"
|
||
if usage_percentage >= 90.0:
|
||
return "critical"
|
||
if usage_percentage >= 80.0:
|
||
return "warning"
|
||
return "ok"
|
||
|
||
def get_quota_limit(self, plan: str, quota_type: QuotaType) -> int:
|
||
"""获取指定套餐的额度限制
|
||
|
||
Args:
|
||
plan: 套餐名称(free/basic/pro/unlimited)
|
||
quota_type: 额度类型
|
||
|
||
Returns:
|
||
额度限制值(-1表示无限)
|
||
"""
|
||
return QUOTA_LIMITS.get(plan, {}).get(quota_type.value, 0)
|
||
|
||
def get_remaining(self, used: int, limit: int) -> int:
|
||
"""计算剩余额度
|
||
|
||
Args:
|
||
used: 已使用量
|
||
limit: 额度限制(-1表示无限)
|
||
|
||
Returns:
|
||
剩余额度(-1表示无限)
|
||
"""
|
||
if limit == -1:
|
||
return -1
|
||
return limit - used
|
||
|
||
def _format_warning_message(self, quota_type: str, status: str, percentage: float) -> str:
|
||
"""格式化预警消息
|
||
|
||
Args:
|
||
quota_type: 额度类型
|
||
status: 预警状态
|
||
percentage: 使用百分比
|
||
|
||
Returns:
|
||
格式化后的预警消息
|
||
"""
|
||
template = WARNING_MESSAGES.get(status, "{quota_type}额度使用情况")
|
||
return template.format(quota_type=quota_type, percentage=percentage)
|
||
|
||
def _get_recommended_action(self, status: str) -> str:
|
||
"""获取建议操作
|
||
|
||
Args:
|
||
status: 预警状态
|
||
|
||
Returns:
|
||
建议操作描述
|
||
"""
|
||
return RECOMMENDED_ACTIONS.get(status, "请关注使用情况")
|
||
|
||
def generate_warning(
|
||
self,
|
||
quota_type: QuotaType,
|
||
status: str,
|
||
usage_percentage: float,
|
||
) -> QuotaWarning:
|
||
"""生成预警信息
|
||
|
||
Args:
|
||
quota_type: 额度类型
|
||
status: 预警状态
|
||
usage_percentage: 使用百分比
|
||
|
||
Returns:
|
||
QuotaWarning预警数据对象
|
||
"""
|
||
return QuotaWarning(
|
||
quota_type=quota_type.value,
|
||
status=status,
|
||
usage_percentage=usage_percentage,
|
||
message=self._format_warning_message(quota_type.value, status, usage_percentage),
|
||
recommended_action=self._get_recommended_action(status),
|
||
)
|
||
|
||
def check_quota(
|
||
self,
|
||
plan: str,
|
||
quota_type: QuotaType,
|
||
used: int,
|
||
) -> QuotaUsage:
|
||
"""检查指定套餐的额度使用情况
|
||
|
||
Args:
|
||
plan: 套餐名称
|
||
quota_type: 额度类型
|
||
used: 已使用量
|
||
|
||
Returns:
|
||
QuotaUsage额度使用数据对象
|
||
"""
|
||
limit = self.get_quota_limit(plan, quota_type)
|
||
percentage = self.calculate_usage_percentage(used, limit)
|
||
status = self.get_quota_status(percentage, limit)
|
||
remaining = self.get_remaining(used, limit)
|
||
|
||
return QuotaUsage(
|
||
quota_type=quota_type.value,
|
||
used=used,
|
||
limit=limit,
|
||
usage_percentage=percentage,
|
||
status=status,
|
||
remaining=remaining,
|
||
)
|
||
|
||
def reset_quota(self, used: int, reset_to: int = 0) -> int:
|
||
"""重置额度使用量
|
||
|
||
Args:
|
||
used: 当前使用量(未使用,仅为接口兼容)
|
||
reset_to: 重置到的值,默认为0
|
||
|
||
Returns:
|
||
重置后的使用量
|
||
"""
|
||
return reset_to
|
||
|
||
def get_all_quota_usage(
|
||
self,
|
||
plan: str,
|
||
api_calls_used: int = 0,
|
||
queries_used: int = 0,
|
||
content_generation_used: int = 0,
|
||
storage_used: int = 0,
|
||
) -> list[QuotaUsage]:
|
||
"""获取所有额度类型的使用情况
|
||
|
||
Args:
|
||
plan: 套餐名称
|
||
api_calls_used: API调用已使用量
|
||
queries_used: 查询已使用量
|
||
content_generation_used: 内容生成已使用量
|
||
storage_used: 存储已使用量(MB)
|
||
|
||
Returns:
|
||
所有额度类型的使用情况列表
|
||
"""
|
||
return [
|
||
self.check_quota(plan, QuotaType.API_CALLS, api_calls_used),
|
||
self.check_quota(plan, QuotaType.QUERIES, queries_used),
|
||
self.check_quota(plan, QuotaType.CONTENT_GENERATION, content_generation_used),
|
||
self.check_quota(plan, QuotaType.STORAGE, storage_used),
|
||
]
|
||
|
||
def get_warnings(self, usage_list: list[QuotaUsage]) -> list[QuotaWarning]:
|
||
"""从使用情况列表中生成预警
|
||
|
||
Args:
|
||
usage_list: 额度使用情况列表
|
||
|
||
Returns:
|
||
预警信息列表(仅包含需要预警的项)
|
||
"""
|
||
warnings = []
|
||
for usage in usage_list:
|
||
if usage.status in ["warning", "critical", "exhausted"]:
|
||
warning = self.generate_warning(
|
||
quota_type=QuotaType(usage.quota_type),
|
||
status=usage.status,
|
||
usage_percentage=usage.usage_percentage,
|
||
)
|
||
warnings.append(warning)
|
||
return warnings
|