diff --git a/syz-cluster/dashboard/handler.go b/syz-cluster/dashboard/handler.go index 794feba83339..2212bd959f38 100644 --- a/syz-cluster/dashboard/handler.go +++ b/syz-cluster/dashboard/handler.go @@ -27,6 +27,7 @@ type dashboardHandler struct { sessionRepo *db.SessionRepository sessionTestRepo *db.SessionTestRepository findingRepo *db.FindingRepository + statsRepo *db.StatsRepository blobStorage blob.Storage templates map[string]*template.Template } @@ -37,7 +38,7 @@ var templates embed.FS func newHandler(env *app.AppEnvironment) (*dashboardHandler, error) { perFile := map[string]*template.Template{} var err error - for _, name := range []string{"index.html", "series.html"} { + for _, name := range []string{"index.html", "series.html", "graphs.html"} { perFile[name], err = template.ParseFS(templates, "templates/base.html", "templates/templates.html", "templates/"+name) if err != nil { @@ -53,6 +54,7 @@ func newHandler(env *app.AppEnvironment) (*dashboardHandler, error) { sessionRepo: db.NewSessionRepository(env.Spanner), sessionTestRepo: db.NewSessionTestRepository(env.Spanner), findingRepo: db.NewFindingRepository(env.Spanner), + statsRepo: db.NewStatsRepository(env.Spanner), }, nil } @@ -69,6 +71,7 @@ func (h *dashboardHandler) Mux() *http.ServeMux { mux.HandleFunc("/patches/{id}", errToStatus(h.patchContent)) mux.HandleFunc("/findings/{id}/{key}", errToStatus(h.findingInfo)) mux.HandleFunc("/builds/{id}/{key}", errToStatus(h.buildInfo)) + mux.HandleFunc("/stats", errToStatus(h.statsPage)) mux.HandleFunc("/", errToStatus(h.seriesList)) staticFiles, err := fs.Sub(staticFs, "static") if err != nil { @@ -211,6 +214,34 @@ func (h *dashboardHandler) seriesInfo(w http.ResponseWriter, r *http.Request) er return h.renderTemplate(w, "series.html", data) } +func (h *dashboardHandler) statsPage(w http.ResponseWriter, r *http.Request) error { + type StatsPageData struct { + Processed []*db.CountPerWeek + Findings []*db.CountPerWeek + Delay []*db.DelayPerWeek + Distribution []*db.StatusPerWeek + } + var data StatsPageData + var err error + data.Processed, err = h.statsRepo.ProcessedSeriesPerWeek(r.Context()) + if err != nil { + return fmt.Errorf("failed to query processed series data: %w", err) + } + data.Findings, err = h.statsRepo.FindingsPerWeek(r.Context()) + if err != nil { + return fmt.Errorf("failed to query findings data: %w", err) + } + data.Delay, err = h.statsRepo.DelayPerWeek(r.Context()) + if err != nil { + return fmt.Errorf("failed to query delay data: %w", err) + } + data.Distribution, err = h.statsRepo.SessionStatusPerWeek(r.Context()) + if err != nil { + return fmt.Errorf("failed to query distribution data: %w", err) + } + return h.renderTemplate(w, "graphs.html", data) +} + func groupFindings(findings []*db.Finding) map[string][]*db.Finding { ret := map[string][]*db.Finding{} for _, finding := range findings { @@ -221,12 +252,14 @@ func groupFindings(findings []*db.Finding) map[string][]*db.Finding { func (h *dashboardHandler) renderTemplate(w http.ResponseWriter, name string, data any) error { type page struct { - Title string - Data any + Title string + Template string + Data any } return h.templates[name].ExecuteTemplate(w, "base.html", page{ - Title: h.title, - Data: data, + Title: h.title, + Template: name, + Data: data, }) } diff --git a/syz-cluster/dashboard/templates/base.html b/syz-cluster/dashboard/templates/base.html index c154de1db12a..519e4f74a3b5 100644 --- a/syz-cluster/dashboard/templates/base.html +++ b/syz-cluster/dashboard/templates/base.html @@ -9,13 +9,16 @@ {{.Title}} -