github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/metrics/librato/librato.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:42</date>
    10  //</624342649570070528>
    11  
    12  package librato
    13  
    14  import (
    15  	"fmt"
    16  	"log"
    17  	"math"
    18  	"regexp"
    19  	"time"
    20  
    21  	"github.com/ethereum/go-ethereum/metrics"
    22  )
    23  
    24  //用于从time.duration.string提取单位的regexp
    25  var unitRegexp = regexp.MustCompile(`[^\\d]+$`)
    26  
    27  //将时间.duration转换为库的帮助程序,用于显示计时器度量的属性
    28  func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) {
    29  	attrs = make(map[string]interface{})
    30  	attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d))
    31  	attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String())))
    32  	return
    33  }
    34  
    35  type Reporter struct {
    36  	Email, Token    string
    37  	Namespace       string
    38  	Source          string
    39  	Interval        time.Duration
    40  	Registry        metrics.Registry
    41  Percentiles     []float64              //要报告的柱状图指标百分比
    42  TimerAttributes map[string]interface{} //显示计时器的单位
    43  	intervalSec     int64
    44  }
    45  
    46  func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
    47  	return &Reporter{e, t, "", s, d, r, p, translateTimerAttributes(u), int64(d / time.Second)}
    48  }
    49  
    50  func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) {
    51  	NewReporter(r, d, e, t, s, p, u).Run()
    52  }
    53  
    54  func (rep *Reporter) Run() {
    55  log.Printf("WARNING: This client has been DEPRECATED! It has been moved to https://github.com/mihasya/go-metrics-libarto,将于2015年8月5日从rcrowley/go metrics中删除)
    56  	ticker := time.Tick(rep.Interval)
    57  	metricsApi := &LibratoClient{rep.Email, rep.Token}
    58  	for now := range ticker {
    59  		var metrics Batch
    60  		var err error
    61  		if metrics, err = rep.BuildRequest(now, rep.Registry); err != nil {
    62  			log.Printf("ERROR constructing librato request body %s", err)
    63  			continue
    64  		}
    65  		if err := metricsApi.PostMetrics(metrics); err != nil {
    66  			log.Printf("ERROR sending metrics to librato %s", err)
    67  			continue
    68  		}
    69  	}
    70  }
    71  
    72  //根据度量提供的数据计算平方和。柱状图
    73  //参见http://en.wikipedia.org/wiki/standard_deviation rapid_calculation_methods
    74  func sumSquares(s metrics.Sample) float64 {
    75  	count := float64(s.Count())
    76  	sumSquared := math.Pow(count*s.Mean(), 2)
    77  	sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count
    78  	if math.IsNaN(sumSquares) {
    79  		return 0.0
    80  	}
    81  	return sumSquares
    82  }
    83  func sumSquaresTimer(t metrics.Timer) float64 {
    84  	count := float64(t.Count())
    85  	sumSquared := math.Pow(count*t.Mean(), 2)
    86  	sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count
    87  	if math.IsNaN(sumSquares) {
    88  		return 0.0
    89  	}
    90  	return sumSquares
    91  }
    92  
    93  func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
    94  	snapshot = Batch{
    95  //将时间戳强制为单步执行fn,以便它们在天秤座图中对齐
    96  		MeasureTime: (now.Unix() / rep.intervalSec) * rep.intervalSec,
    97  		Source:      rep.Source,
    98  	}
    99  	snapshot.Gauges = make([]Measurement, 0)
   100  	snapshot.Counters = make([]Measurement, 0)
   101  	histogramGaugeCount := 1 + len(rep.Percentiles)
   102  	r.Each(func(name string, metric interface{}) {
   103  		if rep.Namespace != "" {
   104  			name = fmt.Sprintf("%s.%s", rep.Namespace, name)
   105  		}
   106  		measurement := Measurement{}
   107  		measurement[Period] = rep.Interval.Seconds()
   108  		switch m := metric.(type) {
   109  		case metrics.Counter:
   110  			if m.Count() > 0 {
   111  				measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
   112  				measurement[Value] = float64(m.Count())
   113  				measurement[Attributes] = map[string]interface{}{
   114  					DisplayUnitsLong:  Operations,
   115  					DisplayUnitsShort: OperationsShort,
   116  					DisplayMin:        "0",
   117  				}
   118  				snapshot.Counters = append(snapshot.Counters, measurement)
   119  			}
   120  		case metrics.Gauge:
   121  			measurement[Name] = name
   122  			measurement[Value] = float64(m.Value())
   123  			snapshot.Gauges = append(snapshot.Gauges, measurement)
   124  		case metrics.GaugeFloat64:
   125  			measurement[Name] = name
   126  			measurement[Value] = m.Value()
   127  			snapshot.Gauges = append(snapshot.Gauges, measurement)
   128  		case metrics.Histogram:
   129  			if m.Count() > 0 {
   130  				gauges := make([]Measurement, histogramGaugeCount)
   131  				s := m.Sample()
   132  				measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
   133  				measurement[Count] = uint64(s.Count())
   134  				measurement[Max] = float64(s.Max())
   135  				measurement[Min] = float64(s.Min())
   136  				measurement[Sum] = float64(s.Sum())
   137  				measurement[SumSquares] = sumSquares(s)
   138  				gauges[0] = measurement
   139  				for i, p := range rep.Percentiles {
   140  					gauges[i+1] = Measurement{
   141  						Name:   fmt.Sprintf("%s.%.2f", measurement[Name], p),
   142  						Value:  s.Percentile(p),
   143  						Period: measurement[Period],
   144  					}
   145  				}
   146  				snapshot.Gauges = append(snapshot.Gauges, gauges...)
   147  			}
   148  		case metrics.Meter:
   149  			measurement[Name] = name
   150  			measurement[Value] = float64(m.Count())
   151  			snapshot.Counters = append(snapshot.Counters, measurement)
   152  			snapshot.Gauges = append(snapshot.Gauges,
   153  				Measurement{
   154  					Name:   fmt.Sprintf("%s.%s", name, "1min"),
   155  					Value:  m.Rate1(),
   156  					Period: int64(rep.Interval.Seconds()),
   157  					Attributes: map[string]interface{}{
   158  						DisplayUnitsLong:  Operations,
   159  						DisplayUnitsShort: OperationsShort,
   160  						DisplayMin:        "0",
   161  					},
   162  				},
   163  				Measurement{
   164  					Name:   fmt.Sprintf("%s.%s", name, "5min"),
   165  					Value:  m.Rate5(),
   166  					Period: int64(rep.Interval.Seconds()),
   167  					Attributes: map[string]interface{}{
   168  						DisplayUnitsLong:  Operations,
   169  						DisplayUnitsShort: OperationsShort,
   170  						DisplayMin:        "0",
   171  					},
   172  				},
   173  				Measurement{
   174  					Name:   fmt.Sprintf("%s.%s", name, "15min"),
   175  					Value:  m.Rate15(),
   176  					Period: int64(rep.Interval.Seconds()),
   177  					Attributes: map[string]interface{}{
   178  						DisplayUnitsLong:  Operations,
   179  						DisplayUnitsShort: OperationsShort,
   180  						DisplayMin:        "0",
   181  					},
   182  				},
   183  			)
   184  		case metrics.Timer:
   185  			measurement[Name] = name
   186  			measurement[Value] = float64(m.Count())
   187  			snapshot.Counters = append(snapshot.Counters, measurement)
   188  			if m.Count() > 0 {
   189  				libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
   190  				gauges := make([]Measurement, histogramGaugeCount)
   191  				gauges[0] = Measurement{
   192  					Name:       libratoName,
   193  					Count:      uint64(m.Count()),
   194  					Sum:        m.Mean() * float64(m.Count()),
   195  					Max:        float64(m.Max()),
   196  					Min:        float64(m.Min()),
   197  					SumSquares: sumSquaresTimer(m),
   198  					Period:     int64(rep.Interval.Seconds()),
   199  					Attributes: rep.TimerAttributes,
   200  				}
   201  				for i, p := range rep.Percentiles {
   202  					gauges[i+1] = Measurement{
   203  						Name:       fmt.Sprintf("%s.timer.%2.0f", name, p*100),
   204  						Value:      m.Percentile(p),
   205  						Period:     int64(rep.Interval.Seconds()),
   206  						Attributes: rep.TimerAttributes,
   207  					}
   208  				}
   209  				snapshot.Gauges = append(snapshot.Gauges, gauges...)
   210  				snapshot.Gauges = append(snapshot.Gauges,
   211  					Measurement{
   212  						Name:   fmt.Sprintf("%s.%s", name, "rate.1min"),
   213  						Value:  m.Rate1(),
   214  						Period: int64(rep.Interval.Seconds()),
   215  						Attributes: map[string]interface{}{
   216  							DisplayUnitsLong:  Operations,
   217  							DisplayUnitsShort: OperationsShort,
   218  							DisplayMin:        "0",
   219  						},
   220  					},
   221  					Measurement{
   222  						Name:   fmt.Sprintf("%s.%s", name, "rate.5min"),
   223  						Value:  m.Rate5(),
   224  						Period: int64(rep.Interval.Seconds()),
   225  						Attributes: map[string]interface{}{
   226  							DisplayUnitsLong:  Operations,
   227  							DisplayUnitsShort: OperationsShort,
   228  							DisplayMin:        "0",
   229  						},
   230  					},
   231  					Measurement{
   232  						Name:   fmt.Sprintf("%s.%s", name, "rate.15min"),
   233  						Value:  m.Rate15(),
   234  						Period: int64(rep.Interval.Seconds()),
   235  						Attributes: map[string]interface{}{
   236  							DisplayUnitsLong:  Operations,
   237  							DisplayUnitsShort: OperationsShort,
   238  							DisplayMin:        "0",
   239  						},
   240  					},
   241  				)
   242  			}
   243  		}
   244  	})
   245  	return
   246  }
   247