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