Source file
src/runtime/metrics.go
1
2
3
4
5 package runtime
6
7
8
9 import (
10 "internal/godebugs"
11 "internal/runtime/gc"
12 "unsafe"
13 )
14
15 var (
16
17
18
19
20
21
22 metricsSema uint32 = 1
23 metricsInit bool
24 metrics map[string]metricData
25
26 sizeClassBuckets []float64
27 timeHistBuckets []float64
28 )
29
30 type metricData struct {
31
32
33
34 deps statDepSet
35
36
37
38 compute func(in *statAggregate, out *metricValue)
39 }
40
41 func metricsLock() {
42
43
44
45 semacquire1(&metricsSema, true, 0, 0, waitReasonSemacquire)
46 if raceenabled {
47 raceacquire(unsafe.Pointer(&metricsSema))
48 }
49 }
50
51 func metricsUnlock() {
52 if raceenabled {
53 racerelease(unsafe.Pointer(&metricsSema))
54 }
55 semrelease(&metricsSema)
56 }
57
58
59
60
61 func initMetrics() {
62 if metricsInit {
63 return
64 }
65
66 sizeClassBuckets = make([]float64, gc.NumSizeClasses, gc.NumSizeClasses+1)
67
68
69
70 sizeClassBuckets[0] = 1
71 for i := 1; i < gc.NumSizeClasses; i++ {
72
73
74
75
76
77
78
79
80
81
82
83 sizeClassBuckets[i] = float64(gc.SizeClassToSize[i] + 1)
84 }
85 sizeClassBuckets = append(sizeClassBuckets, float64Inf())
86
87 timeHistBuckets = timeHistogramMetricsBuckets()
88 metrics = map[string]metricData{
89 "/cgo/go-to-c-calls:calls": {
90 compute: func(_ *statAggregate, out *metricValue) {
91 out.kind = metricKindUint64
92 out.scalar = uint64(NumCgoCall())
93 },
94 },
95 "/cpu/classes/gc/mark/assist:cpu-seconds": {
96 deps: makeStatDepSet(cpuStatsDep),
97 compute: func(in *statAggregate, out *metricValue) {
98 out.kind = metricKindFloat64
99 out.scalar = float64bits(nsToSec(in.cpuStats.GCAssistTime))
100 },
101 },
102 "/cpu/classes/gc/mark/dedicated:cpu-seconds": {
103 deps: makeStatDepSet(cpuStatsDep),
104 compute: func(in *statAggregate, out *metricValue) {
105 out.kind = metricKindFloat64
106 out.scalar = float64bits(nsToSec(in.cpuStats.GCDedicatedTime))
107 },
108 },
109 "/cpu/classes/gc/mark/idle:cpu-seconds": {
110 deps: makeStatDepSet(cpuStatsDep),
111 compute: func(in *statAggregate, out *metricValue) {
112 out.kind = metricKindFloat64
113 out.scalar = float64bits(nsToSec(in.cpuStats.GCIdleTime))
114 },
115 },
116 "/cpu/classes/gc/pause:cpu-seconds": {
117 deps: makeStatDepSet(cpuStatsDep),
118 compute: func(in *statAggregate, out *metricValue) {
119 out.kind = metricKindFloat64
120 out.scalar = float64bits(nsToSec(in.cpuStats.GCPauseTime))
121 },
122 },
123 "/cpu/classes/gc/total:cpu-seconds": {
124 deps: makeStatDepSet(cpuStatsDep),
125 compute: func(in *statAggregate, out *metricValue) {
126 out.kind = metricKindFloat64
127 out.scalar = float64bits(nsToSec(in.cpuStats.GCTotalTime))
128 },
129 },
130 "/cpu/classes/idle:cpu-seconds": {
131 deps: makeStatDepSet(cpuStatsDep),
132 compute: func(in *statAggregate, out *metricValue) {
133 out.kind = metricKindFloat64
134 out.scalar = float64bits(nsToSec(in.cpuStats.IdleTime))
135 },
136 },
137 "/cpu/classes/scavenge/assist:cpu-seconds": {
138 deps: makeStatDepSet(cpuStatsDep),
139 compute: func(in *statAggregate, out *metricValue) {
140 out.kind = metricKindFloat64
141 out.scalar = float64bits(nsToSec(in.cpuStats.ScavengeAssistTime))
142 },
143 },
144 "/cpu/classes/scavenge/background:cpu-seconds": {
145 deps: makeStatDepSet(cpuStatsDep),
146 compute: func(in *statAggregate, out *metricValue) {
147 out.kind = metricKindFloat64
148 out.scalar = float64bits(nsToSec(in.cpuStats.ScavengeBgTime))
149 },
150 },
151 "/cpu/classes/scavenge/total:cpu-seconds": {
152 deps: makeStatDepSet(cpuStatsDep),
153 compute: func(in *statAggregate, out *metricValue) {
154 out.kind = metricKindFloat64
155 out.scalar = float64bits(nsToSec(in.cpuStats.ScavengeTotalTime))
156 },
157 },
158 "/cpu/classes/total:cpu-seconds": {
159 deps: makeStatDepSet(cpuStatsDep),
160 compute: func(in *statAggregate, out *metricValue) {
161 out.kind = metricKindFloat64
162 out.scalar = float64bits(nsToSec(in.cpuStats.TotalTime))
163 },
164 },
165 "/cpu/classes/user:cpu-seconds": {
166 deps: makeStatDepSet(cpuStatsDep),
167 compute: func(in *statAggregate, out *metricValue) {
168 out.kind = metricKindFloat64
169 out.scalar = float64bits(nsToSec(in.cpuStats.UserTime))
170 },
171 },
172 "/gc/cleanups/executed:cleanups": {
173 deps: makeStatDepSet(finalStatsDep),
174 compute: func(in *statAggregate, out *metricValue) {
175 out.kind = metricKindUint64
176 out.scalar = in.finalStats.cleanupsExecuted
177 },
178 },
179 "/gc/cleanups/queued:cleanups": {
180 deps: makeStatDepSet(finalStatsDep),
181 compute: func(in *statAggregate, out *metricValue) {
182 out.kind = metricKindUint64
183 out.scalar = in.finalStats.cleanupsQueued
184 },
185 },
186 "/gc/cycles/automatic:gc-cycles": {
187 deps: makeStatDepSet(sysStatsDep),
188 compute: func(in *statAggregate, out *metricValue) {
189 out.kind = metricKindUint64
190 out.scalar = in.sysStats.gcCyclesDone - in.sysStats.gcCyclesForced
191 },
192 },
193 "/gc/cycles/forced:gc-cycles": {
194 deps: makeStatDepSet(sysStatsDep),
195 compute: func(in *statAggregate, out *metricValue) {
196 out.kind = metricKindUint64
197 out.scalar = in.sysStats.gcCyclesForced
198 },
199 },
200 "/gc/cycles/total:gc-cycles": {
201 deps: makeStatDepSet(sysStatsDep),
202 compute: func(in *statAggregate, out *metricValue) {
203 out.kind = metricKindUint64
204 out.scalar = in.sysStats.gcCyclesDone
205 },
206 },
207 "/gc/finalizers/executed:finalizers": {
208 deps: makeStatDepSet(finalStatsDep),
209 compute: func(in *statAggregate, out *metricValue) {
210 out.kind = metricKindUint64
211 out.scalar = in.finalStats.finalizersExecuted
212 },
213 },
214 "/gc/finalizers/queued:finalizers": {
215 deps: makeStatDepSet(finalStatsDep),
216 compute: func(in *statAggregate, out *metricValue) {
217 out.kind = metricKindUint64
218 out.scalar = in.finalStats.finalizersQueued
219 },
220 },
221 "/gc/scan/globals:bytes": {
222 deps: makeStatDepSet(gcStatsDep),
223 compute: func(in *statAggregate, out *metricValue) {
224 out.kind = metricKindUint64
225 out.scalar = in.gcStats.globalsScan
226 },
227 },
228 "/gc/scan/heap:bytes": {
229 deps: makeStatDepSet(gcStatsDep),
230 compute: func(in *statAggregate, out *metricValue) {
231 out.kind = metricKindUint64
232 out.scalar = in.gcStats.heapScan
233 },
234 },
235 "/gc/scan/stack:bytes": {
236 deps: makeStatDepSet(gcStatsDep),
237 compute: func(in *statAggregate, out *metricValue) {
238 out.kind = metricKindUint64
239 out.scalar = in.gcStats.stackScan
240 },
241 },
242 "/gc/scan/total:bytes": {
243 deps: makeStatDepSet(gcStatsDep),
244 compute: func(in *statAggregate, out *metricValue) {
245 out.kind = metricKindUint64
246 out.scalar = in.gcStats.totalScan
247 },
248 },
249 "/gc/heap/allocs-by-size:bytes": {
250 deps: makeStatDepSet(heapStatsDep),
251 compute: func(in *statAggregate, out *metricValue) {
252 hist := out.float64HistOrInit(sizeClassBuckets)
253 hist.counts[len(hist.counts)-1] = in.heapStats.largeAllocCount
254
255
256 for i, count := range in.heapStats.smallAllocCount[1:] {
257 hist.counts[i] = count
258 }
259 },
260 },
261 "/gc/heap/allocs:bytes": {
262 deps: makeStatDepSet(heapStatsDep),
263 compute: func(in *statAggregate, out *metricValue) {
264 out.kind = metricKindUint64
265 out.scalar = in.heapStats.totalAllocated
266 },
267 },
268 "/gc/heap/allocs:objects": {
269 deps: makeStatDepSet(heapStatsDep),
270 compute: func(in *statAggregate, out *metricValue) {
271 out.kind = metricKindUint64
272 out.scalar = in.heapStats.totalAllocs
273 },
274 },
275 "/gc/heap/frees-by-size:bytes": {
276 deps: makeStatDepSet(heapStatsDep),
277 compute: func(in *statAggregate, out *metricValue) {
278 hist := out.float64HistOrInit(sizeClassBuckets)
279 hist.counts[len(hist.counts)-1] = in.heapStats.largeFreeCount
280
281
282 for i, count := range in.heapStats.smallFreeCount[1:] {
283 hist.counts[i] = count
284 }
285 },
286 },
287 "/gc/heap/frees:bytes": {
288 deps: makeStatDepSet(heapStatsDep),
289 compute: func(in *statAggregate, out *metricValue) {
290 out.kind = metricKindUint64
291 out.scalar = in.heapStats.totalFreed
292 },
293 },
294 "/gc/heap/frees:objects": {
295 deps: makeStatDepSet(heapStatsDep),
296 compute: func(in *statAggregate, out *metricValue) {
297 out.kind = metricKindUint64
298 out.scalar = in.heapStats.totalFrees
299 },
300 },
301 "/gc/heap/goal:bytes": {
302 deps: makeStatDepSet(sysStatsDep),
303 compute: func(in *statAggregate, out *metricValue) {
304 out.kind = metricKindUint64
305 out.scalar = in.sysStats.heapGoal
306 },
307 },
308 "/gc/gomemlimit:bytes": {
309 compute: func(in *statAggregate, out *metricValue) {
310 out.kind = metricKindUint64
311 out.scalar = uint64(gcController.memoryLimit.Load())
312 },
313 },
314 "/gc/gogc:percent": {
315 compute: func(in *statAggregate, out *metricValue) {
316 out.kind = metricKindUint64
317 out.scalar = uint64(gcController.gcPercent.Load())
318 },
319 },
320 "/gc/heap/live:bytes": {
321 deps: makeStatDepSet(heapStatsDep),
322 compute: func(in *statAggregate, out *metricValue) {
323 out.kind = metricKindUint64
324 out.scalar = gcController.heapMarked
325 },
326 },
327 "/gc/heap/objects:objects": {
328 deps: makeStatDepSet(heapStatsDep),
329 compute: func(in *statAggregate, out *metricValue) {
330 out.kind = metricKindUint64
331 out.scalar = in.heapStats.numObjects
332 },
333 },
334 "/gc/heap/tiny/allocs:objects": {
335 deps: makeStatDepSet(heapStatsDep),
336 compute: func(in *statAggregate, out *metricValue) {
337 out.kind = metricKindUint64
338 out.scalar = in.heapStats.tinyAllocCount
339 },
340 },
341 "/gc/limiter/last-enabled:gc-cycle": {
342 compute: func(_ *statAggregate, out *metricValue) {
343 out.kind = metricKindUint64
344 out.scalar = uint64(gcCPULimiter.lastEnabledCycle.Load())
345 },
346 },
347 "/gc/pauses:seconds": {
348 compute: func(_ *statAggregate, out *metricValue) {
349
350 sched.stwTotalTimeGC.write(out)
351 },
352 },
353 "/gc/stack/starting-size:bytes": {
354 compute: func(in *statAggregate, out *metricValue) {
355 out.kind = metricKindUint64
356 out.scalar = uint64(startingStackSize)
357 },
358 },
359 "/memory/classes/heap/free:bytes": {
360 deps: makeStatDepSet(heapStatsDep),
361 compute: func(in *statAggregate, out *metricValue) {
362 out.kind = metricKindUint64
363 out.scalar = uint64(in.heapStats.committed - in.heapStats.inHeap -
364 in.heapStats.inStacks - in.heapStats.inWorkBufs)
365 },
366 },
367 "/memory/classes/heap/objects:bytes": {
368 deps: makeStatDepSet(heapStatsDep),
369 compute: func(in *statAggregate, out *metricValue) {
370 out.kind = metricKindUint64
371 out.scalar = in.heapStats.inObjects
372 },
373 },
374 "/memory/classes/heap/released:bytes": {
375 deps: makeStatDepSet(heapStatsDep),
376 compute: func(in *statAggregate, out *metricValue) {
377 out.kind = metricKindUint64
378 out.scalar = uint64(in.heapStats.released)
379 },
380 },
381 "/memory/classes/heap/stacks:bytes": {
382 deps: makeStatDepSet(heapStatsDep),
383 compute: func(in *statAggregate, out *metricValue) {
384 out.kind = metricKindUint64
385 out.scalar = uint64(in.heapStats.inStacks)
386 },
387 },
388 "/memory/classes/heap/unused:bytes": {
389 deps: makeStatDepSet(heapStatsDep),
390 compute: func(in *statAggregate, out *metricValue) {
391 out.kind = metricKindUint64
392 out.scalar = uint64(in.heapStats.inHeap) - in.heapStats.inObjects
393 },
394 },
395 "/memory/classes/metadata/mcache/free:bytes": {
396 deps: makeStatDepSet(sysStatsDep),
397 compute: func(in *statAggregate, out *metricValue) {
398 out.kind = metricKindUint64
399 out.scalar = in.sysStats.mCacheSys - in.sysStats.mCacheInUse
400 },
401 },
402 "/memory/classes/metadata/mcache/inuse:bytes": {
403 deps: makeStatDepSet(sysStatsDep),
404 compute: func(in *statAggregate, out *metricValue) {
405 out.kind = metricKindUint64
406 out.scalar = in.sysStats.mCacheInUse
407 },
408 },
409 "/memory/classes/metadata/mspan/free:bytes": {
410 deps: makeStatDepSet(sysStatsDep),
411 compute: func(in *statAggregate, out *metricValue) {
412 out.kind = metricKindUint64
413 out.scalar = in.sysStats.mSpanSys - in.sysStats.mSpanInUse
414 },
415 },
416 "/memory/classes/metadata/mspan/inuse:bytes": {
417 deps: makeStatDepSet(sysStatsDep),
418 compute: func(in *statAggregate, out *metricValue) {
419 out.kind = metricKindUint64
420 out.scalar = in.sysStats.mSpanInUse
421 },
422 },
423 "/memory/classes/metadata/other:bytes": {
424 deps: makeStatDepSet(heapStatsDep, sysStatsDep),
425 compute: func(in *statAggregate, out *metricValue) {
426 out.kind = metricKindUint64
427 out.scalar = uint64(in.heapStats.inWorkBufs) + in.sysStats.gcMiscSys
428 },
429 },
430 "/memory/classes/os-stacks:bytes": {
431 deps: makeStatDepSet(sysStatsDep),
432 compute: func(in *statAggregate, out *metricValue) {
433 out.kind = metricKindUint64
434 out.scalar = in.sysStats.stacksSys
435 },
436 },
437 "/memory/classes/other:bytes": {
438 deps: makeStatDepSet(sysStatsDep),
439 compute: func(in *statAggregate, out *metricValue) {
440 out.kind = metricKindUint64
441 out.scalar = in.sysStats.otherSys
442 },
443 },
444 "/memory/classes/profiling/buckets:bytes": {
445 deps: makeStatDepSet(sysStatsDep),
446 compute: func(in *statAggregate, out *metricValue) {
447 out.kind = metricKindUint64
448 out.scalar = in.sysStats.buckHashSys
449 },
450 },
451 "/memory/classes/total:bytes": {
452 deps: makeStatDepSet(heapStatsDep, sysStatsDep),
453 compute: func(in *statAggregate, out *metricValue) {
454 out.kind = metricKindUint64
455 out.scalar = uint64(in.heapStats.committed+in.heapStats.released) +
456 in.sysStats.stacksSys + in.sysStats.mSpanSys +
457 in.sysStats.mCacheSys + in.sysStats.buckHashSys +
458 in.sysStats.gcMiscSys + in.sysStats.otherSys
459 },
460 },
461 "/sched/gomaxprocs:threads": {
462 compute: func(_ *statAggregate, out *metricValue) {
463 out.kind = metricKindUint64
464 out.scalar = uint64(gomaxprocs)
465 },
466 },
467 "/sched/goroutines:goroutines": {
468 compute: func(_ *statAggregate, out *metricValue) {
469 out.kind = metricKindUint64
470 out.scalar = uint64(gcount())
471 },
472 },
473 "/sched/latencies:seconds": {
474 compute: func(_ *statAggregate, out *metricValue) {
475 sched.timeToRun.write(out)
476 },
477 },
478 "/sched/pauses/stopping/gc:seconds": {
479 compute: func(_ *statAggregate, out *metricValue) {
480 sched.stwStoppingTimeGC.write(out)
481 },
482 },
483 "/sched/pauses/stopping/other:seconds": {
484 compute: func(_ *statAggregate, out *metricValue) {
485 sched.stwStoppingTimeOther.write(out)
486 },
487 },
488 "/sched/pauses/total/gc:seconds": {
489 compute: func(_ *statAggregate, out *metricValue) {
490 sched.stwTotalTimeGC.write(out)
491 },
492 },
493 "/sched/pauses/total/other:seconds": {
494 compute: func(_ *statAggregate, out *metricValue) {
495 sched.stwTotalTimeOther.write(out)
496 },
497 },
498 "/sync/mutex/wait/total:seconds": {
499 compute: func(_ *statAggregate, out *metricValue) {
500 out.kind = metricKindFloat64
501 out.scalar = float64bits(nsToSec(totalMutexWaitTimeNanos()))
502 },
503 },
504 }
505
506 for _, info := range godebugs.All {
507 if !info.Opaque {
508 metrics["/godebug/non-default-behavior/"+info.Name+":events"] = metricData{compute: compute0}
509 }
510 }
511
512 metricsInit = true
513 }
514
515 func compute0(_ *statAggregate, out *metricValue) {
516 out.kind = metricKindUint64
517 out.scalar = 0
518 }
519
520 type metricReader func() uint64
521
522 func (f metricReader) compute(_ *statAggregate, out *metricValue) {
523 out.kind = metricKindUint64
524 out.scalar = f()
525 }
526
527
528 func godebug_registerMetric(name string, read func() uint64) {
529 metricsLock()
530 initMetrics()
531 d, ok := metrics[name]
532 if !ok {
533 throw("runtime: unexpected metric registration for " + name)
534 }
535 d.compute = metricReader(read).compute
536 metrics[name] = d
537 metricsUnlock()
538 }
539
540
541
542 type statDep uint
543
544 const (
545 heapStatsDep statDep = iota
546 sysStatsDep
547 cpuStatsDep
548 gcStatsDep
549 finalStatsDep
550 numStatsDeps
551 )
552
553
554
555
556 type statDepSet [1]uint64
557
558
559 func makeStatDepSet(deps ...statDep) statDepSet {
560 var s statDepSet
561 for _, d := range deps {
562 s[d/64] |= 1 << (d % 64)
563 }
564 return s
565 }
566
567
568 func (s statDepSet) difference(b statDepSet) statDepSet {
569 var c statDepSet
570 for i := range s {
571 c[i] = s[i] &^ b[i]
572 }
573 return c
574 }
575
576
577 func (s statDepSet) union(b statDepSet) statDepSet {
578 var c statDepSet
579 for i := range s {
580 c[i] = s[i] | b[i]
581 }
582 return c
583 }
584
585
586 func (s *statDepSet) empty() bool {
587 for _, c := range s {
588 if c != 0 {
589 return false
590 }
591 }
592 return true
593 }
594
595
596 func (s *statDepSet) has(d statDep) bool {
597 return s[d/64]&(1<<(d%64)) != 0
598 }
599
600
601
602
603
604
605 type heapStatsAggregate struct {
606 heapStatsDelta
607
608
609
610
611 inObjects uint64
612
613
614 numObjects uint64
615
616
617
618 totalAllocated uint64
619
620
621
622 totalFreed uint64
623
624
625
626 totalAllocs uint64
627
628
629
630 totalFrees uint64
631 }
632
633
634 func (a *heapStatsAggregate) compute() {
635 memstats.heapStats.read(&a.heapStatsDelta)
636
637
638 a.totalAllocs = a.largeAllocCount
639 a.totalFrees = a.largeFreeCount
640 a.totalAllocated = a.largeAlloc
641 a.totalFreed = a.largeFree
642 for i := range a.smallAllocCount {
643 na := a.smallAllocCount[i]
644 nf := a.smallFreeCount[i]
645 a.totalAllocs += na
646 a.totalFrees += nf
647 a.totalAllocated += na * uint64(gc.SizeClassToSize[i])
648 a.totalFreed += nf * uint64(gc.SizeClassToSize[i])
649 }
650 a.inObjects = a.totalAllocated - a.totalFreed
651 a.numObjects = a.totalAllocs - a.totalFrees
652 }
653
654
655
656
657
658
659
660
661 type sysStatsAggregate struct {
662 stacksSys uint64
663 mSpanSys uint64
664 mSpanInUse uint64
665 mCacheSys uint64
666 mCacheInUse uint64
667 buckHashSys uint64
668 gcMiscSys uint64
669 otherSys uint64
670 heapGoal uint64
671 gcCyclesDone uint64
672 gcCyclesForced uint64
673 }
674
675
676 func (a *sysStatsAggregate) compute() {
677 a.stacksSys = memstats.stacks_sys.load()
678 a.buckHashSys = memstats.buckhash_sys.load()
679 a.gcMiscSys = memstats.gcMiscSys.load()
680 a.otherSys = memstats.other_sys.load()
681 a.heapGoal = gcController.heapGoal()
682 a.gcCyclesDone = uint64(memstats.numgc)
683 a.gcCyclesForced = uint64(memstats.numforcedgc)
684
685 systemstack(func() {
686 lock(&mheap_.lock)
687 a.mSpanSys = memstats.mspan_sys.load()
688 a.mSpanInUse = uint64(mheap_.spanalloc.inuse)
689 a.mCacheSys = memstats.mcache_sys.load()
690 a.mCacheInUse = uint64(mheap_.cachealloc.inuse)
691 unlock(&mheap_.lock)
692 })
693 }
694
695
696
697 type cpuStatsAggregate struct {
698 cpuStats
699 }
700
701
702 func (a *cpuStatsAggregate) compute() {
703 a.cpuStats = work.cpuStats
704
705
706
707
708
709 }
710
711
712
713 type gcStatsAggregate struct {
714 heapScan uint64
715 stackScan uint64
716 globalsScan uint64
717 totalScan uint64
718 }
719
720
721 func (a *gcStatsAggregate) compute() {
722 a.heapScan = gcController.heapScan.Load()
723 a.stackScan = gcController.lastStackScan.Load()
724 a.globalsScan = gcController.globalsScan.Load()
725 a.totalScan = a.heapScan + a.stackScan + a.globalsScan
726 }
727
728
729
730 type finalStatsAggregate struct {
731 finalizersQueued uint64
732 finalizersExecuted uint64
733 cleanupsQueued uint64
734 cleanupsExecuted uint64
735 }
736
737
738 func (a *finalStatsAggregate) compute() {
739 a.finalizersQueued, a.finalizersExecuted = finReadQueueStats()
740 a.cleanupsQueued, a.cleanupsExecuted = gcCleanups.readQueueStats()
741 }
742
743
744
745 func nsToSec(ns int64) float64 {
746 return float64(ns) / 1e9
747 }
748
749
750
751
752
753
754 type statAggregate struct {
755 ensured statDepSet
756 heapStats heapStatsAggregate
757 sysStats sysStatsAggregate
758 cpuStats cpuStatsAggregate
759 gcStats gcStatsAggregate
760 finalStats finalStatsAggregate
761 }
762
763
764
765 func (a *statAggregate) ensure(deps *statDepSet) {
766 missing := deps.difference(a.ensured)
767 if missing.empty() {
768 return
769 }
770 for i := statDep(0); i < numStatsDeps; i++ {
771 if !missing.has(i) {
772 continue
773 }
774 switch i {
775 case heapStatsDep:
776 a.heapStats.compute()
777 case sysStatsDep:
778 a.sysStats.compute()
779 case cpuStatsDep:
780 a.cpuStats.compute()
781 case gcStatsDep:
782 a.gcStats.compute()
783 case finalStatsDep:
784 a.finalStats.compute()
785 }
786 }
787 a.ensured = a.ensured.union(missing)
788 }
789
790
791
792 type metricKind int
793
794 const (
795
796
797 metricKindBad metricKind = iota
798 metricKindUint64
799 metricKindFloat64
800 metricKindFloat64Histogram
801 )
802
803
804
805 type metricSample struct {
806 name string
807 value metricValue
808 }
809
810
811
812 type metricValue struct {
813 kind metricKind
814 scalar uint64
815 pointer unsafe.Pointer
816 }
817
818
819
820
821 func (v *metricValue) float64HistOrInit(buckets []float64) *metricFloat64Histogram {
822 var hist *metricFloat64Histogram
823 if v.kind == metricKindFloat64Histogram && v.pointer != nil {
824 hist = (*metricFloat64Histogram)(v.pointer)
825 } else {
826 v.kind = metricKindFloat64Histogram
827 hist = new(metricFloat64Histogram)
828 v.pointer = unsafe.Pointer(hist)
829 }
830 hist.buckets = buckets
831 if len(hist.counts) != len(hist.buckets)-1 {
832 hist.counts = make([]uint64, len(buckets)-1)
833 }
834 return hist
835 }
836
837
838
839 type metricFloat64Histogram struct {
840 counts []uint64
841 buckets []float64
842 }
843
844
845
846
847
848
849 var agg statAggregate
850
851 type metricName struct {
852 name string
853 kind metricKind
854 }
855
856
857
858
859
860 func readMetricNames() []string {
861 metricsLock()
862 initMetrics()
863 n := len(metrics)
864 metricsUnlock()
865
866 list := make([]string, 0, n)
867
868 metricsLock()
869 for name := range metrics {
870 list = append(list, name)
871 }
872 metricsUnlock()
873
874 return list
875 }
876
877
878
879
880 func readMetrics(samplesp unsafe.Pointer, len int, cap int) {
881 metricsLock()
882
883
884 initMetrics()
885
886
887 readMetricsLocked(samplesp, len, cap)
888 metricsUnlock()
889 }
890
891
892
893
894
895 func readMetricsLocked(samplesp unsafe.Pointer, len int, cap int) {
896
897 sl := slice{samplesp, len, cap}
898 samples := *(*[]metricSample)(unsafe.Pointer(&sl))
899
900
901 agg = statAggregate{}
902
903
904 for i := range samples {
905 sample := &samples[i]
906 data, ok := metrics[sample.name]
907 if !ok {
908 sample.value.kind = metricKindBad
909 continue
910 }
911
912
913 agg.ensure(&data.deps)
914
915
916 data.compute(&agg, &sample.value)
917 }
918 }
919
View as plain text