server.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package devserver
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "net/http/pprof"
  7. "sync"
  8. "github.com/felixge/fgprof"
  9. "github.com/prometheus/client_golang/prometheus/promhttp"
  10. "github.com/zeromicro/go-zero/core/logx"
  11. "github.com/zeromicro/go-zero/core/prometheus"
  12. "github.com/zeromicro/go-zero/core/threading"
  13. "github.com/zeromicro/go-zero/internal/health"
  14. )
  15. var once sync.Once
  16. // Server is inner http server, expose some useful observability information of app.
  17. // For example health check, metrics and pprof.
  18. type Server struct {
  19. config Config
  20. server *http.ServeMux
  21. routes []string
  22. }
  23. // NewServer returns a new inner http Server.
  24. func NewServer(config Config) *Server {
  25. return &Server{
  26. config: config,
  27. server: http.NewServeMux(),
  28. }
  29. }
  30. func (s *Server) addRoutes() {
  31. // route path, routes list
  32. s.handleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
  33. _ = json.NewEncoder(w).Encode(s.routes)
  34. })
  35. // health
  36. s.handleFunc(s.config.HealthPath, health.CreateHttpHandler())
  37. // metrics
  38. if s.config.EnableMetrics {
  39. // enable prometheus global switch
  40. prometheus.Enable()
  41. s.handleFunc(s.config.MetricsPath, promhttp.Handler().ServeHTTP)
  42. }
  43. // pprof
  44. if s.config.EnablePprof {
  45. s.handleFunc("/debug/fgprof", fgprof.Handler().(http.HandlerFunc))
  46. s.handleFunc("/debug/pprof/", pprof.Index)
  47. s.handleFunc("/debug/pprof/cmdline", pprof.Cmdline)
  48. s.handleFunc("/debug/pprof/profile", pprof.Profile)
  49. s.handleFunc("/debug/pprof/symbol", pprof.Symbol)
  50. s.handleFunc("/debug/pprof/trace", pprof.Trace)
  51. }
  52. }
  53. func (s *Server) handleFunc(pattern string, handler http.HandlerFunc) {
  54. s.server.HandleFunc(pattern, handler)
  55. s.routes = append(s.routes, pattern)
  56. }
  57. // StartAsync start inner http server background.
  58. func (s *Server) StartAsync() {
  59. s.addRoutes()
  60. threading.GoSafe(func() {
  61. addr := fmt.Sprintf("%s:%d", s.config.Host, s.config.Port)
  62. logx.Infof("Starting dev http server at %s", addr)
  63. if err := http.ListenAndServe(addr, s.server); err != nil {
  64. logx.Error(err)
  65. }
  66. })
  67. }
  68. // StartAgent start inner http server by config.
  69. func StartAgent(c Config) {
  70. once.Do(func() {
  71. if c.Enabled {
  72. s := NewServer(c)
  73. s.StartAsync()
  74. }
  75. })
  76. }