github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/metricsutil/write_metrics.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package metricsutil 6 7 import ( 8 "fmt" 9 "io" 10 "sort" 11 "time" 12 13 "github.com/rcrowley/go-metrics" 14 ) 15 16 // The code below is adapted from 17 // https://github.com/rcrowley/go-metrics/blob/master/writer.go 18 // . 19 20 // WriteMetrics sorts and writes metrics in the given registry to the given 21 // io.Writer. 22 func WriteMetrics(r metrics.Registry, w io.Writer) { 23 var namedMetrics namedMetricSlice 24 r.Each(func(name string, i interface{}) { 25 namedMetrics = append(namedMetrics, namedMetric{name, i}) 26 }) 27 28 sort.Sort(namedMetrics) 29 for _, namedMetric := range namedMetrics { 30 switch metric := namedMetric.m.(type) { 31 case metrics.Counter: 32 fmt.Fprintf(w, "counter %s\n", namedMetric.name) 33 fmt.Fprintf(w, " count: %9d\n", metric.Count()) 34 case metrics.Gauge: 35 fmt.Fprintf(w, "gauge %s\n", namedMetric.name) 36 fmt.Fprintf(w, " value: %9d\n", metric.Value()) 37 case metrics.GaugeFloat64: 38 fmt.Fprintf(w, "gauge %s\n", namedMetric.name) 39 fmt.Fprintf(w, " value: %f\n", metric.Value()) 40 case metrics.Healthcheck: 41 metric.Check() 42 fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name) 43 fmt.Fprintf(w, " error: %v\n", metric.Error()) 44 case metrics.Histogram: 45 h := metric.Snapshot() 46 ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) 47 fmt.Fprintf(w, "histogram %s\n", namedMetric.name) 48 fmt.Fprintf(w, " count=%d, mean=%.2f, stddef=%.2f\n", h.Count(), h.Mean(), h.StdDev()) 49 fmt.Fprintf(w, " min=%.2fms median=%.2fms max=%.2fms\n", 50 float64(h.Min())/float64(time.Millisecond), 51 ps[0]/float64(time.Millisecond), 52 float64(h.Max())/float64(time.Millisecond)) 53 fmt.Fprintf(w, " %%iles (ms): 75=%.2f 95=%.2f 99=%.2f 99.9=%.2f\n", 54 ps[1]/float64(time.Millisecond), 55 ps[2]/float64(time.Millisecond), 56 ps[3]/float64(time.Millisecond), 57 ps[4]/float64(time.Millisecond)) 58 case metrics.Meter: 59 m := metric.Snapshot() 60 fmt.Fprintf(w, "meter %s\n", namedMetric.name) 61 fmt.Fprintf(w, " count: %d\n", m.Count()) 62 fmt.Fprintf(w, " rates: 1m=%.2f 5m=%.2f 15m=%.2f mean=%.2f\n", m.Rate1(), m.Rate5(), m.Rate15(), m.RateMean()) 63 case metrics.Timer: 64 t := metric.Snapshot() 65 ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) 66 fmt.Fprintf(w, "timer %s\n", namedMetric.name) 67 fmt.Fprintf(w, " count=%d, mean=%.2fms, stddev=%.2fms\n", 68 t.Count(), t.Mean()/float64(time.Millisecond), t.StdDev()/float64(time.Millisecond)) 69 fmt.Fprintf(w, " min=%.2fms median=%.2fms max=%.2fms\n", 70 float64(t.Min())/float64(time.Millisecond), 71 ps[0]/float64(time.Millisecond), 72 float64(t.Max())/float64(time.Millisecond)) 73 fmt.Fprintf(w, " %%iles (ms): 75=%.2f 95=%.2f 99=%.2f 99.9=%.2f\n", 74 ps[1]/float64(time.Millisecond), 75 ps[2]/float64(time.Millisecond), 76 ps[3]/float64(time.Millisecond), 77 ps[4]/float64(time.Millisecond)) 78 fmt.Fprintf(w, " rates: 1m=%.2f 5m=%.2f 15m=%.2f mean=%.2f\n", t.Rate1(), t.Rate5(), t.Rate15(), t.RateMean()) 79 } 80 } 81 } 82 83 type namedMetric struct { 84 name string 85 m interface{} 86 } 87 88 // namedMetricSlice is a slice of namedMetrics that implements sort.Interface. 89 type namedMetricSlice []namedMetric 90 91 func (nms namedMetricSlice) Len() int { return len(nms) } 92 93 func (nms namedMetricSlice) Swap(i, j int) { nms[i], nms[j] = nms[j], nms[i] } 94 95 func (nms namedMetricSlice) Less(i, j int) bool { 96 return nms[i].name < nms[j].name 97 }