From 83b914a1837f0f4de012f4dc6bdc84c9d5bab713 Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Wed, 13 Aug 2025 17:32:02 +0200 Subject: syz-cluster: display statistics Add a web dashboard page with the main statistics concerning patch series fuzzing. Improve the navigation bar on top of the page. --- syz-cluster/dashboard/handler.go | 43 +++++++++-- syz-cluster/dashboard/templates/base.html | 9 ++- syz-cluster/dashboard/templates/graphs.html | 114 ++++++++++++++++++++++++++++ syz-cluster/pkg/db/stats_repo.go | 92 ++++++++++++++++++++++ syz-cluster/pkg/db/stats_repo_test.go | 33 ++++++++ 5 files changed, 283 insertions(+), 8 deletions(-) create mode 100644 syz-cluster/dashboard/templates/graphs.html create mode 100644 syz-cluster/pkg/db/stats_repo.go create mode 100644 syz-cluster/pkg/db/stats_repo_test.go diff --git a/syz-cluster/dashboard/handler.go b/syz-cluster/dashboard/handler.go index 794feba83..2212bd959 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 c154de1db..519e4f74a 100644 --- a/syz-cluster/dashboard/templates/base.html +++ b/syz-cluster/dashboard/templates/base.html @@ -9,13 +9,16 @@ {{.Title}} -