mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Profiling: Enhance configuration and docs (#90048)
Co-authored-by: Dave Henderson <dave.henderson@grafana.com>
This commit is contained in:
committed by
GitHub
parent
8a6e92c0c9
commit
fc8a5cf468
@@ -77,7 +77,7 @@ func RunServer(opts ServerOptions) error {
|
||||
}
|
||||
}()
|
||||
|
||||
if err := setupProfiling(Profile, ProfileAddr, ProfilePort); err != nil {
|
||||
if err := setupProfiling(Profile, ProfileAddr, ProfilePort, ProfileBlockRate, ProfileMutexFraction); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := setupTracing(Tracing, TracingFile, logger); err != nil {
|
||||
|
||||
@@ -12,24 +12,30 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
profilingEnabledEnvName = "GF_DIAGNOSTICS_PROFILING_ENABLED"
|
||||
profilingAddrEnvName = "GF_DIAGNOSTICS_PROFILING_ADDR"
|
||||
profilingPortEnvName = "GF_DIAGNOSTICS_PROFILING_PORT"
|
||||
tracingEnabledEnvName = "GF_DIAGNOSTICS_TRACING_ENABLED"
|
||||
tracingFileEnvName = "GF_DIAGNOSTICS_TRACING_FILE"
|
||||
profilingEnabledEnvName = "GF_DIAGNOSTICS_PROFILING_ENABLED"
|
||||
profilingAddrEnvName = "GF_DIAGNOSTICS_PROFILING_ADDR"
|
||||
profilingPortEnvName = "GF_DIAGNOSTICS_PROFILING_PORT"
|
||||
profilingBlockRateEnvName = "GF_DIAGNOSTICS_PROFILING_BLOCK_RATE"
|
||||
profilingMutexRateEnvName = "GF_DIAGNOSTICS_PROFILING_MUTEX_RATE"
|
||||
tracingEnabledEnvName = "GF_DIAGNOSTICS_TRACING_ENABLED"
|
||||
tracingFileEnvName = "GF_DIAGNOSTICS_TRACING_FILE"
|
||||
)
|
||||
|
||||
type profilingDiagnostics struct {
|
||||
enabled bool
|
||||
addr string
|
||||
port uint64
|
||||
enabled bool
|
||||
addr string
|
||||
port uint64
|
||||
blockRate int
|
||||
mutexRate int
|
||||
}
|
||||
|
||||
func newProfilingDiagnostics(enabled bool, addr string, port uint64) *profilingDiagnostics {
|
||||
func newProfilingDiagnostics(enabled bool, addr string, port uint64, blockRate int, mutexRate int) *profilingDiagnostics {
|
||||
return &profilingDiagnostics{
|
||||
enabled: enabled,
|
||||
addr: addr,
|
||||
port: port,
|
||||
enabled: enabled,
|
||||
addr: addr,
|
||||
port: port,
|
||||
blockRate: blockRate,
|
||||
mutexRate: mutexRate,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +63,24 @@ func (pd *profilingDiagnostics) overrideWithEnv() error {
|
||||
pd.port = port
|
||||
}
|
||||
|
||||
blockRateEnv := os.Getenv(profilingBlockRateEnvName)
|
||||
if blockRateEnv != "" {
|
||||
blockRate, err := strconv.Atoi(blockRateEnv)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse %s environment variable as int", profilingBlockRateEnvName)
|
||||
}
|
||||
pd.blockRate = blockRate
|
||||
}
|
||||
|
||||
mutexFractionEnv := os.Getenv(profilingMutexRateEnvName)
|
||||
if mutexFractionEnv != "" {
|
||||
mutexProfileFraction, err := strconv.Atoi(mutexFractionEnv)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse %s environment variable as int", profilingMutexRateEnvName)
|
||||
}
|
||||
pd.mutexRate = mutexProfileFraction
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -90,15 +114,17 @@ func (td *tracingDiagnostics) overrideWithEnv() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupProfiling(profile bool, profileAddr string, profilePort uint64) error {
|
||||
profileDiagnostics := newProfilingDiagnostics(profile, profileAddr, profilePort)
|
||||
func setupProfiling(profile bool, profileAddr string, profilePort uint64, blockRate int, mutexFraction int) error {
|
||||
profileDiagnostics := newProfilingDiagnostics(profile, profileAddr, profilePort, blockRate, mutexFraction)
|
||||
if err := profileDiagnostics.overrideWithEnv(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if profileDiagnostics.enabled {
|
||||
fmt.Println("diagnostics: pprof profiling enabled", "addr", profileDiagnostics.addr, "port", profileDiagnostics.port)
|
||||
runtime.SetBlockProfileRate(1)
|
||||
fmt.Println("diagnostics: pprof profiling enabled", "addr", profileDiagnostics.addr, "port", profileDiagnostics.port, "blockProfileRate", profileDiagnostics.blockRate, "mutexProfileRate", profileDiagnostics.mutexRate)
|
||||
runtime.SetBlockProfileRate(profileDiagnostics.blockRate)
|
||||
runtime.SetMutexProfileFraction(profileDiagnostics.mutexRate)
|
||||
|
||||
go func() {
|
||||
// TODO: We should enable the linter and fix G114 here.
|
||||
// G114: Use of net/http serve function that has no support for setting timeouts (gosec)
|
||||
|
||||
@@ -9,17 +9,21 @@ import (
|
||||
|
||||
func TestProfilingDiagnostics(t *testing.T) {
|
||||
tcs := []struct {
|
||||
defaults *profilingDiagnostics
|
||||
enabledEnv string
|
||||
addrEnv string
|
||||
portEnv string
|
||||
expected *profilingDiagnostics
|
||||
defaults *profilingDiagnostics
|
||||
enabledEnv string
|
||||
addrEnv string
|
||||
portEnv string
|
||||
blockRateEnv string
|
||||
mutexRateEnv string
|
||||
expected *profilingDiagnostics
|
||||
}{
|
||||
{defaults: newProfilingDiagnostics(false, "localhost", 6060), enabledEnv: "", addrEnv: "", portEnv: "", expected: newProfilingDiagnostics(false, "localhost", 6060)},
|
||||
{defaults: newProfilingDiagnostics(true, "0.0.0.0", 8080), enabledEnv: "", addrEnv: "", portEnv: "", expected: newProfilingDiagnostics(true, "0.0.0.0", 8080)},
|
||||
{defaults: newProfilingDiagnostics(false, "", 6060), enabledEnv: "false", addrEnv: "", portEnv: "8080", expected: newProfilingDiagnostics(false, "", 8080)},
|
||||
{defaults: newProfilingDiagnostics(false, "localhost", 6060), enabledEnv: "true", addrEnv: "0.0.0.0", portEnv: "8080", expected: newProfilingDiagnostics(true, "0.0.0.0", 8080)},
|
||||
{defaults: newProfilingDiagnostics(false, "127.0.0.1", 6060), enabledEnv: "true", addrEnv: "", portEnv: "", expected: newProfilingDiagnostics(true, "127.0.0.1", 6060)},
|
||||
{defaults: newProfilingDiagnostics(false, "localhost", 6060, 0, 0), enabledEnv: "", addrEnv: "", portEnv: "", expected: newProfilingDiagnostics(false, "localhost", 6060, 0, 0)},
|
||||
{defaults: newProfilingDiagnostics(true, "0.0.0.0", 8080, 0, 0), enabledEnv: "", addrEnv: "", portEnv: "", expected: newProfilingDiagnostics(true, "0.0.0.0", 8080, 0, 0)},
|
||||
{defaults: newProfilingDiagnostics(false, "", 6060, 0, 0), enabledEnv: "false", addrEnv: "", portEnv: "8080", expected: newProfilingDiagnostics(false, "", 8080, 0, 0)},
|
||||
{defaults: newProfilingDiagnostics(false, "localhost", 6060, 0, 0), enabledEnv: "true", addrEnv: "0.0.0.0", portEnv: "8080", expected: newProfilingDiagnostics(true, "0.0.0.0", 8080, 0, 0)},
|
||||
{defaults: newProfilingDiagnostics(false, "127.0.0.1", 6060, 0, 0), enabledEnv: "true", addrEnv: "", portEnv: "", expected: newProfilingDiagnostics(true, "127.0.0.1", 6060, 0, 0)},
|
||||
{defaults: newProfilingDiagnostics(true, "localhost", 6060, 0, 0), enabledEnv: "", addrEnv: "", portEnv: "", blockRateEnv: "3", mutexRateEnv: "4", expected: newProfilingDiagnostics(true, "localhost", 6060, 3, 4)},
|
||||
{defaults: newProfilingDiagnostics(true, "localhost", 6060, 0, 0), enabledEnv: "", addrEnv: "", portEnv: "", expected: newProfilingDiagnostics(true, "localhost", 6060, 0, 0)},
|
||||
}
|
||||
|
||||
for i, tc := range tcs {
|
||||
@@ -33,6 +37,12 @@ func TestProfilingDiagnostics(t *testing.T) {
|
||||
if tc.portEnv != "" {
|
||||
t.Setenv(profilingPortEnvName, tc.portEnv)
|
||||
}
|
||||
if tc.blockRateEnv != "" {
|
||||
t.Setenv(profilingBlockRateEnvName, tc.blockRateEnv)
|
||||
}
|
||||
if tc.mutexRateEnv != "" {
|
||||
t.Setenv(profilingMutexRateEnvName, tc.mutexRateEnv)
|
||||
}
|
||||
err := tc.defaults.overrideWithEnv()
|
||||
assert.NoError(t, err)
|
||||
assert.Exactly(t, tc.expected, tc.defaults)
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
package commands
|
||||
|
||||
import "github.com/urfave/cli/v2"
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// flags for the grafana server command(s)
|
||||
var (
|
||||
ConfigFile string
|
||||
HomePath string
|
||||
PidFile string
|
||||
Packaging string
|
||||
ConfigOverrides string
|
||||
Version bool
|
||||
VerboseVersion bool
|
||||
Profile bool
|
||||
ProfileAddr string
|
||||
ProfilePort uint64
|
||||
Tracing bool
|
||||
TracingFile string
|
||||
ConfigFile string
|
||||
HomePath string
|
||||
PidFile string
|
||||
Packaging string
|
||||
ConfigOverrides string
|
||||
Version bool
|
||||
VerboseVersion bool
|
||||
Profile bool
|
||||
ProfileAddr string
|
||||
ProfilePort uint64
|
||||
ProfileBlockRate int
|
||||
ProfileMutexFraction int
|
||||
ProfileContention bool
|
||||
Tracing bool
|
||||
TracingFile string
|
||||
)
|
||||
|
||||
var commonFlags = []cli.Flag{
|
||||
@@ -75,6 +82,18 @@ var commonFlags = []cli.Flag{
|
||||
Usage: "Define custom port for profiling",
|
||||
Destination: &ProfilePort,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "profile-block-rate",
|
||||
Value: 1,
|
||||
Usage: "Controls the fraction of goroutine blocking events that are reported in the blocking profile. The profiler aims to sample an average of one blocking event per rate nanoseconds spent blocked. To turn off profiling entirely, use 0",
|
||||
Destination: &ProfileBlockRate,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "profile-mutex-rate",
|
||||
Value: runtime.SetMutexProfileFraction(-1),
|
||||
Usage: "Controls the fraction of mutex contention events that are reported in the mutex profile. On average 1/rate events are reported. To turn off mutex profiling entirely, use 0",
|
||||
Destination: &ProfileMutexFraction,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "tracing",
|
||||
Value: false,
|
||||
|
||||
@@ -54,7 +54,7 @@ func RunTargetServer(opts ServerOptions) error {
|
||||
}
|
||||
}()
|
||||
|
||||
if err := setupProfiling(Profile, ProfileAddr, ProfilePort); err != nil {
|
||||
if err := setupProfiling(Profile, ProfileAddr, ProfilePort, ProfileBlockRate, ProfileMutexFraction); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := setupTracing(Tracing, TracingFile, logger); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user