Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
117
backend/internal/api/handlers/management/api_key_usage.go
Normal file
117
backend/internal/api/handlers/management/api_key_usage.go
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
package management
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
|
||||
)
|
||||
|
||||
type apiKeyUsageEntry struct {
|
||||
Success int64 `json:"success"`
|
||||
Failed int64 `json:"failed"`
|
||||
RecentRequests []coreauth.RecentRequestBucket `json:"recent_requests"`
|
||||
}
|
||||
|
||||
func mergeRecentRequestBuckets(dst, src []coreauth.RecentRequestBucket) []coreauth.RecentRequestBucket {
|
||||
if len(dst) == 0 {
|
||||
return src
|
||||
}
|
||||
if len(src) == 0 {
|
||||
return dst
|
||||
}
|
||||
if len(dst) != len(src) {
|
||||
n := len(dst)
|
||||
if len(src) < n {
|
||||
n = len(src)
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
dst[i].Success += src[i].Success
|
||||
dst[i].Failed += src[i].Failed
|
||||
}
|
||||
return dst
|
||||
}
|
||||
for i := range dst {
|
||||
dst[i].Success += src[i].Success
|
||||
dst[i].Failed += src[i].Failed
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func apiKeyUsageProviderKey(auth *coreauth.Auth) string {
|
||||
provider := strings.ToLower(strings.TrimSpace(auth.Provider))
|
||||
if auth.Attributes != nil {
|
||||
if compatName := strings.TrimSpace(auth.Attributes["compat_name"]); compatName != "" {
|
||||
provider = strings.ToLower(compatName)
|
||||
}
|
||||
}
|
||||
if provider == "" {
|
||||
return "unknown"
|
||||
}
|
||||
return provider
|
||||
}
|
||||
|
||||
// GetAPIKeyUsage returns recent request buckets for all in-memory api_key auths,
|
||||
// grouped by provider and keyed by "base_url|api_key".
|
||||
func (h *Handler) GetAPIKeyUsage(c *gin.Context) {
|
||||
if h == nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "handler not initialized"})
|
||||
return
|
||||
}
|
||||
|
||||
h.mu.Lock()
|
||||
manager := h.authManager
|
||||
h.mu.Unlock()
|
||||
if manager == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "core auth manager unavailable"})
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
out := make(map[string]map[string]apiKeyUsageEntry)
|
||||
for _, auth := range manager.List() {
|
||||
if auth == nil {
|
||||
continue
|
||||
}
|
||||
kind, apiKey := auth.AccountInfo()
|
||||
if !strings.EqualFold(strings.TrimSpace(kind), "api_key") {
|
||||
continue
|
||||
}
|
||||
apiKey = strings.TrimSpace(apiKey)
|
||||
if apiKey == "" {
|
||||
continue
|
||||
}
|
||||
baseURL := ""
|
||||
if auth.Attributes != nil {
|
||||
baseURL = strings.TrimSpace(auth.Attributes["base_url"])
|
||||
if baseURL == "" {
|
||||
baseURL = strings.TrimSpace(auth.Attributes["base-url"])
|
||||
}
|
||||
}
|
||||
compositeKey := baseURL + "|" + apiKey
|
||||
provider := apiKeyUsageProviderKey(auth)
|
||||
|
||||
recent := auth.RecentRequestsSnapshot(now)
|
||||
providerBucket, ok := out[provider]
|
||||
if !ok {
|
||||
providerBucket = make(map[string]apiKeyUsageEntry)
|
||||
out[provider] = providerBucket
|
||||
}
|
||||
if existing, exists := providerBucket[compositeKey]; exists {
|
||||
existing.Success += auth.Success
|
||||
existing.Failed += auth.Failed
|
||||
existing.RecentRequests = mergeRecentRequestBuckets(existing.RecentRequests, recent)
|
||||
providerBucket[compositeKey] = existing
|
||||
continue
|
||||
}
|
||||
providerBucket[compositeKey] = apiKeyUsageEntry{
|
||||
Success: auth.Success,
|
||||
Failed: auth.Failed,
|
||||
RecentRequests: recent,
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, out)
|
||||
}
|
||||
Loading…
Reference in a new issue