feat(api): add API key stats flush and summary endpoints

Introduce internal endpoint for flushing accumulated APIKey statistics
from data plane to control plane database, updating both individual
API keys and their parent provider groups with request counts and
success/failure rates.

Add admin endpoint to retrieve aggregated API key statistics summary
across all provider groups, including total requests, success/failure
counts, and calculated rates.
This commit is contained in:
zenfun
2025-12-30 00:11:52 +08:00
parent 5156ca9cec
commit 1a2cc5b798
6 changed files with 390 additions and 29 deletions

View File

@@ -0,0 +1,67 @@
package api
import (
"net/http"
"github.com/ez-api/ez-api/internal/model"
"github.com/gin-gonic/gin"
)
type APIKeyStatsSummaryResponse struct {
TotalRequests int64 `json:"total_requests"`
SuccessRequests int64 `json:"success_requests"`
FailureRequests int64 `json:"failure_requests"`
SuccessRate float64 `json:"success_rate"`
FailureRate float64 `json:"failure_rate"`
}
// GetAPIKeyStatsSummary godoc
// @Summary APIKey stats summary (admin)
// @Description Aggregate APIKey success/failure stats across all provider groups
// @Tags admin
// @Produce json
// @Security AdminAuth
// @Success 200 {object} APIKeyStatsSummaryResponse
// @Failure 500 {object} gin.H
// @Router /admin/apikey-stats/summary [get]
func (h *AdminHandler) GetAPIKeyStatsSummary(c *gin.Context) {
if h == nil || h.db == nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "database not configured"})
return
}
var totals struct {
TotalRequests int64 `json:"total_requests"`
SuccessRequests int64 `json:"success_requests"`
FailureRequests int64 `json:"failure_requests"`
}
if err := h.db.Model(&model.APIKey{}).
Select("COALESCE(SUM(total_requests),0) as total_requests, COALESCE(SUM(success_requests),0) as success_requests").
Scan(&totals).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to aggregate api key stats", "details": err.Error()})
return
}
total := totals.TotalRequests
success := totals.SuccessRequests
failure := total - success
if failure < 0 {
failure = 0
}
var successRate float64
var failureRate float64
if total > 0 {
successRate = float64(success) / float64(total)
failureRate = float64(failure) / float64(total)
}
c.JSON(http.StatusOK, APIKeyStatsSummaryResponse{
TotalRequests: total,
SuccessRequests: success,
FailureRequests: failure,
SuccessRate: successRate,
FailureRate: failureRate,
})
}