Files
cpa-plugin/internal/repository/sqlite_summary.go
T

79 lines
3.2 KiB
Go

package repository
import (
"context"
"fmt"
"time"
"cpa-ext/internal/collection"
)
func (r *SQLiteUsageRepository) UsageDashboard(ctx context.Context, today time.Time, days int) (collection.UsageDashboard, error) {
if days < 1 {
days = 7
}
start := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location())
dashboard := collection.UsageDashboard{}
if err := r.db.QueryRowContext(ctx, `
SELECT COUNT(*), COALESCE(SUM(u.input_tokens),0), COALESCE(SUM(u.output_tokens),0),
COALESCE(SUM(u.total_tokens),0), COALESCE(SUM(u.cost_micros),0)
FROM request_detail_index d LEFT JOIN usage_records u ON u.id=d.usage_id
WHERE d.requested_at>=?`, formatTime(start)).Scan(&dashboard.Today.Requests, &dashboard.Today.InputTokens, &dashboard.Today.OutputTokens, &dashboard.Today.TotalTokens, &dashboard.Today.CostMicros); err != nil {
return dashboard, fmt.Errorf("汇总今日用量: %w", err)
}
rows, err := r.db.QueryContext(ctx, `
SELECT d.managed_key_id, COALESCE(k.name, '未识别'),
SUM(CASE WHEN d.requested_at>=? THEN 1 ELSE 0 END),
COALESCE(SUM(CASE WHEN d.requested_at>=? THEN u.input_tokens ELSE 0 END),0),
COALESCE(SUM(CASE WHEN d.requested_at>=? THEN u.output_tokens ELSE 0 END),0),
COALESCE(SUM(CASE WHEN d.requested_at>=? THEN u.total_tokens ELSE 0 END),0),
COALESCE(SUM(CASE WHEN d.requested_at>=? THEN u.cost_micros ELSE 0 END),0),
MAX(d.requested_at)
FROM request_detail_index d
LEFT JOIN usage_records u ON u.id=d.usage_id
LEFT JOIN managed_keys k ON k.id=d.managed_key_id
GROUP BY d.managed_key_id, COALESCE(k.name, '未识别')
ORDER BY 6 DESC, 2`, formatTime(start), formatTime(start), formatTime(start), formatTime(start), formatTime(start))
if err != nil {
return dashboard, fmt.Errorf("汇总用户用量: %w", err)
}
for rows.Next() {
var item collection.UserUsageSummary
var last string
if err := rows.Scan(&item.KeyID, &item.KeyAlias, &item.Today.Requests, &item.Today.InputTokens, &item.Today.OutputTokens, &item.Today.TotalTokens, &item.Today.CostMicros, &last); err != nil {
_ = rows.Close()
return dashboard, fmt.Errorf("读取用户用量汇总: %w", err)
}
if parsed, parseErr := time.Parse(time.RFC3339Nano, last); parseErr == nil {
item.LastUsedAt = &parsed
}
dashboard.Users = append(dashboard.Users, item)
}
_ = rows.Close()
dailyStart := start.AddDate(0, 0, -(days - 1))
rows, err = r.db.QueryContext(ctx, `
SELECT DATE(d.requested_at, '+8 hours'), COALESCE(SUM(u.total_tokens),0)
FROM request_detail_index d LEFT JOIN usage_records u ON u.id=d.usage_id
WHERE d.requested_at>=? GROUP BY DATE(d.requested_at, '+8 hours') ORDER BY 1`, formatTime(dailyStart))
if err != nil {
return dashboard, fmt.Errorf("汇总每日用量: %w", err)
}
byDate := make(map[string]int64)
for rows.Next() {
var date string
var tokens int64
if err := rows.Scan(&date, &tokens); err != nil {
_ = rows.Close()
return dashboard, fmt.Errorf("读取每日用量: %w", err)
}
byDate[date] = tokens
}
_ = rows.Close()
for index := 0; index < days; index++ {
date := dailyStart.AddDate(0, 0, index)
dashboard.Days = append(dashboard.Days, collection.DailyUsageSummary{Date: date, TotalTokens: byDate[date.Format("2006-01-02")]})
}
return dashboard, nil
}