From eeee3b60a1fd8dc8b8b92997f709ef65e4b2097f Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Thu, 19 Mar 2026 23:15:58 +0000 Subject: feat: add errors, throughput, and billing sections to stats dashboard - GET /api/stats?window=7d: pre-aggregated SQL queries for errors, throughput, billing - Errors section: category summary (quota/rate_limit/timeout/git/failed) + failure table - Throughput section: stacked hourly bar chart (completed/failed/other) over 7d - Billing section: KPIs (7d total, avg/day, cost/run) + daily cost bar chart Co-Authored-By: Claude Sonnet 4.6 --- internal/api/executions.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'internal/api/executions.go') diff --git a/internal/api/executions.go b/internal/api/executions.go index 29af139..4d8ba9c 100644 --- a/internal/api/executions.go +++ b/internal/api/executions.go @@ -86,6 +86,23 @@ func (s *Server) handleGetExecutionLog(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, content) } +// handleGetDashboardStats returns pre-aggregated error, throughput, and billing stats. +// GET /api/stats?window=7d|24h +func (s *Server) handleGetDashboardStats(w http.ResponseWriter, r *http.Request) { + window := 7 * 24 * time.Hour + if r.URL.Query().Get("window") == "24h" { + window = 24 * time.Hour + } + since := time.Now().Add(-window) + + stats, err := s.store.QueryDashboardStats(since) + if err != nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + return + } + writeJSON(w, http.StatusOK, stats) +} + // handleGetAgentStatus returns the current status of all agents and recent rate-limit events. // GET /api/agents/status?since= func (s *Server) handleGetAgentStatus(w http.ResponseWriter, r *http.Request) { -- cgit v1.2.3