From 6c48b5b4efc91533658dababa47587689b4a6ae1 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 19 Nov 2015 19:02:30 +0100 Subject: add various statistics to http interface --- manager/html.go | 37 +++++++++++++++++++++++++++++++++++++ manager/manager.go | 10 ++++++++++ 2 files changed, 47 insertions(+) (limited to 'manager') diff --git a/manager/html.go b/manager/html.go index 782fa1953..6123160d9 100644 --- a/manager/html.go +++ b/manager/html.go @@ -11,6 +11,7 @@ import ( "net/http" "sort" "strconv" + "time" "github.com/google/syzkaller/cover" "github.com/google/syzkaller/prog" @@ -47,14 +48,31 @@ func (mgr *Manager) httpInfo(w http.ResponseWriter, r *http.Request) { cc.cov = cover.Union(cc.cov, cover.Cover(inp.Cover)) } + uptime := time.Since(mgr.startTime) data := &UIData{ Name: mgr.cfg.Name, MasterHttp: mgr.masterHttp, MasterCorpusSize: len(mgr.masterCorpus), CorpusSize: len(mgr.corpus), TriageQueue: len(mgr.candidates), + Uptime: fmt.Sprintf("%v", uptime), } + secs := uint64(uptime) / 1e9 + for k, v := range mgr.stats { + val := "" + if x := v / secs; x >= 10 { + val = fmt.Sprintf("%v/sec", x) + } else if x := v * 60 / secs; x >= 10 { + val = fmt.Sprintf("%v/min", x) + } else { + x := v * 60 * 60 / secs + val = fmt.Sprintf("%v/hour", x) + } + data.Stats = append(data.Stats, UIStat{Name: k, Value: val}) + } + sort.Sort(UIStatArray(data.Stats)) + var cov cover.Cover for c, cc := range calls { cov = cover.Union(cov, cc.cov) @@ -171,9 +189,16 @@ type UIData struct { CorpusSize int TriageQueue int CoverSize int + Uptime string + Stats []UIStat Calls []UICallType } +type UIStat struct { + Name string + Value string +} + type UICallType struct { Name string Inputs int @@ -200,6 +225,12 @@ func (a UIInputArray) Len() int { return len(a) } func (a UIInputArray) Less(i, j int) bool { return a[i].Cover > a[j].Cover } func (a UIInputArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +type UIStatArray []UIStat + +func (a UIStatArray) Len() int { return len(a) } +func (a UIStatArray) Less(i, j int) bool { return a[i].Name < a[j].Name } +func (a UIStatArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + var htmlTemplate = template.Must(template.New("").Parse(` @@ -208,11 +239,17 @@ var htmlTemplate = template.Must(template.New("").Parse(` Manager: {{.Name}} [master]
+Uptime: {{.Uptime}}
Master corpus: {{.MasterCorpusSize}}
Corpus: {{.CorpusSize}}
Triage queue len: {{.TriageQueue}}
Cover: {{.CoverSize}}

+Stats:
+{{range $stat := $.Stats}} + {{$stat.Name}}: {{$stat.Value}}
+{{end}} +
{{range $c := $.Calls}} {{$c.Name}} inputs:{{$c.Inputs}} cover:{{$c.Cover}} prio
{{end}} diff --git a/manager/manager.go b/manager/manager.go index ab0372eab..ab40bbe0d 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -29,6 +29,8 @@ type Manager struct { master *rpc.Client masterHttp string instances []vm.Instance + startTime time.Time + stats map[string]uint64 mu sync.Mutex masterCorpus [][]byte // mirror of master corpus @@ -65,6 +67,8 @@ func RunManager(cfg *Config, syscalls map[int]bool, instances []vm.Instance) { cfg: cfg, master: master, masterHttp: r.Http, + startTime: time.Now(), + stats: make(map[string]uint64), instances: instances, masterHashes: make(map[Sig]struct{}), syscalls: syscalls, @@ -181,6 +185,7 @@ func (mgr *Manager) Connect(a *ManagerConnectArgs, r *ManagerConnectRes) error { mgr.mu.Lock() defer mgr.mu.Unlock() + mgr.stats["vm restarts"]++ mgr.minimizeCorpus() mgr.fuzzers[a.Name] = &Fuzzer{ name: a.Name, @@ -202,6 +207,7 @@ func (mgr *Manager) NewInput(a *NewManagerInputArgs, r *int) error { } mgr.corpusCover[call] = cover.Union(mgr.corpusCover[call], a.Cover) mgr.corpus = append(mgr.corpus, a.RpcInput) + mgr.stats["manager new inputs"]++ sig := hash(a.Prog) if _, ok := mgr.masterHashes[sig]; !ok { @@ -222,6 +228,10 @@ func (mgr *Manager) Poll(a *ManagerPollArgs, r *ManagerPollRes) error { mgr.mu.Lock() defer mgr.mu.Unlock() + for k, v := range a.Stats { + mgr.stats[k] += v + } + f := mgr.fuzzers[a.Name] if f == nil { fatalf("fuzzer %v is not connected", a.Name) -- cgit mrf-deployment