Golang 应用集成 Prometheus 统计数据支持

基本概念

Prometheus 所有采集的监控数据均以指标(metric)的形式保存在内置的时间序列数据库当中(TSDB):属于同一指标名称,同一标签集合的、有时间戳标记的数据流。除了存储的时间序列,Prometheus 还可以根据查询请求产生临时的、衍生的时间序列作为返回结果。

样本在时间序列中的每一个点称为一个样本(sample),样本由以下三部分组成:

指标(metric):指标名称和描述当前样本特征的 labelsets;

时间戳(timestamp):一个精确到毫秒的时间戳;

样本值(value): 一个 folat64 的浮点型数据表示当前样本的值。

<metric name>{<label name>=<label value>, ...}

Metric类型

Prometheus 客户端公开了在暴露服务指标时能够运用的四种指标类型。查看 Prometheus 的文档 以获得关于各种指标类型的深入信息。

Counter(计数器

一种累加的 metric,典型的应用如:请求的个数,结束的任务数,出现的错误数等。随着客户端不断请求,数值越来越大。例如api_http_requests_total{method="POST", handler="/messages"}

Gauge(计量器)

一种常规的 metric,典型的应用如:温度,运行的 goroutines 的个数。返回的数值会上下波动。
例如 go_goroutines{instance="172.17.0.2", job="Prometheus"}

Histogram(分布图)

可以理解为柱状图,典型的应用如:请求持续时间,响应大小。可以对观察结果采样,分组及统计。例如设置一个name为web_request_duration_seconds的Histogram 的metrics,并设置区间值为[0.1,0.5,1]会对区间点生成一条统计数据.

# 响应时间小于0.1s的请求有5次
web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="0.1"} 3

# 响应时间小于0.5s的请求有次
web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="0.5"} 5

# 响应时间小于1s的请求有7次
web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="1"} 7

# 总共7次请求
web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="+Inf"} 7

# 7次请求duration的总和
web_request_duration_seconds_sum{endpoint="/query",method="GET"} 2.7190880529999997

Summary(摘要)

跟 histogram 类似,summary 也对观测值(类似请求延迟或回复包大小)进行采样。同时它会给出一个总数以及所有观测值的总和,它在一个滑动的时间窗口上计算可配置的分位数。, 典型的应用如:请求持续时间,响应大小。主要做统计用,设置分位数的值,会实时返回该分位数上的值。

Golang中集成

Prometheus 程序库 提供了一个用 Golang 写成的健壮的插桩库,可以用来注册,收集和暴露服务的指标。在讲述如何在应用程序中暴露指标前,让我们先来探究一下 Prometheus 库提供的各种指标类型。

  1. 下载 Prometheus go 客户端 go get github.com/prometheus/client_golang/prometheus/promhttp.

  2. Golang应用中集成 Prometheus HTTP 服务器

package main

import (
        "net/http"

        "github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
	// expose prometheus metrics接口
	
	server := http.NewServeMux() // create a new mux server
	server.Handle("/metrics", promhttp.Handler()) // register a new handler for the /metrics endpoint
	log.Fatal(http.ListenAndServe(":8080", server)) // start an http server using the mux server
}
  1. 启动应用访问http://localhost:8080/metrics,会返回一些go应用中goroutine,thread、gc、堆栈的基本信息。
# HELP go_gc_duration_seconds A summary of the GC invocation durations.

# TYPE go_gc_duration_seconds summary

go_gc_duration_seconds{quantile="0"} 0

go_gc_duration_seconds{quantile="0.25"} 0

go_gc_duration_seconds{quantile="0.5"} 0

go_gc_duration_seconds{quantile="0.75"} 0

go_gc_duration_seconds{quantile="1"} 0

go_gc_duration_seconds_sum 0

go_gc_duration_seconds_count 0

# HELP go_goroutines Number of goroutines that currently exist.

# TYPE go_goroutines gauge

go_goroutines 6

# HELP go_info Information about the Go environment.

# TYPE go_info gauge

go_info{version="go1.12"} 1

添加自定义指标

  1. 创建指标并注册到prometheus
// 初始化 web_reqeust_total, counter类型指标, 表示接收http请求总次数
var WebRequestTotal = prometheus.NewCounterVec(
  prometheus.CounterOpts{
    Name: "web_reqeust_total",
    Help: "Number of hello requests in total",
  },
  // 设置两个标签 请求方法和 路径 对请求总次数在两个
  []string{"method", "endpoint"},
)

// web_request_duration_seconds,Histogram类型指标,bucket代表duration的分布区间
var WebRequestDuration = prometheus.NewHistogramVec(
  prometheus.HistogramOpts{
    Name: "web_request_duration_seconds",
    Help: "web request duration distribution",
    Buckets: []float64{0.1, 0.3, 0.5, 0.7, 0.9, 1},
  },
  []string{"method", "endpoint"},
)

func init() {
  // 注册监控指标
  prometheus.MustRegister(WebRequestTotal)
  prometheus.MustRegister(WebRequestDuration)
}
  1. 在适当切入点对指标进行记录变更
// 包装 handler function,不侵入业务逻辑
func Monitor(h http.HandlerFunc) http.HandlerFunc {
  return func(w http.ResponseWriter, r *http.Request) {
    start := time.Now()
    h(w, r)
    duration := time.Since(start)
// counter类型 metric的记录方式
    WebRequestTotal.With(prometheus.Labels{"method": r.Method, "endpoint": r.URL.Path}).Inc()
// Histogram类型 meric的记录方式
    WebRequestDuration.With(prometheus.Labels{"method": r.Method, "endpoint": r.URL.Path}).Observe(duration.Seconds())
  }
}

···

func main() {
  // expose prometheus metrics接口
  http.Handle("/metrics", promhttp.Handler())
  http.HandleFunc("/query", monitor.Monitor(Query))
  log.Fatal(http.ListenAndServe(":8080", nil))
}

// query
func Query(w http.ResponseWriter, r *http.Request) {
  //模拟业务查询耗时0~1s
  time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
  _,_ = io.WriteString(w, "some results")
}
  1. 启动并访问http://localhost:8080/query接口,并再次访问http://localhost:8080/metrics接口,返回的指标数据中就有了刚加上的metric,如下所示
# HELP web_reqeust_total Number of hello requests in total
# TYPE web_reqeust_total counter

web_reqeust_total{endpoint="/hello",method="GET"} 1

web_reqeust_total{endpoint="/query",method="GET"} 7

# HELP web_request_duration_seconds web request duration distribution

# TYPE web_request_duration_seconds histogram

web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="0.1"} 3

web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="0.3"} 3

web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="0.5"} 5

web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="0.7"} 5

web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="0.9"} 7

web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="1"} 7

web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="+Inf"} 7

web_request_duration_seconds_sum{endpoint="/query",method="GET"} 2.7190880529999997

web_request_duration_seconds_count{endpoint="/query",method="GET"} 7

代码地址

可以直接安装运行,详细说明可以参考官网

go install github.com/crockitwood/go-prometheus-example

go-prometheus-example

curl http://localhost:8080/query

curl http://localhost:8080/metrics
发布了76 篇原创文章 · 获赞 27 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/kunyus/article/details/101355821