Skip to content

Commit

Permalink
dashboard/app: save suppressed reports
Browse files Browse the repository at this point in the history
Save suppressed reports into a special single bucked "suppressed report".
This will allow some control and monitoring over frequency and will allow to see samples.

Fixes #1941
  • Loading branch information
dvyukov committed Feb 21, 2021
1 parent 3e5ed8b commit e894953
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 17 deletions.
23 changes: 16 additions & 7 deletions dashboard/app/api.go
Expand Up @@ -664,7 +664,10 @@ func apiReportBuildError(c context.Context, ns string, r *http.Request, payload
return nil, nil
}

const corruptedReportTitle = "corrupted report"
const (
corruptedReportTitle = "corrupted report"
suppressedReportTitle = "suppressed report"
)

func apiReportCrash(c context.Context, ns string, r *http.Request, payload []byte) (interface{}, error) {
req := new(dashapi.Crash)
Expand All @@ -689,9 +692,9 @@ func apiReportCrash(c context.Context, ns string, r *http.Request, payload []byt
}

func reportCrash(c context.Context, build *Build, req *dashapi.Crash) (*Bug, error) {
req.Title = canonicalizeCrashTitle(req.Title, req.Corrupted)
if req.Corrupted {
req.AltTitles = []string{corruptedReportTitle}
req.Title = canonicalizeCrashTitle(req.Title, req.Corrupted, req.Suppressed)
if req.Corrupted || req.Suppressed {
req.AltTitles = []string{req.Title}
} else {
for i, t := range req.AltTitles {
req.AltTitles[i] = limitLength(t, maxTextLen)
Expand Down Expand Up @@ -903,7 +906,7 @@ func apiReportFailedRepro(c context.Context, ns string, r *http.Request, payload
if err := json.Unmarshal(payload, req); err != nil {
return nil, fmt.Errorf("failed to unmarshal request: %v", err)
}
req.Title = canonicalizeCrashTitle(req.Title, req.Corrupted)
req.Title = canonicalizeCrashTitle(req.Title, req.Corrupted, req.Suppressed)

bug, err := findExistingBugForCrash(c, ns, []string{req.Title})
if err != nil {
Expand Down Expand Up @@ -944,7 +947,7 @@ func apiNeedRepro(c context.Context, ns string, r *http.Request, payload []byte)
}
return resp, nil
}
req.Title = canonicalizeCrashTitle(req.Title, req.Corrupted)
req.Title = canonicalizeCrashTitle(req.Title, req.Corrupted, req.Suppressed)

bug, err := findExistingBugForCrash(c, ns, []string{req.Title})
if err != nil {
Expand All @@ -966,13 +969,18 @@ func apiNeedRepro(c context.Context, ns string, r *http.Request, payload []byte)
return resp, nil
}

func canonicalizeCrashTitle(title string, corrupted bool) string {
func canonicalizeCrashTitle(title string, corrupted, suppressed bool) string {
if corrupted {
// The report is corrupted and the title is most likely invalid.
// Such reports are usually unactionable and are discarded.
// Collect them into a single bin.
return corruptedReportTitle
}
if suppressed {
// Collect all of them into a single bucket so that it's possible to control and assess them,
// e.g. if there are some spikes in suppressed reports.
return suppressedReportTitle
}
return limitLength(title, maxTextLen)
}

Expand Down Expand Up @@ -1251,6 +1259,7 @@ func needReproForBug(c context.Context, bug *Bug) bool {
return bug.ReproLevel < ReproLevelC &&
len(bug.Commits) == 0 &&
bug.Title != corruptedReportTitle &&
bug.Title != suppressedReportTitle &&
config.Namespaces[bug.Namespace].NeedRepro(bug) &&
(bug.NumRepro < maxReproPerBug ||
bug.ReproLevel == ReproLevelNone &&
Expand Down
2 changes: 2 additions & 0 deletions dashboard/dashapi/dashapi.go
Expand Up @@ -238,6 +238,7 @@ type Crash struct {
Title string
AltTitles []string // alternative titles, used for better deduplication
Corrupted bool // report is corrupted (corrupted title, no stacks, etc)
Suppressed bool
Maintainers []string // deprecated in favor of Recipients
Recipients Recipients
Log []byte
Expand All @@ -264,6 +265,7 @@ type CrashID struct {
BuildID string
Title string
Corrupted bool
Suppressed bool
MayBeMissing bool
}

Expand Down
31 changes: 21 additions & 10 deletions syz-manager/manager.go
Expand Up @@ -669,16 +669,21 @@ func (mgr *Manager) saveCrash(crash *Crash) bool {
mgr.dataRaceFrames[crash.Frame] = true
mgr.mu.Unlock()
}
flags := ""
if crash.Corrupted {
flags += " [corrupted]"
}
if crash.Suppressed {
log.Logf(0, "vm-%v: suppressed crash %v", crash.vmIndex, crash.Title)
mgr.stats.crashSuppressed.inc()
return false
flags += " [suppressed]"
}
corrupted := ""
if crash.Corrupted {
corrupted = " [corrupted]"
log.Logf(0, "vm-%v: crash: %v%v", crash.vmIndex, crash.Title, flags)

if crash.Suppressed {
// Collect all of them into a single bucket so that it's possible to control and assess them,
// e.g. if there are some spikes in suppressed reports.
crash.Title = "suppressed report"
mgr.stats.crashSuppressed.inc()
}
log.Logf(0, "vm-%v: crash: %v%v", crash.vmIndex, crash.Title, corrupted)
if err := mgr.reporter.Symbolize(crash.Report); err != nil {
log.Logf(0, "failed to symbolize report: %v", err)
}
Expand All @@ -700,6 +705,7 @@ func (mgr *Manager) saveCrash(crash *Crash) bool {
Title: crash.Title,
AltTitles: crash.AltTitles,
Corrupted: crash.Corrupted,
Suppressed: crash.Suppressed,
Recipients: crash.Recipients.ToDash(),
Log: crash.Output,
Report: crash.Report.Report,
Expand Down Expand Up @@ -758,7 +764,7 @@ func (mgr *Manager) saveCrash(crash *Crash) bool {
const maxReproAttempts = 3

func (mgr *Manager) needLocalRepro(crash *Crash) bool {
if !mgr.cfg.Reproduce || crash.Corrupted {
if !mgr.cfg.Reproduce || crash.Corrupted || crash.Suppressed {
return false
}
sig := hash.Hash([]byte(crash.Title))
Expand Down Expand Up @@ -790,6 +796,7 @@ func (mgr *Manager) needRepro(crash *Crash) bool {
BuildID: mgr.cfg.Tag,
Title: crash.Title,
Corrupted: crash.Corrupted,
Suppressed: crash.Suppressed,
MayBeMissing: crash.Type == report.MemoryLeak, // we did not send the original crash w/o repro
}
needRepro, err := mgr.dash.NeedRepro(cid)
Expand All @@ -807,8 +814,11 @@ func (mgr *Manager) saveFailedRepro(rep *report.Report, stats *repro.Stats) {
return
}
cid := &dashapi.CrashID{
BuildID: mgr.cfg.Tag,
Title: rep.Title,
BuildID: mgr.cfg.Tag,
Title: rep.Title,
Corrupted: rep.Corrupted,
Suppressed: rep.Suppressed,
MayBeMissing: rep.Type == report.MemoryLeak,
}
if err := mgr.dash.ReportFailedRepro(cid); err != nil {
log.Logf(0, "failed to report failed repro to dashboard: %v", err)
Expand Down Expand Up @@ -868,6 +878,7 @@ func (mgr *Manager) saveRepro(res *repro.Result, stats *repro.Stats, hub bool) {
BuildID: mgr.cfg.Tag,
Title: res.Report.Title,
AltTitles: res.Report.AltTitles,
Suppressed: res.Report.Suppressed,
Recipients: res.Report.Recipients.ToDash(),
Log: res.Report.Output,
Report: res.Report.Report,
Expand Down

0 comments on commit e894953

Please sign in to comment.