File size: 2,665 Bytes
b034029
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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
}