本文以 Go 语言为例,介绍如何在业务中自定义监控埋点,并通过托管 Prometheus 服务进行自定义指标上报,可视化及告警。
说明
Prometheus 的数据格式和 Metrics 类型,请参见 Prometheus 基础知识。
计数类型,数据是单调递增的指标,服务重启之后会重置。可以用 Counter 来监控请求数/异常数/用户登录数/订单数等。
如下展示了一个如何通过 Counter 类型来监控工单的例子。
// 工单 package ticket import ( "github.com/prometheus/client_golang/prometheus" ) // 请求数 var requestCounter = prometheus.NewCounterVec(prometheus.CounterOpts{ Subsystem: "ticket", Name: "request_total", Help: "The total number of ticket requests.", }, []string{"action"}) // 操作 func init() { prometheus.DefaultRegisterer.MustRegister(requestCounter) } // 创建工单 func Create() { requestCounter.With(prometheus.Labels{"action": "create"}).Inc() // 创建工单代码 }
此时,通过 rate() 函数即可获取工单的创建速率。
rate(ticket_request_total{action="create"}[5m])
当前值,监控打点的时候可对其做加减。可以用 Gauge 来监控当前内存使用率/CPU 使用率/当前线程数/队列个数等。
如下展示了一个如何通过 Gauge 类型来监控工单的例子。
// 工单 package ticket import ( "time" "github.com/prometheus/client_golang/prometheus" ) var ( createConcurrencyCh = make(chan struct{}, 8) ) // 并发控制 var ( createConcurrencyCurrent = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ Subsystem: "ticket", Name: "concurrent_create_current", Help: "The number of in-flight create ticket requests.", }, func() float64 { return float64(len(createConcurrencyCh)) }) createConcurrencyCapacity = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ Subsystem: "ticket", Name: "concurrent_create_capacity", Help: "The maximum number of concurrent create ticket requests the server may serve.", }, func() float64 { return float64(cap(createConcurrencyCh)) }) ) func init() { prometheus.DefaultRegisterer.MustRegister(createConcurrencyCurrent, createConcurrencyCapacity) } // 创建工单 func Create() { t := time.NewTimer(30 * time.Second) select { case createConcurrencyCh <- struct{}{}: case <-t.C: // timeout return } defer func() { <-createConcurrencyCh }() // 创建工单代码 }
此时,可以直接查看工单的并发饱和度。
max_over_time(ticket_concurrent_create_current[1m]) / ticket_concurrent_create_capacity
直方图,Prometheus 会根据配置的 Bucket 来计算样本的分布情况,后期可以再加工,一般多用于耗时的监控,通过 Histogram 可以计算出 P99/P95/P50 等耗时,同时也可以监控处理的个数,如果用上 Histogram 就不需要再用 Counter 统计个数。可以用 Histogram 来监控接口响应时间/数据库访问耗时等。
如下展示了一个如何通过 Histogram 类型来监控工单耗时的例子。
// 工单 package ticket import ( "time" "github.com/prometheus/client_golang/prometheus" ) // 请求耗时 var requestDuration = prometheus.HistogramVec(prometheus.HistogramOpts{ Subsystem: "ticket", Name: "request_duration_seconds", Help: "Request duration distribution in seconds.", Buckets: prometheus.DefBuckets, }, []string{"action"}) // 操作 func init() { prometheus.DefaultRegisterer.MustRegister(requestDuration) } // 创建工单 func Create() { start := time.Now() defer requestDuration.With(prometheus.Labels{"action": "create"}).Observe(time.Since(start).Seconds()) // 创建工单代码 }
此时,通过 Histogram 指标,可以直接查看工单的 P95 耗时。
histogram_quantile(0.95, rate(ticket_request_duration_seconds_bucket{action="create"}[5m]))
摘要,和 Histogram 有一点类似,也是计算样本的分布情况,区别是 Summary 会在客户端计算出分布情况(P99/P95/Sum/Count),因此也会更占客户端资源,后期不可再聚合计算处理,同样可以用 Summary 来监控接口响应时间/数据库访问耗时等。
Summary 和 Histogram 的使用方式类似,可以直接参考 Histogram 的使用方式。
通过 promhttp.Handler()
把监控埋点数据暴露到 HTTP 服务上。
package main import ( "net/http" "github.com/prometheus/client_golang/prometheus/promhttp" ) func main() { // 业务代码 // 把 Prometheus 指标暴露在 HTTP 服务上 http.Handle("/metrics", promhttp.Handler()) // 业务代码 }
完成相关业务自定义监控埋点之后,您可以在 VKE 集群中或 ECS 实例中部署应用,完成应用发布。应用发布后,即可接入托管 Prometheus 来获取监控指标数据。
当您的业务部署在不同环境中时,支持不同的服务发现方式:
您可以使用托管 Prometheus 服务的 Explore 功能来查看监控指标数据。详情请参见 指标查询。
也可以搭建自建 Grafana,使用 Grafana 读取托管 Prometheus 服务中存储的数据,并创建指标大盘。详情请参见 在容器服务集群中部署 Grafana 并接入工作区。