metrics: remove librato (#29624)
This commit is contained in:
parent
0e380ddaf7
commit
709e0b3997
|
@ -100,24 +100,6 @@ go influxdb.InfluxDB(metrics.DefaultRegistry,
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Periodically upload every metric to Librato using the [Librato client](https://github.com/mihasya/go-metrics-librato):
|
|
||||||
|
|
||||||
**Note**: the client included with this repository under the `librato` package
|
|
||||||
has been deprecated and moved to the repository linked above.
|
|
||||||
|
|
||||||
```go
|
|
||||||
import "github.com/mihasya/go-metrics-librato"
|
|
||||||
|
|
||||||
go librato.Librato(metrics.DefaultRegistry,
|
|
||||||
10e9, // interval
|
|
||||||
"example@example.com", // account owner email address
|
|
||||||
"token", // Librato API token
|
|
||||||
"hostname", // source
|
|
||||||
[]float64{0.95}, // percentiles to send
|
|
||||||
time.Millisecond, // time unit
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
Periodically emit every metric to StatHat:
|
Periodically emit every metric to StatHat:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -157,7 +139,6 @@ Publishing Metrics
|
||||||
|
|
||||||
Clients are available for the following destinations:
|
Clients are available for the following destinations:
|
||||||
|
|
||||||
* Librato - https://github.com/mihasya/go-metrics-librato
|
|
||||||
* Graphite - https://github.com/cyberdelia/go-metrics-graphite
|
* Graphite - https://github.com/cyberdelia/go-metrics-graphite
|
||||||
* InfluxDB - https://github.com/vrischmann/go-metrics-influxdb
|
* InfluxDB - https://github.com/vrischmann/go-metrics-influxdb
|
||||||
* Ganglia - https://github.com/appscode/metlia
|
* Ganglia - https://github.com/appscode/metlia
|
||||||
|
|
|
@ -1,104 +0,0 @@
|
||||||
package librato
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
const Operations = "operations"
|
|
||||||
const OperationsShort = "ops"
|
|
||||||
|
|
||||||
type LibratoClient struct {
|
|
||||||
Email, Token string
|
|
||||||
}
|
|
||||||
|
|
||||||
// property strings
|
|
||||||
const (
|
|
||||||
// display attributes
|
|
||||||
Color = "color"
|
|
||||||
DisplayMax = "display_max"
|
|
||||||
DisplayMin = "display_min"
|
|
||||||
DisplayUnitsLong = "display_units_long"
|
|
||||||
DisplayUnitsShort = "display_units_short"
|
|
||||||
DisplayStacked = "display_stacked"
|
|
||||||
DisplayTransform = "display_transform"
|
|
||||||
// special gauge display attributes
|
|
||||||
SummarizeFunction = "summarize_function"
|
|
||||||
Aggregate = "aggregate"
|
|
||||||
|
|
||||||
// metric keys
|
|
||||||
Name = "name"
|
|
||||||
Period = "period"
|
|
||||||
Description = "description"
|
|
||||||
DisplayName = "display_name"
|
|
||||||
Attributes = "attributes"
|
|
||||||
|
|
||||||
// measurement keys
|
|
||||||
MeasureTime = "measure_time"
|
|
||||||
Source = "source"
|
|
||||||
Value = "value"
|
|
||||||
|
|
||||||
// special gauge keys
|
|
||||||
Count = "count"
|
|
||||||
Sum = "sum"
|
|
||||||
Max = "max"
|
|
||||||
Min = "min"
|
|
||||||
SumSquares = "sum_squares"
|
|
||||||
|
|
||||||
// batch keys
|
|
||||||
Counters = "counters"
|
|
||||||
Gauges = "gauges"
|
|
||||||
|
|
||||||
MetricsPostUrl = "https://metrics-api.librato.com/v1/metrics"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Measurement map[string]interface{}
|
|
||||||
type Metric map[string]interface{}
|
|
||||||
|
|
||||||
type Batch struct {
|
|
||||||
Gauges []Measurement `json:"gauges,omitempty"`
|
|
||||||
Counters []Measurement `json:"counters,omitempty"`
|
|
||||||
MeasureTime int64 `json:"measure_time"`
|
|
||||||
Source string `json:"source"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *LibratoClient) PostMetrics(batch Batch) (err error) {
|
|
||||||
var (
|
|
||||||
js []byte
|
|
||||||
req *http.Request
|
|
||||||
resp *http.Response
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(batch.Counters) == 0 && len(batch.Gauges) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if js, err = json.Marshal(batch); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if req, err = http.NewRequest(http.MethodPost, MetricsPostUrl, bytes.NewBuffer(js)); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
req.SetBasicAuth(c.Email, c.Token)
|
|
||||||
|
|
||||||
resp, err = http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
var body []byte
|
|
||||||
if body, err = io.ReadAll(resp.Body); err != nil {
|
|
||||||
body = []byte(fmt.Sprintf("(could not fetch response body for error: %s)", err))
|
|
||||||
}
|
|
||||||
err = fmt.Errorf("unable to post to Librato: %d %s %s", resp.StatusCode, resp.Status, string(body))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,254 +0,0 @@
|
||||||
package librato
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
"regexp"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
|
||||||
)
|
|
||||||
|
|
||||||
// a regexp for extracting the unit from time.Duration.String
|
|
||||||
var unitRegexp = regexp.MustCompile(`[^\\d]+$`)
|
|
||||||
|
|
||||||
// a helper that turns a time.Duration into librato display attributes for timer metrics
|
|
||||||
func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) {
|
|
||||||
attrs = make(map[string]interface{})
|
|
||||||
attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d))
|
|
||||||
attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String())))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type Reporter struct {
|
|
||||||
Email, Token string
|
|
||||||
Namespace string
|
|
||||||
Source string
|
|
||||||
Interval time.Duration
|
|
||||||
Registry metrics.Registry
|
|
||||||
Percentiles []float64 // percentiles to report on histogram metrics
|
|
||||||
TimerAttributes map[string]interface{} // units in which timers will be displayed
|
|
||||||
intervalSec int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
|
|
||||||
return &Reporter{e, t, "", s, d, r, p, translateTimerAttributes(u), int64(d / time.Second)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) {
|
|
||||||
NewReporter(r, d, e, t, s, p, u).Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rep *Reporter) Run() {
|
|
||||||
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")
|
|
||||||
ticker := time.NewTicker(rep.Interval)
|
|
||||||
defer ticker.Stop()
|
|
||||||
metricsApi := &LibratoClient{rep.Email, rep.Token}
|
|
||||||
for now := range ticker.C {
|
|
||||||
var metrics Batch
|
|
||||||
var err error
|
|
||||||
if metrics, err = rep.BuildRequest(now, rep.Registry); err != nil {
|
|
||||||
log.Printf("ERROR constructing librato request body %s", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := metricsApi.PostMetrics(metrics); err != nil {
|
|
||||||
log.Printf("ERROR sending metrics to librato %s", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate sum of squares from data provided by metrics.Histogram
|
|
||||||
// see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
|
|
||||||
func sumSquares(icount int64, mean, stDev float64) float64 {
|
|
||||||
count := float64(icount)
|
|
||||||
sumSquared := math.Pow(count*mean, 2)
|
|
||||||
sumSquares := math.Pow(count*stDev, 2) + sumSquared/count
|
|
||||||
if math.IsNaN(sumSquares) {
|
|
||||||
return 0.0
|
|
||||||
}
|
|
||||||
return sumSquares
|
|
||||||
}
|
|
||||||
func sumSquaresTimer(t metrics.TimerSnapshot) float64 {
|
|
||||||
count := float64(t.Count())
|
|
||||||
sumSquared := math.Pow(count*t.Mean(), 2)
|
|
||||||
sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count
|
|
||||||
if math.IsNaN(sumSquares) {
|
|
||||||
return 0.0
|
|
||||||
}
|
|
||||||
return sumSquares
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
|
|
||||||
snapshot = Batch{
|
|
||||||
// coerce timestamps to a stepping fn so that they line up in Librato graphs
|
|
||||||
MeasureTime: (now.Unix() / rep.intervalSec) * rep.intervalSec,
|
|
||||||
Source: rep.Source,
|
|
||||||
}
|
|
||||||
snapshot.Gauges = make([]Measurement, 0)
|
|
||||||
snapshot.Counters = make([]Measurement, 0)
|
|
||||||
histogramGaugeCount := 1 + len(rep.Percentiles)
|
|
||||||
r.Each(func(name string, metric interface{}) {
|
|
||||||
if rep.Namespace != "" {
|
|
||||||
name = fmt.Sprintf("%s.%s", rep.Namespace, name)
|
|
||||||
}
|
|
||||||
measurement := Measurement{}
|
|
||||||
measurement[Period] = rep.Interval.Seconds()
|
|
||||||
switch m := metric.(type) {
|
|
||||||
case metrics.Counter:
|
|
||||||
ms := m.Snapshot()
|
|
||||||
if ms.Count() > 0 {
|
|
||||||
measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
|
|
||||||
measurement[Value] = float64(ms.Count())
|
|
||||||
measurement[Attributes] = map[string]interface{}{
|
|
||||||
DisplayUnitsLong: Operations,
|
|
||||||
DisplayUnitsShort: OperationsShort,
|
|
||||||
DisplayMin: "0",
|
|
||||||
}
|
|
||||||
snapshot.Counters = append(snapshot.Counters, measurement)
|
|
||||||
}
|
|
||||||
case metrics.CounterFloat64:
|
|
||||||
if count := m.Snapshot().Count(); count > 0 {
|
|
||||||
measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
|
|
||||||
measurement[Value] = count
|
|
||||||
measurement[Attributes] = map[string]interface{}{
|
|
||||||
DisplayUnitsLong: Operations,
|
|
||||||
DisplayUnitsShort: OperationsShort,
|
|
||||||
DisplayMin: "0",
|
|
||||||
}
|
|
||||||
snapshot.Counters = append(snapshot.Counters, measurement)
|
|
||||||
}
|
|
||||||
case metrics.Gauge:
|
|
||||||
measurement[Name] = name
|
|
||||||
measurement[Value] = float64(m.Snapshot().Value())
|
|
||||||
snapshot.Gauges = append(snapshot.Gauges, measurement)
|
|
||||||
case metrics.GaugeFloat64:
|
|
||||||
measurement[Name] = name
|
|
||||||
measurement[Value] = m.Snapshot().Value()
|
|
||||||
snapshot.Gauges = append(snapshot.Gauges, measurement)
|
|
||||||
case metrics.GaugeInfo:
|
|
||||||
measurement[Name] = name
|
|
||||||
measurement[Value] = m.Snapshot().Value()
|
|
||||||
snapshot.Gauges = append(snapshot.Gauges, measurement)
|
|
||||||
case metrics.Histogram:
|
|
||||||
ms := m.Snapshot()
|
|
||||||
if ms.Count() > 0 {
|
|
||||||
gauges := make([]Measurement, histogramGaugeCount)
|
|
||||||
measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
|
|
||||||
measurement[Count] = uint64(ms.Count())
|
|
||||||
measurement[Max] = float64(ms.Max())
|
|
||||||
measurement[Min] = float64(ms.Min())
|
|
||||||
measurement[Sum] = float64(ms.Sum())
|
|
||||||
measurement[SumSquares] = sumSquares(ms.Count(), ms.Mean(), ms.StdDev())
|
|
||||||
gauges[0] = measurement
|
|
||||||
for i, p := range rep.Percentiles {
|
|
||||||
gauges[i+1] = Measurement{
|
|
||||||
Name: fmt.Sprintf("%s.%.2f", measurement[Name], p),
|
|
||||||
Value: ms.Percentile(p),
|
|
||||||
Period: measurement[Period],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
snapshot.Gauges = append(snapshot.Gauges, gauges...)
|
|
||||||
}
|
|
||||||
case metrics.Meter:
|
|
||||||
ms := m.Snapshot()
|
|
||||||
measurement[Name] = name
|
|
||||||
measurement[Value] = float64(ms.Count())
|
|
||||||
snapshot.Counters = append(snapshot.Counters, measurement)
|
|
||||||
snapshot.Gauges = append(snapshot.Gauges,
|
|
||||||
Measurement{
|
|
||||||
Name: fmt.Sprintf("%s.%s", name, "1min"),
|
|
||||||
Value: ms.Rate1(),
|
|
||||||
Period: int64(rep.Interval.Seconds()),
|
|
||||||
Attributes: map[string]interface{}{
|
|
||||||
DisplayUnitsLong: Operations,
|
|
||||||
DisplayUnitsShort: OperationsShort,
|
|
||||||
DisplayMin: "0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Measurement{
|
|
||||||
Name: fmt.Sprintf("%s.%s", name, "5min"),
|
|
||||||
Value: ms.Rate5(),
|
|
||||||
Period: int64(rep.Interval.Seconds()),
|
|
||||||
Attributes: map[string]interface{}{
|
|
||||||
DisplayUnitsLong: Operations,
|
|
||||||
DisplayUnitsShort: OperationsShort,
|
|
||||||
DisplayMin: "0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Measurement{
|
|
||||||
Name: fmt.Sprintf("%s.%s", name, "15min"),
|
|
||||||
Value: ms.Rate15(),
|
|
||||||
Period: int64(rep.Interval.Seconds()),
|
|
||||||
Attributes: map[string]interface{}{
|
|
||||||
DisplayUnitsLong: Operations,
|
|
||||||
DisplayUnitsShort: OperationsShort,
|
|
||||||
DisplayMin: "0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
case metrics.Timer:
|
|
||||||
ms := m.Snapshot()
|
|
||||||
measurement[Name] = name
|
|
||||||
measurement[Value] = float64(ms.Count())
|
|
||||||
snapshot.Counters = append(snapshot.Counters, measurement)
|
|
||||||
if ms.Count() > 0 {
|
|
||||||
libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
|
|
||||||
gauges := make([]Measurement, histogramGaugeCount)
|
|
||||||
gauges[0] = Measurement{
|
|
||||||
Name: libratoName,
|
|
||||||
Count: uint64(ms.Count()),
|
|
||||||
Sum: ms.Mean() * float64(ms.Count()),
|
|
||||||
Max: float64(ms.Max()),
|
|
||||||
Min: float64(ms.Min()),
|
|
||||||
SumSquares: sumSquaresTimer(ms),
|
|
||||||
Period: int64(rep.Interval.Seconds()),
|
|
||||||
Attributes: rep.TimerAttributes,
|
|
||||||
}
|
|
||||||
for i, p := range rep.Percentiles {
|
|
||||||
gauges[i+1] = Measurement{
|
|
||||||
Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100),
|
|
||||||
Value: ms.Percentile(p),
|
|
||||||
Period: int64(rep.Interval.Seconds()),
|
|
||||||
Attributes: rep.TimerAttributes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
snapshot.Gauges = append(snapshot.Gauges, gauges...)
|
|
||||||
snapshot.Gauges = append(snapshot.Gauges,
|
|
||||||
Measurement{
|
|
||||||
Name: fmt.Sprintf("%s.%s", name, "rate.1min"),
|
|
||||||
Value: ms.Rate1(),
|
|
||||||
Period: int64(rep.Interval.Seconds()),
|
|
||||||
Attributes: map[string]interface{}{
|
|
||||||
DisplayUnitsLong: Operations,
|
|
||||||
DisplayUnitsShort: OperationsShort,
|
|
||||||
DisplayMin: "0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Measurement{
|
|
||||||
Name: fmt.Sprintf("%s.%s", name, "rate.5min"),
|
|
||||||
Value: ms.Rate5(),
|
|
||||||
Period: int64(rep.Interval.Seconds()),
|
|
||||||
Attributes: map[string]interface{}{
|
|
||||||
DisplayUnitsLong: Operations,
|
|
||||||
DisplayUnitsShort: OperationsShort,
|
|
||||||
DisplayMin: "0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Measurement{
|
|
||||||
Name: fmt.Sprintf("%s.%s", name, "rate.15min"),
|
|
||||||
Value: ms.Rate15(),
|
|
||||||
Period: int64(rep.Interval.Seconds()),
|
|
||||||
Attributes: map[string]interface{}{
|
|
||||||
DisplayUnitsLong: Operations,
|
|
||||||
DisplayUnitsShort: OperationsShort,
|
|
||||||
DisplayMin: "0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
Loading…
Reference in New Issue