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