mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-04 04:01:13 +00:00
The name of a method’s receiver should be a reflection of its identity; often a one or two letter abbreviation of its type suffices (such as “c” or “cl” for “Client”). Don’t use generic names such as “me”, “this” or “self”, identifiers typical of object-oriented languages that place more emphasis on methods as opposed to functions. The name need not be as descriptive as that of a method argument, as its role is obvious and serves no documentary purpose. It can be very short as it will appear on almost every line of every method of the type; familiarity admits brevity. Be consistent, too: if you call the receiver “c” in one method, don’t call it “cl” in another.
235 lines
7.5 KiB
Go
235 lines
7.5 KiB
Go
package librato
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math"
|
|
"regexp"
|
|
"time"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/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 (re *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.Tick(re.Interval)
|
|
metricsApi := &LibratoClient{re.Email, re.Token}
|
|
for now := range ticker {
|
|
var metrics Batch
|
|
var err error
|
|
if metrics, err = re.BuildRequest(now, re.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(s metrics.Sample) float64 {
|
|
count := float64(s.Count())
|
|
sumSquared := math.Pow(count*s.Mean(), 2)
|
|
sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count
|
|
if math.IsNaN(sumSquares) {
|
|
return 0.0
|
|
}
|
|
return sumSquares
|
|
}
|
|
func sumSquaresTimer(t metrics.Timer) 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 (re *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() / re.intervalSec) * re.intervalSec,
|
|
Source: re.Source,
|
|
}
|
|
snapshot.Gauges = make([]Measurement, 0)
|
|
snapshot.Counters = make([]Measurement, 0)
|
|
histogramGaugeCount := 1 + len(re.Percentiles)
|
|
r.Each(func(name string, metric interface{}) {
|
|
if re.Namespace != "" {
|
|
name = fmt.Sprintf("%s.%s", re.Namespace, name)
|
|
}
|
|
measurement := Measurement{}
|
|
measurement[Period] = re.Interval.Seconds()
|
|
switch m := metric.(type) {
|
|
case metrics.Counter:
|
|
if m.Count() > 0 {
|
|
measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
|
|
measurement[Value] = float64(m.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.Value())
|
|
snapshot.Gauges = append(snapshot.Gauges, measurement)
|
|
case metrics.GaugeFloat64:
|
|
measurement[Name] = name
|
|
measurement[Value] = m.Value()
|
|
snapshot.Gauges = append(snapshot.Gauges, measurement)
|
|
case metrics.Histogram:
|
|
if m.Count() > 0 {
|
|
gauges := make([]Measurement, histogramGaugeCount)
|
|
s := m.Sample()
|
|
measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
|
|
measurement[Count] = uint64(s.Count())
|
|
measurement[Max] = float64(s.Max())
|
|
measurement[Min] = float64(s.Min())
|
|
measurement[Sum] = float64(s.Sum())
|
|
measurement[SumSquares] = sumSquares(s)
|
|
gauges[0] = measurement
|
|
for i, p := range re.Percentiles {
|
|
gauges[i+1] = Measurement{
|
|
Name: fmt.Sprintf("%s.%.2f", measurement[Name], p),
|
|
Value: s.Percentile(p),
|
|
Period: measurement[Period],
|
|
}
|
|
}
|
|
snapshot.Gauges = append(snapshot.Gauges, gauges...)
|
|
}
|
|
case metrics.Meter:
|
|
measurement[Name] = name
|
|
measurement[Value] = float64(m.Count())
|
|
snapshot.Counters = append(snapshot.Counters, measurement)
|
|
snapshot.Gauges = append(snapshot.Gauges,
|
|
Measurement{
|
|
Name: fmt.Sprintf("%s.%s", name, "1min"),
|
|
Value: m.Rate1(),
|
|
Period: int64(re.Interval.Seconds()),
|
|
Attributes: map[string]interface{}{
|
|
DisplayUnitsLong: Operations,
|
|
DisplayUnitsShort: OperationsShort,
|
|
DisplayMin: "0",
|
|
},
|
|
},
|
|
Measurement{
|
|
Name: fmt.Sprintf("%s.%s", name, "5min"),
|
|
Value: m.Rate5(),
|
|
Period: int64(re.Interval.Seconds()),
|
|
Attributes: map[string]interface{}{
|
|
DisplayUnitsLong: Operations,
|
|
DisplayUnitsShort: OperationsShort,
|
|
DisplayMin: "0",
|
|
},
|
|
},
|
|
Measurement{
|
|
Name: fmt.Sprintf("%s.%s", name, "15min"),
|
|
Value: m.Rate15(),
|
|
Period: int64(re.Interval.Seconds()),
|
|
Attributes: map[string]interface{}{
|
|
DisplayUnitsLong: Operations,
|
|
DisplayUnitsShort: OperationsShort,
|
|
DisplayMin: "0",
|
|
},
|
|
},
|
|
)
|
|
case metrics.Timer:
|
|
measurement[Name] = name
|
|
measurement[Value] = float64(m.Count())
|
|
snapshot.Counters = append(snapshot.Counters, measurement)
|
|
if m.Count() > 0 {
|
|
libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
|
|
gauges := make([]Measurement, histogramGaugeCount)
|
|
gauges[0] = Measurement{
|
|
Name: libratoName,
|
|
Count: uint64(m.Count()),
|
|
Sum: m.Mean() * float64(m.Count()),
|
|
Max: float64(m.Max()),
|
|
Min: float64(m.Min()),
|
|
SumSquares: sumSquaresTimer(m),
|
|
Period: int64(re.Interval.Seconds()),
|
|
Attributes: re.TimerAttributes,
|
|
}
|
|
for i, p := range re.Percentiles {
|
|
gauges[i+1] = Measurement{
|
|
Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100),
|
|
Value: m.Percentile(p),
|
|
Period: int64(re.Interval.Seconds()),
|
|
Attributes: re.TimerAttributes,
|
|
}
|
|
}
|
|
snapshot.Gauges = append(snapshot.Gauges, gauges...)
|
|
snapshot.Gauges = append(snapshot.Gauges,
|
|
Measurement{
|
|
Name: fmt.Sprintf("%s.%s", name, "rate.1min"),
|
|
Value: m.Rate1(),
|
|
Period: int64(re.Interval.Seconds()),
|
|
Attributes: map[string]interface{}{
|
|
DisplayUnitsLong: Operations,
|
|
DisplayUnitsShort: OperationsShort,
|
|
DisplayMin: "0",
|
|
},
|
|
},
|
|
Measurement{
|
|
Name: fmt.Sprintf("%s.%s", name, "rate.5min"),
|
|
Value: m.Rate5(),
|
|
Period: int64(re.Interval.Seconds()),
|
|
Attributes: map[string]interface{}{
|
|
DisplayUnitsLong: Operations,
|
|
DisplayUnitsShort: OperationsShort,
|
|
DisplayMin: "0",
|
|
},
|
|
},
|
|
Measurement{
|
|
Name: fmt.Sprintf("%s.%s", name, "rate.15min"),
|
|
Value: m.Rate15(),
|
|
Period: int64(re.Interval.Seconds()),
|
|
Attributes: map[string]interface{}{
|
|
DisplayUnitsLong: Operations,
|
|
DisplayUnitsShort: OperationsShort,
|
|
DisplayMin: "0",
|
|
},
|
|
},
|
|
)
|
|
}
|
|
}
|
|
})
|
|
return
|
|
}
|