github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/metrics/graphite.go (about)

     1  package metrics
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"log"
     7  	"net"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  )
    12  
    13  // GraphiteConfig provides a container with configuration parameters for
    14  // the Graphite exporter
    15  type GraphiteConfig struct {
    16  	Addr          *net.TCPAddr  // Network address to connect to
    17  	Registry      Registry      // Registry to be exported
    18  	FlushInterval time.Duration // Flush interval
    19  	DurationUnit  time.Duration // Time conversion unit for durations
    20  	Prefix        string        // Prefix to be prepended to metric names
    21  	Percentiles   []float64     // Percentiles to export from timers and histograms
    22  }
    23  
    24  // Graphite is a blocking exporter function which reports metrics in r
    25  // to a graphite server located at addr, flushing them every d duration
    26  // and prepending metric names with prefix.
    27  func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) {
    28  	GraphiteWithConfig(GraphiteConfig{
    29  		Addr:          addr,
    30  		Registry:      r,
    31  		FlushInterval: d,
    32  		DurationUnit:  time.Nanosecond,
    33  		Prefix:        prefix,
    34  		Percentiles:   []float64{0.5, 0.75, 0.95, 0.99, 0.999},
    35  	})
    36  }
    37  
    38  // GraphiteWithConfig is a blocking exporter function just like Graphite,
    39  // but it takes a GraphiteConfig instead.
    40  func GraphiteWithConfig(c GraphiteConfig) {
    41  	log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015")
    42  	for range time.Tick(c.FlushInterval) {
    43  		if err := graphite(&c); nil != err {
    44  			log.Println(err)
    45  		}
    46  	}
    47  }
    48  
    49  // GraphiteOnce performs a single submission to Graphite, returning a
    50  // non-nil error on failed connections. This can be used in a loop
    51  // similar to GraphiteWithConfig for custom error handling.
    52  func GraphiteOnce(c GraphiteConfig) error {
    53  	log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015")
    54  	return graphite(&c)
    55  }
    56  
    57  func graphite(c *GraphiteConfig) error {
    58  	now := time.Now().Unix()
    59  	du := float64(c.DurationUnit)
    60  	conn, err := net.DialTCP("tcp", nil, c.Addr)
    61  	if nil != err {
    62  		return err
    63  	}
    64  	defer conn.Close()
    65  	w := bufio.NewWriter(conn)
    66  	c.Registry.Each(func(name string, i interface{}) {
    67  		switch metric := i.(type) {
    68  		case Counter:
    69  			fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now)
    70  		case Gauge:
    71  			fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now)
    72  		case GaugeFloat64:
    73  			fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now)
    74  		case Histogram:
    75  			h := metric.Snapshot()
    76  			ps := h.Percentiles(c.Percentiles)
    77  			fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now)
    78  			fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now)
    79  			fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now)
    80  			fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now)
    81  			fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now)
    82  			for psIdx, psKey := range c.Percentiles {
    83  				key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
    84  				fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now)
    85  			}
    86  		case Meter:
    87  			m := metric.Snapshot()
    88  			fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now)
    89  			fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now)
    90  			fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now)
    91  			fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now)
    92  			fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now)
    93  		case Timer:
    94  			t := metric.Snapshot()
    95  			ps := t.Percentiles(c.Percentiles)
    96  			fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now)
    97  			fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now)
    98  			fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now)
    99  			fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now)
   100  			fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now)
   101  			for psIdx, psKey := range c.Percentiles {
   102  				key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
   103  				fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now)
   104  			}
   105  			fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now)
   106  			fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now)
   107  			fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now)
   108  			fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now)
   109  		}
   110  		w.Flush()
   111  	})
   112  	return nil
   113  }