etcdmain: add an option for pprof

This commit adds a new option for activating profiling based on pprof
in etcd process.
 - -enable-pprof: boolean type option which activates profiling

For example, if a client URL is http://localhost:12379, users and
developers access heap profiler with this URL:
http://localhost:12379/debug/pprof/heap
This commit is contained in:
Hitoshi Mitake 2016-01-07 16:15:27 +09:00
parent 1df478ea5d
commit 588f655b4e
7 changed files with 40 additions and 0 deletions

View File

@ -263,6 +263,12 @@ Follow the instructions when using these flags.
+ Print the version and exit. + Print the version and exit.
+ default: false + default: false
## Profiling flags
### -enable-pprof
+ Enable runtime profiling data via HTTP server. Address is at client URL + "/debug/pprof"
+ default: false
[build-cluster]: clustering.md#static [build-cluster]: clustering.md#static
[reconfig]: runtime-configuration.md [reconfig]: runtime-configuration.md
[discovery]: clustering.md#discovery [discovery]: clustering.md#discovery

View File

@ -123,6 +123,8 @@ type config struct {
v3demo bool v3demo bool
gRPCAddr string gRPCAddr string
enablePprof bool
ignored []string ignored []string
} }
@ -230,6 +232,9 @@ func NewConfig() *config {
fs.Var(&flags.DeprecatedFlag{Name: "peers"}, "peers", "DEPRECATED: Use -initial-cluster instead.") fs.Var(&flags.DeprecatedFlag{Name: "peers"}, "peers", "DEPRECATED: Use -initial-cluster instead.")
fs.Var(&flags.DeprecatedFlag{Name: "peers-file"}, "peers-file", "DEPRECATED: Use -initial-cluster instead.") fs.Var(&flags.DeprecatedFlag{Name: "peers-file"}, "peers-file", "DEPRECATED: Use -initial-cluster instead.")
// pprof profiler via HTTP
fs.BoolVar(&cfg.enablePprof, "enable-pprof", false, "Enable runtime profiling data via HTTP server. Address is at client URL + \"/debug/pprof\"")
// ignored // ignored
for _, f := range cfg.ignored { for _, f := range cfg.ignored {
fs.Var(&flags.IgnoredFlag{Name: f}, f, "") fs.Var(&flags.IgnoredFlag{Name: f}, f, "")

View File

@ -20,6 +20,7 @@ import (
"io/ioutil" "io/ioutil"
"net" "net"
"net/http" "net/http"
_ "net/http/pprof"
"os" "os"
"path" "path"
"reflect" "reflect"
@ -294,6 +295,7 @@ func startEtcd(cfg *config) (<-chan struct{}, error) {
ElectionTicks: cfg.electionTicks(), ElectionTicks: cfg.electionTicks(),
V3demo: cfg.v3demo, V3demo: cfg.v3demo,
StrictReconfigCheck: cfg.strictReconfigCheck, StrictReconfigCheck: cfg.strictReconfigCheck,
EnablePprof: cfg.enablePprof,
} }
var s *etcdserver.EtcdServer var s *etcdserver.EtcdServer
s, err = etcdserver.NewServer(srvcfg) s, err = etcdserver.NewServer(srvcfg)

View File

@ -139,5 +139,9 @@ experimental flags:
enable experimental v3 demo API. enable experimental v3 demo API.
--experimental-gRPC-addr '127.0.0.1:2378' --experimental-gRPC-addr '127.0.0.1:2378'
gRPC address for experimental v3 demo API. gRPC address for experimental v3 demo API.
profiling flags:
--enable-pprof 'false'
Enable runtime profiling data via HTTP server. Address is at client URL + "/debug/pprof"
` `
) )

View File

@ -52,6 +52,8 @@ type ServerConfig struct {
V3demo bool V3demo bool
StrictReconfigCheck bool StrictReconfigCheck bool
EnablePprof bool
} }
// VerifyBootstrapConfig sanity-checks the initial config for bootstrap case // VerifyBootstrapConfig sanity-checks the initial config for bootstrap case

View File

@ -21,6 +21,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/http/pprof"
"net/url" "net/url"
"path" "path"
"strconv" "strconv"
@ -54,6 +55,7 @@ const (
healthPath = "/health" healthPath = "/health"
versionPath = "/version" versionPath = "/version"
configPath = "/config" configPath = "/config"
pprofPrefix = "/debug/pprof"
) )
// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests. // NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests.
@ -108,6 +110,23 @@ func NewClientHandler(server *etcdserver.EtcdServer, timeout time.Duration) http
mux.Handle(deprecatedMachinesPrefix, dmh) mux.Handle(deprecatedMachinesPrefix, dmh)
handleAuth(mux, sech) handleAuth(mux, sech)
if server.IsPprofEnabled() {
plog.Infof("pprof is enabled under %s", pprofPrefix)
mux.HandleFunc(pprofPrefix, pprof.Index)
mux.HandleFunc(pprofPrefix+"/profile", pprof.Profile)
mux.HandleFunc(pprofPrefix+"/symbol", pprof.Symbol)
mux.HandleFunc(pprofPrefix+"/cmdline", pprof.Cmdline)
// TODO: currently, we don't create an entry for pprof.Trace,
// because go 1.4 doesn't provide it. After support of go 1.4 is dropped,
// we should add the entry.
mux.Handle(pprofPrefix+"/heap", pprof.Handler("heap"))
mux.Handle(pprofPrefix+"/goroutine", pprof.Handler("goroutine"))
mux.Handle(pprofPrefix+"/threadcreate", pprof.Handler("threadcreate"))
mux.Handle(pprofPrefix+"/block", pprof.Handler("block"))
}
return requestLogger(mux) return requestLogger(mux)
} }

View File

@ -844,6 +844,8 @@ func (s *EtcdServer) Lead() uint64 { return atomic.LoadUint64(&s.r.lead) }
func (s *EtcdServer) Leader() types.ID { return types.ID(s.Lead()) } func (s *EtcdServer) Leader() types.ID { return types.ID(s.Lead()) }
func (s *EtcdServer) IsPprofEnabled() bool { return s.cfg.EnablePprof }
// configure sends a configuration change through consensus and // configure sends a configuration change through consensus and
// then waits for it to be applied to the server. It // then waits for it to be applied to the server. It
// will block until the change is performed or there is an error. // will block until the change is performed or there is an error.