github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/monitor/server.go (about) 1 // Copyright (c) 2015 Arista Networks, Inc. 2 // Use of this source code is governed by the Apache License 2.0 3 // that can be found in the COPYING file. 4 5 // Package monitor provides an embedded HTTP server to expose 6 // metrics for monitoring 7 package monitor 8 9 import ( 10 "expvar" 11 "fmt" 12 "net" 13 "net/http" 14 _ "net/http/pprof" // Go documentation recommended usage 15 16 "github.com/aristanetworks/goarista/netns" 17 18 "github.com/aristanetworks/glog" 19 ) 20 21 // Server represents a monitoring server 22 type Server interface { 23 Run(serveMux *http.ServeMux) 24 Serve(serveMux *http.ServeMux) error 25 } 26 27 // server contains information for the monitoring server 28 type server struct { 29 vrfName string 30 // Server name e.g. host[:port] 31 serverName string 32 loglevel *logsetSrv 33 } 34 35 // NewServer creates a new server struct 36 func NewServer(address string) Server { 37 vrfName, addr, err := netns.ParseAddress(address) 38 if err != nil { 39 glog.Errorf("Failed to parse address: %s", err) 40 } 41 return &server{ 42 vrfName: vrfName, 43 serverName: addr, 44 loglevel: newLogsetSrv(), 45 } 46 } 47 48 func debugHandler(w http.ResponseWriter, r *http.Request) { 49 indexTmpl := `<html> 50 <head> 51 <title>/debug</title> 52 </head> 53 <body> 54 <p>/debug</p> 55 <div><a href="/debug/vars">vars</a></div> 56 <div><a href="/debug/pprof">pprof</a></div> 57 </body> 58 </html> 59 ` 60 fmt.Fprintf(w, indexTmpl) 61 } 62 63 // PrintableHistogram represents a Histogram that can be printed as 64 // a chart. 65 type PrintableHistogram interface { 66 Print() string 67 } 68 69 // Pretty prints the latency histograms 70 func histogramHandler(w http.ResponseWriter, r *http.Request) { 71 expvar.Do(func(kv expvar.KeyValue) { 72 if hist, ok := kv.Value.(PrintableHistogram); ok { 73 w.Write([]byte(hist.Print())) 74 } 75 }) 76 } 77 78 // Run calls Serve. On error the program exits. 79 func (s *server) Run(serveMux *http.ServeMux) { 80 if err := s.Serve(serveMux); err != nil { 81 glog.Fatal(err) 82 } 83 } 84 85 // Serve registers handlers and starts serving. 86 func (s *server) Serve(serveMux *http.ServeMux) error { 87 serveMux.HandleFunc("/debug", debugHandler) 88 serveMux.HandleFunc("/debug/histograms", histogramHandler) 89 // for example, to set glog verbosity to 5: curl localhost:6060/debug/loglevel?glog=5 90 serveMux.Handle("/debug/loglevel", s.loglevel) 91 92 var listener net.Listener 93 err := netns.Do(s.vrfName, func() error { 94 var err error 95 listener, err = net.Listen("tcp", s.serverName) 96 return err 97 }) 98 if err != nil { 99 return fmt.Errorf("could not start monitor server in VRF %q: %s", s.vrfName, err) 100 } 101 102 return http.Serve(listener, serveMux) 103 }