github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/metrics/librato/librato.go (about) 1 package librato 2 3 import ( 4 "fmt" 5 "log" 6 "math" 7 "regexp" 8 "time" 9 10 "github.com/neatio-net/neatio/utilities/metrics" 11 ) 12 13 var unitRegexp = regexp.MustCompile(`[^\\d]+$`) 14 15 func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) { 16 attrs = make(map[string]interface{}) 17 attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d)) 18 attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String()))) 19 return 20 } 21 22 type Reporter struct { 23 Email, Token string 24 Namespace string 25 Source string 26 Interval time.Duration 27 Registry metrics.Registry 28 Percentiles []float64 29 TimerAttributes map[string]interface{} 30 intervalSec int64 31 } 32 33 func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter { 34 return &Reporter{e, t, "", s, d, r, p, translateTimerAttributes(u), int64(d / time.Second)} 35 } 36 37 func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) { 38 NewReporter(r, d, e, t, s, p, u).Run() 39 } 40 41 func (self *Reporter) Run() { 42 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") 43 ticker := time.Tick(self.Interval) 44 metricsApi := &LibratoClient{self.Email, self.Token} 45 for now := range ticker { 46 var metrics Batch 47 var err error 48 if metrics, err = self.BuildRequest(now, self.Registry); err != nil { 49 log.Printf("ERROR constructing librato request body %s", err) 50 continue 51 } 52 if err := metricsApi.PostMetrics(metrics); err != nil { 53 log.Printf("ERROR sending metrics to librato %s", err) 54 continue 55 } 56 } 57 } 58 59 func sumSquares(s metrics.Sample) float64 { 60 count := float64(s.Count()) 61 sumSquared := math.Pow(count*s.Mean(), 2) 62 sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count 63 if math.IsNaN(sumSquares) { 64 return 0.0 65 } 66 return sumSquares 67 } 68 func sumSquaresTimer(t metrics.Timer) float64 { 69 count := float64(t.Count()) 70 sumSquared := math.Pow(count*t.Mean(), 2) 71 sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count 72 if math.IsNaN(sumSquares) { 73 return 0.0 74 } 75 return sumSquares 76 } 77 78 func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) { 79 snapshot = Batch{ 80 MeasureTime: (now.Unix() / self.intervalSec) * self.intervalSec, 81 Source: self.Source, 82 } 83 snapshot.Gauges = make([]Measurement, 0) 84 snapshot.Counters = make([]Measurement, 0) 85 histogramGaugeCount := 1 + len(self.Percentiles) 86 r.Each(func(name string, metric interface{}) { 87 if self.Namespace != "" { 88 name = fmt.Sprintf("%s.%s", self.Namespace, name) 89 } 90 measurement := Measurement{} 91 measurement[Period] = self.Interval.Seconds() 92 switch m := metric.(type) { 93 case metrics.Counter: 94 if m.Count() > 0 { 95 measurement[Name] = fmt.Sprintf("%s.%s", name, "count") 96 measurement[Value] = float64(m.Count()) 97 measurement[Attributes] = map[string]interface{}{ 98 DisplayUnitsLong: Operations, 99 DisplayUnitsShort: OperationsShort, 100 DisplayMin: "0", 101 } 102 snapshot.Counters = append(snapshot.Counters, measurement) 103 } 104 case metrics.Gauge: 105 measurement[Name] = name 106 measurement[Value] = float64(m.Value()) 107 snapshot.Gauges = append(snapshot.Gauges, measurement) 108 case metrics.GaugeFloat64: 109 measurement[Name] = name 110 measurement[Value] = m.Value() 111 snapshot.Gauges = append(snapshot.Gauges, measurement) 112 case metrics.Histogram: 113 if m.Count() > 0 { 114 gauges := make([]Measurement, histogramGaugeCount) 115 s := m.Sample() 116 measurement[Name] = fmt.Sprintf("%s.%s", name, "hist") 117 measurement[Count] = uint64(s.Count()) 118 measurement[Max] = float64(s.Max()) 119 measurement[Min] = float64(s.Min()) 120 measurement[Sum] = float64(s.Sum()) 121 measurement[SumSquares] = sumSquares(s) 122 gauges[0] = measurement 123 for i, p := range self.Percentiles { 124 gauges[i+1] = Measurement{ 125 Name: fmt.Sprintf("%s.%.2f", measurement[Name], p), 126 Value: s.Percentile(p), 127 Period: measurement[Period], 128 } 129 } 130 snapshot.Gauges = append(snapshot.Gauges, gauges...) 131 } 132 case metrics.Meter: 133 measurement[Name] = name 134 measurement[Value] = float64(m.Count()) 135 snapshot.Counters = append(snapshot.Counters, measurement) 136 snapshot.Gauges = append(snapshot.Gauges, 137 Measurement{ 138 Name: fmt.Sprintf("%s.%s", name, "1min"), 139 Value: m.Rate1(), 140 Period: int64(self.Interval.Seconds()), 141 Attributes: map[string]interface{}{ 142 DisplayUnitsLong: Operations, 143 DisplayUnitsShort: OperationsShort, 144 DisplayMin: "0", 145 }, 146 }, 147 Measurement{ 148 Name: fmt.Sprintf("%s.%s", name, "5min"), 149 Value: m.Rate5(), 150 Period: int64(self.Interval.Seconds()), 151 Attributes: map[string]interface{}{ 152 DisplayUnitsLong: Operations, 153 DisplayUnitsShort: OperationsShort, 154 DisplayMin: "0", 155 }, 156 }, 157 Measurement{ 158 Name: fmt.Sprintf("%s.%s", name, "15min"), 159 Value: m.Rate15(), 160 Period: int64(self.Interval.Seconds()), 161 Attributes: map[string]interface{}{ 162 DisplayUnitsLong: Operations, 163 DisplayUnitsShort: OperationsShort, 164 DisplayMin: "0", 165 }, 166 }, 167 ) 168 case metrics.Timer: 169 measurement[Name] = name 170 measurement[Value] = float64(m.Count()) 171 snapshot.Counters = append(snapshot.Counters, measurement) 172 if m.Count() > 0 { 173 libratoName := fmt.Sprintf("%s.%s", name, "timer.mean") 174 gauges := make([]Measurement, histogramGaugeCount) 175 gauges[0] = Measurement{ 176 Name: libratoName, 177 Count: uint64(m.Count()), 178 Sum: m.Mean() * float64(m.Count()), 179 Max: float64(m.Max()), 180 Min: float64(m.Min()), 181 SumSquares: sumSquaresTimer(m), 182 Period: int64(self.Interval.Seconds()), 183 Attributes: self.TimerAttributes, 184 } 185 for i, p := range self.Percentiles { 186 gauges[i+1] = Measurement{ 187 Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100), 188 Value: m.Percentile(p), 189 Period: int64(self.Interval.Seconds()), 190 Attributes: self.TimerAttributes, 191 } 192 } 193 snapshot.Gauges = append(snapshot.Gauges, gauges...) 194 snapshot.Gauges = append(snapshot.Gauges, 195 Measurement{ 196 Name: fmt.Sprintf("%s.%s", name, "rate.1min"), 197 Value: m.Rate1(), 198 Period: int64(self.Interval.Seconds()), 199 Attributes: map[string]interface{}{ 200 DisplayUnitsLong: Operations, 201 DisplayUnitsShort: OperationsShort, 202 DisplayMin: "0", 203 }, 204 }, 205 Measurement{ 206 Name: fmt.Sprintf("%s.%s", name, "rate.5min"), 207 Value: m.Rate5(), 208 Period: int64(self.Interval.Seconds()), 209 Attributes: map[string]interface{}{ 210 DisplayUnitsLong: Operations, 211 DisplayUnitsShort: OperationsShort, 212 DisplayMin: "0", 213 }, 214 }, 215 Measurement{ 216 Name: fmt.Sprintf("%s.%s", name, "rate.15min"), 217 Value: m.Rate15(), 218 Period: int64(self.Interval.Seconds()), 219 Attributes: map[string]interface{}{ 220 DisplayUnitsLong: Operations, 221 DisplayUnitsShort: OperationsShort, 222 DisplayMin: "0", 223 }, 224 }, 225 ) 226 } 227 } 228 }) 229 return 230 }