123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- // Copyright 2014 The Macaron Authors
- //
- // Licensed under the Apache License, Version 2.0 (the "License"): you may
- // not use this file except in compliance with the License. You may obtain
- // a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- // License for the specific language governing permissions and limitations
- // under the License.
- // Package toolbox is a middleware that provides health check, pprof, profile and statistic services for Macaron.
- package toolbox
- import (
- "fmt"
- "io"
- "net/http"
- "net/http/pprof"
- "path"
- "time"
- "gopkg.in/macaron.v1"
- )
- const _VERSION = "0.1.3"
- func Version() string {
- return _VERSION
- }
- // Toolbox represents a tool box service for Macaron instance.
- type Toolbox interface {
- AddHealthCheck(HealthChecker)
- AddHealthCheckFunc(string, HealthCheckFunc)
- AddStatistics(string, string, time.Duration)
- GetMap(io.Writer)
- JSON(io.Writer)
- }
- type toolbox struct {
- *UrlMap
- healthCheckJobs []*healthCheck
- }
- // Options represents a struct for specifying configuration options for the Toolbox middleware.
- type Options struct {
- // URL prefix for toolbox dashboard. Default is "/debug".
- URLPrefix string
- // URL for health check request. Default is "/healthcheck".
- HealthCheckURL string
- // Health checkers.
- HealthCheckers []HealthChecker
- // Health check functions.
- HealthCheckFuncs []*HealthCheckFuncDesc
- // URL for URL map json. Default is "/urlmap.json".
- URLMapPrefix string
- // URL prefix of pprof. Default is "/debug/pprof/".
- PprofURLPrefix string
- // URL prefix of profile. Default is "/debug/profile/".
- ProfileURLPrefix string
- // Path store profile files. Default is "profile".
- ProfilePath string
- }
- var opt Options
- func prepareOptions(options []Options) {
- if len(options) > 0 {
- opt = options[0]
- }
- // Defaults.
- if len(opt.URLPrefix) == 0 {
- opt.URLPrefix = "/debug"
- }
- if len(opt.HealthCheckURL) == 0 {
- opt.HealthCheckURL = "/healthcheck"
- }
- if len(opt.URLMapPrefix) == 0 {
- opt.URLMapPrefix = "/urlmap.json"
- }
- if len(opt.PprofURLPrefix) == 0 {
- opt.PprofURLPrefix = "/debug/pprof/"
- } else if opt.PprofURLPrefix[len(opt.PprofURLPrefix)-1] != '/' {
- opt.PprofURLPrefix += "/"
- }
- if len(opt.ProfileURLPrefix) == 0 {
- opt.ProfileURLPrefix = "/debug/profile/"
- } else if opt.ProfileURLPrefix[len(opt.ProfileURLPrefix)-1] != '/' {
- opt.ProfileURLPrefix += "/"
- }
- if len(opt.ProfilePath) == 0 {
- opt.ProfilePath = path.Join(macaron.Root, "profile")
- }
- }
- func dashboard(ctx *macaron.Context) string {
- return fmt.Sprintf(`<p>Toolbox Index:</p>
- <ol>
- <li><a href="%s">Pprof Information</a></li>
- <li><a href="%s">Profile Operations</a></li>
- </ol>`, opt.PprofURLPrefix, opt.ProfileURLPrefix)
- }
- var _ Toolbox = &toolbox{}
- // Toolboxer is a middleware provides health check, pprof, profile and statistic services for your application.
- func Toolboxer(m *macaron.Macaron, options ...Options) macaron.Handler {
- prepareOptions(options)
- t := &toolbox{
- healthCheckJobs: make([]*healthCheck, 0, len(opt.HealthCheckers)+len(opt.HealthCheckFuncs)),
- }
- // Dashboard.
- m.Get(opt.URLPrefix, dashboard)
- // Health check.
- for _, hc := range opt.HealthCheckers {
- t.AddHealthCheck(hc)
- }
- for _, fd := range opt.HealthCheckFuncs {
- t.AddHealthCheckFunc(fd.Desc, fd.Func)
- }
- m.Route(opt.HealthCheckURL, "HEAD,GET", t.handleHealthCheck)
- // URL map.
- m.Get(opt.URLMapPrefix, func(rw http.ResponseWriter) {
- t.JSON(rw)
- })
- // Pprof.
- m.Any(path.Join(opt.PprofURLPrefix, "cmdline"), pprof.Cmdline)
- m.Any(path.Join(opt.PprofURLPrefix, "profile"), pprof.Profile)
- m.Any(path.Join(opt.PprofURLPrefix, "symbol"), pprof.Symbol)
- m.Any(opt.PprofURLPrefix, pprof.Index)
- m.Any(path.Join(opt.PprofURLPrefix, "*"), pprof.Index)
- // Profile.
- profilePath = opt.ProfilePath
- m.Get(opt.ProfileURLPrefix, handleProfile)
- // Routes statistic.
- t.UrlMap = &UrlMap{
- urlmap: make(map[string]map[string]*Statistics),
- }
- return func(ctx *macaron.Context) {
- ctx.MapTo(t, (*Toolbox)(nil))
- }
- }
|