2015-06-22 04:00:55 -05:00
|
|
|
package metrics
|
|
|
|
|
|
|
|
import (
|
|
|
|
"runtime/debug"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
debugMetrics struct {
|
|
|
|
GCStats struct {
|
metrics, cmd/geth: change init-process of metrics (#30814)
This PR modifies how the metrics library handles `Enabled`: previously,
the package `init` decided whether to serve real metrics or just
dummy-types.
This has several drawbacks:
- During pkg init, we need to determine whether metrics are enabled or
not. So we first hacked in a check if certain geth-specific
commandline-flags were enabled. Then we added a similar check for
geth-env-vars. Then we almost added a very elaborate check for
toml-config-file, plus toml parsing.
- Using "real" types and dummy types interchangeably means that
everything is hidden behind interfaces. This has a performance penalty,
and also it just adds a lot of code.
This PR removes the interface stuff, uses concrete types, and allows for
the setting of Enabled to happen later. It is still assumed that
`metrics.Enable()` is invoked early on.
The somewhat 'heavy' operations, such as ticking meters and exp-decay,
now checks the enable-flag to prevent resource leak.
The change may be large, but it's mostly pretty trivial, and from the
last time I gutted the metrics, I ensured that we have fairly good test
coverage.
---------
Co-authored-by: Felix Lange <fjl@twurst.com>
2024-12-10 06:27:29 -06:00
|
|
|
LastGC *Gauge
|
|
|
|
NumGC *Gauge
|
2015-06-22 04:00:55 -05:00
|
|
|
Pause Histogram
|
|
|
|
//PauseQuantiles Histogram
|
metrics, cmd/geth: change init-process of metrics (#30814)
This PR modifies how the metrics library handles `Enabled`: previously,
the package `init` decided whether to serve real metrics or just
dummy-types.
This has several drawbacks:
- During pkg init, we need to determine whether metrics are enabled or
not. So we first hacked in a check if certain geth-specific
commandline-flags were enabled. Then we added a similar check for
geth-env-vars. Then we almost added a very elaborate check for
toml-config-file, plus toml parsing.
- Using "real" types and dummy types interchangeably means that
everything is hidden behind interfaces. This has a performance penalty,
and also it just adds a lot of code.
This PR removes the interface stuff, uses concrete types, and allows for
the setting of Enabled to happen later. It is still assumed that
`metrics.Enable()` is invoked early on.
The somewhat 'heavy' operations, such as ticking meters and exp-decay,
now checks the enable-flag to prevent resource leak.
The change may be large, but it's mostly pretty trivial, and from the
last time I gutted the metrics, I ensured that we have fairly good test
coverage.
---------
Co-authored-by: Felix Lange <fjl@twurst.com>
2024-12-10 06:27:29 -06:00
|
|
|
PauseTotal *Gauge
|
2015-06-22 04:00:55 -05:00
|
|
|
}
|
metrics, cmd/geth: change init-process of metrics (#30814)
This PR modifies how the metrics library handles `Enabled`: previously,
the package `init` decided whether to serve real metrics or just
dummy-types.
This has several drawbacks:
- During pkg init, we need to determine whether metrics are enabled or
not. So we first hacked in a check if certain geth-specific
commandline-flags were enabled. Then we added a similar check for
geth-env-vars. Then we almost added a very elaborate check for
toml-config-file, plus toml parsing.
- Using "real" types and dummy types interchangeably means that
everything is hidden behind interfaces. This has a performance penalty,
and also it just adds a lot of code.
This PR removes the interface stuff, uses concrete types, and allows for
the setting of Enabled to happen later. It is still assumed that
`metrics.Enable()` is invoked early on.
The somewhat 'heavy' operations, such as ticking meters and exp-decay,
now checks the enable-flag to prevent resource leak.
The change may be large, but it's mostly pretty trivial, and from the
last time I gutted the metrics, I ensured that we have fairly good test
coverage.
---------
Co-authored-by: Felix Lange <fjl@twurst.com>
2024-12-10 06:27:29 -06:00
|
|
|
ReadGCStats *Timer
|
2015-06-22 04:00:55 -05:00
|
|
|
}
|
|
|
|
gcStats debug.GCStats
|
|
|
|
)
|
|
|
|
|
2024-05-27 01:34:53 -05:00
|
|
|
// CaptureDebugGCStats captures new values for the Go garbage collector statistics
|
|
|
|
// exported in debug.GCStats. This is designed to be called as a goroutine.
|
2015-06-22 04:00:55 -05:00
|
|
|
func CaptureDebugGCStats(r Registry, d time.Duration) {
|
2018-02-23 03:56:08 -06:00
|
|
|
for range time.Tick(d) {
|
2015-06-22 04:00:55 -05:00
|
|
|
CaptureDebugGCStatsOnce(r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-27 01:34:53 -05:00
|
|
|
// CaptureDebugGCStatsOnce captures new values for the Go garbage collector
|
|
|
|
// statistics exported in debug.GCStats. This is designed to be called in
|
|
|
|
// a background goroutine. Giving a registry which has not been given to
|
|
|
|
// RegisterDebugGCStats will panic.
|
2015-06-22 04:00:55 -05:00
|
|
|
//
|
|
|
|
// Be careful (but much less so) with this because debug.ReadGCStats calls
|
|
|
|
// the C function runtime·lock(runtime·mheap) which, while not a stop-the-world
|
|
|
|
// operation, isn't something you want to be doing all the time.
|
|
|
|
func CaptureDebugGCStatsOnce(r Registry) {
|
|
|
|
lastGC := gcStats.LastGC
|
|
|
|
t := time.Now()
|
|
|
|
debug.ReadGCStats(&gcStats)
|
|
|
|
debugMetrics.ReadGCStats.UpdateSince(t)
|
|
|
|
|
2018-02-23 03:56:08 -06:00
|
|
|
debugMetrics.GCStats.LastGC.Update(gcStats.LastGC.UnixNano())
|
|
|
|
debugMetrics.GCStats.NumGC.Update(gcStats.NumGC)
|
2015-06-22 04:00:55 -05:00
|
|
|
if lastGC != gcStats.LastGC && 0 < len(gcStats.Pause) {
|
|
|
|
debugMetrics.GCStats.Pause.Update(int64(gcStats.Pause[0]))
|
|
|
|
}
|
|
|
|
//debugMetrics.GCStats.PauseQuantiles.Update(gcStats.PauseQuantiles)
|
|
|
|
debugMetrics.GCStats.PauseTotal.Update(int64(gcStats.PauseTotal))
|
|
|
|
}
|
|
|
|
|
2024-05-27 01:34:53 -05:00
|
|
|
// RegisterDebugGCStats registers metrics for the Go garbage collector statistics
|
|
|
|
// exported in debug.GCStats. The metrics are named by their fully-qualified Go
|
|
|
|
// symbols, i.e. debug.GCStats.PauseTotal.
|
2015-06-22 04:00:55 -05:00
|
|
|
func RegisterDebugGCStats(r Registry) {
|
|
|
|
debugMetrics.GCStats.LastGC = NewGauge()
|
|
|
|
debugMetrics.GCStats.NumGC = NewGauge()
|
|
|
|
debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015))
|
|
|
|
//debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015))
|
|
|
|
debugMetrics.GCStats.PauseTotal = NewGauge()
|
|
|
|
debugMetrics.ReadGCStats = NewTimer()
|
|
|
|
|
|
|
|
r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC)
|
|
|
|
r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC)
|
|
|
|
r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause)
|
|
|
|
//r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles)
|
|
|
|
r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal)
|
|
|
|
r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate an initial slice for gcStats.Pause to avoid allocations during
|
|
|
|
// normal operation.
|
|
|
|
func init() {
|
|
|
|
gcStats.Pause = make([]time.Duration, 11)
|
|
|
|
}
|