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:
|
||||
|
||||
```go
|
||||
@ -157,7 +139,6 @@ Publishing Metrics
|
||||
|
||||
Clients are available for the following destinations:
|
||||
|
||||
* Librato - https://github.com/mihasya/go-metrics-librato
|
||||
* Graphite - https://github.com/cyberdelia/go-metrics-graphite
|
||||
* InfluxDB - https://github.com/vrischmann/go-metrics-influxdb
|
||||
* 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
Block a user