Collect returns the current state of all metrics of the collector.
(ch chan<- Metric)
| 75 | |
| 76 | // Collect returns the current state of all metrics of the collector. |
| 77 | func (c *goCollector) Collect(ch chan<- Metric) { |
| 78 | var ( |
| 79 | ms = &runtime.MemStats{} |
| 80 | done = make(chan struct{}) |
| 81 | ) |
| 82 | // Start reading memstats first as it might take a while. |
| 83 | go func() { |
| 84 | c.msRead(ms) |
| 85 | c.msMtx.Lock() |
| 86 | c.msLast = ms |
| 87 | c.msLastTimestamp = time.Now() |
| 88 | c.msMtx.Unlock() |
| 89 | close(done) |
| 90 | }() |
| 91 | |
| 92 | // Collect base non-memory metrics. |
| 93 | c.base.Collect(ch) |
| 94 | |
| 95 | timer := time.NewTimer(c.msMaxWait) |
| 96 | select { |
| 97 | case <-done: // Our own ReadMemStats succeeded in time. Use it. |
| 98 | timer.Stop() // Important for high collection frequencies to not pile up timers. |
| 99 | c.msCollect(ch, ms) |
| 100 | return |
| 101 | case <-timer.C: // Time out, use last memstats if possible. Continue below. |
| 102 | } |
| 103 | c.msMtx.Lock() |
| 104 | if time.Since(c.msLastTimestamp) < c.msMaxAge { |
| 105 | // Last memstats are recent enough. Collect from them under the lock. |
| 106 | c.msCollect(ch, c.msLast) |
| 107 | c.msMtx.Unlock() |
| 108 | return |
| 109 | } |
| 110 | // If we are here, the last memstats are too old or don't exist. We have |
| 111 | // to wait until our own ReadMemStats finally completes. For that to |
| 112 | // happen, we have to release the lock. |
| 113 | c.msMtx.Unlock() |
| 114 | <-done |
| 115 | c.msCollect(ch, ms) |
| 116 | } |
| 117 | |
| 118 | func (c *goCollector) msCollect(ch chan<- Metric, ms *runtime.MemStats) { |
| 119 | for _, i := range c.msMetrics { |