forked from trustbloc/fabric-mod
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FAB-12372 Collect info on go routines
Collect information about all of the currently executing go routines within a process by handling SIGUSR1. SIGUSR1 will not terminate the process. Change-Id: Ide5a26a8f1ee9bae93d3c6ba4b0b178661cbfd6c Signed-off-by: Saad Karim <[email protected]> Signed-off-by: Matthew Sykes <[email protected]>
- Loading branch information
Showing
5 changed files
with
207 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
Copyright IBM Corp All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package diag | ||
|
||
import ( | ||
"bytes" | ||
"runtime/pprof" | ||
) | ||
|
||
type Logger interface { | ||
Infof(template string, args ...interface{}) | ||
Errorf(template string, args ...interface{}) | ||
} | ||
|
||
func CaptureGoRoutines() (string, error) { | ||
var buf bytes.Buffer | ||
err := pprof.Lookup("goroutine").WriteTo(&buf, 2) | ||
if err != nil { | ||
return "", err | ||
} | ||
return buf.String(), nil | ||
} | ||
|
||
func LogGoRoutines(logger Logger) { | ||
output, err := CaptureGoRoutines() | ||
if err != nil { | ||
logger.Errorf("failed to capture go routines: %s", err) | ||
return | ||
} | ||
|
||
logger.Infof("Go routines report:\n%s", output) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
Copyright IBM Corp All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package diag_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/hyperledger/fabric/common/diag" | ||
"github.com/hyperledger/fabric/common/flogging/floggingtest" | ||
. "github.com/onsi/gomega" | ||
"github.com/onsi/gomega/gbytes" | ||
) | ||
|
||
func TestCaptureGoRoutines(t *testing.T) { | ||
gt := NewGomegaWithT(t) | ||
output, err := diag.CaptureGoRoutines() | ||
gt.Expect(err).NotTo(HaveOccurred()) | ||
|
||
gt.Expect(output).To(MatchRegexp(`goroutine \d+ \[running\]:`)) | ||
gt.Expect(output).To(ContainSubstring("github.com/hyperledger/fabric/common/diag.CaptureGoRoutines")) | ||
} | ||
|
||
func TestLogGoRoutines(t *testing.T) { | ||
gt := NewGomegaWithT(t) | ||
logger, recorder := floggingtest.NewTestLogger(t, floggingtest.Named("goroutine")) | ||
diag.LogGoRoutines(logger) | ||
|
||
gt.Expect(recorder).To(gbytes.Say(`goroutine \d+ \[running\]:`)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
Copyright IBM Corp All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package e2e | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"syscall" | ||
|
||
docker "github.com/fsouza/go-dockerclient" | ||
"github.com/hyperledger/fabric/integration/nwo" | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
"github.com/onsi/gomega/gbytes" | ||
"github.com/tedsuo/ifrit" | ||
"github.com/tedsuo/ifrit/ginkgomon" | ||
) | ||
|
||
var _ = Describe("SignalHandling", func() { | ||
var ( | ||
testDir string | ||
client *docker.Client | ||
network *nwo.Network | ||
|
||
peerRunner, ordererRunner *ginkgomon.Runner | ||
peerProcess, ordererProcess ifrit.Process | ||
) | ||
|
||
BeforeEach(func() { | ||
var err error | ||
testDir, err = ioutil.TempDir("", "e2e-sigs") | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
client, err = docker.NewClientFromEnv() | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
network = nwo.New(nwo.BasicSolo(), testDir, client, BasePort(), components) | ||
network.GenerateConfigTree() | ||
network.Bootstrap() | ||
|
||
ordererRunner = network.OrdererRunner(network.Orderers[0]) | ||
ordererProcess = ifrit.Invoke(ordererRunner) | ||
Eventually(ordererProcess.Ready(), network.EventuallyTimeout).Should(BeClosed()) | ||
|
||
peerRunner = network.PeerRunner(network.Peers[0]) | ||
peerProcess = ifrit.Invoke(peerRunner) | ||
Eventually(peerProcess.Ready(), network.EventuallyTimeout).Should(BeClosed()) | ||
}) | ||
|
||
AfterEach(func() { | ||
if peerProcess != nil { | ||
peerProcess.Signal(syscall.SIGKILL) | ||
} | ||
if ordererProcess != nil { | ||
ordererProcess.Signal(syscall.SIGKILL) | ||
} | ||
if network != nil { | ||
network.Cleanup() | ||
} | ||
os.RemoveAll(testDir) | ||
}) | ||
|
||
It("handles signals", func() { | ||
By("verifying SIGUSR1 to the peer dumps go routines") | ||
peerProcess.Signal(syscall.SIGUSR1) | ||
Eventually(peerRunner.Err()).Should(gbytes.Say("Received signal: ")) | ||
Eventually(peerRunner.Err()).Should(gbytes.Say(`Go routines report`)) | ||
|
||
By("verifying SIGUSR1 to the orderer dumps go routines") | ||
ordererProcess.Signal(syscall.SIGUSR1) | ||
Eventually(ordererRunner.Err()).Should(gbytes.Say("Received signal: ")) | ||
Eventually(ordererRunner.Err()).Should(gbytes.Say(`Go routines report`)) | ||
|
||
By("verifying SIGUSR1 does not terminate processes") | ||
Consistently(peerProcess.Wait()).ShouldNot(Receive()) | ||
Consistently(ordererProcess.Wait()).ShouldNot(Receive()) | ||
|
||
By("verifying SIGTERM to the peer stops the process") | ||
peerProcess.Signal(syscall.SIGTERM) | ||
Eventually(peerRunner.Err()).Should(gbytes.Say("Received signal: ")) | ||
Eventually(peerProcess.Wait()).Should(Receive()) | ||
peerProcess = nil | ||
|
||
By("verifying SIGTERM to the orderer stops the process") | ||
ordererProcess.Signal(syscall.SIGTERM) | ||
Eventually(ordererRunner.Err()).Should(gbytes.Say("Received signal: ")) | ||
Eventually(ordererProcess.Wait()).Should(Receive()) | ||
ordererProcess = nil | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters