aboutsummaryrefslogtreecommitdiffstats
path: root/manager
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-11-19 19:02:30 +0100
committerDmitry Vyukov <dvyukov@google.com>2015-11-19 19:02:30 +0100
commit6c48b5b4efc91533658dababa47587689b4a6ae1 (patch)
treefcaff6eb6f3336de892bb3b925f22ed8d16918f7 /manager
parent7677b07a714e16bc48aa541e1deb807f2ce0774e (diff)
add various statistics to http interface
Diffstat (limited to 'manager')
-rw-r--r--manager/html.go37
-rw-r--r--manager/manager.go10
2 files changed, 47 insertions, 0 deletions
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(`
<!doctype html>
<html>
@@ -208,11 +239,17 @@ var htmlTemplate = template.Must(template.New("").Parse(`
</head>
<body>
Manager: {{.Name}} <a href='http://{{.MasterHttp}}'>[master]</a> <br>
+Uptime: {{.Uptime}}<br>
Master corpus: {{.MasterCorpusSize}} <br>
Corpus: {{.CorpusSize}}<br>
Triage queue len: {{.TriageQueue}}<br>
<a href='/cover'>Cover: {{.CoverSize}}</a> <br>
<br>
+Stats: <br>
+{{range $stat := $.Stats}}
+ {{$stat.Name}}: {{$stat.Value}}<br>
+{{end}}
+<br>
{{range $c := $.Calls}}
{{$c.Name}} <a href='/corpus?call={{$c.Name}}'>inputs:{{$c.Inputs}}</a> <a href='/cover?call={{$c.Name}}'>cover:{{$c.Cover}}</a> <a href='/prio?call={{$c.Name}}'>prio</a> <br>
{{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)