server.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. // Package monitor provides an embedded HTTP server to expose
  5. // metrics for monitoring
  6. package monitor
  7. import (
  8. "expvar"
  9. "fmt"
  10. "net"
  11. "net/http"
  12. _ "net/http/pprof" // Go documentation recommended usage
  13. "notabug.org/themusicgod1/goarista/netns"
  14. "notabug.org/themusicgod1/glog"
  15. )
  16. // Server represents a monitoring server
  17. type Server interface {
  18. Run(serveMux *http.ServeMux)
  19. }
  20. // server contains information for the monitoring server
  21. type server struct {
  22. vrfName string
  23. // Server name e.g. host[:port]
  24. serverName string
  25. }
  26. // NewServer creates a new server struct
  27. func NewServer(address string) Server {
  28. vrfName, addr, err := netns.ParseAddress(address)
  29. if err != nil {
  30. glog.Errorf("Failed to parse address: %s", err)
  31. }
  32. return &server{
  33. vrfName: vrfName,
  34. serverName: addr,
  35. }
  36. }
  37. func debugHandler(w http.ResponseWriter, r *http.Request) {
  38. indexTmpl := `<html>
  39. <head>
  40. <title>/debug</title>
  41. </head>
  42. <body>
  43. <p>/debug</p>
  44. <div><a href="/debug/vars">vars</a></div>
  45. <div><a href="/debug/pprof">pprof</a></div>
  46. </body>
  47. </html>
  48. `
  49. fmt.Fprintf(w, indexTmpl)
  50. }
  51. // PrintableHistogram represents a Histogram that can be printed as
  52. // a chart.
  53. type PrintableHistogram interface {
  54. Print() string
  55. }
  56. // Pretty prints the latency histograms
  57. func histogramHandler(w http.ResponseWriter, r *http.Request) {
  58. expvar.Do(func(kv expvar.KeyValue) {
  59. if hist, ok := kv.Value.(PrintableHistogram); ok {
  60. w.Write([]byte(hist.Print()))
  61. }
  62. })
  63. }
  64. // Run sets up the HTTP server and any handlers
  65. func (s *server) Run(serveMux *http.ServeMux) {
  66. serveMux.HandleFunc("/debug", debugHandler)
  67. serveMux.HandleFunc("/debug/histograms", histogramHandler)
  68. var listener net.Listener
  69. err := netns.Do(s.vrfName, func() error {
  70. var err error
  71. listener, err = net.Listen("tcp", s.serverName)
  72. return err
  73. })
  74. if err != nil {
  75. glog.Fatalf("Could not start monitor server in VRF %q: %s", s.vrfName, err)
  76. }
  77. err = http.Serve(listener, serveMux)
  78. if err != nil {
  79. glog.Fatal("http serve returned with error:", err)
  80. }
  81. }