### 0x00 四类指标介绍
Prometheus定义了4种不同的指标类型:Counter(计数器),Gauge(仪表盘),Histogram(直方图),Summary(摘要)。
这四类指标的特征为:
- `Counter`:只增不减(除非系统发生重启,或者用户进程有异常)的计数器。常见的监控指标如http_requests_total, node_cpu都是Counter类型的监控指标。一般推荐在定义为Counter的指标末尾加上_total作为后缀。
- `Gauge`:可增可减的仪表盘。Gauge类型的指标侧重于反应系统当前的状态。因此此类指标的数据可增可减。常见的例如node_memory_MemAvailable_bytes(可用内存)。
- `Histogram`:分析数据分布的直方图。显示数据的区间分布。例如统计请求耗时在0-10ms的请求数量和10ms-20ms的请求数量分布。
- `Summary`: 分析数据分布的摘要。显示数据的中位数,9分数等。
### 0x01 Build Your Own Exportor
官方文档 [WRITING EXPORTERS](https://prometheus.io/docs/instrumenting/writing_exporters/) 介绍了编写 Exportor 的一些注意点。Prometheus 的 client 库提供了实现自定义 Exportor 的[接口](https://github.com/prometheus/client_golang/blob/main/prometheus/collector.go#L27),Collector 接口定义了两个方法 Describe 和 Collect,实现这两个方法就可以暴露自定义的数据:
**collector.go**
```golang
package collector
import (
"github.com/prometheus/client_golang/prometheus"
)
//
var (
FlowRegistry = prometheus.NewRegistry()
//判断自定义collector是否实现了collector这个接口的所有方法
_ prometheus.Collector = (*FlowCollector)(nil)
)
var testvalue = 0
type FlowCollector struct {
flowStatusDesc *prometheus.Desc
}
// 通过NewFlowCollector方法创建结构体及对应的指标信息
func NewFlowCollector() *FlowCollector {
return &FlowCollector{
// func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc
flowStatusDesc: prometheus.NewDesc("azkaban_flows_status",
"Azkaban flows status",
[]string{"project_id", "flow_id", "submit_user", "status"},
prometheus.Labels{"app": "azkaban"},
),
}
}
// 采集器必须实现prometheus.Collector接口,也必须实现Describe和Collect方法。
func (a *FlowCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- a.flowStatusDesc
}
// go client Colletor只会在每次响应Prometheus请求的时候才收集数据
// Collect方法是核心,它会抓取你需要的所有数据,根据需求对其进行分析,然后将指标发送回客户端库。
// 用于传递所有可能指标的定义描述符
// 可以在程序运行期间添加新的描述,收集新的指标信息
func (a *FlowCollector) Collect(ch chan<- prometheus.Metric) {
testvalue++
// func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) Metric
ch <- prometheus.MustNewConstMetric(a.flowStatusDesc,
prometheus.CounterValue,
float64(testvalue),
"projectId", "flowId", "submitUser", "failed",
)
}
func init() {
FlowRegistry.MustRegister(NewFlowCollector())
}
```
**main.go**
```golang
package main
import (
"azkaban_exporter/collector"
"net/http"
"log"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`<html>
<head><title>azkaban_exporter</title></head>
<body>
<h1><a style="text-decoration:none" href=''>azkaban_exporter</a></h1>
<p><a href='/metrics'>Metrics</a></p>
<h2>Build</h2>
<pre>v0.0.1</pre>
</body>
</html>`))
})
http.Handle("/metrics", promhttp.HandlerFor(collector.FlowRegistry,
promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}),
)
log.Fatal(http.ListenAndServe(":9101", nil))
}
```
Go 开发 Prometheus Exporter