daili-usage-keeper / internal /api /usage_credentials.go
pjpjq's picture
fix: build usage keeper from source
b034029 verified
package api
import (
"net/http"
"time"
"cpa-usage-keeper/internal/service"
"github.com/gin-gonic/gin"
)
type usageCredentialsResponse struct {
Credentials []usageCredentialPayload `json:"credentials"`
}
type usageCredentialPayload struct {
Source string `json:"source"`
SourceType string `json:"source_type,omitempty"`
SourceKey string `json:"source_key,omitempty"`
SuccessCount int64 `json:"success_count"`
FailureCount int64 `json:"failure_count"`
TotalCount int64 `json:"total_count"`
}
func registerUsageCredentialsRoute(
router gin.IRoutes,
usageProvider service.UsageProvider,
usageIdentityProvider service.UsageIdentityProvider,
) {
router.GET("/usage/credentials", func(c *gin.Context) {
if usageProvider == nil {
c.JSON(http.StatusOK, usageCredentialsResponse{Credentials: []usageCredentialPayload{}})
return
}
filter, err := parseUsageFilterQuery(c.Request, time.Now().UTC())
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
rows, err := usageProvider.ListUsageCredentialStats(c.Request.Context(), filter)
if err != nil {
writeInternalError(c, "list usage credential stats failed", err)
return
}
identities, err := loadUsageResolutionData(c, usageIdentityProvider)
if err != nil {
writeInternalError(c, "load usage resolution data failed", err)
return
}
resolver := newUsageSourceResolver(identities)
c.JSON(http.StatusOK, usageCredentialsResponse{Credentials: buildUsageCredentialsPayload(rows, resolver)})
})
}
func buildUsageCredentialsPayload(rows []service.UsageCredentialStat, resolver usageSourceResolver) []usageCredentialPayload {
if len(rows) == 0 {
return []usageCredentialPayload{}
}
buckets := make(map[string]*usageCredentialPayload, len(rows))
orderedKeys := make([]string, 0, len(rows))
for _, row := range rows {
resolved := resolver.resolve(row.Source, row.AuthIndex)
bucketKey := resolved.SourceKey
if bucketKey == "" {
bucketKey = resolved.DisplayName
}
payload, ok := buckets[bucketKey]
if !ok {
payload = &usageCredentialPayload{
Source: resolved.DisplayName,
SourceType: resolved.SourceType,
SourceKey: resolved.SourceKey,
}
buckets[bucketKey] = payload
orderedKeys = append(orderedKeys, bucketKey)
}
if row.Failed {
payload.FailureCount += row.RequestCount
} else {
payload.SuccessCount += row.RequestCount
}
payload.TotalCount = payload.SuccessCount + payload.FailureCount
}
result := make([]usageCredentialPayload, 0, len(orderedKeys))
for _, key := range orderedKeys {
result = append(result, *buckets[key])
}
return result
}