Spaces:
Running
Running
| 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 | |
| } | |