package main import ( "flag" "fmt" "log" "math/rand" "net/http" "strings" "time" "github.com/gorilla/mux" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) var ( addr = flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.") ) var ( requestTimes = prometheus.NewCounterVec(prometheus.CounterOpts{ Name: "request_times", Help: "请求次数", }, []string{"method", "url", "host"}) // 多个label,需要与requestTimes.WithLabelValues(strings.ToLower(r.Method), r.URL.String())一一对应, // 效果为可用promql request_times{method="get",url="/metrics",host="172.20.16.185:8080"}查询 requestTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: "request_time", Help: "每次请求花费的时间", }, []string{"method", "url", "host"}) // 需要计算,开销大 requestSummary = prometheus.NewSummaryVec(prometheus.SummaryOpts{ Name: "request_time_summary", Help: "summary test", Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, // 0.5,0.9,0.99表示分位数,0.05,0.01,0.001表示可接收的误差,比如0.5分位的值为10,其实这个10可能是(0.45,0.55)这个区间内的某个值,太过精确会导致cpu压力过大 }, []string{"request_time"}) // Histogram只计数,不计算,开销小 // 线性桶 requestHistogram = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Name: "request_time_histogram", Help: "histogram LinearBuckets test", Buckets: prometheus.LinearBuckets(1, 2, 20), // 初始为1,间隔为2,一共20个取值,Buckets会隐式添加 `+Inf` 值作为取值区间的最大值 // request_time_histogram_bucket{instance="172.20.16.185:8080", job="my_metrics", le="1.0", request_time="request_time"} // request_time_histogram_bucket{instance="172.20.16.185:8080", job="my_metrics", le="3.0", request_time="request_time"} // ... // 会生成如上所示的指标,le: 小于等于 // 即,比如第一个数据的值,表示为小于等于1.0的个数,此处即为响应时间小于等于1.0的请求的个数 }, []string{"request_time"}) // 默认桶 requestHistogramDef = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Name: "request_time_histogram_def_buckets", Help: "histogram DefBuckets test", Buckets: prometheus.DefBuckets, }, []string{"request_time"}) // 指数桶 requestHistogramExponentialBuckets = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Name: "request_time_histogram_exponential_buckets", Help: "histogram ExponentialBuckets test", Buckets: prometheus.ExponentialBuckets(1, 2, 20), // 初始值为1,指数为2增长,20个取值 }, []string{"request_time"}) // 不同的桶根据具体情况而定 ) func init() { // Add Go module build info. // 也可prometheus.MustRegister(xx, yy) prometheus.MustRegister(requestTime) prometheus.MustRegister(requestTimes) prometheus.MustRegister(requestSummary) prometheus.MustRegister(requestHistogram, requestHistogramDef, requestHistogramExponentialBuckets) } func main() { flag.Parse() r := mux.NewRouter() r.HandleFunc("/", handler) r.Use(metricsMiddleware) r.Handle("/metrics", promhttp.HandlerFor( prometheus.DefaultGatherer, promhttp.HandlerOpts{ // Opt into OpenMetrics to support exemplars. EnableOpenMetrics: true, }, )) log.Fatal(http.ListenAndServe(*addr, r)) } func metricsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now().Unix() next.ServeHTTP(w, r) end := time.Now().Unix() requestTime.WithLabelValues(strings.ToLower(r.Method), r.URL.String(), r.Host).Set(float64(end - start)) requestTimes.WithLabelValues(strings.ToLower(r.Method), r.URL.String(), r.Host).Add(1) requestSummary.WithLabelValues("request_time").Observe(float64(end - start)) requestHistogram.WithLabelValues("request_time").Observe(float64(end - start)) requestHistogramDef.WithLabelValues("request_time").Observe(float64(end - start)) requestHistogramExponentialBuckets.WithLabelValues("request_time").Observe(float64(end - start)) }) } func handler(w http.ResponseWriter, r *http.Request) { x := rand.Intn(3) time.Sleep(time.Duration(x) * time.Second) _, _ = w.Write([]byte("handler response")) fmt.Println("print handler") } // 清除数据,各项数据都会清零 func dataClear() { requestTime.Reset() requestTimes.Reset() requestHistogram.Reset() requestHistogramExponentialBuckets.Reset() requestHistogramDef.Reset() requestSummary.Reset() }