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