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