1package metrics
2
3import (
4	"fmt"
5	"io"
6	"sort"
7	"time"
8)
9
10// Write sorts writes each metric in the given registry periodically to the
11// given io.Writer.
12func Write(r Registry, d time.Duration, w io.Writer) {
13	for _ = range time.Tick(d) {
14		WriteOnce(r, w)
15	}
16}
17
18// WriteOnce sorts and writes metrics in the given registry to the given
19// io.Writer.
20func WriteOnce(r Registry, w io.Writer) {
21	var namedMetrics namedMetricSlice
22	r.Each(func(name string, i interface{}) {
23		namedMetrics = append(namedMetrics, namedMetric{name, i})
24	})
25
26	sort.Sort(namedMetrics)
27	for _, namedMetric := range namedMetrics {
28		switch metric := namedMetric.m.(type) {
29		case Counter:
30			fmt.Fprintf(w, "counter %s\n", namedMetric.name)
31			fmt.Fprintf(w, "  count:       %9d\n", metric.Count())
32		case Gauge:
33			fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
34			fmt.Fprintf(w, "  value:       %9d\n", metric.Value())
35		case GaugeFloat64:
36			fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
37			fmt.Fprintf(w, "  value:       %f\n", metric.Value())
38		case Healthcheck:
39			metric.Check()
40			fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name)
41			fmt.Fprintf(w, "  error:       %v\n", metric.Error())
42		case Histogram:
43			h := metric.Snapshot()
44			ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
45			fmt.Fprintf(w, "histogram %s\n", namedMetric.name)
46			fmt.Fprintf(w, "  count:       %9d\n", h.Count())
47			fmt.Fprintf(w, "  min:         %9d\n", h.Min())
48			fmt.Fprintf(w, "  max:         %9d\n", h.Max())
49			fmt.Fprintf(w, "  mean:        %12.2f\n", h.Mean())
50			fmt.Fprintf(w, "  stddev:      %12.2f\n", h.StdDev())
51			fmt.Fprintf(w, "  median:      %12.2f\n", ps[0])
52			fmt.Fprintf(w, "  75%%:         %12.2f\n", ps[1])
53			fmt.Fprintf(w, "  95%%:         %12.2f\n", ps[2])
54			fmt.Fprintf(w, "  99%%:         %12.2f\n", ps[3])
55			fmt.Fprintf(w, "  99.9%%:       %12.2f\n", ps[4])
56		case Meter:
57			m := metric.Snapshot()
58			fmt.Fprintf(w, "meter %s\n", namedMetric.name)
59			fmt.Fprintf(w, "  count:       %9d\n", m.Count())
60			fmt.Fprintf(w, "  1-min rate:  %12.2f\n", m.Rate1())
61			fmt.Fprintf(w, "  5-min rate:  %12.2f\n", m.Rate5())
62			fmt.Fprintf(w, "  15-min rate: %12.2f\n", m.Rate15())
63			fmt.Fprintf(w, "  mean rate:   %12.2f\n", m.RateMean())
64		case Timer:
65			t := metric.Snapshot()
66			ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
67			fmt.Fprintf(w, "timer %s\n", namedMetric.name)
68			fmt.Fprintf(w, "  count:       %9d\n", t.Count())
69			fmt.Fprintf(w, "  min:         %9d\n", t.Min())
70			fmt.Fprintf(w, "  max:         %9d\n", t.Max())
71			fmt.Fprintf(w, "  mean:        %12.2f\n", t.Mean())
72			fmt.Fprintf(w, "  stddev:      %12.2f\n", t.StdDev())
73			fmt.Fprintf(w, "  median:      %12.2f\n", ps[0])
74			fmt.Fprintf(w, "  75%%:         %12.2f\n", ps[1])
75			fmt.Fprintf(w, "  95%%:         %12.2f\n", ps[2])
76			fmt.Fprintf(w, "  99%%:         %12.2f\n", ps[3])
77			fmt.Fprintf(w, "  99.9%%:       %12.2f\n", ps[4])
78			fmt.Fprintf(w, "  1-min rate:  %12.2f\n", t.Rate1())
79			fmt.Fprintf(w, "  5-min rate:  %12.2f\n", t.Rate5())
80			fmt.Fprintf(w, "  15-min rate: %12.2f\n", t.Rate15())
81			fmt.Fprintf(w, "  mean rate:   %12.2f\n", t.RateMean())
82		}
83	}
84}
85
86type namedMetric struct {
87	name string
88	m    interface{}
89}
90
91// namedMetricSlice is a slice of namedMetrics that implements sort.Interface.
92type namedMetricSlice []namedMetric
93
94func (nms namedMetricSlice) Len() int { return len(nms) }
95
96func (nms namedMetricSlice) Swap(i, j int) { nms[i], nms[j] = nms[j], nms[i] }
97
98func (nms namedMetricSlice) Less(i, j int) bool {
99	return nms[i].name < nms[j].name
100}
101