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  }