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