toolbox.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Copyright 2014 The Macaron Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"): you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. // License for the specific language governing permissions and limitations
  13. // under the License.
  14. // Package toolbox is a middleware that provides health check, pprof, profile and statistic services for Macaron.
  15. package toolbox
  16. import (
  17. "fmt"
  18. "io"
  19. "net/http"
  20. "net/http/pprof"
  21. "path"
  22. "time"
  23. "gopkg.in/macaron.v1"
  24. )
  25. const _VERSION = "0.1.2"
  26. func Version() string {
  27. return _VERSION
  28. }
  29. // Toolbox represents a tool box service for Macaron instance.
  30. type Toolbox interface {
  31. AddHealthCheck(HealthChecker)
  32. AddHealthCheckFunc(string, HealthCheckFunc)
  33. AddStatistics(string, string, time.Duration)
  34. GetMap(io.Writer)
  35. JSON(io.Writer)
  36. }
  37. type toolbox struct {
  38. *UrlMap
  39. healthCheckJobs []*healthCheck
  40. }
  41. // Options represents a struct for specifying configuration options for the Toolbox middleware.
  42. type Options struct {
  43. // URL prefix for toolbox dashboard. Default is "/debug".
  44. URLPrefix string
  45. // URL for health check request. Default is "/healthcheck".
  46. HealthCheckURL string
  47. // Health checkers.
  48. HealthCheckers []HealthChecker
  49. // Health check functions.
  50. HealthCheckFuncs []*HealthCheckFuncDesc
  51. // URL for URL map json. Default is "/urlmap.json".
  52. URLMapPrefix string
  53. // URL prefix of pprof. Default is "/debug/pprof/".
  54. PprofURLPrefix string
  55. // URL prefix of profile. Default is "/debug/profile/".
  56. ProfileURLPrefix string
  57. // Path store profile files. Default is "profile".
  58. ProfilePath string
  59. }
  60. var opt Options
  61. func prepareOptions(options []Options) {
  62. if len(options) > 0 {
  63. opt = options[0]
  64. }
  65. // Defaults.
  66. if len(opt.URLPrefix) == 0 {
  67. opt.URLPrefix = "/debug"
  68. }
  69. if len(opt.HealthCheckURL) == 0 {
  70. opt.HealthCheckURL = "/healthcheck"
  71. }
  72. if len(opt.URLMapPrefix) == 0 {
  73. opt.URLMapPrefix = "/urlmap.json"
  74. }
  75. if len(opt.PprofURLPrefix) == 0 {
  76. opt.PprofURLPrefix = "/debug/pprof/"
  77. } else if opt.PprofURLPrefix[len(opt.PprofURLPrefix)-1] != '/' {
  78. opt.PprofURLPrefix += "/"
  79. }
  80. if len(opt.ProfileURLPrefix) == 0 {
  81. opt.ProfileURLPrefix = "/debug/profile/"
  82. } else if opt.ProfileURLPrefix[len(opt.ProfileURLPrefix)-1] != '/' {
  83. opt.ProfileURLPrefix += "/"
  84. }
  85. if len(opt.ProfilePath) == 0 {
  86. opt.ProfilePath = path.Join(macaron.Root, "profile")
  87. }
  88. }
  89. func dashboard(ctx *macaron.Context) string {
  90. return fmt.Sprintf(`<p>Toolbox Index:</p>
  91. <ol>
  92. <li><a href="%s">Pprof Information</a></li>
  93. <li><a href="%s">Profile Operations</a></li>
  94. </ol>`, opt.PprofURLPrefix, opt.ProfileURLPrefix)
  95. }
  96. var _ Toolbox = &toolbox{}
  97. // Toolboxer is a middleware provides health check, pprof, profile and statistic services for your application.
  98. func Toolboxer(m *macaron.Macaron, options ...Options) macaron.Handler {
  99. prepareOptions(options)
  100. t := &toolbox{
  101. healthCheckJobs: make([]*healthCheck, 0, len(opt.HealthCheckers)+len(opt.HealthCheckFuncs)),
  102. }
  103. // Dashboard.
  104. m.Get(opt.URLPrefix, dashboard)
  105. // Health check.
  106. for _, hc := range opt.HealthCheckers {
  107. t.AddHealthCheck(hc)
  108. }
  109. for _, fd := range opt.HealthCheckFuncs {
  110. t.AddHealthCheckFunc(fd.Desc, fd.Func)
  111. }
  112. m.Get(opt.HealthCheckURL, t.handleHealthCheck)
  113. // URL map.
  114. m.Get(opt.URLMapPrefix, func(rw http.ResponseWriter) {
  115. t.JSON(rw)
  116. })
  117. // Pprof.
  118. m.Any(path.Join(opt.PprofURLPrefix, "cmdline"), pprof.Cmdline)
  119. m.Any(path.Join(opt.PprofURLPrefix, "profile"), pprof.Profile)
  120. m.Any(path.Join(opt.PprofURLPrefix, "symbol"), pprof.Symbol)
  121. m.Any(opt.PprofURLPrefix, pprof.Index)
  122. m.Any(path.Join(opt.PprofURLPrefix, "*"), pprof.Index)
  123. // Profile.
  124. profilePath = opt.ProfilePath
  125. m.Get(opt.ProfileURLPrefix, handleProfile)
  126. // Routes statistic.
  127. t.UrlMap = &UrlMap{
  128. urlmap: make(map[string]map[string]*Statistics),
  129. }
  130. return func(ctx *macaron.Context) {
  131. ctx.MapTo(t, (*Toolbox)(nil))
  132. }
  133. }