Collect returns the current state of all metrics of the collector.
(ch chan<- Metric)
| 304 | |
| 305 | // Collect returns the current state of all metrics of the collector. |
| 306 | func (c *goCollector) Collect(ch chan<- Metric) { |
| 307 | // Collect base non-memory metrics. |
| 308 | c.base.Collect(ch) |
| 309 | |
| 310 | if len(c.sampleBuf) == 0 { |
| 311 | return |
| 312 | } |
| 313 | |
| 314 | // Collect must be thread-safe, so prevent concurrent use of |
| 315 | // sampleBuf elements. Just read into sampleBuf but write all the data |
| 316 | // we get into our Metrics or MemStats. |
| 317 | // |
| 318 | // This lock also ensures that the Metrics we send out are all from |
| 319 | // the same updates, ensuring their mutual consistency insofar as |
| 320 | // is guaranteed by the runtime/metrics package. |
| 321 | // |
| 322 | // N.B. This locking is heavy-handed, but Collect is expected to be called |
| 323 | // relatively infrequently. Also the core operation here, metrics.Read, |
| 324 | // is fast (O(tens of microseconds)) so contention should certainly be |
| 325 | // low, though channel operations and any allocations may add to that. |
| 326 | c.mu.Lock() |
| 327 | defer c.mu.Unlock() |
| 328 | |
| 329 | // Populate runtime/metrics sample buffer. |
| 330 | metrics.Read(c.sampleBuf) |
| 331 | |
| 332 | // Collect all our runtime/metrics user chose to expose from sampleBuf (if any). |
| 333 | for i, metric := range c.rmExposedMetrics { |
| 334 | // We created samples for exposed metrics first in order, so indexes match. |
| 335 | sample := c.sampleBuf[i] |
| 336 | |
| 337 | // N.B. switch on concrete type because it's significantly more efficient |
| 338 | // than checking for the Counter and Gauge interface implementations. In |
| 339 | // this case, we control all the types here. |
| 340 | switch m := metric.(type) { |
| 341 | case *counter: |
| 342 | // Guard against decreases. This should never happen, but a failure |
| 343 | // to do so will result in a panic, which is a harsh consequence for |
| 344 | // a metrics collection bug. |
| 345 | v0, v1 := m.get(), unwrapScalarRMValue(sample.Value) |
| 346 | if v1 > v0 { |
| 347 | m.Add(unwrapScalarRMValue(sample.Value) - m.get()) |
| 348 | } |
| 349 | m.Collect(ch) |
| 350 | case *gauge: |
| 351 | m.Set(unwrapScalarRMValue(sample.Value)) |
| 352 | m.Collect(ch) |
| 353 | case *batchHistogram: |
| 354 | m.update(sample.Value.Float64Histogram(), c.exactSumFor(sample.Name)) |
| 355 | m.Collect(ch) |
| 356 | default: |
| 357 | panic("unexpected metric type") |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | if c.msMetricsEnabled { |
| 362 | // ms is a dummy MemStats that we populate ourselves so that we can |
| 363 | // populate the old metrics from it if goMemStatsCollection is enabled. |
nothing calls this directly
no test coverage detected