github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/metrics/opentsdb.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 "os" 26 "strings" 27 "time" 28 ) 29 30 var shortHostName = "" 31 32 // OpenTSDBConfig provides a container with configuration parameters for 33 // the OpenTSDB exporter 34 type OpenTSDBConfig struct { 35 Addr *net.TCPAddr // Network address to connect to 36 Registry Registry // Registry to be exported 37 FlushInterval time.Duration // Flush interval 38 DurationUnit time.Duration // Time conversion unit for durations 39 Prefix string // Prefix to be prepended to metric names 40 } 41 42 // OpenTSDB is a blocking exporter function which reports metrics in r 43 // to a TSDB server located at addr, flushing them every d duration 44 // and prepending metric names with prefix. 45 func OpenTSDB(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { 46 OpenTSDBWithConfig(OpenTSDBConfig{ 47 Addr: addr, 48 Registry: r, 49 FlushInterval: d, 50 DurationUnit: time.Nanosecond, 51 Prefix: prefix, 52 }) 53 } 54 55 // OpenTSDBWithConfig is a blocking exporter function just like OpenTSDB, 56 // but it takes a OpenTSDBConfig instead. 57 func OpenTSDBWithConfig(c OpenTSDBConfig) { 58 for range time.Tick(c.FlushInterval) { 59 if err := openTSDB(&c); nil != err { 60 log.Println(err) 61 } 62 } 63 } 64 65 func getShortHostname() string { 66 if shortHostName == "" { 67 host, _ := os.Hostname() 68 if index := strings.Index(host, "."); index > 0 { 69 shortHostName = host[:index] 70 } else { 71 shortHostName = host 72 } 73 } 74 return shortHostName 75 } 76 77 func openTSDB(c *OpenTSDBConfig) error { 78 shortHostname := getShortHostname() 79 now := time.Now().Unix() 80 du := float64(c.DurationUnit) 81 conn, err := net.DialTCP("tcp", nil, c.Addr) 82 if nil != err { 83 return err 84 } 85 defer conn.Close() 86 w := bufio.NewWriter(conn) 87 c.Registry.Each(func(name string, i interface{}) { 88 switch metric := i.(type) { 89 case Counter: 90 fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname) 91 case Gauge: 92 fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) 93 case GaugeFloat64: 94 fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) 95 case Histogram: 96 h := metric.Snapshot() 97 ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) 98 fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, h.Count(), shortHostname) 99 fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, h.Min(), shortHostname) 100 fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, h.Max(), shortHostname) 101 fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, h.Mean(), shortHostname) 102 fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, h.StdDev(), shortHostname) 103 fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0], shortHostname) 104 fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1], shortHostname) 105 fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2], shortHostname) 106 fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3], shortHostname) 107 fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4], shortHostname) 108 case Meter: 109 m := metric.Snapshot() 110 fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, m.Count(), shortHostname) 111 fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate1(), shortHostname) 112 fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate5(), shortHostname) 113 fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate15(), shortHostname) 114 fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, m.RateMean(), shortHostname) 115 case Timer: 116 t := metric.Snapshot() 117 ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) 118 fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, t.Count(), shortHostname) 119 fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, t.Min()/int64(du), shortHostname) 120 fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, t.Max()/int64(du), shortHostname) 121 fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, t.Mean()/du, shortHostname) 122 fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, t.StdDev()/du, shortHostname) 123 fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0]/du, shortHostname) 124 fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1]/du, shortHostname) 125 fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2]/du, shortHostname) 126 fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3]/du, shortHostname) 127 fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4]/du, shortHostname) 128 fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate1(), shortHostname) 129 fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate5(), shortHostname) 130 fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate15(), shortHostname) 131 fmt.Fprintf(w, "put %s.%s.mean-rate %d %.2f host=%s\n", c.Prefix, name, now, t.RateMean(), shortHostname) 132 } 133 w.Flush() 134 }) 135 return nil 136 }