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