这个是收集器的代码,用go带的扩展包,实现对本机基本数据的采集,然后通过定义指定的指标结构体,初始化指标结构体,将结构体的指标传递给channl,后面采集器按指标采集数据,最后那段代码就是用go收集到数据的过程
package collector
import (
"github.com/ip"
"github.com/prometheus/client_golang/prometheus"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/host"
"github.com/shirou/gopsutil/mem"
"github.com/shirou/gopsutil/net"
"sync"
"time"
)
// 指标结构体
type Metrics struct {
metrics map[string]*prometheus.Desc
mutex sync.Mutex
}
/**
* 函数:newGlobalMetric
* 功能:创建指标描述符
*/
func newGlobalMetric(namespace string, metricName string, docString string, labels []string) *prometheus.Desc {
return prometheus.NewDesc(namespace+"_"+metricName, docString, labels, nil)
}
/**
* 工厂方法:NewMetrics
* 功能:初始化指标信息,即Metrics结构体
*/
func NewMetrics(namespace string) *Metrics {
return &Metrics{
metrics: map[string]*prometheus.Desc{
"my_counter_metric": newGlobalMetric(namespace, "server_A_Name","The description of my_counter_metric",[]string{
"name"}),
"my_ip_metric": newGlobalMetric(namespace, "server_A_IP","The description of my_counter_metric",[]string{
"ip"}),
"my_gauge_metric": newGlobalMetric(namespace, "server_Network","The description of my_gauge_metric", []string{
"name"}),
"my_cpu_metric": newGlobalMetric(namespace, "server_Cpu","The description of my_cpu_metric", []string{
"name"}),
"my_disk_metric": newGlobalMetric(namespace, "server_Disk","The description of my_cpu_metric", []string{
"name"}),
"my_mem_metric": newGlobalMetric(namespace, "server_Mem","The description of my_cpu_metric", []string{
"name"}),
},
}
}
/**
* 接口:Describe
* 功能:传递结构体中的指标描述符到channel
*/
func (c *Metrics) Describe(ch chan<- *prometheus.Desc) {
for _, m := range c.metrics {
ch <- m
}
}
/**
* 接口:Collect
* 功能:抓取最新的数据,传递给channel
*/
func (c *Metrics) Collect(ch chan<- prometheus.Metric) {
c.mutex.Lock() // 加锁
defer c.mutex.Unlock()
mockCounterMetricData, mockGaugeMetricData, mockCpuMetricData, mockDiskMetricData, mockMemMetricData, mockIpMetricData := c.GenerateMockData()
for host, currentValue := range mockCounterMetricData {
ch <-prometheus.MustNewConstMetric(c.metrics["my_counter_metric"], prometheus.CounterValue,float64(currentValue),host)
}
for host, currentValue := range mockGaugeMetricData {
ch <-prometheus.MustNewConstMetric(c.metrics["my_gauge_metric"], prometheus.GaugeValue,float64(currentValue),host)
}
for host, currentValue := range mockCpuMetricData {
ch <-prometheus.MustNewConstMetric(c.metrics["my_cpu_metric"], prometheus.GaugeValue,float64(currentValue),host)
}
for host, currentValue := range mockDiskMetricData {
ch <-prometheus.MustNewConstMetric(c.metrics["my_disk_metric"], prometheus.GaugeValue,float64(currentValue),host)
}
for host, currentValue := range mockMemMetricData {
ch <-prometheus.MustNewConstMetric(c.metrics["my_mem_metric"], prometheus.GaugeValue,float64(currentValue),host)
}
for host, currentValue := range mockIpMetricData {
ch <-prometheus.MustNewConstMetric(c.metrics["my_ip_metric"], prometheus.CounterValue,float64(currentValue),host)
}
}
/**
* 函数:GenerateMockData
* 功能:生成模拟数据
*/
func (c *Metrics) GenerateMockData() (mockCounterMetricData map[string]float64, mockGaugeMetricData map[string]float64, mockCpuMetricData map[string]float64, mockDiskMetricData map[string]float64, mockMemMetricData map[string]float64, mockIpMetricData map[string]float64){
n, _ := host.Info()
d, _ := disk.Usage("/")
v, _ := mem.VirtualMemory()
boottime, _ := host.BootTime()
btime := time.Unix(int64(boottime), 0).Format("2006-01-02 15:04:05")
cc, _ := cpu.Percent(time.Second, false)
nv, _ := net.IOCounters(true)
ip := ip.GetOutboundIP()
diskTotal := float64(d.Total/1024/1024/1024)
diskFree := float64(d.Free/1024/1024/1024)
diskUsage := float64(d.UsedPercent)
memTotal := float64(v.Total/1024/1024)
memFree :=float64(v.Available/1024/1024)
memUsed :=float64(v.Used/1024/1024)
memUsage :=float64(v.UsedPercent)
cpuUsage :=float64(cc[0])
bytesRecv :=float64(nv[0].BytesRecv)
bytesSent :=float64(nv[0].BytesSent)
mockCounterMetricData = map[string]float64{
n.Hostname:0,
btime:0,
}
mockIpMetricData = map[string]float64{
ip:0,
}
mockCpuMetricData = map[string]float64{
"Cpu Usage(%)":cpuUsage,
}
mockDiskMetricData = map[string]float64{
"Disk Total(GB)":diskTotal,
"Disk Free(GB)":diskFree,
"Disk Usage(%)":diskUsage,
}
mockMemMetricData = map[string]float64{
"Mem Total(MB)":memTotal,
"Mem Free(MB)":memFree,
"Mem Used(MB)":memUsed,
"Mem Usage(%)":memUsage,
}
mockGaugeMetricData = map[string]float64{
// "disk Total(GB)":diskTotal,
// "disk Free(GB)":diskFree,
// "disk Usage(%)":diskUsage,
// "mem Total(MB)":memTotal,
// "mem Free(MB)":memFree,
// "mem Used(MB)":memUsed,
// "mem Usage(%)":memUsage,
// "cpu Usage(%)":cpuUsage,
"Bytes Recv(bytes)":bytesRecv,
"Bytes Sent(bytes)":bytesSent,
}
return
}
可以获取到自己的本机ip,返回到collect函数进行收集
package ip
import (
"fmt"
"net"
)
func GetOutboundIP() string {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
println("error")
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
fmt.Println(localAddr.String())
return localAddr.IP.String()
}
定义用prometheus的http扩展包来实现数据传递,将collect函数收集到的数据传到prometueus上,底下设置prometheus主机的ip端口,就可以了。
package main
import (
"flag"
"github.com/collector"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"log"
"net/http"
)
var (
// Set during go build
// version string
// gitCommit string
// 命令行参数
listenAddr = flag.String("web.listen-port", "9000", "An port to listen on for web interface and telemetry.")
metricsPath = flag.String("web.telemetry-path", "/metrics", "A path under which to expose metrics.")
metricsNamespace = flag.String("metric.namespace", "ECSDATA", "Prometheus metrics namespace, as the prefix of metrics name")
)
func main() {
flag.Parse()
metrics := collector.NewMetrics(*metricsNamespace)
registry := prometheus.NewRegistry()
registry.MustRegister(metrics)
http.Handle(*metricsPath, promhttp.HandlerFor(registry, promhttp.HandlerOpts{
}))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`
A Prometheus Exporter
A Prometheus Exporter
`))
})
log.Printf("Starting Server at http://localhost:%s%s", *listenAddr, *metricsPath)
log.Fatal(http.ListenAndServe(":"+*listenAddr, nil))
}
后面go run mian.go 就好,去浏览器看127.0.0.1:9001,就可以看到
Go语言中也是通过包来组织代码文件,我们可以引用别人的包也可以发布自己的包,但是为了防止不同包的项目名冲突,我们通常使用顶级域名来作为包名的前缀,这样就不担心项目名冲突的问题了。
因为不是每个个人开发者都拥有自己的顶级域名,所以目前流行的方式是使用个人的github用户名来区分不同的包。
举个例子:张三和李四都有一个名叫studygo的项目,那么这两个包的路径就会是:
import "github.com/zhangsan/studygo"
和
import "github.com/lisi/studygo"
以后我们从github上下载别人包的时候,如:
go get github.com/jmoiron/sqlx
那么,这个包会下载到我们本地GOPATH目录下的src/github.com/jmoiron/sqlx。
github地址:https://github.com/daoenqiangsen/prometheus_expoler
参考博客:
https://www.cnblogs.com/koangel/p/6647826.html
https://blog.csdn.net/lisonglisonglisong/article/details/81743555
https://github.com/SongLee24/prometheus-exporter