mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-23 08:04:45 +08:00
feat: Anthropic 账号被动用量采样,页面默认展示被动数据
从上游 /v1/messages 响应头被动采集 5h/7d utilization 并存储到 Account.Extra,页面加载时直接读取本地数据而非调用外部 Usage API。 用户可点击"查询"按钮主动拉取最新数据,主动查询结果自动回写被动缓存。 后端: - UpdateSessionWindow 合并采集 5h + 7d headers 为单次 DB 写入 - 新增 GetPassiveUsage 从 Extra 构建 UsageInfo (复用 estimateSetupTokenUsage) - GetUsage 主动查询后 syncActiveToPassive 回写被动缓存 - passive_usage_ 前缀注册为 scheduler-neutral 前端: - Anthropic 账号 mount/refresh 默认 source=passive - 新增"被动采样"标签和"查询"按钮 (带 loading 动画)
This commit is contained in:
@@ -1110,10 +1110,13 @@ func (s *RateLimitService) UpdateSessionWindow(ctx context.Context, account *Acc
|
||||
slog.Info("account_session_window_initialized", "account_id", account.ID, "window_start", start, "window_end", end, "status", status)
|
||||
}
|
||||
|
||||
// 窗口重置时清除旧的 utilization,避免残留上个窗口的数据
|
||||
// 窗口重置时清除旧的 utilization 和被动采样数据,避免残留上个窗口的数据
|
||||
if windowEnd != nil && needInitWindow {
|
||||
_ = s.accountRepo.UpdateExtra(ctx, account.ID, map[string]any{
|
||||
"session_window_utilization": nil,
|
||||
"session_window_utilization": nil,
|
||||
"passive_usage_7d_utilization": nil,
|
||||
"passive_usage_7d_reset": nil,
|
||||
"passive_usage_sampled_at": nil,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1121,14 +1124,33 @@ func (s *RateLimitService) UpdateSessionWindow(ctx context.Context, account *Acc
|
||||
slog.Warn("session_window_update_failed", "account_id", account.ID, "error", err)
|
||||
}
|
||||
|
||||
// 存储真实的 utilization 值(0-1 小数),供 estimateSetupTokenUsage 使用
|
||||
// 被动采样:从响应头收集 5h + 7d utilization,合并为一次 DB 写入
|
||||
extraUpdates := make(map[string]any, 4)
|
||||
// 5h utilization(0-1 小数),供 estimateSetupTokenUsage 使用
|
||||
if utilStr := headers.Get("anthropic-ratelimit-unified-5h-utilization"); utilStr != "" {
|
||||
if util, err := strconv.ParseFloat(utilStr, 64); err == nil {
|
||||
if err := s.accountRepo.UpdateExtra(ctx, account.ID, map[string]any{
|
||||
"session_window_utilization": util,
|
||||
}); err != nil {
|
||||
slog.Warn("session_window_utilization_update_failed", "account_id", account.ID, "error", err)
|
||||
extraUpdates["session_window_utilization"] = util
|
||||
}
|
||||
}
|
||||
// 7d utilization(0-1 小数)
|
||||
if utilStr := headers.Get("anthropic-ratelimit-unified-7d-utilization"); utilStr != "" {
|
||||
if util, err := strconv.ParseFloat(utilStr, 64); err == nil {
|
||||
extraUpdates["passive_usage_7d_utilization"] = util
|
||||
}
|
||||
}
|
||||
// 7d reset timestamp
|
||||
if resetStr := headers.Get("anthropic-ratelimit-unified-7d-reset"); resetStr != "" {
|
||||
if ts, err := strconv.ParseInt(resetStr, 10, 64); err == nil {
|
||||
if ts > 1e11 {
|
||||
ts = ts / 1000
|
||||
}
|
||||
extraUpdates["passive_usage_7d_reset"] = ts
|
||||
}
|
||||
}
|
||||
if len(extraUpdates) > 0 {
|
||||
extraUpdates["passive_usage_sampled_at"] = time.Now().UTC().Format(time.RFC3339)
|
||||
if err := s.accountRepo.UpdateExtra(ctx, account.ID, extraUpdates); err != nil {
|
||||
slog.Warn("passive_usage_update_failed", "account_id", account.ID, "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user