github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/metrics/graphite.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 package metrics 19 20 import ( 21 "bufio" 22 "fmt" 23 "log" 24 "net" 25 "strconv" 26 "strings" 27 "time" 28 ) 29 30 // GraphiteConfig provides a container with configuration parameters for 31 // the Graphite exporter 32 type GraphiteConfig struct { 33 Addr *net.TCPAddr // Network address to connect to 34 Registry Registry // Registry to be exported 35 FlushInterval time.Duration // Flush interval 36 DurationUnit time.Duration // Time conversion unit for durations 37 Prefix string // Prefix to be prepended to metric names 38 Percentiles []float64 // Percentiles to export from timers and histograms 39 } 40 41 // Graphite is a blocking exporter function which reports metrics in r 42 // to a graphite server located at addr, flushing them every d duration 43 // and prepending metric names with prefix. 44 func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { 45 GraphiteWithConfig(GraphiteConfig{ 46 Addr: addr, 47 Registry: r, 48 FlushInterval: d, 49 DurationUnit: time.Nanosecond, 50 Prefix: prefix, 51 Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999}, 52 }) 53 } 54 55 // GraphiteWithConfig is a blocking exporter function just like Graphite, 56 // but it takes a GraphiteConfig instead. 57 func GraphiteWithConfig(c GraphiteConfig) { 58 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") 59 for range time.Tick(c.FlushInterval) { 60 if err := graphite(&c); nil != err { 61 log.Println(err) 62 } 63 } 64 } 65 66 // GraphiteOnce performs a single submission to Graphite, returning a 67 // non-nil error on failed connections. This can be used in a loop 68 // similar to GraphiteWithConfig for custom error handling. 69 func GraphiteOnce(c GraphiteConfig) error { 70 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") 71 return graphite(&c) 72 } 73 74 func graphite(c *GraphiteConfig) error { 75 now := time.Now().Unix() 76 du := float64(c.DurationUnit) 77 conn, err := net.DialTCP("tcp", nil, c.Addr) 78 if nil != err { 79 return err 80 } 81 defer conn.Close() 82 w := bufio.NewWriter(conn) 83 c.Registry.Each(func(name string, i interface{}) { 84 switch metric := i.(type) { 85 case Counter: 86 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now) 87 case Gauge: 88 fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now) 89 case GaugeFloat64: 90 fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now) 91 case Histogram: 92 h := metric.Snapshot() 93 ps := h.Percentiles(c.Percentiles) 94 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now) 95 fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now) 96 fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now) 97 fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now) 98 fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now) 99 for psIdx, psKey := range c.Percentiles { 100 key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) 101 fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) 102 } 103 case Meter: 104 m := metric.Snapshot() 105 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now) 106 fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now) 107 fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now) 108 fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now) 109 fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now) 110 case Timer: 111 t := metric.Snapshot() 112 ps := t.Percentiles(c.Percentiles) 113 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now) 114 fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now) 115 fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now) 116 fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now) 117 fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now) 118 for psIdx, psKey := range c.Percentiles { 119 key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) 120 fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) 121 } 122 fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now) 123 fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now) 124 fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now) 125 fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now) 126 } 127 w.Flush() 128 }) 129 return nil 130 }