基本概念

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

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

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

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

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

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

metric类型

1. counter

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

2. Gauge

一种常规的 metric,典型的应用如:温度,运行的 goroutines 的个数。返回的数值会上下波动。

例如go_goroutines{instance="172.17.0.2", job="Prometheus"}

3.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
4.Summary

类似于 Histogram, 典型的应用如:请求持续时间,响应大小。

主要做统计用,设置分位数的值,会实时返回该分位数上的值。

golang中集成

  1. 下载 prometheus go 客户端 go get github.com/prometheus/client_golang/prometheus/promhttp.
  2. golang应用中集成
func main() {



  // expose prometheus metrics接口

  http.Handle("/metrics", promhttp.Handler())

  log.Fatal(http.ListenAndServe(":8080", nil))

}
  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