add net/http/pprof profiler

This commit is contained in:
Asim Aslam 2019-12-08 20:31:16 +00:00
parent a9be1288d2
commit e2b2a30668
4 changed files with 105 additions and 6 deletions

View File

@ -0,0 +1,78 @@
// Package http enables the http profiler
package http
import (
"context"
"net/http"
"net/http/pprof"
"sync"
"github.com/micro/go-micro/debug/profile"
)
type httpProfile struct {
sync.Mutex
running bool
server *http.Server
}
var (
DefaultAddress = ":6060"
)
// Start the profiler
func (h *httpProfile) Start() error {
h.Lock()
defer h.Unlock()
if h.running {
return nil
}
go func() {
if err := h.server.ListenAndServe(); err != nil {
h.Lock()
h.running = false
h.Unlock()
}
}()
h.running = true
return nil
}
// Stop the profiler
func (h *httpProfile) Stop() error {
h.Lock()
defer h.Unlock()
if !h.running {
return nil
}
h.running = false
return h.server.Shutdown(context.TODO())
}
func (h *httpProfile) String() string {
return "http"
}
func NewProfile(opts ...profile.Option) profile.Profile {
mux := http.NewServeMux()
mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
return &httpProfile{
server: &http.Server{
Addr: DefaultAddress,
Handler: mux,
},
}
}

View File

@ -107,6 +107,10 @@ func (p *profiler) Stop() error {
} }
} }
func (p *profiler) String() string {
return "pprof"
}
func NewProfile(opts ...profile.Option) profile.Profile { func NewProfile(opts ...profile.Option) profile.Profile {
var options profile.Options var options profile.Options
for _, o := range opts { for _, o := range opts {

View File

@ -6,6 +6,8 @@ type Profile interface {
Start() error Start() error
// Stop the profiler // Stop the profiler
Stop() error Stop() error
// Name of the profiler
String() string
} }
type Options struct { type Options struct {

View File

@ -3,6 +3,7 @@ package micro
import ( import (
"os" "os"
"os/signal" "os/signal"
"runtime"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
@ -10,6 +11,7 @@ import (
"github.com/micro/go-micro/client" "github.com/micro/go-micro/client"
"github.com/micro/go-micro/config/cmd" "github.com/micro/go-micro/config/cmd"
"github.com/micro/go-micro/debug/profile" "github.com/micro/go-micro/debug/profile"
"github.com/micro/go-micro/debug/profile/http"
"github.com/micro/go-micro/debug/profile/pprof" "github.com/micro/go-micro/debug/profile/pprof"
"github.com/micro/go-micro/debug/service/handler" "github.com/micro/go-micro/debug/service/handler"
"github.com/micro/go-micro/plugin" "github.com/micro/go-micro/plugin"
@ -151,12 +153,25 @@ func (s *service) Run() error {
// start the profiler // start the profiler
// TODO: set as an option to the service, don't just use pprof // TODO: set as an option to the service, don't just use pprof
if prof := os.Getenv("MICRO_DEBUG_PROFILE"); len(prof) > 0 { if prof := os.Getenv("MICRO_DEBUG_PROFILE"); len(prof) > 0 {
service := s.opts.Server.Options().Name var profiler profile.Profile
version := s.opts.Server.Options().Version
id := s.opts.Server.Options().Id // to view mutex contention
profiler := pprof.NewProfile( runtime.SetMutexProfileFraction(5)
profile.Name(service + "." + version + "." + id), // to view blocking profile
) runtime.SetBlockProfileRate(1)
switch prof {
case "http":
profiler = http.NewProfile()
default:
service := s.opts.Server.Options().Name
version := s.opts.Server.Options().Version
id := s.opts.Server.Options().Id
profiler = pprof.NewProfile(
profile.Name(service + "." + version + "." + id),
)
}
if err := profiler.Start(); err != nil { if err := profiler.Start(); err != nil {
return err return err
} }