蓝鲸 exporter 监控组件开发
实验概述
监控常见开源组件及商业中间件的性能指标,比如Nginx的每分钟客户端请求数(req_per_min)、等待中的连接数(waiting)等,或Oracle的并发等待时间( CONCURRENCY_WAIT_TIME)等 ;蓝鲸监控除内置组件性能指标的采集能力,同时兼容Prometheus Exporter的导入及开发能力,全面覆盖组件的采集能力。本实验将带来基于exporter的自定义组件监控采集开发实战。
任务一: 开发一个自己的exporter
数据链路
- 监控整体链路图
- 自定义组件采集流程
- 蓝鲸监控通过job部署prometheus 社区的exporter,对目标组件进行性能数据采集。接着bkmetricbeat从exporter上周期拉取性能数据并通过数据通道上报。
自定义组件采集导入流程
- 蓝鲸监控当前支持使用go编写exporter。
- 在社区找到适合自己的exporter或者编写新的exporter。
- 将源码编译成二进制文件。
- 将编译的exporter打成zip包
- 上传配置文件。
exporter开发
Exporter简介
- Exporter 本质上就是将收集的数据,转化为对应的文本格式,并提供 http 接口,供蓝鲸监控采集器定期采集数据
Exporter基础
- 指标介绍 Prometheus中主要使用的四类指标类型,如下所示
- Counter (累加指标)
- Gauge (测量指标)
- Summary (概略图)
- Histogram (直方图)
最常使用的是Gauge,Gauge代表了采集的一个单一数据,这个数据可以增加也可以减少,比如CPU使用情况,内存使用量,硬盘当前的空间容量等。
Counter 一个累加指标数据,这个值随着时间只会逐渐的增加,比如程序完成的总任务数量,运行错误发生的总次数等,代表了持续增加的数据包或者传输字节累加值。
【注】:所有指标的值仅支持 float64类型
- 文本格式 以下面的输出为例:
# metric:
sample_metric1 12.47
sample_metric2{partition="c:"} 0.44
其中:
#
表示注释
sample_metric1
和sample_metric2
表示指标名称
partition
表示指标的作用维度,例如磁盘分区使用率,维度就是磁盘分区,即每个磁盘分区都有一个磁盘分区使用率的值
c:
表示维度的值,例如磁盘分区的C盘/D盘等
12.47
和0.44
表示对应指标的值
Exporter开发
- 环境搭建:
Golang安装
apt-get install git
wget https://dl.google.com/go/go1.10.7.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.10.7.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
export GOPATH=
你的代码目录
不同系统安装介绍:https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/01.1.md
- Prometheus exporter 开发依赖库 首先引入Prometheus的依赖库
go get -v github.com/prometheus/client_golang/prometheus
- 开发示例
- 导入依赖模块 本例计划采集主机的内存和磁盘信息,因此引入以下依赖库
go get -v github.com/shirou/gopsutil
go get -v github.com/go-ole/go-ole
go get -v github.com/StackExchange/wmi
go get -v github.com/golang/protobuf/proto
go get -v golang.org/x/sys/unix
- 新建一个exporter项目: 一个exporter只需要一个文件即可;在GOPATH下src目录下新建一个test_exporter目录和一个test_exporter.go文件:
test_exporter.go 文件第一行必须写上
图片描述 package main
可执行的命令必须始终使用package main。
package main
import (
"flag"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/mem"
"log"
"net/http"
)
- 定义exporter的版本(Version)、监听地址(listenAddress)、采集url(metricPath)以及首页(landingPage)
var (
Version = "1.0.0.dev"
listenAddress = flag.String("web.listen-address", ":9601", "Address to listen on for web interface and telemetry.")
metricPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.")
landingPage = []byte("<html><head><title>Example Exporter " + Version +
"</title></head><body><h1>Example Exporter " + Version + "</h1><p><a href='" + *metricPath + "'>Metrics</a></p></body></html>")
)
- 定义Exporter结构体
type Exporter struct {
error prometheus.Gauge
scrapeErrors *prometheus.CounterVec
}
- 定义结构体实例化的函数NewExporter
func NewExporter() *Exporter {
return &Exporter{
}
}
- Describe函数,传递指标描述符到channel,这个函数不用动,直接使用即可,用来生成采集指标的描述信息
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
metricCh := make(chan prometheus.Metric)
doneCh := make(chan struct{})
go func() {
for m := range metricCh {
ch <- m.Desc()
}
close(doneCh)
}()
e.Collect(metricCh)
close(metricCh)
<-doneCh
}
- Collect函数将执行抓取函数并返回数据,返回的数据传递到channel中,并且传递的同时绑定原先的指标描述符,以及指标的类型(Guage);需要将所有的指标获取函数在这里写入。
//collect函数,采集数据的入口
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
var err error
//每个指标值的采集逻辑,在对应的采集函数中
if err = ScrapeMem(ch); err != nil {
e.scrapeErrors.WithLabelValues("mem").Inc()
}
if err = ScrapeDisk(ch); err != nil {
e.scrapeErrors.WithLabelValues("disk").Inc()
}
}
- 指标仅有单条数据,不带维度信息示例如下:
func ScrapeMem(ch chan<- prometheus.Metric) error {
//指标获取逻辑,此处不做具体操作,仅仅赋值进行示例
mem_info, _ := mem.VirtualMemory()
//生成采集的指标名
metric_name := prometheus.BuildFQName("sys", "", "mem_usage")
//生成NewDesc类型的数据格式,该指标无维度,[]string{}为空
new_desc := prometheus.NewDesc(metric_name, "Gauge metric with mem_usage", []string{}, nil)
//生成具体的采集信息并写入ch通道
metric_mes := prometheus.MustNewConstMetric(new_desc, prometheus.GaugeValue, mem_info.UsedPercent)
ch <- metric_mes
return nil
}
- 指标有多条数据,带维度信息示例如下:
func ScrapeDisk(ch chan<- prometheus.Metric) error {
fs, _ := disk.Partitions(false)
for _, val := range fs {
d, _ := disk.Usage(val.Mountpoint)
metric_name := prometheus.BuildFQName("sys", "", "disk_size")
new_desc := prometheus.NewDesc(metric_name, "Gauge metric with disk_usage", []string{"mountpoint"}, nil)
metric_mes := prometheus.MustNewConstMetric(new_desc, prometheus.GaugeValue, float64(d.UsedPercent), val.Mountpoint)
ch <- metric_mes
}
return nil
}
- 主函数
func main() {
//解析定义的监听端口等信息
flag.Parse()
//生成一个Exporter类型的对象,该exporter需具有collect和Describe方法
exporter := NewExporter()
//将exporter注册入prometheus,prometheus将定期从exporter拉取数据
prometheus.MustRegister(exporter)
//接收http请求时,触发collect函数,采集数据
http.Handle(*metricPath, promhttp.Handler())
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write(landingPage)
})
log.Fatal(http.ListenAndServe(*listenAddress, nil))
}
- 编译Exporter
go build test_exporter.go
- cmd/shell中运行即可,访问http://127.0.0.1:9601/metrics即可验证
至此Exporter开发完成,其中8,9两步中的函数是重点,目前仅仅写了一些数据进行示例,其中的监控指标获取数据就是该部分的主要功能,需要编写对应逻辑获取指标的值。
任务二: 制作一键导入包
exporter编译
蓝鲸监控exporter默认只支持64位机器运行exporter。
linux系统
# 编译 windows exporter
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ./exporter-windows.exe test_exporter
# test_exporter 为GOPATH下我们创建的目录名
# 编译 linux exporter
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./exporter-linux test_exporter
windows系统
# 编译 windows exporter
SET CGO_ENABLED=0
SET GOOS=windows
SET GOARCH=amd64
go build -o ./exporter-windows.exe test_exporter
# 编译 linux exporter
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build -o ./exporter-linux test_exporter
exporter打包
- 上传的exporter文件限定为zip压缩包
- 上传后,后台会读取相应的压缩包特定名称的文件,因此必须保证命名的准确性。读取的文件如下:
exporter-linux
: linux采集器exporter-windows.exe
: windows采集器 - 至少提供以上任意一种采集器,否则会报错;如果只上传了一种采集器,那视为该组件不支持其他系统。
- 上传成功后如下图:
配置文件开发
指标项
- 通常,Exporter上报的指标(metric)种类非常多,而用户只会关心其中一部分重要指标。因此用户需要通过编写指标配置文件来配置自己关注的指标。同时,配置文件也决定了结果表的格式。
指标配置文件是JSON格式的文件。
图片描述 - 配置文件样例
[{
"fields": [{
"monitor_type": "metric",
"type": "double",
"name": "sys_disk_size",
"unit": "%",
"description": "磁盘使用率"
}, {
"monitor_type": "dimension",
"type": "string",
"name": "mountpoint",
"unit": "",
"description": "挂载点"
}],
"table_name": "disk",
"table_desc": "磁盘"
},
{
"fields": [{
"monitor_type": "metric",
"type": "double",
"name": "sys_mem_usage",
"unit": "%",
"description": "内存使用率"
}],
"table_name": "mem",
"table_desc": "内存"
}]
- 数据结构说明 首先,最外层为列表,列表的每个元素为Object,每个元素均代表一个结果表。 每个元素的字段说明和取值见下表:
字段名 | 解释 | 是否必填 | 取值 | 最大长度 |
---|---|---|---|---|
table_name | 结果表英文名 | 是 | \^a-zA-Z*$ | 15 |
table_desc | 结果表中文描述 | 是 | 15 | |
fields[].monitor_type | 字段类型 | 是 | 可选"metric"和"dimension" | |
fields[].type | 字段数据类型 | 是 | 可选"long", "double"和"string" | |
fields[].name | 字段名称,不能超过50个字符 | 是 | \^a-zA-Z*$ | 50 |
fields[].unit | 字段单位,可空 | 是 | ||
fields[].description | 字段描述 | 是 | 15 | |
fields[].is_diff_metric | 是否为差值指标 | 否 | true 或 false |
配置项(exporter启动参数配置)
- 大多数exporter在启动时,需要提供额外的参数,如服务地址等。因此用户需要对启动所需参数项进行配置,在exporter启动时才能提供对应参数值。
参数配置文件是JSON格式的文件
。配置项将直接体现在配置表单中图片描述 - 配置文件样例
[{
"default": "http://localhost:9601/metrics",
"mode": "collector",
"type": "text",
"name": "_exporter_url_",
"description": "采集URL",
"visible": false
},{
"default": "localhost:9601",
"mode": "cmd",
"type": "text",
"name": "--web.listen-address",
"description": "监听地址",
"visible": false
}]
- 数据结构说明 首先,最外层为列表,列表的每个元素为Object,每个元素均代表一个配置项。 每个元素的字段说明和取值见下表:
字段名 | 解释 | 是否必填 | 取值 | 最大长度 |
---|---|---|---|---|
name | 配置名称,可空,为空时必须将该项置于首位 | 是 | 50 | |
mode | 传参方式 | 是 | 可选"cmd"(命令行参数),"env"(环境变量)或"collector"(exporter_url字段专用) | |
type | 数据类型 | 是 | 可选"text","password"或"file"(需要上传文件) | |
description | 配置描述 | 是 | 50 | |
default | 配置默认值,可空 | 是 |
- 命令行参数拼接规则
- 当配置名称以
--
开头,参数名称和参数值的拼接方式为用=
拼接,如--settings=something
- 当配置名称不以
--
开头,参数名称和参数值的拼接方式为用空格拼接,如-settings something
- 重要提示
配置文件中,必须提供
_exporter_url_
参数。该参数为获取metric的完整url。且该参数必须设置默认值。出于安全考虑,监听地址的IP只能设置为127.0.0.1
或localhost
,配置方式参见上述样例
logo
155*65的图片即可
描述
使用Markdown语法编写组件描述描述,在用户组件接入时提供指导。
保存自定义组件采集
- 填写组件名
- 上传 exporter
- 上传 metrics.json
- 上传 config_schema.json
- 上传 logo.png
- 上传 description.md
- 选择服务器
- 填写配置
- 采集测试
- 设置采集周期
- 完成并下发采集器
以上动作完成后,在组件监控页面,将会多一个组件。选择自定义分类,可以看到所有自定义采集的组件。
自定义组件一键导入
为了方便自己开发的组件采集exporter可以共享给更多的用户,蓝鲸监控支持一键导入。
已经添加成功的自定义组件,可以按照以下格式打成zip压缩包:
- 后台解析文件时,无视文件目录结构,直接扫描符合命名规则的文件
- 不得出现相同文件名的文件,否则会报错
文件名 | 解释 |
---|---|
exporter-linux | linux exporter的二进制文件 (至少提供一种exporter) |
exporter-windows.exe | windows exporter的二进制文件 (至少提供一种exporter) |
logo.png | 组件Logo,限定PNG格式 |
description.md | 组件描述,限定Markdown格式 |
metrics.json | 指标项配置文件,配置格式参见 指标配置文件 |
config_schema.json | 配置项配置文件,配置格式参见 exporter启动参数配置文件 |
info.json | exporter包信息,需要提供name(必须)和display_name(可选) |
info.json
以上文件列表,有一个新的文件info.json
info.json 文件示例
{
"name":"example",
"display_name":"example",
"supported_version":"linux"
}
字段名 | 含义 |
---|---|
name | 组件名称,唯一标识符,只能由字母和数字组成 |
display_name | 组件显示名称 |
supported_version | 采集器支持版本,版本信息会显示在配置页面上 |
显示效果如下
自定义组件更新
如果需要更新组件,进入编辑模式,选择相应文件进行更新即可
附件是一个样例exporter一键导入包,另外包含了打包好的exporter以及源码
使用附件导入后,选择主机下发后,效果如下:
学员评价