diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2024-01-22 14:29:41 +0100 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2024-01-23 11:46:32 +0000 |
| commit | 312699d7f4fcaf0e1a7a007f15195e770a99b3c2 (patch) | |
| tree | 9040a57619174294e5bf5213d83c3d93627b529c | |
| parent | 1c0ecc51adc9f44c7bd3f45c2aa1b62718d1236e (diff) | |
dashboard: capture cover and PCs after corpus triage
This statistics allows us to better estimate the amount of coverage that
is lost after every syzbot instance is restarted.
| -rw-r--r-- | dashboard/app/api.go | 6 | ||||
| -rw-r--r-- | dashboard/app/entities.go | 3 | ||||
| -rw-r--r-- | dashboard/app/graph_fuzzing.html | 2 | ||||
| -rw-r--r-- | dashboard/app/graphs.go | 46 | ||||
| -rw-r--r-- | dashboard/dashapi/dashapi.go | 4 | ||||
| -rw-r--r-- | syz-manager/manager.go | 14 |
6 files changed, 52 insertions, 23 deletions
diff --git a/dashboard/app/api.go b/dashboard/app/api.go index 6a84c758b..381853716 100644 --- a/dashboard/app/api.go +++ b/dashboard/app/api.go @@ -1142,6 +1142,12 @@ func apiManagerStats(c context.Context, ns string, r *http.Request, payload []by stats.TotalCrashes += int64(req.Crashes) stats.SuppressedCrashes += int64(req.SuppressedCrashes) stats.TotalExecs += int64(req.Execs) + if cur := int64(req.TriagedCoverage); cur > stats.TriagedCoverage { + stats.TriagedCoverage = cur + } + if cur := int64(req.TriagedPCs); cur > stats.TriagedPCs { + stats.TriagedPCs = cur + } return nil }) return nil, err diff --git a/dashboard/app/entities.go b/dashboard/app/entities.go index 71f4a92fc..74221af57 100644 --- a/dashboard/app/entities.go +++ b/dashboard/app/entities.go @@ -50,6 +50,9 @@ type ManagerStats struct { CrashTypes int64 // unique crash types SuppressedCrashes int64 TotalExecs int64 + // These are only recorded once right after corpus is triaged. + TriagedCoverage int64 + TriagedPCs int64 } type Asset struct { diff --git a/dashboard/app/graph_fuzzing.html b/dashboard/app/graph_fuzzing.html index ab18a2742..5ed07ba63 100644 --- a/dashboard/app/graph_fuzzing.html +++ b/dashboard/app/graph_fuzzing.html @@ -24,7 +24,7 @@ Manager statistics graphs. {{- end}} data.addRows([ {{range $.Graph.Columns}} [ "{{.Hint}}", {{range .Vals}} - {{if .Val}}{{.Val}}{{end}}, '{{.Hint}}', + {{if .IsNull}}null{{else if .Val}}{{.Val}}{{end}}, '{{.Hint}}', {{- end}} ], {{- end}} diff --git a/dashboard/app/graphs.go b/dashboard/app/graphs.go index 125b909a6..7c023ca89 100644 --- a/dashboard/app/graphs.go +++ b/dashboard/app/graphs.go @@ -63,8 +63,9 @@ type uiGraphColumn struct { } type uiGraphValue struct { - Val float32 - Hint string + Val float32 + IsNull bool + Hint string } type uiCrashPageTable struct { @@ -328,7 +329,7 @@ func handleGraphFuzzing(c context.Context, w http.ResponseWriter, r *http.Reques metrics, err := createCheckBox(r, "Metrics", []string{ "MaxCorpus", "MaxCover", "MaxPCs", "TotalFuzzingTime", "TotalCrashes", "CrashTypes", "SuppressedCrashes", "TotalExecs", - "ExecsPerSec"}) + "ExecsPerSec", "TriagedPCs", "TriagedCoverage"}) if err != nil { return err } @@ -381,10 +382,11 @@ func createManagersGraph(c context.Context, ns string, selManagers, selMetrics [ continue } for metricIndex, metric := range selMetrics { - val := extractMetric(stat, metric) + val, canBeZero := extractMetric(stat, metric) graph.Columns[dayIndex].Vals[mgrIndex*len(selMetrics)+metricIndex] = uiGraphValue{ - Val: float32(val), - Hint: fmt.Sprintf("%.2f", val), + Val: float32(val), + IsNull: !canBeZero && val == 0, + Hint: fmt.Sprintf("%.2f", val), } } } @@ -398,7 +400,11 @@ func createManagersGraph(c context.Context, ns string, selManagers, selMetrics [ max := float32(1) for col := range graph.Columns { for mgrIndex := range selManagers { - val := graph.Columns[col].Vals[mgrIndex*len(selMetrics)+metricIndex].Val + item := graph.Columns[col].Vals[mgrIndex*len(selMetrics)+metricIndex] + if item.IsNull { + continue + } + val := item.Val if max < val { max = val } @@ -414,30 +420,34 @@ func createManagersGraph(c context.Context, ns string, selManagers, selMetrics [ return graph, nil } -func extractMetric(stat *ManagerStats, metric string) float64 { +func extractMetric(stat *ManagerStats, metric string) (val float64, canBeZero bool) { switch metric { case "MaxCorpus": - return float64(stat.MaxCorpus) + return float64(stat.MaxCorpus), false case "MaxCover": - return float64(stat.MaxCover) + return float64(stat.MaxCover), false case "MaxPCs": - return float64(stat.MaxPCs) + return float64(stat.MaxPCs), false case "TotalFuzzingTime": - return float64(stat.TotalFuzzingTime) + return float64(stat.TotalFuzzingTime), true case "TotalCrashes": - return float64(stat.TotalCrashes) + return float64(stat.TotalCrashes), true case "CrashTypes": - return float64(stat.CrashTypes) + return float64(stat.CrashTypes), true case "SuppressedCrashes": - return float64(stat.SuppressedCrashes) + return float64(stat.SuppressedCrashes), true case "TotalExecs": - return float64(stat.TotalExecs) + return float64(stat.TotalExecs), true case "ExecsPerSec": timeSec := float64(stat.TotalFuzzingTime) / 1e9 if timeSec == 0 { - return 0 + return 0, true } - return float64(stat.TotalExecs) / timeSec + return float64(stat.TotalExecs) / timeSec, true + case "TriagedCoverage": + return float64(stat.TriagedCoverage), false + case "TriagedPCs": + return float64(stat.TriagedPCs), false default: panic(fmt.Sprintf("unknown metric %q", metric)) } diff --git a/dashboard/dashapi/dashapi.go b/dashboard/dashapi/dashapi.go index aaaf3edfa..520a991fc 100644 --- a/dashboard/dashapi/dashapi.go +++ b/dashboard/dashapi/dashapi.go @@ -725,6 +725,10 @@ type ManagerStatsReq struct { Crashes uint64 SuppressedCrashes uint64 Execs uint64 + + // Non-zero only when set. + TriagedCoverage uint64 + TriagedPCs uint64 } func (dash *Dashboard) UploadManagerStats(req *ManagerStatsReq) error { diff --git a/syz-manager/manager.go b/syz-manager/manager.go index 3efee4f0e..0670a6bb3 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -90,10 +90,11 @@ type Manager struct { // Maps file name to modification time. usedFiles map[string]time.Time - modules []host.KernelModule - coverFilter map[uint32]uint32 - execCoverFilter map[uint32]uint32 - modulesInitialized bool + modules []host.KernelModule + coverFilter map[uint32]uint32 + execCoverFilter map[uint32]uint32 + modulesInitialized bool + afterTriageStatSent bool assetStorage *asset.Storage } @@ -1521,6 +1522,11 @@ func (mgr *Manager) dashboardReporter() { SuppressedCrashes: suppressedCrashes - lastSuppressedCrashes, Execs: execs - lastExecs, } + if mgr.phase >= phaseTriagedCorpus && !mgr.afterTriageStatSent { + mgr.afterTriageStatSent = true + req.TriagedCoverage = mgr.stats.corpusSignal.get() + req.TriagedPCs = mgr.stats.corpusCover.get() + } mgr.mu.Unlock() if err := mgr.dash.UploadManagerStats(req); err != nil { |
