gitlab.com/aquachain/aquachain@v1.17.16-rc3.0.20221018032414-e3ddf1e1c055/common/metrics/opentsdb.go (about)

     1  // Copyright 2018 The aquachain Authors
     2  // This file is part of the aquachain library.
     3  //
     4  // The aquachain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The aquachain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the aquachain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package metrics
    18  
    19  import (
    20  	"bufio"
    21  	"fmt"
    22  	"log"
    23  	"net"
    24  	"os"
    25  	"strings"
    26  	"time"
    27  )
    28  
    29  var shortHostName string = ""
    30  
    31  // OpenTSDBConfig provides a container with configuration parameters for
    32  // the OpenTSDB exporter
    33  type OpenTSDBConfig struct {
    34  	Addr          *net.TCPAddr  // Network address to connect to
    35  	Registry      Registry      // Registry to be exported
    36  	FlushInterval time.Duration // Flush interval
    37  	DurationUnit  time.Duration // Time conversion unit for durations
    38  	Prefix        string        // Prefix to be prepended to metric names
    39  }
    40  
    41  // OpenTSDB is a blocking exporter function which reports metrics in r
    42  // to a TSDB server located at addr, flushing them every d duration
    43  // and prepending metric names with prefix.
    44  func OpenTSDB(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) {
    45  	OpenTSDBWithConfig(OpenTSDBConfig{
    46  		Addr:          addr,
    47  		Registry:      r,
    48  		FlushInterval: d,
    49  		DurationUnit:  time.Nanosecond,
    50  		Prefix:        prefix,
    51  	})
    52  }
    53  
    54  // OpenTSDBWithConfig is a blocking exporter function just like OpenTSDB,
    55  // but it takes a OpenTSDBConfig instead.
    56  func OpenTSDBWithConfig(c OpenTSDBConfig) {
    57  	for range time.Tick(c.FlushInterval) {
    58  		if err := openTSDB(&c); nil != err {
    59  			log.Println(err)
    60  		}
    61  	}
    62  }
    63  
    64  func getShortHostname() string {
    65  	if shortHostName == "" {
    66  		host, _ := os.Hostname()
    67  		if index := strings.Index(host, "."); index > 0 {
    68  			shortHostName = host[:index]
    69  		} else {
    70  			shortHostName = host
    71  		}
    72  	}
    73  	return shortHostName
    74  }
    75  
    76  func openTSDB(c *OpenTSDBConfig) error {
    77  	shortHostname := getShortHostname()
    78  	now := time.Now().Unix()
    79  	du := float64(c.DurationUnit)
    80  	conn, err := net.DialTCP("tcp", nil, c.Addr)
    81  	if nil != err {
    82  		return err
    83  	}
    84  	defer conn.Close()
    85  	w := bufio.NewWriter(conn)
    86  	c.Registry.Each(func(name string, i interface{}) {
    87  		switch metric := i.(type) {
    88  		case Counter:
    89  			fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname)
    90  		case Gauge:
    91  			fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname)
    92  		case GaugeFloat64:
    93  			fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname)
    94  		case Histogram:
    95  			h := metric.Snapshot()
    96  			ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
    97  			fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, h.Count(), shortHostname)
    98  			fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, h.Min(), shortHostname)
    99  			fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, h.Max(), shortHostname)
   100  			fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, h.Mean(), shortHostname)
   101  			fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, h.StdDev(), shortHostname)
   102  			fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0], shortHostname)
   103  			fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1], shortHostname)
   104  			fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2], shortHostname)
   105  			fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3], shortHostname)
   106  			fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4], shortHostname)
   107  		case Meter:
   108  			m := metric.Snapshot()
   109  			fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, m.Count(), shortHostname)
   110  			fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate1(), shortHostname)
   111  			fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate5(), shortHostname)
   112  			fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate15(), shortHostname)
   113  			fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, m.RateMean(), shortHostname)
   114  		case Timer:
   115  			t := metric.Snapshot()
   116  			ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
   117  			fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, t.Count(), shortHostname)
   118  			fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, t.Min()/int64(du), shortHostname)
   119  			fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, t.Max()/int64(du), shortHostname)
   120  			fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, t.Mean()/du, shortHostname)
   121  			fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, t.StdDev()/du, shortHostname)
   122  			fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0]/du, shortHostname)
   123  			fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1]/du, shortHostname)
   124  			fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2]/du, shortHostname)
   125  			fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3]/du, shortHostname)
   126  			fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4]/du, shortHostname)
   127  			fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate1(), shortHostname)
   128  			fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate5(), shortHostname)
   129  			fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate15(), shortHostname)
   130  			fmt.Fprintf(w, "put %s.%s.mean-rate %d %.2f host=%s\n", c.Prefix, name, now, t.RateMean(), shortHostname)
   131  		}
   132  		w.Flush()
   133  	})
   134  	return nil
   135  }