github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/syz-verifier/monitoring_api.go (about) 1 // Copyright 2021 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package main 5 6 import ( 7 "encoding/json" 8 "net/http" 9 "time" 10 ) 11 12 // Monitor provides http based data for the syz-verifier monitoring. 13 // TODO: Add tests to monitoring_api. 14 type Monitor struct { 15 externalStats *Stats 16 } 17 18 // MakeMonitor creates the Monitor instance. 19 func MakeMonitor() *Monitor { 20 instance := &Monitor{} 21 instance.initHTTPHandlers() 22 return instance 23 } 24 25 // ListenAndServe starts the server. 26 func (monitor *Monitor) ListenAndServe(addr string) error { 27 return http.ListenAndServe(addr, nil) 28 } 29 30 // SetStatsTracking points Monitor to the Stats object to monitor. 31 func (monitor *Monitor) SetStatsTracking(s *Stats) { 32 monitor.externalStats = s 33 } 34 35 // InitHTTPHandlers initializes the API routing. 36 func (monitor *Monitor) initHTTPHandlers() { 37 http.Handle("/api/stats.json", jsonResponse(monitor.renderStats)) 38 39 http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { 40 writer.Write([]byte("<a href='api/stats.json'>stats_json</a>")) 41 }) 42 } 43 44 // statsJSON provides information for the "/api/stats.json" render. 45 type statsJSON struct { 46 StartTime time.Time 47 TotalCallMismatches uint64 48 TotalProgs uint64 49 ExecErrorProgs uint64 50 FlakyProgs uint64 51 MismatchingProgs uint64 52 AverExecSpeed uint64 53 } 54 55 // renderStats renders the statsJSON object. 56 func (monitor *Monitor) renderStats() interface{} { 57 stats := monitor.externalStats 58 59 return &statsJSON{ 60 StartTime: stats.StartTime.Get(), 61 TotalCallMismatches: stats.TotalCallMismatches.Get(), 62 TotalProgs: stats.TotalProgs.Get(), 63 ExecErrorProgs: stats.ExecErrorProgs.Get(), 64 FlakyProgs: stats.FlakyProgs.Get(), 65 MismatchingProgs: stats.MismatchingProgs.Get(), 66 AverExecSpeed: 60 * stats.TotalProgs.Get() / uint64(1+time.Since(stats.StartTime.Get()).Seconds()), 67 } 68 } 69 70 // jsonResponse provides general response forming logic. 71 func jsonResponse(getData func() interface{}) http.Handler { 72 return http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { 73 w.Header().Set("Content-Type", "application/json") 74 75 data := getData() 76 json, err := json.MarshalIndent( 77 data, 78 "", 79 "\t", 80 ) 81 if err != nil { 82 http.Error(w, err.Error(), 500) // Internal Server Error. 83 return 84 } 85 86 w.Write(json) 87 }) 88 }