Spaces:
Running
Running
File size: 4,610 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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | package api
import (
"net/http"
"time"
"cpa-usage-keeper/internal/redact"
"cpa-usage-keeper/internal/service"
"github.com/gin-gonic/gin"
)
type usageAnalysisResponse struct {
APIs []usageAnalysisAPIPayload `json:"apis"`
Models []usageAnalysisModelPayload `json:"models"`
}
type usageAnalysisAPIPayload struct {
APIKey string `json:"api_key"`
DisplayName string `json:"display_name"`
TotalRequests int64 `json:"total_requests"`
SuccessCount int64 `json:"success_count"`
FailureCount int64 `json:"failure_count"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
ReasoningTokens int64 `json:"reasoning_tokens"`
CachedTokens int64 `json:"cached_tokens"`
TotalTokens int64 `json:"total_tokens"`
Models []usageAnalysisModelPayload `json:"models"`
}
type usageAnalysisModelPayload struct {
Model string `json:"model"`
TotalRequests int64 `json:"total_requests"`
SuccessCount int64 `json:"success_count"`
FailureCount int64 `json:"failure_count"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
ReasoningTokens int64 `json:"reasoning_tokens"`
CachedTokens int64 `json:"cached_tokens"`
TotalTokens int64 `json:"total_tokens"`
TotalLatencyMS int64 `json:"total_latency_ms"`
LatencySampleCount int64 `json:"latency_sample_count"`
}
func registerUsageAnalysisRoute(router gin.IRoutes, usageProvider service.UsageProvider) {
router.GET("/usage/analysis", func(c *gin.Context) {
if usageProvider == nil {
c.JSON(http.StatusOK, usageAnalysisResponse{APIs: []usageAnalysisAPIPayload{}, Models: []usageAnalysisModelPayload{}})
return
}
filter, err := parseUsageFilterQuery(c.Request, time.Now().UTC())
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
analysis, err := usageProvider.GetUsageAnalysis(c.Request.Context(), filter)
if err != nil {
writeInternalError(c, "get usage analysis failed", err)
return
}
c.JSON(http.StatusOK, buildUsageAnalysisPayload(analysis))
})
}
func buildUsageAnalysisPayload(snapshot *service.UsageAnalysisSnapshot) usageAnalysisResponse {
if snapshot == nil {
return usageAnalysisResponse{APIs: []usageAnalysisAPIPayload{}, Models: []usageAnalysisModelPayload{}}
}
apis := make([]usageAnalysisAPIPayload, 0, len(snapshot.APIs))
for _, api := range snapshot.APIs {
models := make([]usageAnalysisModelPayload, 0, len(api.Models))
for _, model := range api.Models {
models = append(models, usageAnalysisModelPayload{
Model: model.Model,
TotalRequests: model.TotalRequests,
SuccessCount: model.SuccessCount,
FailureCount: model.FailureCount,
InputTokens: model.InputTokens,
OutputTokens: model.OutputTokens,
ReasoningTokens: model.ReasoningTokens,
CachedTokens: model.CachedTokens,
TotalTokens: model.TotalTokens,
TotalLatencyMS: model.TotalLatencyMS,
LatencySampleCount: model.LatencySampleCount,
})
}
apiKey := redact.APIAlias(api.APIKey)
displayName := redact.APIKeyDisplayName(api.APIKey)
apis = append(apis, usageAnalysisAPIPayload{
APIKey: apiKey,
DisplayName: displayName,
TotalRequests: api.TotalRequests,
SuccessCount: api.SuccessCount,
FailureCount: api.FailureCount,
InputTokens: api.InputTokens,
OutputTokens: api.OutputTokens,
ReasoningTokens: api.ReasoningTokens,
CachedTokens: api.CachedTokens,
TotalTokens: api.TotalTokens,
Models: models,
})
}
models := make([]usageAnalysisModelPayload, 0, len(snapshot.Models))
for _, model := range snapshot.Models {
models = append(models, usageAnalysisModelPayload{
Model: model.Model,
TotalRequests: model.TotalRequests,
SuccessCount: model.SuccessCount,
FailureCount: model.FailureCount,
InputTokens: model.InputTokens,
OutputTokens: model.OutputTokens,
ReasoningTokens: model.ReasoningTokens,
CachedTokens: model.CachedTokens,
TotalTokens: model.TotalTokens,
TotalLatencyMS: model.TotalLatencyMS,
LatencySampleCount: model.LatencySampleCount,
})
}
return usageAnalysisResponse{APIs: apis, Models: models}
}
|