summaryrefslogtreecommitdiff
path: root/internal/api
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-03-19 23:15:58 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-03-19 23:15:58 +0000
commiteeee3b60a1fd8dc8b8b92997f709ef65e4b2097f (patch)
treed1c440a84617d31cf5d91b422b1f5d687c277af1 /internal/api
parent7e8967decbc8221694953abf1435fda8aaf18824 (diff)
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 <noreply@anthropic.com>
Diffstat (limited to 'internal/api')
-rw-r--r--internal/api/executions.go17
-rw-r--r--internal/api/server.go1
2 files changed, 18 insertions, 0 deletions
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=<RFC3339>
func (s *Server) handleGetAgentStatus(w http.ResponseWriter, r *http.Request) {
diff --git a/internal/api/server.go b/internal/api/server.go
index 2d5c308..0127ab9 100644
--- a/internal/api/server.go
+++ b/internal/api/server.go
@@ -121,6 +121,7 @@ func (s *Server) routes() {
s.mux.HandleFunc("GET /api/tasks/{id}/subtasks", s.handleListSubtasks)
s.mux.HandleFunc("GET /api/tasks/{id}/executions", s.handleListExecutions)
s.mux.HandleFunc("GET /api/executions", s.handleListRecentExecutions)
+ s.mux.HandleFunc("GET /api/stats", s.handleGetDashboardStats)
s.mux.HandleFunc("GET /api/agents/status", s.handleGetAgentStatus)
s.mux.HandleFunc("GET /api/executions/{id}", s.handleGetExecution)
s.mux.HandleFunc("GET /api/executions/{id}/log", s.handleGetExecutionLog)