github.com/theQRL/go-zond@v0.1.1/metrics/opentsdb.go (about)

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