github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/metrics/exp/exp.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 19:16:39</date> 10 //</624450098406887424> 11 12 //将Go度量挂钩到expvar中 13 //在任何/debug/metrics请求上,将注册表中的所有var加载到expvar,并执行常规expvar处理程序 14 package exp 15 16 import ( 17 "expvar" 18 "fmt" 19 "net/http" 20 "sync" 21 22 "github.com/ethereum/go-ethereum/metrics" 23 ) 24 25 type exp struct { 26 expvarLock sync.Mutex //如果您尝试注册同一个var两次,expvar将崩溃,因此我们必须安全地探测它。 27 registry metrics.Registry 28 } 29 30 func (exp *exp) expHandler(w http.ResponseWriter, r *http.Request) { 31 //将变量加载到expvar中 32 exp.syncToExpvar() 33 34 //现在只需运行官方的expvar处理程序代码(它不是可公开调用的,所以是内联粘贴的) 35 w.Header().Set("Content-Type", "application/json; charset=utf-8") 36 fmt.Fprintf(w, "{\n") 37 first := true 38 expvar.Do(func(kv expvar.KeyValue) { 39 if !first { 40 fmt.Fprintf(w, ",\n") 41 } 42 first = false 43 fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) 44 }) 45 fmt.Fprintf(w, "\n}\n") 46 } 47 48 //exp将使用http.defaultservemux在“/debug/vars”上注册一个expvar支持的度量处理程序。 49 func Exp(r metrics.Registry) { 50 h := ExpHandler(r) 51 //这会引起恐慌: 52 //死机:http:/debug/vars的多个注册 53 //http.handlefunc(“/debug/vars”,e.exphandler) 54 //还没有找到一种优雅的方式,所以只需使用一个不同的端点 55 http.Handle("/debug/metrics", h) 56 } 57 58 //exphandler将返回一个expvar支持的度量处理程序。 59 func ExpHandler(r metrics.Registry) http.Handler { 60 e := exp{sync.Mutex{}, r} 61 return http.HandlerFunc(e.expHandler) 62 } 63 64 func (exp *exp) getInt(name string) *expvar.Int { 65 var v *expvar.Int 66 exp.expvarLock.Lock() 67 p := expvar.Get(name) 68 if p != nil { 69 v = p.(*expvar.Int) 70 } else { 71 v = new(expvar.Int) 72 expvar.Publish(name, v) 73 } 74 exp.expvarLock.Unlock() 75 return v 76 } 77 78 func (exp *exp) getFloat(name string) *expvar.Float { 79 var v *expvar.Float 80 exp.expvarLock.Lock() 81 p := expvar.Get(name) 82 if p != nil { 83 v = p.(*expvar.Float) 84 } else { 85 v = new(expvar.Float) 86 expvar.Publish(name, v) 87 } 88 exp.expvarLock.Unlock() 89 return v 90 } 91 92 func (exp *exp) publishCounter(name string, metric metrics.Counter) { 93 v := exp.getInt(name) 94 v.Set(metric.Count()) 95 } 96 97 func (exp *exp) publishGauge(name string, metric metrics.Gauge) { 98 v := exp.getInt(name) 99 v.Set(metric.Value()) 100 } 101 func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64) { 102 exp.getFloat(name).Set(metric.Value()) 103 } 104 105 func (exp *exp) publishHistogram(name string, metric metrics.Histogram) { 106 h := metric.Snapshot() 107 ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) 108 exp.getInt(name + ".count").Set(h.Count()) 109 exp.getFloat(name + ".min").Set(float64(h.Min())) 110 exp.getFloat(name + ".max").Set(float64(h.Max())) 111 exp.getFloat(name + ".mean").Set(h.Mean()) 112 exp.getFloat(name + ".std-dev").Set(h.StdDev()) 113 exp.getFloat(name + ".50-percentile").Set(ps[0]) 114 exp.getFloat(name + ".75-percentile").Set(ps[1]) 115 exp.getFloat(name + ".95-percentile").Set(ps[2]) 116 exp.getFloat(name + ".99-percentile").Set(ps[3]) 117 exp.getFloat(name + ".999-percentile").Set(ps[4]) 118 } 119 120 func (exp *exp) publishMeter(name string, metric metrics.Meter) { 121 m := metric.Snapshot() 122 exp.getInt(name + ".count").Set(m.Count()) 123 exp.getFloat(name + ".one-minute").Set(m.Rate1()) 124 exp.getFloat(name + ".five-minute").Set(m.Rate5()) 125 exp.getFloat(name + ".fifteen-minute").Set((m.Rate15())) 126 exp.getFloat(name + ".mean").Set(m.RateMean()) 127 } 128 129 func (exp *exp) publishTimer(name string, metric metrics.Timer) { 130 t := metric.Snapshot() 131 ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) 132 exp.getInt(name + ".count").Set(t.Count()) 133 exp.getFloat(name + ".min").Set(float64(t.Min())) 134 exp.getFloat(name + ".max").Set(float64(t.Max())) 135 exp.getFloat(name + ".mean").Set(t.Mean()) 136 exp.getFloat(name + ".std-dev").Set(t.StdDev()) 137 exp.getFloat(name + ".50-percentile").Set(ps[0]) 138 exp.getFloat(name + ".75-percentile").Set(ps[1]) 139 exp.getFloat(name + ".95-percentile").Set(ps[2]) 140 exp.getFloat(name + ".99-percentile").Set(ps[3]) 141 exp.getFloat(name + ".999-percentile").Set(ps[4]) 142 exp.getFloat(name + ".one-minute").Set(t.Rate1()) 143 exp.getFloat(name + ".five-minute").Set(t.Rate5()) 144 exp.getFloat(name + ".fifteen-minute").Set(t.Rate15()) 145 exp.getFloat(name + ".mean-rate").Set(t.RateMean()) 146 } 147 148 func (exp *exp) publishResettingTimer(name string, metric metrics.ResettingTimer) { 149 t := metric.Snapshot() 150 ps := t.Percentiles([]float64{50, 75, 95, 99}) 151 exp.getInt(name + ".count").Set(int64(len(t.Values()))) 152 exp.getFloat(name + ".mean").Set(t.Mean()) 153 exp.getInt(name + ".50-percentile").Set(ps[0]) 154 exp.getInt(name + ".75-percentile").Set(ps[1]) 155 exp.getInt(name + ".95-percentile").Set(ps[2]) 156 exp.getInt(name + ".99-percentile").Set(ps[3]) 157 } 158 159 func (exp *exp) syncToExpvar() { 160 exp.registry.Each(func(name string, i interface{}) { 161 switch i := i.(type) { 162 case metrics.Counter: 163 exp.publishCounter(name, i) 164 case metrics.Gauge: 165 exp.publishGauge(name, i) 166 case metrics.GaugeFloat64: 167 exp.publishGaugeFloat64(name, i) 168 case metrics.Histogram: 169 exp.publishHistogram(name, i) 170 case metrics.Meter: 171 exp.publishMeter(name, i) 172 case metrics.Timer: 173 exp.publishTimer(name, i) 174 case metrics.ResettingTimer: 175 exp.publishResettingTimer(name, i) 176 default: 177 panic(fmt.Sprintf("unsupported type for '%s': %T", name, i)) 178 } 179 }) 180 } 181