You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
4.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package main
import (
"flag"
"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.50.90.99表示分位数0.050.010.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"})
// 不同的桶根据具体情况而定
metricsPath = flag.String("web.telemetry-path", "/metrics",
"Path under which to expose metrics")
)
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("/", handlerIndex)
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 handlerIndex(w http.ResponseWriter, r *http.Request) {
x := rand.Intn(3)
time.Sleep(time.Duration(x) * time.Second)
//_, _ = w.Write([]byte("handler response"))
_, _ = w.Write([]byte(`<html>
<head><title>SRE Promethus Exporter</title></head>
<body>
<h1>SRE Promethus Exporter</h1>
<p><a href='` + *metricsPath + `'>Metrics</a></p>
</body>
</html>`))
log.Println("print handler index")
}
// 清除数据,各项数据都会清零
func dataClear() {
requestTime.Reset()
requestTimes.Reset()
requestHistogram.Reset()
requestHistogramExponentialBuckets.Reset()
requestHistogramDef.Reset()
requestSummary.Reset()
}