Prometheus官方提供了Go语言版本的sdk,Go应用借助sdk可以很方便地接入Prometheus监控,接下来会从几个方面来说明:
创建一个简单的Go应用并暴露一个用于Prometheus监控的HTTP地址
介绍主流的Golang框架接入Prometheus监控的方法,分别是Echo、Gin和gRPC
Go应用需要暴露一个HTTP路由用于Prometheus server拉取监控数据,具体的HTTP路由地址可以自定义,官方建议使用 /metrics 。
package main
import (
"net/http""github.com/prometheus/client_golang/prometheus/promhttp"
)
funcmain() {
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":2112", nil)
}
启动应用后访问 metrics 接口即可看到基础的监控指标
curl http://localhost:2112/metrics
怎么加入自定义的监控指标呢,示例代码如下:
package main
import (
"net/http""time""github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promauto""github.com/prometheus/client_golang/prometheus/promhttp"
)
funcrecordMetrics() {
gofunc() {
for {
opsProcessed.Inc()
time.Sleep(2 * time.Second)
}
}()
}
var (
opsProcessed = promauto.NewCounter(prometheus.CounterOpts{
Name: "myapp_processed_ops_total",
Help: "The total number of processed events",
})
)
funcmain() {
recordMetrics()
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":2112", nil)
}
启动应用后访问 metrics 接口即可看到添加进去的自定义指标 myapp_processed_ops_total
curl http://localhost:2112/metrics
1、echo框架接入
监控基础指标
package main
import (
"github.com/labstack/echo/v4""github.com/labstack/echo-contrib/prometheus"
)
funcmain() {
e := echo.New()
// Enable metrics middleware
p := prometheus.NewPrometheus("echo", nil)
p.Use(e)
e.Logger.Fatal(e.Start(":1323"))
}
加入自定义指标
package main
import (
"time"
"github.com/labstack/echo-contrib/prometheus"
"github.com/labstack/echo/v4"
prom "github.com/prometheus/client_golang/prometheus"
)
const cKeyMetrics = "custom_metrics"// See the NewMetrics func for proper descriptions and prometheus names!// In case you add a metric here later, make sure to include it in the// MetricsList method or you'll going to have a bad time.type Metrics struct {
customCnt *prometheus.Metric
customDur *prometheus.Metric
}
// Needed by echo-contrib so echo can register and collect these metricsfunc(m *Metrics)MetricList() []*prometheus.Metric {
return []*prometheus.Metric{
// ADD EVERY METRIC HERE!
m.customCnt,
m.customDur,
}
}
// Creates and populates a new Metrics struct// This is where all the prometheus metrics, names and labels are specifiedfuncNewMetrics() *Metrics {
return &Metrics{
customCnt: &prometheus.Metric{
Name: "custom_total",
Description: "Custom counter events.",
Type: "counter_vec",
Args: []string{"label_one", "label_two"},
},
customDur: &prometheus.Metric{
Name: "custom_duration_seconds",
Description: "Custom duration observations.",
Type: "histogram_vec",
Args: []string{"label_one", "label_two"},
Buckets: prom.DefBuckets, // or your Buckets
},
}
}
// This will push your metrics object into every request context for later usefunc(m *Metrics)AddCustomMetricsMiddleware(next echo.HandlerFunc)echo.HandlerFunc {
returnfunc(c echo.Context)error {
c.Set(cKeyMetrics, m)
return next(c)
}
}
func(m *Metrics)IncCustomCnt(labelOne, labelTwo string) {
labels := prom.Labels{"label_one": labelOne, "label_two": labelTwo}
m.customCnt.MetricCollector.(*prom.CounterVec).With(labels).Inc()
}
func(m *Metrics)ObserveCustomDur(labelOne, labelTwo string, d time.Duration) {
labels := prom.Labels{"label_one": labelOne, "label_two": labelTwo}
m.customCnt.MetricCollector.(*prom.HistogramVec).With(labels).Observe(d.Seconds())
}
funcmain() {
e := echo.New()
m := NewMetrics()
// Enable metrics middleware
p := prometheus.NewPrometheus("echo", nil, m.MetricList())
p.Use(e)
e.Use(m.AddCustomMetricsMiddleware)
e.GET("/custom", func(c echo.Context)error {
metrics := c.Get(cKeyMetrics).(*Metrics)
metrics.IncCustomCnt("any", "value")
returnnil
})
e.Logger.Fatal(e.Start(":1323"))
}
2、Ging框架接入
package main
import (
"github.com/gin-gonic/gin"
"github.com/sunmi-OS/gocore/v2/lib/prometheus"
"log"
)
funcmain() {
r := gin.New()
//Enable metrics middleware
p := prometheus.NewPrometheus("app")
p.Use(r)
log.Fatal(r.Run(":1323"))
}
加入自定义指标
package main
import (
"github.com/gin-gonic/gin"
prom "github.com/prometheus/client_golang/prometheus""github.com/sunmi-OS/gocore/v2/lib/prometheus""log""time"
)
const cKeyMetrics = "custom_metrics"// See the NewMetrics func for proper descriptions and prometheus names!// In case you add a metric here later, make sure to include it in the// MetricsList method or you'll going to have a bad time.type Metrics struct {
customCnt *prometheus.Metric
customDur *prometheus.Metric
}
// Needed by echo-contrib so echo can register and collect these metricsfunc(m *Metrics)MetricList() []*prometheus.Metric {
return []*prometheus.Metric{
// ADD EVERY METRIC HERE!
m.customCnt,
m.customDur,
}
}
// Creates and populates a new Metrics struct// This is where all the prometheus metrics, names and labels are specifiedfuncNewMetrics() *Metrics {
return &Metrics{
customCnt: &prometheus.Metric{
Name: "custom_total",
Description: "Custom counter events.",
Type: "counter_vec",
Args: []string{"label_one", "label_two"},
},
customDur: &prometheus.Metric{
Name: "custom_duration_seconds",
Description: "Custom duration observations.",
Type: "histogram_vec",
Args: []string{"label_one", "label_two"},
},
}
}
// This will push your metrics object into every request context for later usefunc(m *Metrics)AddCustomMetricsMiddleware()gin.HandlerFunc {
returnfunc(c *gin.Context) {
c.Set(cKeyMetrics, m)
c.Next()
}
}
func(m *Metrics)IncCustomCnt(labelOne, labelTwo string) {
labels := prom.Labels{"label_one": labelOne, "label_two": labelTwo}
m.customCnt.MetricCollector.(*prom.CounterVec).With(labels).Inc()
}
func(m *Metrics)ObserveCustomDur(labelOne, labelTwo string, d time.Duration) {
labels := prom.Labels{"label_one": labelOne, "label_two": labelTwo}
m.customCnt.MetricCollector.(*prom.HistogramVec).With(labels).Observe(d.Seconds())
}
funcmain() {
r := gin.New()
m := NewMetrics()
//Enable metrics middleware
p := prometheus.NewPrometheus("app", m.MetricList())
p.Use(r)
r.GET("/custom", func(c *gin.Context) {
if v, ok := c.Get(cKeyMetrics); ok {
metric := v.(*Metrics)
metric.IncCustomCnt("any", "value")
}
})
log.Fatal(r.Run(":1323"))
}
3、grpc接入
在gRPC服务启动时,使用协程启动一个用于prometheus监控服务的HTTP服务即可。
package main
import (
...
grpcPrometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
funcmain() {
//集成prometheus监控,使用协程启动一个http服务gofunc() {
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":1323", nil)
}()
//添加prometheus拦截器
s := grpc.NewServer(
...
grpc.UnaryInterceptor(grpcPrometheus.UnaryServerInterceptor),
grpc.StreamInterceptor(grpcprometheus.StreamServerInterceptor),
)
...
}