debug.go 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package metrics
  2. import (
  3. "runtime/debug"
  4. "sync"
  5. "time"
  6. )
  7. var (
  8. debugMetrics struct {
  9. GCStats struct {
  10. LastGC Gauge
  11. NumGC Gauge
  12. Pause Histogram
  13. //PauseQuantiles Histogram
  14. PauseTotal Gauge
  15. }
  16. ReadGCStats Timer
  17. }
  18. gcStats debug.GCStats
  19. registerDebugMetricsOnce = sync.Once{}
  20. )
  21. // Capture new values for the Go garbage collector statistics exported in
  22. // debug.GCStats. This is designed to be called as a goroutine.
  23. func CaptureDebugGCStats(r Registry, d time.Duration) {
  24. for _ = range time.Tick(d) {
  25. CaptureDebugGCStatsOnce(r)
  26. }
  27. }
  28. // Capture new values for the Go garbage collector statistics exported in
  29. // debug.GCStats. This is designed to be called in a background goroutine.
  30. // Giving a registry which has not been given to RegisterDebugGCStats will
  31. // panic.
  32. //
  33. // Be careful (but much less so) with this because debug.ReadGCStats calls
  34. // the C function runtime·lock(runtime·mheap) which, while not a stop-the-world
  35. // operation, isn't something you want to be doing all the time.
  36. func CaptureDebugGCStatsOnce(r Registry) {
  37. lastGC := gcStats.LastGC
  38. t := time.Now()
  39. debug.ReadGCStats(&gcStats)
  40. debugMetrics.ReadGCStats.UpdateSince(t)
  41. debugMetrics.GCStats.LastGC.Update(int64(gcStats.LastGC.UnixNano()))
  42. debugMetrics.GCStats.NumGC.Update(int64(gcStats.NumGC))
  43. if lastGC != gcStats.LastGC && 0 < len(gcStats.Pause) {
  44. debugMetrics.GCStats.Pause.Update(int64(gcStats.Pause[0]))
  45. }
  46. //debugMetrics.GCStats.PauseQuantiles.Update(gcStats.PauseQuantiles)
  47. debugMetrics.GCStats.PauseTotal.Update(int64(gcStats.PauseTotal))
  48. }
  49. // Register metrics for the Go garbage collector statistics exported in
  50. // debug.GCStats. The metrics are named by their fully-qualified Go symbols,
  51. // i.e. debug.GCStats.PauseTotal.
  52. func RegisterDebugGCStats(r Registry) {
  53. registerDebugMetricsOnce.Do(func() {
  54. debugMetrics.GCStats.LastGC = NewGauge()
  55. debugMetrics.GCStats.NumGC = NewGauge()
  56. debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015))
  57. //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015))
  58. debugMetrics.GCStats.PauseTotal = NewGauge()
  59. debugMetrics.ReadGCStats = NewTimer()
  60. r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC)
  61. r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC)
  62. r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause)
  63. //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles)
  64. r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal)
  65. r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats)
  66. })
  67. }
  68. // Allocate an initial slice for gcStats.Pause to avoid allocations during
  69. // normal operation.
  70. func init() {
  71. gcStats.Pause = make([]time.Duration, 11)
  72. }