GetAllUsageBySource is the admin variant of GetUserUsageBySource. Optional filters: userID and apiKeyID. Legacy is included. truncated == true iff the per-key roll-up was capped at maxKeyTotals.
(db *gorm.DB, period, userID, apiKeyID string)
| 416 | // Optional filters: userID and apiKeyID. Legacy is included. |
| 417 | // truncated == true iff the per-key roll-up was capped at maxKeyTotals. |
| 418 | func GetAllUsageBySource(db *gorm.DB, period, userID, apiKeyID string) ([]UsageBucket, SourceTotals, bool, error) { |
| 419 | sqlite := isSQLiteDB(db) |
| 420 | since, dateFmt := periodToWindow(period, sqlite) |
| 421 | bucketExpr := fmt.Sprintf("%s as bucket", dateFmt) |
| 422 | |
| 423 | query := db.Model(&UsageRecord{}). |
| 424 | Select(bucketExpr+", source, COALESCE(api_key_id, '') as api_key_id, api_key_name, "+ |
| 425 | "user_id, user_name, "+ |
| 426 | "SUM(prompt_tokens) as prompt_tokens, "+ |
| 427 | "SUM(completion_tokens) as completion_tokens, "+ |
| 428 | "SUM(total_tokens) as total_tokens, "+ |
| 429 | "COUNT(*) as request_count"). |
| 430 | Group("bucket, source, api_key_id, api_key_name, user_id, user_name"). |
| 431 | Order("bucket ASC") |
| 432 | |
| 433 | query = applyFilters(query, userID, apiKeyID, since, true) |
| 434 | |
| 435 | var buckets []UsageBucket |
| 436 | if err := query.Find(&buckets).Error; err != nil { |
| 437 | return nil, SourceTotals{}, false, err |
| 438 | } |
| 439 | |
| 440 | totals := computeSourceTotals(db, userID, apiKeyID, since, true) |
| 441 | |
| 442 | // Count distinct api_key_ids matching the filters. If > maxKeyTotals, |
| 443 | // the by_key slice was capped and we signal truncation to the caller. |
| 444 | truncated := false |
| 445 | var distinct int64 |
| 446 | countQ := applyFilters( |
| 447 | db.Model(&UsageRecord{}). |
| 448 | Distinct("api_key_id"). |
| 449 | Where("api_key_id IS NOT NULL AND api_key_id <> ''"), |
| 450 | userID, apiKeyID, since, true, |
| 451 | ) |
| 452 | if err := countQ.Count(&distinct).Error; err != nil { |
| 453 | xlog.Warn("GetAllUsageBySource: distinct api_key_id count failed", "error", err) |
| 454 | } else { |
| 455 | truncated = distinct > maxKeyTotals |
| 456 | } |
| 457 | |
| 458 | return buckets, totals, truncated, nil |
| 459 | } |
| 460 | |
| 461 | func applyFilters(q *gorm.DB, userID, apiKeyID string, since time.Time, includeLegacy bool) *gorm.DB { |
| 462 | if userID != "" { |