blob: 266b6c93d21def6b339d6f14a686095b2c736d12 [file] [log] [blame]
Scott Bakereee8dd82019-09-24 12:52:34 -07001package metrics
2
3import (
4 "bufio"
5 "fmt"
6 "log"
7 "net"
8 "os"
9 "strings"
10 "time"
11)
12
13var shortHostName string = ""
14
15// OpenTSDBConfig provides a container with configuration parameters for
16// the OpenTSDB exporter
17type 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.
28func 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.
40func 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
48func 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
60func 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}