Skip to content

Commit 7cc1700

Browse files
committed
dashboard/app: add targeting controls to the coverage page
It allows to control known parameters: 1. Period (months or days). 2. Target subsystem. 3. Target manager. And adds the disabled "Only unique" checkbox.
1 parent 9220929 commit 7cc1700

File tree

4 files changed

+95
-16
lines changed

4 files changed

+95
-16
lines changed

dashboard/app/graphs.go

+23-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"net/http"
1111
"net/url"
1212
"regexp"
13+
"slices"
1314
"sort"
1415
"strconv"
1516
"time"
@@ -194,8 +195,8 @@ func handleFoundBugsGraph(c context.Context, w http.ResponseWriter, r *http.Requ
194195
return serveTemplate(w, "graph_histogram.html", data)
195196
}
196197

197-
type funcStyleBodyJS func(ctx context.Context, projectID, ns, subsystem, manager string,
198-
periods []coveragedb.TimePeriod) (template.CSS, template.HTML, template.HTML, error)
198+
type funcStyleBodyJS func(ctx context.Context, projectID string, scope *cover.SelectScope, sss, managers []string,
199+
) (template.CSS, template.HTML, template.HTML, error)
199200

200201
func handleCoverageHeatmap(c context.Context, w http.ResponseWriter, r *http.Request) error {
201202
return handleHeatmap(c, w, r, cover.DoHeatMapStyleBodyJS)
@@ -235,9 +236,28 @@ func handleHeatmap(c context.Context, w http.ResponseWriter, r *http.Request, f
235236
if err != nil {
236237
return fmt.Errorf("%s: %w", err.Error(), ErrClientBadRequest)
237238
}
239+
managers, err := CachedManagerList(c, hdr.Namespace)
240+
if err != nil {
241+
return err
242+
}
243+
ssService := getNsConfig(c, hdr.Namespace).Subsystems.Service
244+
var subsystems []string
245+
for _, ss := range ssService.List() {
246+
subsystems = append(subsystems, ss.Name)
247+
}
248+
slices.Sort(managers)
249+
slices.Sort(subsystems)
250+
238251
var style template.CSS
239252
var body, js template.HTML
240-
if style, body, js, err = f(c, "syzkaller", hdr.Namespace, ss, manager, periods); err != nil {
253+
if style, body, js, err = f(c, "syzkaller",
254+
&cover.SelectScope{
255+
Ns: hdr.Namespace,
256+
Subsystem: ss,
257+
Manager: manager,
258+
Periods: periods,
259+
},
260+
subsystems, managers); err != nil {
241261
return fmt.Errorf("failed to generate heatmap: %w", err)
242262
}
243263
return serveTemplate(w, "custom_content.html", struct {

dashboard/app/static/coverage.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// Copyright 2024 syzkaller project authors. All rights reserved.
22
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
33

4-
initTogglers();
4+
$(document).ready(initTogglers());
5+
$(document).ready(initUpdateForm);
56

67
// Initializes the file tree onClick collapse logic.
78
function initTogglers(){
@@ -11,6 +12,14 @@ function initTogglers(){
1112
});
1213
}
1314

15+
function initUpdateForm(){
16+
var curUrlParams = new URLSearchParams(window.location.search);
17+
$('#target-period').val(curUrlParams.get('period'));
18+
$('#target-subsystem').val(curUrlParams.get('subsystem'));
19+
$('#target-manager').val(curUrlParams.get('manager'));
20+
$("#only-unique").prop("checked", curUrlParams.get('subsystem') == "1");
21+
}
22+
1423
// This handler is called when user clicks on the coverage percentage.
1524
// It downloads the kernel file coverage html block and adjust page to show it.
1625
// "#file-content-prev" and "#file-content-curr" are the file content <div>s.

pkg/cover/heatmap.go

+24-12
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ type templateHeatmapRow struct {
3737
}
3838

3939
type templateHeatmap struct {
40-
Root *templateHeatmapRow
41-
Periods []string
40+
Root *templateHeatmapRow
41+
Periods []string
42+
Subsystems []string
43+
Managers []string
4244
}
4345

4446
func (thm *templateHeatmapRow) addParts(depth int, pathLeft []string, filePath string, instrumented, covered int64,
@@ -188,17 +190,17 @@ where
188190
return stmt
189191
}
190192

191-
func filesCoverageWithDetails(ctx context.Context, projectID, ns, subsystem, manager string,
192-
timePeriods []coveragedb.TimePeriod) ([]*fileCoverageWithDetails, error) {
193+
func filesCoverageWithDetails(ctx context.Context, projectID string, scope *SelectScope,
194+
) ([]*fileCoverageWithDetails, error) {
193195
client, err := spannerclient.NewClient(ctx, projectID)
194196
if err != nil {
195197
return nil, fmt.Errorf("spanner.NewClient() failed: %s", err.Error())
196198
}
197199
defer client.Close()
198200

199201
res := []*fileCoverageWithDetails{}
200-
for _, timePeriod := range timePeriods {
201-
stmt := filesCoverageWithDetailsStmt(ns, subsystem, manager, timePeriod)
202+
for _, timePeriod := range scope.Periods {
203+
stmt := filesCoverageWithDetailsStmt(scope.Ns, scope.Subsystem, scope.Manager, timePeriod)
202204
iter := client.Single().Query(ctx, stmt)
203205
defer iter.Stop()
204206
for {
@@ -243,19 +245,28 @@ func stylesBodyJSTemplate(templData *templateHeatmap,
243245
template.HTML(js.Bytes()), nil
244246
}
245247

246-
func DoHeatMapStyleBodyJS(ctx context.Context, projectID, ns, subsystem, manager string,
247-
periods []coveragedb.TimePeriod) (template.CSS, template.HTML, template.HTML, error) {
248-
covAndDates, err := filesCoverageWithDetails(ctx, projectID, ns, subsystem, manager, periods)
248+
type SelectScope struct {
249+
Ns string
250+
Subsystem string
251+
Manager string
252+
Periods []coveragedb.TimePeriod
253+
}
254+
255+
func DoHeatMapStyleBodyJS(ctx context.Context, projectID string, scope *SelectScope, sss, managers []string,
256+
) (template.CSS, template.HTML, template.HTML, error) {
257+
covAndDates, err := filesCoverageWithDetails(ctx, projectID, scope)
249258
if err != nil {
250259
return "", "", "", fmt.Errorf("failed to filesCoverageWithDetails: %w", err)
251260
}
252261
templData := filesCoverageToTemplateData(covAndDates)
262+
templData.Subsystems = sss
263+
templData.Managers = managers
253264
return stylesBodyJSTemplate(templData)
254265
}
255266

256-
func DoSubsystemsHeatMapStyleBodyJS(ctx context.Context, projectID, ns, subsystem, manager string,
257-
periods []coveragedb.TimePeriod) (template.CSS, template.HTML, template.HTML, error) {
258-
covWithDetails, err := filesCoverageWithDetails(ctx, projectID, ns, subsystem, manager, periods)
267+
func DoSubsystemsHeatMapStyleBodyJS(ctx context.Context, projectID string, scope *SelectScope, sss, managers []string,
268+
) (template.CSS, template.HTML, template.HTML, error) {
269+
covWithDetails, err := filesCoverageWithDetails(ctx, projectID, scope)
259270
if err != nil {
260271
panic(err)
261272
}
@@ -274,6 +285,7 @@ func DoSubsystemsHeatMapStyleBodyJS(ctx context.Context, projectID, ns, subsyste
274285
}
275286
}
276287
templData := filesCoverageToTemplateData(ssCovAndDates)
288+
templData.Managers = managers
277289
return stylesBodyJSTemplate(templData)
278290
}
279291

pkg/cover/templates/heatmap.html

+38
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,44 @@
104104
{{ end }}
105105

106106
{{ define "body" }}
107+
<div style="display:inline-block">
108+
<form method="get">
109+
<div style="display:inline-block; vertical-align: top">
110+
<label for="target-period">Periods:</label>
111+
<br>
112+
<label for="target-subsystem">Subsystem:</label>
113+
<br>
114+
<label for="target-manager">Manager:</label>
115+
<br>
116+
<label for="only-unique">Only unique:</label>
117+
</div>
118+
<div style="display:inline-block; vertical-align: top">
119+
<select id="target-period" name="period">
120+
<option value="month">Month</option>
121+
<option value="day">Day</option>
122+
</select>
123+
<br>
124+
<select id="target-subsystem" name="subsystem">
125+
<option value="">*</option>
126+
{{ range $ss := .Subsystems }}
127+
<option value="{{ $ss }}">{{ $ss }}</option>
128+
{{ end }}
129+
</select>
130+
<br>
131+
<select id="target-manager" name="manager">
132+
<option value="">*</option>
133+
{{ range $manager := .Managers }}
134+
<option value="{{ $manager }}">{{ $manager }}</option>
135+
{{ end }}
136+
</select>
137+
<br>
138+
<input type="checkbox" id="only-unique" name="unique-only" disabled>
139+
</div>
140+
<br>
141+
<button id="updateButton">Update</button>
142+
</form>
143+
</div>
144+
<hr>
107145
<div style="white-space: nowrap">
108146
<div style="display:inline-block">
109147
<ul id="collapsible-list">

0 commit comments

Comments
 (0)