diff --git a/dashboard/app/graphs.go b/dashboard/app/graphs.go index 54520820f942..9918f9200dac 100644 --- a/dashboard/app/graphs.go +++ b/dashboard/app/graphs.go @@ -10,6 +10,7 @@ import ( "net/http" "net/url" "regexp" + "slices" "sort" "strconv" "time" @@ -194,8 +195,8 @@ func handleFoundBugsGraph(c context.Context, w http.ResponseWriter, r *http.Requ return serveTemplate(w, "graph_histogram.html", data) } -type funcStyleBodyJS func(ctx context.Context, projectID, ns, subsystem, manager string, - periods []coveragedb.TimePeriod) (template.CSS, template.HTML, template.HTML, error) +type funcStyleBodyJS func(ctx context.Context, projectID string, scope *cover.SelectScope, sss, managers []string, +) (template.CSS, template.HTML, template.HTML, error) func handleCoverageHeatmap(c context.Context, w http.ResponseWriter, r *http.Request) error { return handleHeatmap(c, w, r, cover.DoHeatMapStyleBodyJS) @@ -235,9 +236,28 @@ func handleHeatmap(c context.Context, w http.ResponseWriter, r *http.Request, f if err != nil { return fmt.Errorf("%s: %w", err.Error(), ErrClientBadRequest) } + managers, err := CachedManagerList(c, hdr.Namespace) + if err != nil { + return err + } + ssService := getNsConfig(c, hdr.Namespace).Subsystems.Service + var subsystems []string + for _, ss := range ssService.List() { + subsystems = append(subsystems, ss.Name) + } + slices.Sort(managers) + slices.Sort(subsystems) + var style template.CSS var body, js template.HTML - if style, body, js, err = f(c, "syzkaller", hdr.Namespace, ss, manager, periods); err != nil { + if style, body, js, err = f(c, "syzkaller", + &cover.SelectScope{ + Ns: hdr.Namespace, + Subsystem: ss, + Manager: manager, + Periods: periods, + }, + subsystems, managers); err != nil { return fmt.Errorf("failed to generate heatmap: %w", err) } return serveTemplate(w, "custom_content.html", struct { diff --git a/dashboard/app/static/coverage.js b/dashboard/app/static/coverage.js index 16eb4fcd7e1f..5a17ad0a9e5b 100644 --- a/dashboard/app/static/coverage.js +++ b/dashboard/app/static/coverage.js @@ -1,7 +1,8 @@ // Copyright 2024 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. -initTogglers(); +$(document).ready(initTogglers()); +$(document).ready(initUpdateForm); // Initializes the file tree onClick collapse logic. function initTogglers(){ @@ -11,6 +12,14 @@ function initTogglers(){ }); } +function initUpdateForm(){ + var curUrlParams = new URLSearchParams(window.location.search); + $('#target-period').val(curUrlParams.get('period')); + $('#target-subsystem').val(curUrlParams.get('subsystem')); + $('#target-manager').val(curUrlParams.get('manager')); + $("#only-unique").prop("checked", curUrlParams.get('subsystem') == "1"); +} + // This handler is called when user clicks on the coverage percentage. // It downloads the kernel file coverage html block and adjust page to show it. // "#file-content-prev" and "#file-content-curr" are the file content
s. diff --git a/pkg/cover/heatmap.go b/pkg/cover/heatmap.go index 903294095568..b8e3bbfa6690 100644 --- a/pkg/cover/heatmap.go +++ b/pkg/cover/heatmap.go @@ -37,8 +37,10 @@ type templateHeatmapRow struct { } type templateHeatmap struct { - Root *templateHeatmapRow - Periods []string + Root *templateHeatmapRow + Periods []string + Subsystems []string + Managers []string } func (thm *templateHeatmapRow) addParts(depth int, pathLeft []string, filePath string, instrumented, covered int64, @@ -188,8 +190,8 @@ where return stmt } -func filesCoverageWithDetails(ctx context.Context, projectID, ns, subsystem, manager string, - timePeriods []coveragedb.TimePeriod) ([]*fileCoverageWithDetails, error) { +func filesCoverageWithDetails(ctx context.Context, projectID string, scope *SelectScope, +) ([]*fileCoverageWithDetails, error) { client, err := spannerclient.NewClient(ctx, projectID) if err != nil { return nil, fmt.Errorf("spanner.NewClient() failed: %s", err.Error()) @@ -197,8 +199,8 @@ func filesCoverageWithDetails(ctx context.Context, projectID, ns, subsystem, man defer client.Close() res := []*fileCoverageWithDetails{} - for _, timePeriod := range timePeriods { - stmt := filesCoverageWithDetailsStmt(ns, subsystem, manager, timePeriod) + for _, timePeriod := range scope.Periods { + stmt := filesCoverageWithDetailsStmt(scope.Ns, scope.Subsystem, scope.Manager, timePeriod) iter := client.Single().Query(ctx, stmt) defer iter.Stop() for { @@ -243,19 +245,28 @@ func stylesBodyJSTemplate(templData *templateHeatmap, template.HTML(js.Bytes()), nil } -func DoHeatMapStyleBodyJS(ctx context.Context, projectID, ns, subsystem, manager string, - periods []coveragedb.TimePeriod) (template.CSS, template.HTML, template.HTML, error) { - covAndDates, err := filesCoverageWithDetails(ctx, projectID, ns, subsystem, manager, periods) +type SelectScope struct { + Ns string + Subsystem string + Manager string + Periods []coveragedb.TimePeriod +} + +func DoHeatMapStyleBodyJS(ctx context.Context, projectID string, scope *SelectScope, sss, managers []string, +) (template.CSS, template.HTML, template.HTML, error) { + covAndDates, err := filesCoverageWithDetails(ctx, projectID, scope) if err != nil { return "", "", "", fmt.Errorf("failed to filesCoverageWithDetails: %w", err) } templData := filesCoverageToTemplateData(covAndDates) + templData.Subsystems = sss + templData.Managers = managers return stylesBodyJSTemplate(templData) } -func DoSubsystemsHeatMapStyleBodyJS(ctx context.Context, projectID, ns, subsystem, manager string, - periods []coveragedb.TimePeriod) (template.CSS, template.HTML, template.HTML, error) { - covWithDetails, err := filesCoverageWithDetails(ctx, projectID, ns, subsystem, manager, periods) +func DoSubsystemsHeatMapStyleBodyJS(ctx context.Context, projectID string, scope *SelectScope, sss, managers []string, +) (template.CSS, template.HTML, template.HTML, error) { + covWithDetails, err := filesCoverageWithDetails(ctx, projectID, scope) if err != nil { panic(err) } @@ -274,6 +285,7 @@ func DoSubsystemsHeatMapStyleBodyJS(ctx context.Context, projectID, ns, subsyste } } templData := filesCoverageToTemplateData(ssCovAndDates) + templData.Managers = managers return stylesBodyJSTemplate(templData) } diff --git a/pkg/cover/templates/heatmap.html b/pkg/cover/templates/heatmap.html index fc1b457c9998..5dd951afe7b0 100644 --- a/pkg/cover/templates/heatmap.html +++ b/pkg/cover/templates/heatmap.html @@ -104,6 +104,44 @@ {{ end }} {{ define "body" }} +
+
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+
+