玩转Prometheus(1)--第1个例子
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 前言 在工作的这几年里,接触不少监控系统, Nagios、Cacti、Zabbix、Open-falcon, 今年开始在新公司使用Prometheus, 网上有文章把Prometheus 称为新一代的监控系统,我一直很好奇,它的新体现在哪儿,相比与传统的监控系统,它有什么优势。 在经过一段时间的使用以后,我觉得我有了一些体会,下面我们通过1个例子来感受一下。 Prometheus的体系架构图 应用场景 从目前各个公司的实践情况来看,Prometheus主要用于应用服务的监控,尤其是基于docker的应用服务;而像主机的运行情况(cpu使用率、内存使用率),网络设备的监控等,依然由传统的监控系统来做。 1. 模拟的应用服务 假定我们有一个web服务叫fake_service fake_server.go package main import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "gopkg.in/gin-gonic/gin.v1" "strconv" "strings" "time" ) var ( //HTTPReqDuration metric:http_request_duration_seconds HTTPReqDuration *prometheus.HistogramVec //HTTPReqTotal metric:http_request_total HTTPReqTotal *prometheus.CounterVec ) func init() { // 监控接口请求耗时 // HistogramVec 是一组Histogram HTTPReqDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "The HTTP request latencies in seconds.", Buckets: nil, }, []string{"method", "path"}) // 这里的"method"、"path" 都是label // 监控接口请求次数 // HistogramVec 是一组Histogram HTTPReqTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests made.", }, []string{"method", "path", "status"}) // 这里的"method"、"path"、"status" 都是label prometheus.MustRegister( HTTPReqDuration, HTTPReqTotal, ) } // /api/epgInfo/1371648200 -> /api/epgInfo func parsePath(path string) string { itemList := strings.Split(path, "/") if len(path) >= 4 { return strings.Join(itemList[0:3], "/") } return path } //Metric metric middleware func Metric() gin.HandlerFunc { return func(c *gin.Context) { tBegin := time.Now() c.Next() duration := float64(time.Since(tBegin)) / float64(time.Second) path := parsePath(c.Request.URL.Path) // 请求数加1 HTTPReqTotal.With(prometheus.Labels{ "method": c.Request.Method, "path": path, "status": strconv.Itoa(c.Writer.Status()), }).Inc() // 记录本次请求处理时间 HTTPReqDuration.With(prometheus.Labels{ "method": c.Request.Method, "path": path, }).Observe(duration) } } func DealAPI1(c *gin.Context) { time.Sleep(time.Microsecond * 10) c.Writer.Write([]byte("/api/api1")) } func DealAPI2(c *gin.Context) { time.Sleep(time.Microsecond * 20) c.Writer.Write([]byte("/api/api2")) } func main() { router := gin.Default() g := router.Group("/api") g.Use(Metric()) g.GET("api1", DealAPI1) g.GET("api2", DealAPI2) // 暴露给Prometheus router.GET("/metrics", gin.WrapH(promhttp.Handler())) router.Run(":28181") } 使用fake_client.go模拟真实用户的请求 完整代码 用法: ...