通过go语言编写prometheus的node-exporter,获取本机的cpu,内存,ip,等基本信息

collect函数

这个是收集器的代码,用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地址方法

可以获取到自己的本机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

Metrics

`
)) }) 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语言编写prometheus的node-exporter,获取本机的cpu,内存,ip,等基本信息_第1张图片

通过go语言编写prometheus的node-exporter,获取本机的cpu,内存,ip,等基本信息_第2张图片

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。

注意:我这个获取的是可以获取到,但是获取出来的格式不好看,注意自己的扩展包放的位置是在自己的$root/src/…,拓展包的下载可以直接搜例如:github.com/prometheus/client_golang/prometheus,我的collector函数包也是在那个目录下

我的github.com是在 /usr/local/go/src/github.com/ 下面有很多包,大家导入包的时候注意地址

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

你可能感兴趣的:(企业,go,golang,Prometheus,Node_exporter,Prometheus,运维)