From 55da69adaca5facd3adfa65be5976a4cc5409c7c Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Wed, 1 Feb 2023 10:21:17 +0300 Subject: [PATCH] [#22] node: Add optional linters Includes `block` and `mutex` profiles configuration. Signed-off-by: Pavel Karpy --- cmd/frostfs-node/config/profiler/config.go | 33 +++++++++++++++++++ .../config/profiler/config_test.go | 10 ++++++ cmd/frostfs-node/pprof.go | 14 ++++++++ config/example/node.env | 2 ++ config/example/node.json | 6 +++- config/example/node.yaml | 3 ++ docs/storage-node-configuration.md | 20 ++++++++--- 7 files changed, 82 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-node/config/profiler/config.go b/cmd/frostfs-node/config/profiler/config.go index 17aabaa80..8dfb793fc 100644 --- a/cmd/frostfs-node/config/profiler/config.go +++ b/cmd/frostfs-node/config/profiler/config.go @@ -1,6 +1,7 @@ package profilerconfig import ( + "runtime" "time" "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" @@ -51,3 +52,35 @@ func Address(c *config.Config) string { return AddressDefault } + +const profilesSubsection = "profiles" + +// Profiles returns structure that provides access to a "profiles" +// configuration subsection. +func Profiles(c *config.Config) ProfilesConfig { + runtime.SetBlockProfileRate() + runtime.SetMutexProfileFraction() + + return ProfilesConfig{ + c.Sub(subsection).Sub(profilesSubsection), + } +} + +// ProfilesConfig is a wrapper over "pprof.profiles" config section +// which provides access to the configuration of the specific +// profiles. +type ProfilesConfig struct { + cfg *config.Config +} + +// BlockRates returns the value of "block" config parameter +// from "pprof.profiles" section. +func (c ProfilesConfig) BlockRates() int { + return int(config.IntSafe(c.cfg, "block")) +} + +// MutexRate returns the value of "mutex" config parameter +// from "pprof.profiles" section. +func (c ProfilesConfig) MutexRate() int { + return int(config.IntSafe(c.cfg, "mutex")) +} diff --git a/cmd/frostfs-node/config/profiler/config_test.go b/cmd/frostfs-node/config/profiler/config_test.go index edb457bbb..11c3a5d5d 100644 --- a/cmd/frostfs-node/config/profiler/config_test.go +++ b/cmd/frostfs-node/config/profiler/config_test.go @@ -18,6 +18,11 @@ func TestProfilerSection(t *testing.T) { require.Equal(t, profilerconfig.ShutdownTimeoutDefault, to) require.Equal(t, profilerconfig.AddressDefault, addr) require.False(t, profilerconfig.Enabled(configtest.EmptyConfig())) + + pp := profilerconfig.Profiles(configtest.EmptyConfig()) + + require.Zero(t, pp.BlockRates()) + require.Zero(t, pp.MutexRate()) }) const path = "../../../../config/example/node" @@ -29,6 +34,11 @@ func TestProfilerSection(t *testing.T) { require.Equal(t, 15*time.Second, to) require.Equal(t, "localhost:6060", addr) require.True(t, profilerconfig.Enabled(c)) + + pp := profilerconfig.Profiles(c) + + require.Equal(t, int(1), pp.BlockRates()) + require.Equal(t, int(1), pp.MutexRate()) } configtest.ForEachFileType(path, fileConfigTest) diff --git a/cmd/frostfs-node/pprof.go b/cmd/frostfs-node/pprof.go index 73461879c..d66369aa9 100644 --- a/cmd/frostfs-node/pprof.go +++ b/cmd/frostfs-node/pprof.go @@ -2,6 +2,7 @@ package main import ( "context" + "runtime" profilerconfig "github.com/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/profiler" httputil "github.com/TrueCloudLab/frostfs-node/pkg/util/http" @@ -14,6 +15,19 @@ func initProfiler(c *cfg) { return } + profiles := profilerconfig.Profiles(c.appCfg) + blockRate := profiles.BlockRates() + mutexRate := profiles.MutexRate() + + if mutexRate == 0 { + // according to docs, setting mutex rate to "0" just + // returns current rate not disables it + mutexRate = -1 + } + + runtime.SetBlockProfileRate(blockRate) + runtime.SetMutexProfileFraction(mutexRate) + var prm httputil.Prm prm.Address = profilerconfig.Address(c.appCfg) diff --git a/config/example/node.env b/config/example/node.env index 4df2d35d0..1bbafa4b1 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -3,6 +3,8 @@ NEOFS_LOGGER_LEVEL=debug NEOFS_PPROF_ENABLED=true NEOFS_PPROF_ADDRESS=localhost:6060 NEOFS_PPROF_SHUTDOWN_TIMEOUT=15s +NEOFS_PPROF_PROFILES_BLOCK=1 +NEOFS_PPROF_PROFILES_MUTEX=1 NEOFS_PROMETHEUS_ENABLED=true NEOFS_PROMETHEUS_ADDRESS=localhost:9090 diff --git a/config/example/node.json b/config/example/node.json index e739b0572..18883124e 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -5,7 +5,11 @@ "pprof": { "enabled": true, "address": "localhost:6060", - "shutdown_timeout": "15s" + "shutdown_timeout": "15s", + "profiles": { + "block": 1, + "mutex": 1 + } }, "prometheus": { "enabled": true, diff --git a/config/example/node.yaml b/config/example/node.yaml index bf2f0a27b..6f5613793 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -5,6 +5,9 @@ pprof: enabled: true address: localhost:6060 # endpoint for Node profiling shutdown_timeout: 15s # timeout for profiling HTTP server graceful shutdown + profiles: + block: 1 # sampling rate: an average of one blocking event per rate nanoseconds spent blocked is reported; "1" reports every blocking event; "0" disables profiler + mutex: 1 # sampling rate: on average 1/rate events are reported; "0" disables profiler prometheus: enabled: true diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index c41aebc32..0fbee4593 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -75,13 +75,23 @@ element. Contains configuration for the `pprof` profiler. -| Parameter | Type | Default value | Description | -|--------------------|------------|---------------|-----------------------------------------| -| `enabled` | `bool` | `false` | Flag to enable the service. | -| `address` | `string` | | Address that service listener binds to. | -| `shutdown_timeout` | `duration` | `30s` | Time to wait for a graceful shutdown. | +| Parameter | Type | Default value | Description | +|--------------------|-----------------------------------------|---------------|-----------------------------------------| +| `enabled` | `bool` | `false` | Flag to enable the service. | +| `address` | `string` | | Address that service listener binds to. | +| `shutdown_timeout` | `duration` | `30s` | Time to wait for a graceful shutdown. | +| `profiles` | [Profiles config](#profiles-subsection) | | Optional profiles configuration | +## `profiles` subsection + +Contains optional profiles configuration. + +| Parameter | Type | Default value | Description | +|-----------|-------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `block` | `int` | `0` | 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. Non-positive values disable profiler reports. | +| `mutex` | `int` | `0` | Controls the fraction of mutex contention events that are reported in the mutex profile. On average 1/rate events are reported. The previous rate is returned. Non-positive values disable profiler reports. | + # `prometheus` section Contains configuration for the `prometheus` metrics service.