From a54954dcac5b4a5771485f1552bf025a696f04df Mon Sep 17 00:00:00 2001 From: bcbrock Date: Wed, 2 Nov 2016 12:19:05 -0500 Subject: [PATCH] Add Go pprof support to the orderer Fixes FAB-813. The profiling service is disabled by default, and defaults to using the 0.0.0.0:6060 interface if enabled. Change-Id: Ia8abaaacf1a8524444af6c0697c622386c4939d9 Signed-off-by: Bishop Brock --- orderer/README.md | 6 ++++++ orderer/config/config.go | 14 ++++++++++++++ orderer/main.go | 13 +++++++++++++ orderer/orderer.yaml | 6 ++++++ 4 files changed, 39 insertions(+) diff --git a/orderer/README.md b/orderer/README.md index 4b85087049f..d1e7305260f 100644 --- a/orderer/README.md +++ b/orderer/README.md @@ -29,3 +29,9 @@ There are currently no other raw ledgers available, although it is anticipated t To experiment with the orderer service you may build the orderer binary by simply typing `go build` in the `hyperledger/fabric/orderer` directory. You may then invoke the orderer binary with no parameters, or you can override the bind address, port, and backing ledger by setting the environment variables `ORDERER_LISTEN_ADDRESS`, `ORDERER_LISTEN_PORT` and `ORDERER_LEDGER_TYPE` respectively. Presently, only the solo orderer is supported. The deployment and configuration is very stopgap at this point, so expect for this to change noticably in the future. There are sample clients in the `fabric/orderer/sample_clients` directory. The `broadcast_timestamp` client sends a message containing the timestamp to the `Broadcast` service. The `deliver_stdout` client prints received batches to stdout from the `Deliver` interface. These may both be build simply by typing `go build` in their respective directories. Neither presently supports config, so editing the source manually to adjust address and port is required. + +### Profiling + +Profiling the orderer service is possible through a standard HTTP interface documented [here](https://golang.org/pkg/net/http/pprof). The profiling service can be configured using the **config.yaml** file, or through environment variables. To enable profiling set `ORDERER_GENERAL_PROFILE_ENABLED=true`, and optionally set `ORDERER_GENERAL_PROFILE_ADDRESS` to the desired network address for the profiling service. The default address is `0.0.0.0:6060` as in the Golang documentation. + +Note that failures of the profiling service, either at startup or anytime during the run, will cause the overall orderer service to fail. Therefore it is currently not recommended to enable profiling in production settings. diff --git a/orderer/config/config.go b/orderer/config/config.go index 118793fdd82..30d88021771 100644 --- a/orderer/config/config.go +++ b/orderer/config/config.go @@ -48,6 +48,13 @@ type General struct { ListenAddress string ListenPort uint16 GenesisMethod string + Profile Profile +} + +// Profile contains configuration for Go pprof profiling +type Profile struct { + Enabled bool + Address string } // RAMLedger contains config for the RAM ledger @@ -99,6 +106,10 @@ var defaults = TopLevel{ ListenAddress: "127.0.0.1", ListenPort: 5151, GenesisMethod: "static", + Profile: Profile{ + Enabled: false, + Address: "0.0.0.0:6060", + }, }, RAMLedger: RAMLedger{ HistorySize: 10000, @@ -150,6 +161,9 @@ func (c *TopLevel) completeInitialization() { c.General.ListenPort = defaults.General.ListenPort case c.General.GenesisMethod == "": c.General.GenesisMethod = defaults.General.GenesisMethod + case c.General.Profile.Enabled && (c.General.Profile.Address == ""): + logger.Infof("Profiling enabled and General.Profile.Address unset, setting to %s", defaults.General.Profile.Address) + c.General.Profile.Address = defaults.General.Profile.Address case c.FileLedger.Prefix == "": logger.Infof("FileLedger.Prefix unset, setting to %s", defaults.FileLedger.Prefix) c.FileLedger.Prefix = defaults.FileLedger.Prefix diff --git a/orderer/main.go b/orderer/main.go index cdf9c9c2688..5f0a3598d19 100644 --- a/orderer/main.go +++ b/orderer/main.go @@ -22,6 +22,8 @@ import ( "io/ioutil" "log" "net" + "net/http" + _ "net/http/pprof" "os" "os/signal" @@ -45,9 +47,20 @@ import ( "google.golang.org/grpc" ) +var logger = logging.MustGetLogger("orderer/main") + func main() { conf := config.Load() + // Start the profiling service if enabled. The ListenAndServe() + // call does not return unless an error occurs. + if conf.General.Profile.Enabled { + go func() { + logger.Infof("Starting Go pprof profiling service on %s", conf.General.Profile.Address) + panic(fmt.Errorf("Go pprof service failed: %s", http.ListenAndServe(conf.General.Profile.Address, nil))) + }() + } + switch conf.General.OrdererType { case "solo": launchSolo(conf) diff --git a/orderer/orderer.yaml b/orderer/orderer.yaml index 6fab99c901a..9a1dc77944c 100644 --- a/orderer/orderer.yaml +++ b/orderer/orderer.yaml @@ -41,6 +41,12 @@ General: # Genesis method: The method by which to retrieve/generate the genesis block GenesisMethod: static + # Enable an HTTP service for Go "pprof" profiling as documented at + # https://golang.org/pkg/net/http/pprof + Profile: + Enabled: false + Address: 0.0.0.0:6060 + ################################################################################ # # SECTION: RAM Ledger