metrics data info

master
dustoair 2 years ago
commit c2f972220e

7
.gitignore vendored

@ -0,0 +1,7 @@
.idea
go.sum
*.exe
host.csv
monitor.csv
logs
*.log

@ -0,0 +1,41 @@
/*
*
@author: sre
@date: 2023/11/19 0019
@desc: todo
*
*/
package main
import "strings"
// getCPUInfo 获取cpu核心 使用率
func getCPUInfo(ip, port string) (int, float64, error) {
var cpuTotal, cpuIdle float64
var cpuCount int
data, err := getMetrics(ip, port)
if err != nil {
return 0, 0, err
}
// 解析metrics数据
lines := strings.Split(data, "\n")
for _, line := range lines {
if strings.HasPrefix(line, "node_cpu_seconds_total") {
fields := strings.Fields(line)
if len(fields) == 2 {
cpuData, err := extractMetricValue(fields[1])
if err != nil {
//fmt.Println("无法提取指标值: ", err)
return 0, 0, err
}
cpuTotal += cpuData
if strings.Contains(line, "mode=\"idle\"") {
cpuIdle += cpuData
cpuCount += 1
}
}
}
}
return cpuCount, 100 * (1 - cpuIdle/cpuTotal), nil
}

@ -0,0 +1,50 @@
/*
*
@author: sre
@date: 2023/11/19 0019
@desc: todo
*
*/
package main
import (
"github.com/gocarina/gocsv"
"os"
)
// Monitor for output
type Monitor struct {
IP string `csv:"ip"`
Port string `csv:"port"`
CPUCore int `csv:"cpu_core"`
CPUUsage float64 `csv:"cpu_usage"`
MemTotal float64 `csv:"mem_total"`
MemAvailable float64 `csv:"mem_available"`
NodeLoad1 float64 `csv:"node_load1"`
NodeLoad5 float64 `csv:"node_load5"`
NodeLoad15 float64 `csv:"node_load15"`
ERROR string `csv:"error"`
}
// Host for input
type Host struct {
IP string `csv:"ip"`
Port string `csv:"port"`
}
func GetHostListFromCSV() ([]*Host, error) {
hostssFile, err := os.OpenFile(INPUTFILE, os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil {
return nil, err
}
defer hostssFile.Close()
hosts := []*Host{}
if err := gocsv.UnmarshalFile(hostssFile, &hosts); err != nil { // Load hosts from file
//if err := gocsv.UnmarshalBytes(CSVDATA, &hosts); err != nil { // Load hosts from file
return nil, err
}
return hosts, nil
}

@ -0,0 +1,30 @@
/*
*
@author: sre
@date: 2023/11/19 0019
@desc: todo
*
*/
package main
import (
"fmt"
"testing"
)
func TestGetHostListFromCSV(t *testing.T) {
hosts, err := GetHostListFromCSV()
if err != nil {
fmt.Println(err)
}
for _, host := range hosts {
fmt.Println(host)
}
}
func TestStrclean(t *testing.T) {
s1 := "\"30.1 30.251.46,\","
fmt.Println(strClean(s1))
}

@ -0,0 +1,5 @@
module exporterData
go 1.21
require github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a

@ -0,0 +1,3 @@
ip,port
119.91.19.44,9100
119.91.19.44,9100
1 ip port
2 119.91.19.44 9100
3 119.91.19.44 9100

@ -0,0 +1,2 @@
ip,port
127.0.0.1,19100
1 ip port
2 127.0.0.1 19100

@ -0,0 +1,58 @@
/*
*
@author: sre
@date: 2023/11/19 0019
@desc: todo
*
*/
package main
import "strings"
func getLoadInfo(ip, port string) (float64, float64, float64, error) {
var node_load1, node_load5, node_load15 float64
data, err := getMetrics(ip, port)
if err != nil {
return 0, 0, 0, err
}
// 解析metrics数据
lines := strings.Split(data, "\n")
for _, line := range lines {
//node_load1
if strings.HasPrefix(line, "node_load1 ") {
fields := strings.Fields(line)
if len(fields) == 2 {
node_load1, err = extractMetricValue(fields[1])
if err != nil {
return 0, 0, 0, err
}
}
}
//node_load5
if strings.HasPrefix(line, "node_load5 ") {
fields := strings.Fields(line)
if len(fields) == 2 {
node_load1, err = extractMetricValue(fields[1])
if err != nil {
return 0, 0, 0, err
}
}
}
//node_load15
if strings.HasPrefix(line, "node_load15 ") {
fields := strings.Fields(line)
if len(fields) == 2 {
node_load1, err = extractMetricValue(fields[1])
if err != nil {
return 0, 0, 0, err
}
}
}
}
return node_load1, node_load5, node_load15, nil
}

@ -0,0 +1,126 @@
package main
import (
"fmt"
"github.com/gocarina/gocsv"
"io"
"log"
"net"
"net/http"
"os"
"strconv"
"strings"
"time"
)
func main() {
monitorsFile, err := os.OpenFile(OUTPUTFILE, os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil {
panic(err)
}
defer monitorsFile.Close()
monitors := []*Monitor{}
hosts, err := GetHostListFromCSV()
if err != nil {
fmt.Println(err)
}
totalHosts := len(hosts)
count := 0
log.Println("本次要处理主机数量: ", totalHosts)
for _, host := range hosts {
fmt.Println(host)
var errorflag string
serverIP := strClean(host.IP)
if !isTCPOpen(serverIP, host.Port) {
count += 1
log.Println(count, "/", totalHosts, "端口不通: ", serverIP, host.Port)
continue
}
cpuCore, cpuUsage, err1 := getCPUInfo(serverIP, host.Port)
memTotal, memAvailable, err2 := getMemoryInfo(serverIP, host.Port)
nodeLoad1, nodeLoad5, nodeLoad15, err3 := getLoadInfo(serverIP, host.Port)
if err1 != nil || err2 != nil || err3 != nil {
fmt.Println("host error: ", err)
errorflag = "error"
}
monitors = append(monitors, &Monitor{
IP: serverIP,
Port: host.Port,
CPUCore: cpuCore,
CPUUsage: cpuUsage,
MemTotal: memTotal,
MemAvailable: memAvailable,
NodeLoad1: nodeLoad1,
NodeLoad5: nodeLoad5,
NodeLoad15: nodeLoad15,
ERROR: errorflag,
})
count += 1
log.Println(count, "/", totalHosts, " handled: ", serverIP)
}
err = gocsv.MarshalFile(&monitors, monitorsFile) // Use this to save the CSV back to the file
if err != nil {
panic(err)
}
}
func getMetrics(ip, port string) (string, error) {
// 发送HTTP请求获取Node Exporter的metrics数据
address := "http://" + ip + ":" + port + "/metrics"
response, err := http.Get(address)
if err != nil {
log.Println("无法发送HTTP请求", err)
//log.Fatal("无法发送HTTP请求", err)
return "", err
}
defer response.Body.Close()
// 读取响应内容
body, err := io.ReadAll(response.Body)
if err != nil {
log.Println("无法读取响应内容:", err)
//log.Fatal("无法读取响应内容:", err)
return "", err
}
return string(body), nil
}
// 从指标行中提取指标值,并将其转换为浮点数类型
func extractMetricValue(value string) (float64, error) {
// 去除指标值的单位(此处假设单位为'count'
value = strings.Split(value, " ")[0]
// 将指标值转换为浮点数类型并返回
return parseFloat(value)
}
// 将字符串转换为浮点数类型,并处理可能的错误情况
func parseFloat(value string) (float64, error) {
f, err := strconv.ParseFloat(value, 64)
if err != nil {
return 0, err
}
return f, nil
}
func strClean(str string) string {
str = strings.ReplaceAll(str, " ", "")
str = strings.ReplaceAll(str, ",", "")
str = strings.ReplaceAll(str, "\"", "")
return str
}
func isTCPOpen(ip, port string) bool {
// 尝试在指定端口上建立连接
address := ip + ":" + port
conn, err := net.DialTimeout("tcp", address, time.Millisecond*10)
if err != nil {
return false
}
defer conn.Close()
return true
}

@ -0,0 +1,75 @@
/*
*
@author: sre
@date: 2023/11/19 0019
@desc: todo
*
*/
package main
import (
"strings"
)
// getMemoryInfo 返回总内存 可用内存
func getMemoryInfo(ip, port string) (float64, float64, error) {
var memTotal, memAvailable float64
data, err := getMetrics(ip, port)
if err != nil {
return 0, 0, err
}
// 解析metrics数据
lines := strings.Split(data, "\n")
for _, line := range lines {
//memTotal
if strings.HasPrefix(line, "node_memory_MemTotal_bytes ") {
fields := strings.Fields(line)
if len(fields) == 2 {
memTotal, err = extractMetricValue(fields[1])
if err != nil {
return 0, 0, err
}
}
}
//memAvailable
if strings.HasPrefix(line, "node_memory_MemAvailable_bytes ") {
fields := strings.Fields(line)
if len(fields) == 2 {
memAvailable, err = extractMetricValue(fields[1])
if err != nil {
return 0, 0, err
}
}
}
}
return memTotal, memAvailable, nil
}
//// 解析Node Exporter的响应内容提取内存使用率指标
//func parseMemoryUsage(response string) float64 {
// // 在响应中找到相关的指标行,例如 "node_memory_MemTotal: 167772160000 149510252888 149510252888"
// lines := strings.Split(response, "\n")
// for _, line := range lines {
// if strings.Contains(line, "node_memory_MemTotal") {
// fields := strings.Fields(line)
// if len(fields) >= 4 {
// // 从指标行中提取内存使用率指标,并将其转换为百分比形式
// memoryUsage := strings.TrimSuffix(fields[2], " ") + "%"
// return getPercentage(memoryUsage)
// }
// }
// }
//
// // 如果找不到相关的指标行则返回0%
// return 0.0
//}
//
//// 从字符串中提取百分比值,并将其转换为浮点数形式
//func getPercentage(percentage string) float64 {
// // 去掉百分号,并将其转换为浮点数形式
// percentage = strings.ReplaceAll(percentage, "%", "")
// return parseFloat(percentage) * (100.0 / 100) // 将字符串转换为浮点数并乘以100转换为百分比形式
//}

@ -0,0 +1,16 @@
交叉编译
```cmd
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build
```
```cmd
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=arm64
go build
```

@ -0,0 +1,13 @@
/*
*
@author: sre
@date: 2023/11/19 0019
@desc: todo
*
*/
package main
const (
INPUTFILE = "host.csv"
OUTPUTFILE = "monitor.csv"
)
Loading…
Cancel
Save