Pull request 1947: AG-24320 home: pprof conf
Squashed commit of the following:
commit bc0facffe41e140fab00edeeeca3b69306cf2ceb
Merge: 71e0806ba c0691cab6
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date: Wed Aug 2 17:34:15 2023 +0300
Merge branch 'master' into pprof-conf
commit 71e0806bac52412cae7cad2748216ece7fbed36f
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date: Wed Aug 2 08:37:51 2023 +0300
all: docs
commit 6ebb6f9a5f4dbeb753dd470879f2e5ff556ee5f1
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date: Tue Aug 1 15:56:45 2023 +0300
home: imp code
commit ca084011cddc20f5c0b770ee38f9ac55d62bff24
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date: Tue Aug 1 13:57:53 2023 +0300
all: docs
commit 1b498a84d6cb8207d350fceb4db64d45dc2aa46d
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date: Tue Aug 1 13:46:13 2023 +0300
all: docs
commit 0cd76c057e0f3e9e62e5bf38f95080afa830f4ff
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date: Tue Aug 1 13:00:43 2023 +0300
home: pprof conf
This commit is contained in:
parent
c0691cab6a
commit
5eb3cd0f92
30
CHANGELOG.md
30
CHANGELOG.md
|
@ -23,6 +23,36 @@ See also the [v0.107.37 GitHub milestone][ms-v0.107.37].
|
||||||
NOTE: Add new changes BELOW THIS COMMENT.
|
NOTE: Add new changes BELOW THIS COMMENT.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- The ability to set the port for the `pprof` debug API, see configuration
|
||||||
|
changes below.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
#### Configuration Changes
|
||||||
|
|
||||||
|
In this release, the schema version has changed from 24 to 25.
|
||||||
|
|
||||||
|
- Property `debug_pprof` which used to setup profiling HTTP handler, is now
|
||||||
|
moved to the new `pprof` object under `http` section. The new object contains
|
||||||
|
properties `enabled` and `port`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# BEFORE:
|
||||||
|
'debug_pprof': true
|
||||||
|
|
||||||
|
# AFTER:
|
||||||
|
'http':
|
||||||
|
'pprof':
|
||||||
|
'enabled': true
|
||||||
|
'port': 6060
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the new default `6060` is used as default. To rollback this change,
|
||||||
|
remove the new object `pprof`, set back `debug_pprof`, and change the
|
||||||
|
`schema_version` back to `24`.
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
NOTE: Add new changes ABOVE THIS COMMENT.
|
NOTE: Add new changes ABOVE THIS COMMENT.
|
||||||
-->
|
-->
|
||||||
|
|
|
@ -114,8 +114,6 @@ type configuration struct {
|
||||||
Language string `yaml:"language"`
|
Language string `yaml:"language"`
|
||||||
// Theme is a UI theme for current user.
|
// Theme is a UI theme for current user.
|
||||||
Theme Theme `yaml:"theme"`
|
Theme Theme `yaml:"theme"`
|
||||||
// DebugPProf defines if the profiling HTTP handler will listen on :6060.
|
|
||||||
DebugPProf bool `yaml:"debug_pprof"`
|
|
||||||
|
|
||||||
DNS dnsConfig `yaml:"dns"`
|
DNS dnsConfig `yaml:"dns"`
|
||||||
TLS tlsConfigSettings `yaml:"tls"`
|
TLS tlsConfigSettings `yaml:"tls"`
|
||||||
|
@ -155,6 +153,9 @@ type configuration struct {
|
||||||
// Field ordering is important, YAML fields better not to be reordered, if it's
|
// Field ordering is important, YAML fields better not to be reordered, if it's
|
||||||
// not absolutely necessary.
|
// not absolutely necessary.
|
||||||
type httpConfig struct {
|
type httpConfig struct {
|
||||||
|
// Pprof defines the profiling HTTP handler.
|
||||||
|
Pprof *httpPprofConfig `yaml:"pprof"`
|
||||||
|
|
||||||
// Address is the address to serve the web UI on.
|
// Address is the address to serve the web UI on.
|
||||||
Address netip.AddrPort
|
Address netip.AddrPort
|
||||||
|
|
||||||
|
@ -163,6 +164,15 @@ type httpConfig struct {
|
||||||
SessionTTL timeutil.Duration `yaml:"session_ttl"`
|
SessionTTL timeutil.Duration `yaml:"session_ttl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// httpPprofConfig is the block with pprof HTTP configuration.
|
||||||
|
type httpPprofConfig struct {
|
||||||
|
// Port for the profiling handler.
|
||||||
|
Port uint16 `yaml:"port"`
|
||||||
|
|
||||||
|
// Enabled defines if the profiling handler is enabled.
|
||||||
|
Enabled bool `yaml:"enabled"`
|
||||||
|
}
|
||||||
|
|
||||||
// dnsConfig is a block with DNS configuration params.
|
// dnsConfig is a block with DNS configuration params.
|
||||||
//
|
//
|
||||||
// Field ordering is important, YAML fields better not to be reordered, if it's
|
// Field ordering is important, YAML fields better not to be reordered, if it's
|
||||||
|
@ -277,6 +287,10 @@ var config = &configuration{
|
||||||
HTTPConfig: httpConfig{
|
HTTPConfig: httpConfig{
|
||||||
Address: netip.AddrPortFrom(netip.IPv4Unspecified(), 3000),
|
Address: netip.AddrPortFrom(netip.IPv4Unspecified(), 3000),
|
||||||
SessionTTL: timeutil.Duration{Duration: 30 * timeutil.Day},
|
SessionTTL: timeutil.Duration{Duration: 30 * timeutil.Day},
|
||||||
|
Pprof: &httpPprofConfig{
|
||||||
|
Enabled: false,
|
||||||
|
Port: 6060,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
DNS: dnsConfig{
|
DNS: dnsConfig{
|
||||||
BindHosts: []netip.Addr{netip.IPv4Unspecified()},
|
BindHosts: []netip.Addr{netip.IPv4Unspecified()},
|
||||||
|
|
|
@ -567,9 +567,8 @@ func run(opts options, clientBuildFS fs.FS) {
|
||||||
err = config.write()
|
err = config.write()
|
||||||
fatalOnError(err)
|
fatalOnError(err)
|
||||||
|
|
||||||
if config.DebugPProf {
|
if config.HTTPConfig.Pprof.Enabled {
|
||||||
// TODO(a.garipov): Make the address configurable.
|
startPprof(config.HTTPConfig.Pprof.Port)
|
||||||
startPprof("localhost:6060")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// currentSchemaVersion is the current schema version.
|
// currentSchemaVersion is the current schema version.
|
||||||
const currentSchemaVersion = 24
|
const currentSchemaVersion = 25
|
||||||
|
|
||||||
// These aliases are provided for convenience.
|
// These aliases are provided for convenience.
|
||||||
type (
|
type (
|
||||||
|
@ -99,6 +99,7 @@ func upgradeConfigSchema(oldVersion int, diskConf yobj) (err error) {
|
||||||
upgradeSchema21to22,
|
upgradeSchema21to22,
|
||||||
upgradeSchema22to23,
|
upgradeSchema22to23,
|
||||||
upgradeSchema23to24,
|
upgradeSchema23to24,
|
||||||
|
upgradeSchema24to25,
|
||||||
}
|
}
|
||||||
|
|
||||||
n := 0
|
n := 0
|
||||||
|
@ -1380,6 +1381,50 @@ func upgradeSchema23to24(diskConf yobj) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// upgradeSchema24to25 performs the following changes:
|
||||||
|
//
|
||||||
|
// # BEFORE:
|
||||||
|
// 'debug_pprof': true
|
||||||
|
//
|
||||||
|
// # AFTER:
|
||||||
|
// 'http':
|
||||||
|
// 'pprof':
|
||||||
|
// 'enabled': true
|
||||||
|
// 'port': 6060
|
||||||
|
func upgradeSchema24to25(diskConf yobj) (err error) {
|
||||||
|
log.Printf("Upgrade yaml: 24 to 25")
|
||||||
|
diskConf["schema_version"] = 25
|
||||||
|
|
||||||
|
debugPprofVal, ok := diskConf["debug_pprof"]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPprofEnabled, ok := debugPprofVal.(bool)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unexpected type of debug_pprof: %T", debugPprofVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
httpVal, ok := diskConf["http"]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
httpObj, ok := httpVal.(yobj)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unexpected type of dns: %T", httpVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
httpObj["pprof"] = yobj{
|
||||||
|
"enabled": debugPprofEnabled,
|
||||||
|
"port": 6060,
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(diskConf, "debug_pprof")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// moveField gets field value for key from diskConf, and then set this value
|
// moveField gets field value for key from diskConf, and then set this value
|
||||||
// in newConf for newKey.
|
// in newConf for newKey.
|
||||||
func moveField[T any](diskConf, newConf yobj, key, newKey string) (err error) {
|
func moveField[T any](diskConf, newConf yobj, key, newKey string) (err error) {
|
||||||
|
|
|
@ -1379,3 +1379,90 @@ func TestUpgradeSchema23to24(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpgradeSchema24to25(t *testing.T) {
|
||||||
|
const newSchemaVer = 25
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
in yobj
|
||||||
|
want yobj
|
||||||
|
name string
|
||||||
|
wantErrMsg string
|
||||||
|
}{{
|
||||||
|
name: "empty",
|
||||||
|
in: yobj{},
|
||||||
|
want: yobj{
|
||||||
|
"schema_version": newSchemaVer,
|
||||||
|
},
|
||||||
|
wantErrMsg: "",
|
||||||
|
}, {
|
||||||
|
name: "ok",
|
||||||
|
in: yobj{
|
||||||
|
"http": yobj{
|
||||||
|
"address": "0.0.0.0:3000",
|
||||||
|
"session_ttl": "720h",
|
||||||
|
},
|
||||||
|
"debug_pprof": true,
|
||||||
|
},
|
||||||
|
want: yobj{
|
||||||
|
"http": yobj{
|
||||||
|
"address": "0.0.0.0:3000",
|
||||||
|
"session_ttl": "720h",
|
||||||
|
"pprof": yobj{
|
||||||
|
"enabled": true,
|
||||||
|
"port": 6060,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"schema_version": newSchemaVer,
|
||||||
|
},
|
||||||
|
wantErrMsg: "",
|
||||||
|
}, {
|
||||||
|
name: "ok_disabled",
|
||||||
|
in: yobj{
|
||||||
|
"http": yobj{
|
||||||
|
"address": "0.0.0.0:3000",
|
||||||
|
"session_ttl": "720h",
|
||||||
|
},
|
||||||
|
"debug_pprof": false,
|
||||||
|
},
|
||||||
|
want: yobj{
|
||||||
|
"http": yobj{
|
||||||
|
"address": "0.0.0.0:3000",
|
||||||
|
"session_ttl": "720h",
|
||||||
|
"pprof": yobj{
|
||||||
|
"enabled": false,
|
||||||
|
"port": 6060,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"schema_version": newSchemaVer,
|
||||||
|
},
|
||||||
|
wantErrMsg: "",
|
||||||
|
}, {
|
||||||
|
name: "invalid",
|
||||||
|
in: yobj{
|
||||||
|
"http": yobj{
|
||||||
|
"address": "0.0.0.0:3000",
|
||||||
|
"session_ttl": "720h",
|
||||||
|
},
|
||||||
|
"debug_pprof": 1,
|
||||||
|
},
|
||||||
|
want: yobj{
|
||||||
|
"http": yobj{
|
||||||
|
"address": "0.0.0.0:3000",
|
||||||
|
"session_ttl": "720h",
|
||||||
|
},
|
||||||
|
"debug_pprof": 1,
|
||||||
|
"schema_version": newSchemaVer,
|
||||||
|
},
|
||||||
|
wantErrMsg: "unexpected type of debug_pprof: int",
|
||||||
|
}}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
err := upgradeSchema24to25(tc.in)
|
||||||
|
testutil.AssertErrorMsg(t, tc.wantErrMsg, err)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.want, tc.in)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -312,8 +312,10 @@ func (web *webAPI) mustStartHTTP3(address string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// startPprof launches the debug and profiling server on addr.
|
// startPprof launches the debug and profiling server on the provided port.
|
||||||
func startPprof(addr string) {
|
func startPprof(port uint16) {
|
||||||
|
addr := netip.AddrPortFrom(netutil.IPv4Localhost(), port)
|
||||||
|
|
||||||
runtime.SetBlockProfileRate(1)
|
runtime.SetBlockProfileRate(1)
|
||||||
runtime.SetMutexProfileFraction(1)
|
runtime.SetMutexProfileFraction(1)
|
||||||
|
|
||||||
|
@ -324,7 +326,7 @@ func startPprof(addr string) {
|
||||||
defer log.OnPanic("pprof server")
|
defer log.OnPanic("pprof server")
|
||||||
|
|
||||||
log.Info("pprof: listening on %q", addr)
|
log.Info("pprof: listening on %q", addr)
|
||||||
err := http.ListenAndServe(addr, mux)
|
err := http.ListenAndServe(addr.String(), mux)
|
||||||
if !errors.Is(err, http.ErrServerClosed) {
|
if !errors.Is(err, http.ErrServerClosed) {
|
||||||
log.Error("pprof: shutting down: %s", err)
|
log.Error("pprof: shutting down: %s", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue