github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/metrics/librato/librato.go (about)

     1  package librato
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"math"
     7  	"regexp"
     8  	"time"
     9  
    10  	"github.com/neatlab/neatio/utilities/metrics"
    11  )
    12  
    13  var unitRegexp = regexp.MustCompile(`[^\\d]+$`)
    14  
    15  func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) {
    16  	attrs = make(map[string]interface{})
    17  	attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d))
    18  	attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String())))
    19  	return
    20  }
    21  
    22  type Reporter struct {
    23  	Email, Token    string
    24  	Namespace       string
    25  	Source          string
    26  	Interval        time.Duration
    27  	Registry        metrics.Registry
    28  	Percentiles     []float64
    29  	TimerAttributes map[string]interface{}
    30  	intervalSec     int64
    31  }
    32  
    33  func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
    34  	return &Reporter{e, t, "", s, d, r, p, translateTimerAttributes(u), int64(d / time.Second)}
    35  }
    36  
    37  func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) {
    38  	NewReporter(r, d, e, t, s, p, u).Run()
    39  }
    40  
    41  func (self *Reporter) Run() {
    42  	log.Printf("WARNING: This client has been DEPRECATED! It has been moved to https://github.com/mihasya/go-metrics-librato and will be removed from rcrowley/go-metrics on August 5th 2015")
    43  	ticker := time.Tick(self.Interval)
    44  	metricsApi := &LibratoClient{self.Email, self.Token}
    45  	for now := range ticker {
    46  		var metrics Batch
    47  		var err error
    48  		if metrics, err = self.BuildRequest(now, self.Registry); err != nil {
    49  			log.Printf("ERROR constructing librato request body %s", err)
    50  			continue
    51  		}
    52  		if err := metricsApi.PostMetrics(metrics); err != nil {
    53  			log.Printf("ERROR sending metrics to librato %s", err)
    54  			continue
    55  		}
    56  	}
    57  }
    58  
    59  func sumSquares(s metrics.Sample) float64 {
    60  	count := float64(s.Count())
    61  	sumSquared := math.Pow(count*s.Mean(), 2)
    62  	sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count
    63  	if math.IsNaN(sumSquares) {
    64  		return 0.0
    65  	}
    66  	return sumSquares
    67  }
    68  func sumSquaresTimer(t metrics.Timer) float64 {
    69  	count := float64(t.Count())
    70  	sumSquared := math.Pow(count*t.Mean(), 2)
    71  	sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count
    72  	if math.IsNaN(sumSquares) {
    73  		return 0.0
    74  	}
    75  	return sumSquares
    76  }
    77  
    78  func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
    79  	snapshot = Batch{
    80  		MeasureTime: (now.Unix() / self.intervalSec) * self.intervalSec,
    81  		Source:      self.Source,
    82  	}
    83  	snapshot.Gauges = make([]Measurement, 0)
    84  	snapshot.Counters = make([]Measurement, 0)
    85  	histogramGaugeCount := 1 + len(self.Percentiles)
    86  	r.Each(func(name string, metric interface{}) {
    87  		if self.Namespace != "" {
    88  			name = fmt.Sprintf("%s.%s", self.Namespace, name)
    89  		}
    90  		measurement := Measurement{}
    91  		measurement[Period] = self.Interval.Seconds()
    92  		switch m := metric.(type) {
    93  		case metrics.Counter:
    94  			if m.Count() > 0 {
    95  				measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
    96  				measurement[Value] = float64(m.Count())
    97  				measurement[Attributes] = map[string]interface{}{
    98  					DisplayUnitsLong:  Operations,
    99  					DisplayUnitsShort: OperationsShort,
   100  					DisplayMin:        "0",
   101  				}
   102  				snapshot.Counters = append(snapshot.Counters, measurement)
   103  			}
   104  		case metrics.Gauge:
   105  			measurement[Name] = name
   106  			measurement[Value] = float64(m.Value())
   107  			snapshot.Gauges = append(snapshot.Gauges, measurement)
   108  		case metrics.GaugeFloat64:
   109  			measurement[Name] = name
   110  			measurement[Value] = m.Value()
   111  			snapshot.Gauges = append(snapshot.Gauges, measurement)
   112  		case metrics.Histogram:
   113  			if m.Count() > 0 {
   114  				gauges := make([]Measurement, histogramGaugeCount)
   115  				s := m.Sample()
   116  				measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
   117  				measurement[Count] = uint64(s.Count())
   118  				measurement[Max] = float64(s.Max())
   119  				measurement[Min] = float64(s.Min())
   120  				measurement[Sum] = float64(s.Sum())
   121  				measurement[SumSquares] = sumSquares(s)
   122  				gauges[0] = measurement
   123  				for i, p := range self.Percentiles {
   124  					gauges[i+1] = Measurement{
   125  						Name:   fmt.Sprintf("%s.%.2f", measurement[Name], p),
   126  						Value:  s.Percentile(p),
   127  						Period: measurement[Period],
   128  					}
   129  				}
   130  				snapshot.Gauges = append(snapshot.Gauges, gauges...)
   131  			}
   132  		case metrics.Meter:
   133  			measurement[Name] = name
   134  			measurement[Value] = float64(m.Count())
   135  			snapshot.Counters = append(snapshot.Counters, measurement)
   136  			snapshot.Gauges = append(snapshot.Gauges,
   137  				Measurement{
   138  					Name:   fmt.Sprintf("%s.%s", name, "1min"),
   139  					Value:  m.Rate1(),
   140  					Period: int64(self.Interval.Seconds()),
   141  					Attributes: map[string]interface{}{
   142  						DisplayUnitsLong:  Operations,
   143  						DisplayUnitsShort: OperationsShort,
   144  						DisplayMin:        "0",
   145  					},
   146  				},
   147  				Measurement{
   148  					Name:   fmt.Sprintf("%s.%s", name, "5min"),
   149  					Value:  m.Rate5(),
   150  					Period: int64(self.Interval.Seconds()),
   151  					Attributes: map[string]interface{}{
   152  						DisplayUnitsLong:  Operations,
   153  						DisplayUnitsShort: OperationsShort,
   154  						DisplayMin:        "0",
   155  					},
   156  				},
   157  				Measurement{
   158  					Name:   fmt.Sprintf("%s.%s", name, "15min"),
   159  					Value:  m.Rate15(),
   160  					Period: int64(self.Interval.Seconds()),
   161  					Attributes: map[string]interface{}{
   162  						DisplayUnitsLong:  Operations,
   163  						DisplayUnitsShort: OperationsShort,
   164  						DisplayMin:        "0",
   165  					},
   166  				},
   167  			)
   168  		case metrics.Timer:
   169  			measurement[Name] = name
   170  			measurement[Value] = float64(m.Count())
   171  			snapshot.Counters = append(snapshot.Counters, measurement)
   172  			if m.Count() > 0 {
   173  				libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
   174  				gauges := make([]Measurement, histogramGaugeCount)
   175  				gauges[0] = Measurement{
   176  					Name:       libratoName,
   177  					Count:      uint64(m.Count()),
   178  					Sum:        m.Mean() * float64(m.Count()),
   179  					Max:        float64(m.Max()),
   180  					Min:        float64(m.Min()),
   181  					SumSquares: sumSquaresTimer(m),
   182  					Period:     int64(self.Interval.Seconds()),
   183  					Attributes: self.TimerAttributes,
   184  				}
   185  				for i, p := range self.Percentiles {
   186  					gauges[i+1] = Measurement{
   187  						Name:       fmt.Sprintf("%s.timer.%2.0f", name, p*100),
   188  						Value:      m.Percentile(p),
   189  						Period:     int64(self.Interval.Seconds()),
   190  						Attributes: self.TimerAttributes,
   191  					}
   192  				}
   193  				snapshot.Gauges = append(snapshot.Gauges, gauges...)
   194  				snapshot.Gauges = append(snapshot.Gauges,
   195  					Measurement{
   196  						Name:   fmt.Sprintf("%s.%s", name, "rate.1min"),
   197  						Value:  m.Rate1(),
   198  						Period: int64(self.Interval.Seconds()),
   199  						Attributes: map[string]interface{}{
   200  							DisplayUnitsLong:  Operations,
   201  							DisplayUnitsShort: OperationsShort,
   202  							DisplayMin:        "0",
   203  						},
   204  					},
   205  					Measurement{
   206  						Name:   fmt.Sprintf("%s.%s", name, "rate.5min"),
   207  						Value:  m.Rate5(),
   208  						Period: int64(self.Interval.Seconds()),
   209  						Attributes: map[string]interface{}{
   210  							DisplayUnitsLong:  Operations,
   211  							DisplayUnitsShort: OperationsShort,
   212  							DisplayMin:        "0",
   213  						},
   214  					},
   215  					Measurement{
   216  						Name:   fmt.Sprintf("%s.%s", name, "rate.15min"),
   217  						Value:  m.Rate15(),
   218  						Period: int64(self.Interval.Seconds()),
   219  						Attributes: map[string]interface{}{
   220  							DisplayUnitsLong:  Operations,
   221  							DisplayUnitsShort: OperationsShort,
   222  							DisplayMin:        "0",
   223  						},
   224  					},
   225  				)
   226  			}
   227  		}
   228  	})
   229  	return
   230  }