github.com/zjj1991/quorum@v0.0.0-20190524123704-ae4b0a1e1a19/metrics/graphite.go (about) 1 package metrics 2 3 import ( 4 "bufio" 5 "fmt" 6 "log" 7 "net" 8 "strconv" 9 "strings" 10 "time" 11 ) 12 13 // GraphiteConfig provides a container with configuration parameters for 14 // the Graphite exporter 15 type GraphiteConfig struct { 16 Addr *net.TCPAddr // Network address to connect to 17 Registry Registry // Registry to be exported 18 FlushInterval time.Duration // Flush interval 19 DurationUnit time.Duration // Time conversion unit for durations 20 Prefix string // Prefix to be prepended to metric names 21 Percentiles []float64 // Percentiles to export from timers and histograms 22 } 23 24 // Graphite is a blocking exporter function which reports metrics in r 25 // to a graphite server located at addr, flushing them every d duration 26 // and prepending metric names with prefix. 27 func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { 28 GraphiteWithConfig(GraphiteConfig{ 29 Addr: addr, 30 Registry: r, 31 FlushInterval: d, 32 DurationUnit: time.Nanosecond, 33 Prefix: prefix, 34 Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999}, 35 }) 36 } 37 38 // GraphiteWithConfig is a blocking exporter function just like Graphite, 39 // but it takes a GraphiteConfig instead. 40 func GraphiteWithConfig(c GraphiteConfig) { 41 log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") 42 for range time.Tick(c.FlushInterval) { 43 if err := graphite(&c); nil != err { 44 log.Println(err) 45 } 46 } 47 } 48 49 // GraphiteOnce performs a single submission to Graphite, returning a 50 // non-nil error on failed connections. This can be used in a loop 51 // similar to GraphiteWithConfig for custom error handling. 52 func GraphiteOnce(c GraphiteConfig) error { 53 log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") 54 return graphite(&c) 55 } 56 57 func graphite(c *GraphiteConfig) error { 58 now := time.Now().Unix() 59 du := float64(c.DurationUnit) 60 conn, err := net.DialTCP("tcp", nil, c.Addr) 61 if nil != err { 62 return err 63 } 64 defer conn.Close() 65 w := bufio.NewWriter(conn) 66 c.Registry.Each(func(name string, i interface{}) { 67 switch metric := i.(type) { 68 case Counter: 69 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now) 70 case Gauge: 71 fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now) 72 case GaugeFloat64: 73 fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now) 74 case Histogram: 75 h := metric.Snapshot() 76 ps := h.Percentiles(c.Percentiles) 77 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now) 78 fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now) 79 fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now) 80 fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now) 81 fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now) 82 for psIdx, psKey := range c.Percentiles { 83 key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) 84 fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) 85 } 86 case Meter: 87 m := metric.Snapshot() 88 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now) 89 fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now) 90 fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now) 91 fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now) 92 fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now) 93 case Timer: 94 t := metric.Snapshot() 95 ps := t.Percentiles(c.Percentiles) 96 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now) 97 fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now) 98 fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now) 99 fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now) 100 fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now) 101 for psIdx, psKey := range c.Percentiles { 102 key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) 103 fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) 104 } 105 fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now) 106 fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now) 107 fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now) 108 fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now) 109 } 110 w.Flush() 111 }) 112 return nil 113 }