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