mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
profiler: Fix it properly and generate/save profiles even failure situations. (#2607)
Fixes #2594
This commit is contained in:
parent
bf62ba57cf
commit
7398d737b5
22
cmd/main.go
22
cmd/main.go
@ -23,7 +23,6 @@ import (
|
|||||||
|
|
||||||
"github.com/minio/cli"
|
"github.com/minio/cli"
|
||||||
"github.com/minio/mc/pkg/console"
|
"github.com/minio/mc/pkg/console"
|
||||||
"github.com/pkg/profile"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -130,6 +129,7 @@ func registerApp() *cli.App {
|
|||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify main command syntax.
|
||||||
func checkMainSyntax(c *cli.Context) {
|
func checkMainSyntax(c *cli.Context) {
|
||||||
configPath, err := getConfigPath()
|
configPath, err := getConfigPath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -140,12 +140,7 @@ func checkMainSyntax(c *cli.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global profiler to be cleanly set and saved inside graceful shutdown.
|
// Main main for minio server.
|
||||||
var globalProfiler interface {
|
|
||||||
Stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main - main for minio server.
|
|
||||||
func Main() {
|
func Main() {
|
||||||
app := registerApp()
|
app := registerApp()
|
||||||
app.Before = func(c *cli.Context) error {
|
app.Before = func(c *cli.Context) error {
|
||||||
@ -181,16 +176,9 @@ func Main() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set ``MINIO_PROFILE_DIR`` to the directory where profiling information should be persisted
|
// Start profiler if env is set.
|
||||||
profileDir := os.Getenv("MINIO_PROFILE_DIR")
|
if profiler := os.Getenv("MINIO_PROFILER"); profiler != "" {
|
||||||
// Enable profiler if ``MINIO_PROFILER`` is set. Supported options are [cpu, mem, block].
|
globalProfiler = startProfiler(profiler)
|
||||||
switch os.Getenv("MINIO_PROFILER") {
|
|
||||||
case "cpu":
|
|
||||||
globalProfiler = profile.Start(profile.CPUProfile, profile.ProfilePath(profileDir))
|
|
||||||
case "mem":
|
|
||||||
globalProfiler = profile.Start(profile.MemProfile, profile.ProfilePath(profileDir))
|
|
||||||
case "block":
|
|
||||||
globalProfiler = profile.Start(profile.BlockProfile, profile.ProfilePath(profileDir))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the app - exit on error.
|
// Run the app - exit on error.
|
||||||
|
49
cmd/utils.go
49
cmd/utils.go
@ -26,6 +26,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/pkg/profile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// xmlDecoder provide decoded value in xml.
|
// xmlDecoder provide decoded value in xml.
|
||||||
@ -154,17 +156,44 @@ const (
|
|||||||
shutdownRestart
|
shutdownRestart
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Starts a profiler returns nil if profiler is not enabled, caller needs to handle this.
|
||||||
|
func startProfiler(profiler string) interface {
|
||||||
|
Stop()
|
||||||
|
} {
|
||||||
|
// Set ``MINIO_PROFILE_DIR`` to the directory where profiling information should be persisted
|
||||||
|
profileDir := os.Getenv("MINIO_PROFILE_DIR")
|
||||||
|
// Enable profiler if ``MINIO_PROFILER`` is set. Supported options are [cpu, mem, block].
|
||||||
|
switch profiler {
|
||||||
|
case "cpu":
|
||||||
|
return profile.Start(profile.CPUProfile, profile.NoShutdownHook, profile.ProfilePath(profileDir))
|
||||||
|
case "mem":
|
||||||
|
return profile.Start(profile.MemProfile, profile.NoShutdownHook, profile.ProfilePath(profileDir))
|
||||||
|
case "block":
|
||||||
|
return profile.Start(profile.BlockProfile, profile.NoShutdownHook, profile.ProfilePath(profileDir))
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Global shutdown signal channel.
|
// Global shutdown signal channel.
|
||||||
var globalShutdownSignalCh = make(chan shutdownSignal, 1)
|
var globalShutdownSignalCh = make(chan shutdownSignal, 1)
|
||||||
|
|
||||||
|
// Global profiler to be used by shutdown go-routine.
|
||||||
|
var globalProfiler interface {
|
||||||
|
Stop()
|
||||||
|
}
|
||||||
|
|
||||||
// Start to monitor shutdownSignal to execute shutdown callbacks
|
// Start to monitor shutdownSignal to execute shutdown callbacks
|
||||||
func startMonitorShutdownSignal(onExitFn onExitFunc) error {
|
func startMonitorShutdownSignal(onExitFn onExitFunc) error {
|
||||||
// Validate exit func.
|
// Validate exit func.
|
||||||
if onExitFn == nil {
|
if onExitFn == nil {
|
||||||
return errInvalidArgument
|
return errInvalidArgument
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start listening on shutdown signal.
|
||||||
go func() {
|
go func() {
|
||||||
defer close(globalShutdownSignalCh)
|
defer close(globalShutdownSignalCh)
|
||||||
|
|
||||||
// Monitor signals.
|
// Monitor signals.
|
||||||
trapCh := signalTrap(os.Interrupt, syscall.SIGTERM)
|
trapCh := signalTrap(os.Interrupt, syscall.SIGTERM)
|
||||||
for {
|
for {
|
||||||
@ -177,6 +206,10 @@ func startMonitorShutdownSignal(onExitFn onExitFunc) error {
|
|||||||
for _, callback := range globalShutdownCBs.GetObjectLayerCBs() {
|
for _, callback := range globalShutdownCBs.GetObjectLayerCBs() {
|
||||||
exitCode := callback()
|
exitCode := callback()
|
||||||
if exitCode != exitSuccess {
|
if exitCode != exitSuccess {
|
||||||
|
// If global profiler is set stop before we exit.
|
||||||
|
if globalProfiler != nil {
|
||||||
|
globalProfiler.Stop()
|
||||||
|
}
|
||||||
onExitFn(int(exitCode))
|
onExitFn(int(exitCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +218,10 @@ func startMonitorShutdownSignal(onExitFn onExitFunc) error {
|
|||||||
for _, callback := range globalShutdownCBs.GetGenericCBs() {
|
for _, callback := range globalShutdownCBs.GetGenericCBs() {
|
||||||
exitCode := callback()
|
exitCode := callback()
|
||||||
if exitCode != exitSuccess {
|
if exitCode != exitSuccess {
|
||||||
|
// If global profiler is set stop before we exit.
|
||||||
|
if globalProfiler != nil {
|
||||||
|
globalProfiler.Stop()
|
||||||
|
}
|
||||||
onExitFn(int(exitCode))
|
onExitFn(int(exitCode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,14 +238,18 @@ func startMonitorShutdownSignal(onExitFn onExitFunc) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(errors.New("Unable to reboot."), err.Error())
|
errorIf(errors.New("Unable to reboot."), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If global profiler is set stop before we exit.
|
||||||
|
if globalProfiler != nil {
|
||||||
|
globalProfiler.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
// Successfully forked.
|
// Successfully forked.
|
||||||
onExitFn(int(exitSuccess))
|
onExitFn(int(exitSuccess))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable profiler if ``MINIO_PROFILER`` is set.
|
// If global profiler is set stop before we exit.
|
||||||
switch os.Getenv("MINIO_PROFILER") {
|
if globalProfiler != nil {
|
||||||
case "cpu", "mem", "block":
|
|
||||||
// Stop any running profiler.
|
|
||||||
globalProfiler.Stop()
|
globalProfiler.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user