From 8a6e3ecf23ef7abb48095e5e9852643e6a036d81 Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Mon, 20 Jul 2015 20:55:38 -0700 Subject: [PATCH 01/10] adds general and heap memory statistics --- prometheus/go_collector.go | 154 +++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index 85fa20b..9990132 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -4,9 +4,12 @@ import ( "runtime" "runtime/debug" "time" + + "github.com/prometheus/client_golang/prometheus" ) type goCollector struct { + *memStatsCollector goroutines Gauge gcDesc *Desc } @@ -23,6 +26,7 @@ func NewGoCollector() *goCollector { "go_gc_duration_seconds", "A summary of the GC invocation durations.", nil, nil), + memStatsCollector: newMemStatsCollector(), } } @@ -48,3 +52,153 @@ func (c *goCollector) Collect(ch chan<- Metric) { quantiles[0.0] = stats.PauseQuantiles[0].Seconds() ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles) } + +// memStatsCollector collects runtime.MemStats +type memStatsCollector struct { + alloc prometheus.Gauge + totalAlloc prometheus.Gauge + sys prometheus.Gauge + lookups prometheus.Gauge + mallocs prometheus.Gauge + frees prometheus.Gauge + heapAlloc prometheus.Gauge + heapSys prometheus.Gauge + heapIdle prometheus.Gauge + heapInuse prometheus.Gauge + heapReleased prometheus.Gauge + heapObjects prometheus.Gauge +} + +// newMemStatsCollector creates a new runtime.MemStats collector +func newMemStatsCollector() *memStatsCollector { + return &MemStatsCollector{ + alloc: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "alloc_bytes", + Help: "bytes allocated and still in use", + }), + totalAlloc: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "alloc_bytes_total", + Help: "bytes allocated (even if freed)", + }), + sys: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "sys", + Help: "bytes obtained from system", + }), + lookups: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "lookups", + Help: "number of pointer lookups", + }), + mallocs: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "mallocs", + Help: "number of mallocs", + }), + frees: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "frees", + Help: "number of frees", + }), + heapAlloc: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_alloc", + Help: "bytes allocated and still in use", + }), + heapSys: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_sys", + Help: "bytes obtained from system", + }), + heapIdle: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_idle", + Help: "bytes in idle spans", + }), + heapInuse: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_inuse", + Help: "bytes in non-idle span", + }), + heapReleased: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_released", + Help: "bytes released to the OS", + }), + heapObjects: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_objects", + Help: "total number of allocated objects", + }), + } +} + +// Describe sends Desc objects for each memstat we intend to collect. +func (m *MemStatsCollector) Describe(ch chan<- *prometheus.Desc) { + if m == nil { + m = NewMemStatsCollector() + } + + ch <- m.alloc.Desc() + ch <- m.totalAlloc.Desc() + ch <- m.sys.Desc() + ch <- m.lookups.Desc() + ch <- m.mallocs.Desc() + ch <- m.frees.Desc() + ch <- m.heapAlloc.Desc() + ch <- m.heapSys.Desc() + ch <- m.heapIdle.Desc() + ch <- m.heapInuse.Desc() + ch <- m.heapReleased.Desc() + ch <- m.heapObjects.Desc() +} + +// Collect does the trick by calling ReadMemStats once and then constructing +// three different Metrics on the fly. +func (m *MemStatsCollector) Collect(ch chan<- prometheus.Metric) { + if m == nil { + m = NewMemStatsCollector() + } + + var ms runtime.MemStats + runtime.ReadMemStats(&ms) + + m.alloc.Set(float64(ms.Alloc)) + ch <- m.alloc + m.totalAlloc.Set(float64(ms.TotalAlloc)) + ch <- m.totalAlloc + m.sys.Set(float64(ms.Sys)) + ch <- m.sys + m.lookups.Set(float64(ms.Lookups)) + ch <- m.lookups + m.mallocs.Set(float64(ms.Mallocs)) + ch <- m.mallocs + m.frees.Set(float64(ms.Frees)) + ch <- m.frees + m.heapAlloc.Set(float64(ms.HeapAlloc)) + ch <- m.heapAlloc + m.heapSys.Set(float64(ms.HeapSys)) + ch <- m.heapSys + m.heapIdle.Set(float64(ms.HeapIdle)) + ch <- m.heapIdle + m.heapInuse.Set(float64(ms.HeapInuse)) + ch <- m.heapInuse + m.heapReleased.Set(float64(ms.HeapReleased)) + ch <- m.heapReleased + m.heapObjects.Set(float64(ms.HeapObjects)) + ch <- m.heapObjects +} From b14b1499309ddf31628116a10941f9eb4443a54c Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Tue, 21 Jul 2015 08:24:22 -0700 Subject: [PATCH 02/10] use counters where applicable, improve descriptions --- prometheus/go_collector.go | 224 ++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 126 deletions(-) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index 9990132..c513a39 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -9,9 +9,20 @@ import ( ) type goCollector struct { - *memStatsCollector - goroutines Gauge - gcDesc *Desc + goroutines Gauge + gcDesc *Desc + alloc prometheus.Gauge + totalAlloc prometheus.Gauge + sys prometheus.Gauge + lookups prometheus.Gauge + mallocs prometheus.Gauge + frees prometheus.Gauge + heapAlloc prometheus.Gauge + heapSys prometheus.Gauge + heapIdle prometheus.Gauge + heapInuse prometheus.Gauge + heapReleased prometheus.Gauge + heapObjects prometheus.Gauge } // NewGoCollector returns a collector which exports metrics about the current @@ -26,7 +37,78 @@ func NewGoCollector() *goCollector { "go_gc_duration_seconds", "A summary of the GC invocation durations.", nil, nil), - memStatsCollector: newMemStatsCollector(), + alloc: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "alloc_bytes", + Help: "Number of bytes allocated and still in use.", + }), + totalAlloc: prometheus.NewCounter(prometheus.CounterOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "alloc_bytes_total", + Help: "Total number of bytes allocated, even if freed.", + }), + sys: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "sys_bytes", + Help: "Number of bytes obtained from system", + }), + lookups: prometheus.NewCounter(prometheus.CounterOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "lookups_total", + Help: "Total number of pointer lookups.", + }), + mallocs: prometheus.NewCounter(prometheus.CounterOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "mallocs_total", + Help: "Total number of mallocs.", + }), + frees: prometheus.NewCounter(prometheus.CounterOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "frees_total", + Help: "Total number of frees.", + }), + heapAlloc: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_alloc_bytes", + Help: "Number heap bytes allocated and still in use.", + }), + heapSys: prometheus.NewCounter(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_sys_bytes", + Help: "Total bytes in heap obtained from system.", + }), + heapIdle: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_idle_bytes", + Help: "Number bytes in heap waiting to be used.", + }), + heapInuse: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_inuse_bytes", + Help: "Number of bytes in heap that are in use.", + }), + heapReleased: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_released_bytes", + Help: "Number of bytes in heap released to OS.", + }), + heapObjects: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "go", + Subsystem: "memstats", + Name: "heap_objects", + Help: "Number of allocated objects.", + }), } } @@ -34,6 +116,18 @@ func NewGoCollector() *goCollector { func (c *goCollector) Describe(ch chan<- *Desc) { ch <- c.goroutines.Desc() ch <- c.gcDesc + ch <- m.alloc.Desc() + ch <- m.totalAlloc.Desc() + ch <- m.sys.Desc() + ch <- m.lookups.Desc() + ch <- m.mallocs.Desc() + ch <- m.frees.Desc() + ch <- m.heapAlloc.Desc() + ch <- m.heapSys.Desc() + ch <- m.heapIdle.Desc() + ch <- m.heapInuse.Desc() + ch <- m.heapReleased.Desc() + ch <- m.heapObjects.Desc() } // Collect returns the current state of all metrics of the collector. @@ -51,128 +145,6 @@ func (c *goCollector) Collect(ch chan<- Metric) { } quantiles[0.0] = stats.PauseQuantiles[0].Seconds() ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles) -} - -// memStatsCollector collects runtime.MemStats -type memStatsCollector struct { - alloc prometheus.Gauge - totalAlloc prometheus.Gauge - sys prometheus.Gauge - lookups prometheus.Gauge - mallocs prometheus.Gauge - frees prometheus.Gauge - heapAlloc prometheus.Gauge - heapSys prometheus.Gauge - heapIdle prometheus.Gauge - heapInuse prometheus.Gauge - heapReleased prometheus.Gauge - heapObjects prometheus.Gauge -} - -// newMemStatsCollector creates a new runtime.MemStats collector -func newMemStatsCollector() *memStatsCollector { - return &MemStatsCollector{ - alloc: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "alloc_bytes", - Help: "bytes allocated and still in use", - }), - totalAlloc: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "alloc_bytes_total", - Help: "bytes allocated (even if freed)", - }), - sys: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "sys", - Help: "bytes obtained from system", - }), - lookups: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "lookups", - Help: "number of pointer lookups", - }), - mallocs: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "mallocs", - Help: "number of mallocs", - }), - frees: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "frees", - Help: "number of frees", - }), - heapAlloc: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_alloc", - Help: "bytes allocated and still in use", - }), - heapSys: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_sys", - Help: "bytes obtained from system", - }), - heapIdle: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_idle", - Help: "bytes in idle spans", - }), - heapInuse: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_inuse", - Help: "bytes in non-idle span", - }), - heapReleased: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_released", - Help: "bytes released to the OS", - }), - heapObjects: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_objects", - Help: "total number of allocated objects", - }), - } -} - -// Describe sends Desc objects for each memstat we intend to collect. -func (m *MemStatsCollector) Describe(ch chan<- *prometheus.Desc) { - if m == nil { - m = NewMemStatsCollector() - } - - ch <- m.alloc.Desc() - ch <- m.totalAlloc.Desc() - ch <- m.sys.Desc() - ch <- m.lookups.Desc() - ch <- m.mallocs.Desc() - ch <- m.frees.Desc() - ch <- m.heapAlloc.Desc() - ch <- m.heapSys.Desc() - ch <- m.heapIdle.Desc() - ch <- m.heapInuse.Desc() - ch <- m.heapReleased.Desc() - ch <- m.heapObjects.Desc() -} - -// Collect does the trick by calling ReadMemStats once and then constructing -// three different Metrics on the fly. -func (m *MemStatsCollector) Collect(ch chan<- prometheus.Metric) { - if m == nil { - m = NewMemStatsCollector() - } var ms runtime.MemStats runtime.ReadMemStats(&ms) From 59305998f6e0ae702a7d8e03422c79d8d596b420 Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Tue, 21 Jul 2015 08:34:50 -0700 Subject: [PATCH 03/10] remove prometheus namespace references, copy paste error --- prometheus/go_collector.go | 50 ++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index c513a39..8bcfa0a 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -4,25 +4,23 @@ import ( "runtime" "runtime/debug" "time" - - "github.com/prometheus/client_golang/prometheus" ) type goCollector struct { goroutines Gauge gcDesc *Desc - alloc prometheus.Gauge - totalAlloc prometheus.Gauge - sys prometheus.Gauge - lookups prometheus.Gauge - mallocs prometheus.Gauge - frees prometheus.Gauge - heapAlloc prometheus.Gauge - heapSys prometheus.Gauge - heapIdle prometheus.Gauge - heapInuse prometheus.Gauge - heapReleased prometheus.Gauge - heapObjects prometheus.Gauge + alloc Gauge + totalAlloc Gauge + sys Gauge + lookups Gauge + mallocs Gauge + frees Gauge + heapAlloc Gauge + heapSys Gauge + heapIdle Gauge + heapInuse Gauge + heapReleased Gauge + heapObjects Gauge } // NewGoCollector returns a collector which exports metrics about the current @@ -37,73 +35,73 @@ func NewGoCollector() *goCollector { "go_gc_duration_seconds", "A summary of the GC invocation durations.", nil, nil), - alloc: prometheus.NewGauge(prometheus.GaugeOpts{ + alloc: NewGauge(GaugeOpts{ Namespace: "go", Subsystem: "memstats", Name: "alloc_bytes", Help: "Number of bytes allocated and still in use.", }), - totalAlloc: prometheus.NewCounter(prometheus.CounterOpts{ + totalAlloc: NewCounter(CounterOpts{ Namespace: "go", Subsystem: "memstats", Name: "alloc_bytes_total", Help: "Total number of bytes allocated, even if freed.", }), - sys: prometheus.NewGauge(prometheus.GaugeOpts{ + sys: NewGauge(GaugeOpts{ Namespace: "go", Subsystem: "memstats", Name: "sys_bytes", Help: "Number of bytes obtained from system", }), - lookups: prometheus.NewCounter(prometheus.CounterOpts{ + lookups: NewCounter(CounterOpts{ Namespace: "go", Subsystem: "memstats", Name: "lookups_total", Help: "Total number of pointer lookups.", }), - mallocs: prometheus.NewCounter(prometheus.CounterOpts{ + mallocs: NewCounter(CounterOpts{ Namespace: "go", Subsystem: "memstats", Name: "mallocs_total", Help: "Total number of mallocs.", }), - frees: prometheus.NewCounter(prometheus.CounterOpts{ + frees: NewCounter(CounterOpts{ Namespace: "go", Subsystem: "memstats", Name: "frees_total", Help: "Total number of frees.", }), - heapAlloc: prometheus.NewGauge(prometheus.GaugeOpts{ + heapAlloc: NewGauge(GaugeOpts{ Namespace: "go", Subsystem: "memstats", Name: "heap_alloc_bytes", Help: "Number heap bytes allocated and still in use.", }), - heapSys: prometheus.NewCounter(prometheus.GaugeOpts{ + heapSys: NewCounter(GaugeOpts{ Namespace: "go", Subsystem: "memstats", Name: "heap_sys_bytes", Help: "Total bytes in heap obtained from system.", }), - heapIdle: prometheus.NewGauge(prometheus.GaugeOpts{ + heapIdle: NewGauge(GaugeOpts{ Namespace: "go", Subsystem: "memstats", Name: "heap_idle_bytes", Help: "Number bytes in heap waiting to be used.", }), - heapInuse: prometheus.NewGauge(prometheus.GaugeOpts{ + heapInuse: NewGauge(GaugeOpts{ Namespace: "go", Subsystem: "memstats", Name: "heap_inuse_bytes", Help: "Number of bytes in heap that are in use.", }), - heapReleased: prometheus.NewGauge(prometheus.GaugeOpts{ + heapReleased: NewGauge(GaugeOpts{ Namespace: "go", Subsystem: "memstats", Name: "heap_released_bytes", Help: "Number of bytes in heap released to OS.", }), - heapObjects: prometheus.NewGauge(prometheus.GaugeOpts{ + heapObjects: NewGauge(GaugeOpts{ Namespace: "go", Subsystem: "memstats", Name: "heap_objects", From 5e9294fbb71b3eb212a36a18885d2c0565740134 Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Tue, 21 Jul 2015 08:38:46 -0700 Subject: [PATCH 04/10] continue to fix errors --- prometheus/go_collector.go | 84 +++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index 8bcfa0a..09cb0c2 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -10,11 +10,11 @@ type goCollector struct { goroutines Gauge gcDesc *Desc alloc Gauge - totalAlloc Gauge - sys Gauge - lookups Gauge - mallocs Gauge - frees Gauge + totalAlloc Counter + sys Counter + lookups Counter + mallocs Counter + frees Counter heapAlloc Gauge heapSys Gauge heapIdle Gauge @@ -77,7 +77,7 @@ func NewGoCollector() *goCollector { Name: "heap_alloc_bytes", Help: "Number heap bytes allocated and still in use.", }), - heapSys: NewCounter(GaugeOpts{ + heapSys: NewGauge(GaugeOpts{ Namespace: "go", Subsystem: "memstats", Name: "heap_sys_bytes", @@ -114,18 +114,18 @@ func NewGoCollector() *goCollector { func (c *goCollector) Describe(ch chan<- *Desc) { ch <- c.goroutines.Desc() ch <- c.gcDesc - ch <- m.alloc.Desc() - ch <- m.totalAlloc.Desc() - ch <- m.sys.Desc() - ch <- m.lookups.Desc() - ch <- m.mallocs.Desc() - ch <- m.frees.Desc() - ch <- m.heapAlloc.Desc() - ch <- m.heapSys.Desc() - ch <- m.heapIdle.Desc() - ch <- m.heapInuse.Desc() - ch <- m.heapReleased.Desc() - ch <- m.heapObjects.Desc() + ch <- c.alloc.Desc() + ch <- c.totalAlloc.Desc() + ch <- c.sys.Desc() + ch <- c.lookups.Desc() + ch <- c.mallocs.Desc() + ch <- c.frees.Desc() + ch <- c.heapAlloc.Desc() + ch <- c.heapSys.Desc() + ch <- c.heapIdle.Desc() + ch <- c.heapInuse.Desc() + ch <- c.heapReleased.Desc() + ch <- c.heapObjects.Desc() } // Collect returns the current state of all metrics of the collector. @@ -147,28 +147,28 @@ func (c *goCollector) Collect(ch chan<- Metric) { var ms runtime.MemStats runtime.ReadMemStats(&ms) - m.alloc.Set(float64(ms.Alloc)) - ch <- m.alloc - m.totalAlloc.Set(float64(ms.TotalAlloc)) - ch <- m.totalAlloc - m.sys.Set(float64(ms.Sys)) - ch <- m.sys - m.lookups.Set(float64(ms.Lookups)) - ch <- m.lookups - m.mallocs.Set(float64(ms.Mallocs)) - ch <- m.mallocs - m.frees.Set(float64(ms.Frees)) - ch <- m.frees - m.heapAlloc.Set(float64(ms.HeapAlloc)) - ch <- m.heapAlloc - m.heapSys.Set(float64(ms.HeapSys)) - ch <- m.heapSys - m.heapIdle.Set(float64(ms.HeapIdle)) - ch <- m.heapIdle - m.heapInuse.Set(float64(ms.HeapInuse)) - ch <- m.heapInuse - m.heapReleased.Set(float64(ms.HeapReleased)) - ch <- m.heapReleased - m.heapObjects.Set(float64(ms.HeapObjects)) - ch <- m.heapObjects + c.alloc.Set(float64(ms.Alloc)) + ch <- c.alloc + c.totalAlloc.Set(float64(ms.TotalAlloc)) + ch <- c.totalAlloc + c.sys.Set(float64(ms.Sys)) + ch <- c.sys + c.lookups.Set(float64(ms.Lookups)) + ch <- c.lookups + c.mallocs.Set(float64(ms.Mallocs)) + ch <- c.mallocs + c.frees.Set(float64(ms.Frees)) + ch <- c.frees + c.heapAlloc.Set(float64(ms.HeapAlloc)) + ch <- c.heapAlloc + c.heapSys.Set(float64(ms.HeapSys)) + ch <- c.heapSys + c.heapIdle.Set(float64(ms.HeapIdle)) + ch <- c.heapIdle + c.heapInuse.Set(float64(ms.HeapInuse)) + ch <- c.heapInuse + c.heapReleased.Set(float64(ms.HeapReleased)) + ch <- c.heapReleased + c.heapObjects.Set(float64(ms.HeapObjects)) + ch <- c.heapObjects } From c945ed62c1f9e1ad69f3714bf46a9bd051d37347 Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Tue, 21 Jul 2015 20:29:02 -0700 Subject: [PATCH 05/10] use metrics struct. include more statistics --- prometheus/go_collector.go | 375 ++++++++++++++++++++++++------------- 1 file changed, 248 insertions(+), 127 deletions(-) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index 09cb0c2..dd06968 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -1,26 +1,17 @@ package prometheus import ( + "fmt" "runtime" "runtime/debug" "time" ) type goCollector struct { - goroutines Gauge - gcDesc *Desc - alloc Gauge - totalAlloc Counter - sys Counter - lookups Counter - mallocs Counter - frees Counter - heapAlloc Gauge - heapSys Gauge - heapIdle Gauge - heapInuse Gauge - heapReleased Gauge - heapObjects Gauge + goroutines Gauge + gcDesc *Desc + + memstats *memStatCollector } // NewGoCollector returns a collector which exports metrics about the current @@ -28,104 +19,233 @@ type goCollector struct { func NewGoCollector() *goCollector { return &goCollector{ goroutines: NewGauge(GaugeOpts{ - Name: "go_goroutines", - Help: "Number of goroutines that currently exist.", + Namespace: "go", + Name: "goroutines", + Help: "Number of goroutines that currently exist.", }), gcDesc: NewDesc( "go_gc_duration_seconds", "A summary of the GC invocation durations.", nil, nil), - alloc: NewGauge(GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "alloc_bytes", - Help: "Number of bytes allocated and still in use.", - }), - totalAlloc: NewCounter(CounterOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "alloc_bytes_total", - Help: "Total number of bytes allocated, even if freed.", - }), - sys: NewGauge(GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "sys_bytes", - Help: "Number of bytes obtained from system", - }), - lookups: NewCounter(CounterOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "lookups_total", - Help: "Total number of pointer lookups.", - }), - mallocs: NewCounter(CounterOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "mallocs_total", - Help: "Total number of mallocs.", - }), - frees: NewCounter(CounterOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "frees_total", - Help: "Total number of frees.", - }), - heapAlloc: NewGauge(GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_alloc_bytes", - Help: "Number heap bytes allocated and still in use.", - }), - heapSys: NewGauge(GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_sys_bytes", - Help: "Total bytes in heap obtained from system.", - }), - heapIdle: NewGauge(GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_idle_bytes", - Help: "Number bytes in heap waiting to be used.", - }), - heapInuse: NewGauge(GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_inuse_bytes", - Help: "Number of bytes in heap that are in use.", - }), - heapReleased: NewGauge(GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_released_bytes", - Help: "Number of bytes in heap released to OS.", - }), - heapObjects: NewGauge(GaugeOpts{ - Namespace: "go", - Subsystem: "memstats", - Name: "heap_objects", - Help: "Number of allocated objects.", - }), + memstats: &memStatCollector{ + ms: new(runtime.MemStats), + metrics: memStatsMetrics{ + { + desc: NewDesc( + memstatNamespace("alloc_bytes"), + "Number of bytes allocated and still in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("alloc_bytes_total"), + "Total number of bytes allocated, even if freed.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("sys_bytes"), + "Number of bytes obtained from system", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("lookups_total"), + "Total number of pointer lookups.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("mallocs_total"), + "Total number of mallocs.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("frees_total"), + "Total number of frees.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("heap_alloc_bytes"), + "Number heap bytes allocated and still in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_sys_bytes"), + "Total bytes in heap obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_idle_bytes"), + "Number bytes in heap waiting to be used.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_inuse_bytes"), + "Number of bytes in heap that are in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_released_bytes"), + "Number of bytes in heap released to OS.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_objects"), + "Number of allocated objects.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("stack_bytes_inuse"), + "Number of bytes in use by the stack allocator.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("stack_sys_bytes"), + "Number of bytes in obtained from system for stack allocator.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mspan_inuse"), + "Number of mspan structures in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mspan_sys"), + "Number of mspan structures obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mcache_inuse"), + "Number of mcache structures in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mcache_sys"), + "Number of mcache structures obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("buck_hash_sys"), + "Profiling bucket hash table.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("gc_metadata"), + "GC metadata.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("other_sys"), + "Other system allocations.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("next_gc"), + "Next collection will happen when HeapAlloc ≥ this amount.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("last_gc"), + "End time of last garbage collection (nanoseconds since 1970).", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("pause_total"), + "Total garbage collection pauses for all collections.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.PauseTotalNs) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("gc_total"), + "Number of garbage collection.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.NumGC) }, + valType: CounterValue, + }, + }, + }, } } +func memstatNamespace(s string) string { + return fmt.Sprintf("go_memstats_%s", s) +} + // Describe returns all descriptions of the collector. func (c *goCollector) Describe(ch chan<- *Desc) { ch <- c.goroutines.Desc() ch <- c.gcDesc - ch <- c.alloc.Desc() - ch <- c.totalAlloc.Desc() - ch <- c.sys.Desc() - ch <- c.lookups.Desc() - ch <- c.mallocs.Desc() - ch <- c.frees.Desc() - ch <- c.heapAlloc.Desc() - ch <- c.heapSys.Desc() - ch <- c.heapIdle.Desc() - ch <- c.heapInuse.Desc() - ch <- c.heapReleased.Desc() - ch <- c.heapObjects.Desc() + + c.memstats.Describe(ch) } // Collect returns the current state of all metrics of the collector. @@ -144,31 +264,32 @@ func (c *goCollector) Collect(ch chan<- Metric) { quantiles[0.0] = stats.PauseQuantiles[0].Seconds() ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles) - var ms runtime.MemStats - runtime.ReadMemStats(&ms) - - c.alloc.Set(float64(ms.Alloc)) - ch <- c.alloc - c.totalAlloc.Set(float64(ms.TotalAlloc)) - ch <- c.totalAlloc - c.sys.Set(float64(ms.Sys)) - ch <- c.sys - c.lookups.Set(float64(ms.Lookups)) - ch <- c.lookups - c.mallocs.Set(float64(ms.Mallocs)) - ch <- c.mallocs - c.frees.Set(float64(ms.Frees)) - ch <- c.frees - c.heapAlloc.Set(float64(ms.HeapAlloc)) - ch <- c.heapAlloc - c.heapSys.Set(float64(ms.HeapSys)) - ch <- c.heapSys - c.heapIdle.Set(float64(ms.HeapIdle)) - ch <- c.heapIdle - c.heapInuse.Set(float64(ms.HeapInuse)) - ch <- c.heapInuse - c.heapReleased.Set(float64(ms.HeapReleased)) - ch <- c.heapReleased - c.heapObjects.Set(float64(ms.HeapObjects)) - ch <- c.heapObjects + c.memstats.Collect(ch) +} + +// metrics that provide description, value, and value type for memstat metrics +type memStatsMetrics []struct { + desc *Desc + eval func(*runtime.MemStats) float64 + valType ValueType +} + +type memStatCollector struct { + // memstats object to reuse + ms *runtime.MemStats + // metrics to describe and collect + metrics memStatsMetrics +} + +func (c *memStatCollector) Describe(ch chan<- *Desc) { + for _, i := range c.metrics { + ch <- i.desc + } +} + +func (c *memStatCollector) Collect(ch chan<- Metric) { + runtime.ReadMemStats(c.ms) + for _, i := range c.metrics { + ch <- MustNewConstMetric(i.desc, i.valType, i.eval(c.ms)) + } } From 8a031ee219b141dcd82fa27d330f8aca74352c03 Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Fri, 2 Oct 2015 18:10:36 -0700 Subject: [PATCH 06/10] unembed memstats collector --- prometheus/go_collector.go | 446 ++++++++++++++++++------------------- 1 file changed, 216 insertions(+), 230 deletions(-) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index dd06968..c55c5d5 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -11,13 +11,17 @@ type goCollector struct { goroutines Gauge gcDesc *Desc - memstats *memStatCollector + // memstats object to reuse + ms *runtime.MemStats + // metrics to describe and collect + metrics memStatsMetrics } // NewGoCollector returns a collector which exports metrics about the current // go process. func NewGoCollector() *goCollector { return &goCollector{ + ms: new(runtime.MemStats), goroutines: NewGauge(GaugeOpts{ Namespace: "go", Name: "goroutines", @@ -27,210 +31,207 @@ func NewGoCollector() *goCollector { "go_gc_duration_seconds", "A summary of the GC invocation durations.", nil, nil), - memstats: &memStatCollector{ - ms: new(runtime.MemStats), - metrics: memStatsMetrics{ - { - desc: NewDesc( - memstatNamespace("alloc_bytes"), - "Number of bytes allocated and still in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("alloc_bytes_total"), - "Total number of bytes allocated, even if freed.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("sys_bytes"), - "Number of bytes obtained from system", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("lookups_total"), - "Total number of pointer lookups.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("mallocs_total"), - "Total number of mallocs.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("frees_total"), - "Total number of frees.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("heap_alloc_bytes"), - "Number heap bytes allocated and still in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_sys_bytes"), - "Total bytes in heap obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_idle_bytes"), - "Number bytes in heap waiting to be used.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_inuse_bytes"), - "Number of bytes in heap that are in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_released_bytes"), - "Number of bytes in heap released to OS.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_objects"), - "Number of allocated objects.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("stack_bytes_inuse"), - "Number of bytes in use by the stack allocator.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("stack_sys_bytes"), - "Number of bytes in obtained from system for stack allocator.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mspan_inuse"), - "Number of mspan structures in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mspan_sys"), - "Number of mspan structures obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mcache_inuse"), - "Number of mcache structures in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mcache_sys"), - "Number of mcache structures obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("buck_hash_sys"), - "Profiling bucket hash table.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("gc_metadata"), - "GC metadata.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("other_sys"), - "Other system allocations.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("next_gc"), - "Next collection will happen when HeapAlloc ≥ this amount.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("last_gc"), - "End time of last garbage collection (nanoseconds since 1970).", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("pause_total"), - "Total garbage collection pauses for all collections.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.PauseTotalNs) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("gc_total"), - "Number of garbage collection.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.NumGC) }, - valType: CounterValue, - }, + metrics: memStatsMetrics{ + { + desc: NewDesc( + memstatNamespace("alloc_bytes"), + "Number of bytes allocated and still in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("alloc_bytes_total"), + "Total number of bytes allocated, even if freed.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("sys_bytes"), + "Number of bytes obtained from system", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("lookups_total"), + "Total number of pointer lookups.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("mallocs_total"), + "Total number of mallocs.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("frees_total"), + "Total number of frees.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("heap_alloc_bytes"), + "Number heap bytes allocated and still in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_sys_bytes"), + "Total bytes in heap obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_idle_bytes"), + "Number bytes in heap waiting to be used.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_inuse_bytes"), + "Number of bytes in heap that are in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_released_bytes"), + "Number of bytes in heap released to OS.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_objects"), + "Number of allocated objects.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("stack_bytes_inuse"), + "Number of bytes in use by the stack allocator.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("stack_sys_bytes"), + "Number of bytes in obtained from system for stack allocator.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mspan_inuse"), + "Number of mspan structures in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mspan_sys"), + "Number of mspan structures obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mcache_inuse"), + "Number of mcache structures in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mcache_sys"), + "Number of mcache structures obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("buck_hash_sys"), + "Profiling bucket hash table.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("gc_metadata"), + "GC metadata.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("other_sys"), + "Other system allocations.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("next_gc"), + "Next collection will happen when HeapAlloc ≥ this amount.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("last_gc"), + "End time of last garbage collection (nanoseconds since 1970).", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("pause_total"), + "Total garbage collection pauses for all collections.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.PauseTotalNs) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("gc_total"), + "Number of garbage collection.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.NumGC) }, + valType: CounterValue, }, }, } @@ -245,7 +246,9 @@ func (c *goCollector) Describe(ch chan<- *Desc) { ch <- c.goroutines.Desc() ch <- c.gcDesc - c.memstats.Describe(ch) + for _, i := range c.metrics { + ch <- i.desc + } } // Collect returns the current state of all metrics of the collector. @@ -264,32 +267,15 @@ func (c *goCollector) Collect(ch chan<- Metric) { quantiles[0.0] = stats.PauseQuantiles[0].Seconds() ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles) - c.memstats.Collect(ch) -} - -// metrics that provide description, value, and value type for memstat metrics -type memStatsMetrics []struct { - desc *Desc - eval func(*runtime.MemStats) float64 - valType ValueType -} - -type memStatCollector struct { - // memstats object to reuse - ms *runtime.MemStats - // metrics to describe and collect - metrics memStatsMetrics -} - -func (c *memStatCollector) Describe(ch chan<- *Desc) { - for _, i := range c.metrics { - ch <- i.desc - } -} - -func (c *memStatCollector) Collect(ch chan<- Metric) { runtime.ReadMemStats(c.ms) for _, i := range c.metrics { ch <- MustNewConstMetric(i.desc, i.valType, i.eval(c.ms)) } } + +// memStatsMetrics provide description, value, and value type for memstat metrics +type memStatsMetrics []struct { + desc *Desc + eval func(*runtime.MemStats) float64 + valType ValueType +} From 6c7a1db6bfeccc0020bce50eb97cb83dedcef9e1 Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Mon, 5 Oct 2015 07:37:59 -0700 Subject: [PATCH 07/10] don't reuse memstats --- prometheus/go_collector.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index c55c5d5..015e350 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -11,8 +11,6 @@ type goCollector struct { goroutines Gauge gcDesc *Desc - // memstats object to reuse - ms *runtime.MemStats // metrics to describe and collect metrics memStatsMetrics } @@ -21,7 +19,6 @@ type goCollector struct { // go process. func NewGoCollector() *goCollector { return &goCollector{ - ms: new(runtime.MemStats), goroutines: NewGauge(GaugeOpts{ Namespace: "go", Name: "goroutines", @@ -267,13 +264,14 @@ func (c *goCollector) Collect(ch chan<- Metric) { quantiles[0.0] = stats.PauseQuantiles[0].Seconds() ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles) - runtime.ReadMemStats(c.ms) + ms := &runtime.MemStats{} + runtime.ReadMemStats(ms) for _, i := range c.metrics { - ch <- MustNewConstMetric(i.desc, i.valType, i.eval(c.ms)) + ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms)) } } -// memStatsMetrics provide description, value, and value type for memstat metrics +// memStatsMetrics provide description, value, and value type for memstat metrics. type memStatsMetrics []struct { desc *Desc eval func(*runtime.MemStats) float64 From 9a6b9d3ddfdffd6edd5cccc94cc6623821c87075 Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Mon, 5 Oct 2015 09:27:28 -0700 Subject: [PATCH 08/10] fix descriptions --- prometheus/go_collector.go | 72 +++++++++++++++----------------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index 015e350..47e294c 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -48,11 +48,11 @@ func NewGoCollector() *goCollector { }, { desc: NewDesc( memstatNamespace("sys_bytes"), - "Number of bytes obtained from system", + "Number of bytes obtained by system. Sum of all system allocations.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) }, - valType: CounterValue, + valType: GaugeValue, }, { desc: NewDesc( memstatNamespace("lookups_total"), @@ -80,7 +80,7 @@ func NewGoCollector() *goCollector { }, { desc: NewDesc( memstatNamespace("heap_alloc_bytes"), - "Number heap bytes allocated and still in use.", + "Number of heap bytes allocated and still in use.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) }, @@ -88,7 +88,7 @@ func NewGoCollector() *goCollector { }, { desc: NewDesc( memstatNamespace("heap_sys_bytes"), - "Total bytes in heap obtained from system.", + "Number of heap bytes obtained from system.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) }, @@ -96,7 +96,7 @@ func NewGoCollector() *goCollector { }, { desc: NewDesc( memstatNamespace("heap_idle_bytes"), - "Number bytes in heap waiting to be used.", + "Number of heap bytes waiting to be used.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) }, @@ -104,7 +104,7 @@ func NewGoCollector() *goCollector { }, { desc: NewDesc( memstatNamespace("heap_inuse_bytes"), - "Number of bytes in heap that are in use.", + "Number of heap bytes that are in use.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) }, @@ -127,7 +127,7 @@ func NewGoCollector() *goCollector { valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("stack_bytes_inuse"), + memstatNamespace("stack_inuse_bytes"), "Number of bytes in use by the stack allocator.", nil, nil, ), @@ -136,99 +136,83 @@ func NewGoCollector() *goCollector { }, { desc: NewDesc( memstatNamespace("stack_sys_bytes"), - "Number of bytes in obtained from system for stack allocator.", + "Number of bytes obtained from system for stack allocator.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) }, valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("mspan_inuse"), - "Number of mspan structures in use.", + memstatNamespace("mspan_inuse_bytes"), + "Number of bytes in use by mspan structures.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) }, valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("mspan_sys"), - "Number of mspan structures obtained from system.", + memstatNamespace("mspan_sys_bytes"), + "Number of bytes used for mspan structures obtained from system.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) }, valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("mcache_inuse"), - "Number of mcache structures in use.", + memstatNamespace("mcache_inuse_bytes"), + "Number of bytes in use by mcache structures.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) }, valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("mcache_sys"), - "Number of mcache structures obtained from system.", + memstatNamespace("mcache_sys_bytes"), + "Number of bytes used for mcache structures obtained from system.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) }, valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("buck_hash_sys"), - "Profiling bucket hash table.", + memstatNamespace("buck_hash_sys_bytes"), + "Number of bytes used by the profiling bucket hash table.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) }, valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("gc_metadata"), - "GC metadata.", + memstatNamespace("gc_sys_bytes"), + "Number of bytes used for garbage collection system metadata.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) }, valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("other_sys"), - "Other system allocations.", + memstatNamespace("other_sys_bytes"), + "Number of bytes used for other system allocations.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) }, valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("next_gc"), - "Next collection will happen when HeapAlloc ≥ this amount.", + memstatNamespace("next_gc_bytes"), + "Number of heap bytes when next garbage collection will take place.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) }, valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("last_gc"), - "End time of last garbage collection (nanoseconds since 1970).", + memstatNamespace("last_gc_time_seconds"), + "Number of seconds since 1970 of last garbage collection.", nil, nil, ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("pause_total"), - "Total garbage collection pauses for all collections.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.PauseTotalNs) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("gc_total"), - "Number of garbage collection.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.NumGC) }, - valType: CounterValue, + eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC*10 ^ 9) }, + valType: GaugeValue, }, }, } From 1eb8d032a8ff0d4ed48dd0d95ef531ee04999b5f Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Tue, 6 Oct 2015 08:18:17 -0700 Subject: [PATCH 09/10] use counter for heap released bytes --- prometheus/go_collector.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index 47e294c..4e131c0 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -116,7 +116,7 @@ func NewGoCollector() *goCollector { nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) }, - valType: GaugeValue, + valType: CounterValue, }, { desc: NewDesc( memstatNamespace("heap_objects"), From db58b27d95ff8fa1515407a1cd58b4550f67fbc2 Mon Sep 17 00:00:00 2001 From: Kevin Pike Date: Wed, 7 Oct 2015 11:21:49 -0700 Subject: [PATCH 10/10] heap bytes released total --- prometheus/go_collector.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prometheus/go_collector.go b/prometheus/go_collector.go index 4e131c0..8be2476 100644 --- a/prometheus/go_collector.go +++ b/prometheus/go_collector.go @@ -111,8 +111,8 @@ func NewGoCollector() *goCollector { valType: GaugeValue, }, { desc: NewDesc( - memstatNamespace("heap_released_bytes"), - "Number of bytes in heap released to OS.", + memstatNamespace("heap_released_bytes_total"), + "Total number of heap bytes released to OS.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) },