- 新增 RoutingCache 组件,使用 sync.Map 缓存 Provider 和 Model - 新增 StatsBuffer 组件,使用 sync.Map + atomic.Int64 缓冲统计数据 - 扩展 StatsRepository.BatchUpdate 支持批量增量更新 - 改造 RoutingService/StatsService/ProviderService/ModelService 集成缓存 - 更新 usage-statistics spec,新增 routing-cache 和 stats-buffer spec - 新增单元测试覆盖缓存命中/失效/并发场景
5.5 KiB
5.5 KiB
Usage Statistics
Purpose
定义 API 使用统计规范,支持请求统计记录、按供应商/模型/日期范围查询统计、统计聚合以及并发安全的统计记录。
Requirements
Requirement: 记录请求统计
网关 SHALL 为每次 API 调用记录请求统计。
Scenario: 记录成功请求
- WHEN 请求成功转发到供应商
- THEN 网关 SHALL 通过 StatsBuffer 增加该供应商和模型的请求计数
- THEN 网关 SHALL 异步批量写入数据库(定时或阈值触发)
- THEN 网关 SHALL 不阻塞响应
Scenario: 记录流式请求
- WHEN 流式请求成功完成
- THEN 网关 SHALL 通过 StatsBuffer 增加该供应商和模型的请求计数
- THEN 网关 SHALL 在流结束后异步记录统计
Requirement: 使用统计记录统一模型标识
系统 SHALL 使用 providerID 和 modelName(上游模型名)记录使用统计。
Scenario: 代理请求统计记录
- WHEN 代理请求成功完成
- THEN SHALL 记录 provider_id 和 model_name 到 usage_stats 表(参数来自路由结果)
- THEN SHALL 异步执行,不阻塞响应
Scenario: 查询统计
- WHEN 查询统计数据
- THEN 支持按 provider_id 和 model_name 过滤
Requirement: 按供应商查询统计
网关 SHALL 允许按供应商过滤查询统计。
Scenario: 查询特定供应商的统计
- WHEN 向
/api/stats?provider_id=<provider_id>发送 GET 请求 - THEN 网关 SHALL 仅返回指定供应商的统计
变更说明: 通过 StatsService 和 StatsRepository 实现。API 接口保持不变。
Requirement: 按模型查询统计
网关 SHALL 允许按模型过滤查询统计。
Scenario: 查询特定模型的统计
- WHEN 向
/api/stats?model_name=<model_name>发送 GET 请求 - THEN 网关 SHALL 仅返回指定模型的统计
变更说明: 通过 StatsService 和 StatsRepository 实现。API 接口保持不变。
Requirement: 按日期范围查询统计
网关 SHALL 允许在日期范围内查询统计。
Scenario: 使用日期范围查询统计
- WHEN 向
/api/stats?start=<start_date>&end=<end_date>发送 GET 请求 - THEN 网关 SHALL 仅返回指定范围内的日期统计
- THEN 日期格式 SHALL 为 YYYY-MM-DD
变更说明: 通过 StatsService 和 StatsRepository 实现。API 接口保持不变。
Requirement: 聚合统计
网关 SHALL 按日期聚合统计。
Scenario: 同一天多次请求
- WHEN 同一天对同一供应商和模型发起多次请求
- THEN 网关 SHALL 为该天维护单条统计记录
- THEN 请求计数 SHALL 为所有请求的总和
变更说明: 聚合逻辑在 StatsRepository 中实现。API 接口保持不变。
Requirement: 支持并发统计记录
网关 SHALL 支持并发请求统计记录而无冲突。
Scenario: 并发请求
- WHEN 同时处理多个并发请求
- THEN 网关 SHALL 使用原子操作正确增加每个请求的计数
- THEN 不 SHALL 因并发写入而丢失统计
- THEN SHALL 使用 StatsBuffer 的内存计数器
Requirement: 使用 service 层处理业务逻辑
Handler SHALL 通过 StatsService 处理业务逻辑。
Scenario: 调用 service 方法
- WHEN handler 收到统计查询请求
- THEN SHALL 调用对应的 StatsService 方法(Get、Aggregate)
- THEN SHALL 使用 domain.UsageStats 类型
Scenario: 异步记录统计
- WHEN 请求完成需要记录统计
- THEN SHALL 异步调用 StatsService.Record()
- THEN SHALL 不阻塞响应返回
Requirement: 使用 repository 层访问数据
Service SHALL 通过 StatsRepository 访问数据。
Scenario: 调用 repository 方法
- WHEN service 处理业务逻辑
- THEN SHALL 调用对应的 StatsRepository 方法
- THEN SHALL 使用 domain.UsageStats 类型
Scenario: 批量更新统计
- WHEN StatsBuffer 刷新统计
- THEN SHALL 调用 StatsRepository.BatchUpdate
- THEN SHALL 使用事务更新或创建统计记录
- THEN SHALL 支持增量更新(request_count + delta)
Scenario: 事务处理
- WHEN 记录统计
- THEN SHALL 在 repository 层使用数据库事务
- THEN SHALL 确保并发安全
Requirement: 统计查询优化
统计查询 SHALL 使用索引优化性能。
Scenario: 使用索引
- WHEN 查询统计
- THEN SHALL 使用 (provider_id, model_name, date) 复合索引
- THEN SHALL 优化查询性能
Requirement: 统计数据可接受少量丢失
统计记录方式改为内存缓冲,可接受少量丢失。
Scenario: 进程崩溃丢失统计
- WHEN 进程崩溃
- THEN MAY 丢失最近 flushInterval 内的统计
- THEN 统计数据用于监控,可接受少量丢失
Scenario: 优雅关闭保证不丢失
- WHEN 服务优雅关闭
- THEN SHALL 调用 StatsBuffer.Stop
- THEN SHALL 等待最后一次刷新完成
- THEN SHALL 保证统计数据不丢失
Requirement: StatsRepository 支持批量更新
StatsRepository SHALL 新增 BatchUpdate 方法支持批量增量更新。
Scenario: BatchUpdate 更新现有记录
- WHEN 调用 BatchUpdate 且当日记录存在
- THEN SHALL 使用事务更新 request_count = request_count + delta
- THEN SHALL 不创建新记录
Scenario: BatchUpdate 创建新记录
- WHEN 调用 BatchUpdate 且当日记录不存在
- THEN SHALL 创建新记录,request_count = delta
- THEN SHALL 使用事务保证原子性