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  }