macaron-toolbox/toolbox.go

159 lines
4.2 KiB
Go

// 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"
"gitea.com/macaron/macaron"
)
const _VERSION = "0.1.4"
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
// DisableDebug turns off all debug functionality.
DisableDebug bool
// 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() 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)
})
if !opt.DisableDebug {
// 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))
}
}