1 // Copyright 2018 The Prometheus Authors
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
23 type goCollector struct {
29 // metrics to describe and collect
30 metrics memStatsMetrics
33 // NewGoCollector returns a collector which exports metrics about the current Go
34 // process. This includes memory stats. To collect those, runtime.ReadMemStats
35 // is called. This causes a stop-the-world, which is very short with Go1.9+
36 // (~25µs). However, with older Go versions, the stop-the-world duration depends
37 // on the heap size and can be quite significant (~1.7 ms/GiB as per
38 // https://go-review.googlesource.com/c/go/+/34937).
39 func NewGoCollector() Collector {
41 goroutinesDesc: NewDesc(
43 "Number of goroutines that currently exist.",
47 "Number of OS threads created.",
50 "go_gc_duration_seconds",
51 "A summary of the GC invocation durations.",
55 "Information about the Go environment.",
56 nil, Labels{"version": runtime.Version()}),
57 metrics: memStatsMetrics{
60 memstatNamespace("alloc_bytes"),
61 "Number of bytes allocated and still in use.",
64 eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) },
68 memstatNamespace("alloc_bytes_total"),
69 "Total number of bytes allocated, even if freed.",
72 eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) },
73 valType: CounterValue,
76 memstatNamespace("sys_bytes"),
77 "Number of bytes obtained from system.",
80 eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) },
84 memstatNamespace("lookups_total"),
85 "Total number of pointer lookups.",
88 eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) },
89 valType: CounterValue,
92 memstatNamespace("mallocs_total"),
93 "Total number of mallocs.",
96 eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) },
97 valType: CounterValue,
100 memstatNamespace("frees_total"),
101 "Total number of frees.",
104 eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) },
105 valType: CounterValue,
108 memstatNamespace("heap_alloc_bytes"),
109 "Number of heap bytes allocated and still in use.",
112 eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) },
116 memstatNamespace("heap_sys_bytes"),
117 "Number of heap bytes obtained from system.",
120 eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) },
124 memstatNamespace("heap_idle_bytes"),
125 "Number of heap bytes waiting to be used.",
128 eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) },
132 memstatNamespace("heap_inuse_bytes"),
133 "Number of heap bytes that are in use.",
136 eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) },
140 memstatNamespace("heap_released_bytes"),
141 "Number of heap bytes released to OS.",
144 eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) },
148 memstatNamespace("heap_objects"),
149 "Number of allocated objects.",
152 eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) },
156 memstatNamespace("stack_inuse_bytes"),
157 "Number of bytes in use by the stack allocator.",
160 eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) },
164 memstatNamespace("stack_sys_bytes"),
165 "Number of bytes obtained from system for stack allocator.",
168 eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) },
172 memstatNamespace("mspan_inuse_bytes"),
173 "Number of bytes in use by mspan structures.",
176 eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) },
180 memstatNamespace("mspan_sys_bytes"),
181 "Number of bytes used for mspan structures obtained from system.",
184 eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) },
188 memstatNamespace("mcache_inuse_bytes"),
189 "Number of bytes in use by mcache structures.",
192 eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) },
196 memstatNamespace("mcache_sys_bytes"),
197 "Number of bytes used for mcache structures obtained from system.",
200 eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) },
204 memstatNamespace("buck_hash_sys_bytes"),
205 "Number of bytes used by the profiling bucket hash table.",
208 eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) },
212 memstatNamespace("gc_sys_bytes"),
213 "Number of bytes used for garbage collection system metadata.",
216 eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) },
220 memstatNamespace("other_sys_bytes"),
221 "Number of bytes used for other system allocations.",
224 eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) },
228 memstatNamespace("next_gc_bytes"),
229 "Number of heap bytes when next garbage collection will take place.",
232 eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) },
236 memstatNamespace("last_gc_time_seconds"),
237 "Number of seconds since 1970 of last garbage collection.",
240 eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) / 1e9 },
244 memstatNamespace("gc_cpu_fraction"),
245 "The fraction of this program's available CPU time used by the GC since the program started.",
248 eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction },
255 func memstatNamespace(s string) string {
256 return fmt.Sprintf("go_memstats_%s", s)
259 // Describe returns all descriptions of the collector.
260 func (c *goCollector) Describe(ch chan<- *Desc) {
261 ch <- c.goroutinesDesc
265 for _, i := range c.metrics {
270 // Collect returns the current state of all metrics of the collector.
271 func (c *goCollector) Collect(ch chan<- Metric) {
272 ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine()))
273 n, _ := runtime.ThreadCreateProfile(nil)
274 ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n))
276 var stats debug.GCStats
277 stats.PauseQuantiles = make([]time.Duration, 5)
278 debug.ReadGCStats(&stats)
280 quantiles := make(map[float64]float64)
281 for idx, pq := range stats.PauseQuantiles[1:] {
282 quantiles[float64(idx+1)/float64(len(stats.PauseQuantiles)-1)] = pq.Seconds()
284 quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
285 ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), stats.PauseTotal.Seconds(), quantiles)
287 ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1)
289 ms := &runtime.MemStats{}
290 runtime.ReadMemStats(ms)
291 for _, i := range c.metrics {
292 ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms))
296 // memStatsMetrics provide description, value, and value type for memstat metrics.
297 type memStatsMetrics []struct {
299 eval func(*runtime.MemStats) float64