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