1// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package metrics_test
6
7import (
8	"fmt"
9	"runtime/metrics"
10)
11
12func ExampleRead_readingOneMetric() {
13	// Name of the metric we want to read.
14	const myMetric = "/memory/classes/heap/free:bytes"
15
16	// Create a sample for the metric.
17	sample := make([]metrics.Sample, 1)
18	sample[0].Name = myMetric
19
20	// Sample the metric.
21	metrics.Read(sample)
22
23	// Check if the metric is actually supported.
24	// If it's not, the resulting value will always have
25	// kind KindBad.
26	if sample[0].Value.Kind() == metrics.KindBad {
27		panic(fmt.Sprintf("metric %q no longer supported", myMetric))
28	}
29
30	// Handle the result.
31	//
32	// It's OK to assume a particular Kind for a metric;
33	// they're guaranteed not to change.
34	freeBytes := sample[0].Value.Uint64()
35
36	fmt.Printf("free but not released memory: %d\n", freeBytes)
37}
38
39func ExampleRead_readingAllMetrics() {
40	// Get descriptions for all supported metrics.
41	descs := metrics.All()
42
43	// Create a sample for each metric.
44	samples := make([]metrics.Sample, len(descs))
45	for i := range samples {
46		samples[i].Name = descs[i].Name
47	}
48
49	// Sample the metrics. Re-use the samples slice if you can!
50	metrics.Read(samples)
51
52	// Iterate over all results.
53	for _, sample := range samples {
54		// Pull out the name and value.
55		name, value := sample.Name, sample.Value
56
57		// Handle each sample.
58		switch value.Kind() {
59		case metrics.KindUint64:
60			fmt.Printf("%s: %d\n", name, value.Uint64())
61		case metrics.KindFloat64:
62			fmt.Printf("%s: %f\n", name, value.Float64())
63		case metrics.KindFloat64Histogram:
64			// The histogram may be quite large, so let's just pull out
65			// a crude estimate for the median for the sake of this example.
66			fmt.Printf("%s: %f\n", name, medianBucket(value.Float64Histogram()))
67		case metrics.KindBad:
68			// This should never happen because all metrics are supported
69			// by construction.
70			panic("bug in runtime/metrics package!")
71		default:
72			// This may happen as new metrics get added.
73			//
74			// The safest thing to do here is to simply log it somewhere
75			// as something to look into, but ignore it for now.
76			// In the worst case, you might temporarily miss out on a new metric.
77			fmt.Printf("%s: unexpected metric Kind: %v\n", name, value.Kind())
78		}
79	}
80}
81
82func medianBucket(h *metrics.Float64Histogram) float64 {
83	total := uint64(0)
84	for _, count := range h.Counts {
85		total += count
86	}
87	thresh := total / 2
88	total = 0
89	for i, count := range h.Counts {
90		total += count
91		if total >= thresh {
92			return h.Buckets[i]
93		}
94	}
95	panic("should not happen")
96}
97