forked from wrenn/wrenn
v0.0.1 (#8)
Co-authored-by: Tasnim Kabir Sadik <tksadik92@gmail.com> Reviewed-on: wrenn/sandbox#8
This commit is contained in:
95
internal/api/handlers_stats.go
Normal file
95
internal/api/handlers_stats.go
Normal file
@ -0,0 +1,95 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.omukk.dev/wrenn/sandbox/internal/auth"
|
||||
"git.omukk.dev/wrenn/sandbox/internal/service"
|
||||
)
|
||||
|
||||
type statsHandler struct {
|
||||
svc *service.StatsService
|
||||
}
|
||||
|
||||
func newStatsHandler(svc *service.StatsService) *statsHandler {
|
||||
return &statsHandler{svc: svc}
|
||||
}
|
||||
|
||||
type statsCurrentResponse struct {
|
||||
RunningCount int32 `json:"running_count"`
|
||||
VCPUsReserved int32 `json:"vcpus_reserved"`
|
||||
MemoryMBReserved int32 `json:"memory_mb_reserved"`
|
||||
}
|
||||
|
||||
type statsPeaksResponse struct {
|
||||
RunningCount int32 `json:"running_count"`
|
||||
VCPUs int32 `json:"vcpus"`
|
||||
MemoryMB int32 `json:"memory_mb"`
|
||||
}
|
||||
|
||||
type statsSeriesResponse struct {
|
||||
Labels []string `json:"labels"`
|
||||
Running []int32 `json:"running"`
|
||||
VCPUs []int32 `json:"vcpus"`
|
||||
MemoryMB []int32 `json:"memory_mb"`
|
||||
}
|
||||
|
||||
type statsResponse struct {
|
||||
Range string `json:"range"`
|
||||
Current statsCurrentResponse `json:"current"`
|
||||
Peaks statsPeaksResponse `json:"peaks"`
|
||||
Series statsSeriesResponse `json:"series"`
|
||||
}
|
||||
|
||||
// GetStats handles GET /v1/sandboxes/stats?range=5m|1h|6h|24h|30d
|
||||
func (h *statsHandler) GetStats(w http.ResponseWriter, r *http.Request) {
|
||||
ac := auth.MustFromContext(r.Context())
|
||||
|
||||
rangeParam := r.URL.Query().Get("range")
|
||||
if rangeParam == "" {
|
||||
rangeParam = string(service.Range1h)
|
||||
}
|
||||
tr := service.TimeRange(rangeParam)
|
||||
if !service.ValidRange(tr) {
|
||||
writeError(w, http.StatusBadRequest, "invalid_request", "range must be one of: 5m, 1h, 6h, 24h, 30d")
|
||||
return
|
||||
}
|
||||
|
||||
current, peaks, series, err := h.svc.GetStats(r.Context(), ac.TeamID, tr)
|
||||
if err != nil {
|
||||
slog.Error("stats handler: get stats failed", "team_id", ac.TeamID, "error", err)
|
||||
writeError(w, http.StatusInternalServerError, "internal_error", "failed to retrieve stats")
|
||||
return
|
||||
}
|
||||
|
||||
resp := statsResponse{
|
||||
Range: rangeParam,
|
||||
Current: statsCurrentResponse{
|
||||
RunningCount: current.RunningCount,
|
||||
VCPUsReserved: current.VCPUsReserved,
|
||||
MemoryMBReserved: current.MemoryMBReserved,
|
||||
},
|
||||
Peaks: statsPeaksResponse{
|
||||
RunningCount: peaks.RunningCount,
|
||||
VCPUs: peaks.VCPUs,
|
||||
MemoryMB: peaks.MemoryMB,
|
||||
},
|
||||
Series: statsSeriesResponse{
|
||||
Labels: make([]string, len(series)),
|
||||
Running: make([]int32, len(series)),
|
||||
VCPUs: make([]int32, len(series)),
|
||||
MemoryMB: make([]int32, len(series)),
|
||||
},
|
||||
}
|
||||
|
||||
for i, pt := range series {
|
||||
resp.Series.Labels[i] = pt.Bucket.UTC().Format(time.RFC3339)
|
||||
resp.Series.Running[i] = pt.RunningCount
|
||||
resp.Series.VCPUs[i] = pt.VCPUsReserved
|
||||
resp.Series.MemoryMB[i] = pt.MemoryMBReserved
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, resp)
|
||||
}
|
||||
Reference in New Issue
Block a user