通过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(`<html>
			<head><title>A Prometheus Exporter</title></head>
			<body>
			<h1>A Prometheus Exporter</h1>
			<p><a href='/metrics'>Metrics</a></p>
			</body>
			</html>`))
	})

	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。

注意:我这个获取的是可以获取到,但是获取出来的格式不好看,注意自己的扩展包放的位置是在自己的$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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是 prometheus 节点 CPU内存、磁盘使用率的报警规则和 node-exporter 应建的报警规则的 yaml 配置文件示例: 1. prometheus 节点 CPU内存、磁盘使用率的报警规则 ```yaml groups: - name: prometheus_rules rules: - alert: NodeCPUUsageHigh expr: 100 * (1 - avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)) > 90 for: 5m labels: severity: warning annotations: summary: "CPU usage is high on instance {{ $labels.instance }}" description: "CPU usage is high on instance {{ $labels.instance }} (value: {{ $value }})." - alert: NodeMemoryUsageHigh expr: 100 * (node_memory_MemTotal_bytes - node_memory_MemFree_bytes - node_memory_Buffers_bytes - node_memory_Cached_bytes) / node_memory_MemTotal_bytes > 90 for: 5m labels: severity: warning annotations: summary: "Memory usage is high on instance {{ $labels.instance }}" description: "Memory usage is high on instance {{ $labels.instance }} (value: {{ $value }})." - alert: NodeDiskUsageHigh expr: 100 * node_filesystem_size_bytes{fstype!="tmpfs", fstype!="rootfs"} - node_filesystem_free_bytes{fstype!="tmpfs", fstype!="rootfs"} > 90 * node_filesystem_size_bytes{fstype!="tmpfs", fstype!="rootfs"} for: 5m labels: severity: warning annotations: summary: "Disk usage is high on instance {{ $labels.instance }}" description: "Disk usage is high on instance {{ $labels.instance }} (value: {{ $value }})." ``` 2. node-exporter 应建的报警规则 ```yaml groups: - name: node_exporter_rules rules: - alert: NodeCPUUsageHigh expr: 100 * (1 - avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)) > 90 for: 5m labels: severity: warning annotations: summary: "CPU usage is high on instance {{ $labels.instance }}" description: "CPU usage is high on instance {{ $labels.instance }} (value: {{ $value }})." - alert: NodeMemoryUsageHigh expr: 100 * (node_memory_MemTotal_bytes - node_memory_MemFree_bytes - node_memory_Buffers_bytes - node_memory_Cached_bytes) / node_memory_MemTotal_bytes > 90 for: 5m labels: severity: warning annotations: summary: "Memory usage is high on instance {{ $labels.instance }}" description: "Memory usage is high on instance {{ $labels.instance }} (value: {{ $value }})." - alert: NodeDiskUsageHigh expr: 100 * node_filesystem_size_bytes{fstype!="tmpfs", fstype!="rootfs"} - node_filesystem_free_bytes{fstype!="tmpfs", fstype!="rootfs"} > 90 * node_filesystem_size_bytes{fstype!="tmpfs", fstype!="rootfs"} for: 5m labels: severity: warning annotations: summary: "Disk usage is high on instance {{ $labels.instance }}" description: "Disk usage is high on instance {{ $labels.instance }} (value: {{ $value }})." - alert: NetworkTrafficHigh expr: sum(rate(node_network_receive_bytes_total[5m]) + rate(node_network_transmit_bytes_total[5m])) by (instance) > 1e+08 for: 5m labels: severity: warning annotations: summary: "Network traffic is high on instance {{ $labels.instance }}" description: "Network traffic is high on instance {{ $labels.instance }} (value: {{ $value }})." - alert: ProcessCountHigh expr: count(processes) by (instance) > 600 for: 5m labels: severity: warning annotations: summary: "Process count is high on instance {{ $labels.instance }}" description: "Process count is high on instance {{ $labels.instance }} (value: {{ $value }})." - alert: SystemLoadHigh expr: node_load1 > 2.5 or node_load5 > 2 or node_load15 > 1.5 for: 5m labels: severity: warning annotations: summary: "System load is high on instance {{ $labels.instance }}" description: "System load is high on instance {{ $labels.instance }} (value: {{ $value }})." ``` 需要注意的是,上述示例中的 promql 表达式只是简单的示例,具体的阈值和表达式应该根据实际情况进行调整。另外,需要将上述 yaml 配置文件保存为一个文件,比如 node-exporter-rules.yaml,并将该文件加入到 Prometheus 的配置文件中以启用这些报警规则。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值