用go编写prometheus自研exporter——CPU及内存的指标
16lz
2021-04-07
需求:利用go语言获取linux主机的cpu利用率及内存使用量和剩余量,并将其制作成exporter
编写go代码及注解如下:
package mainimport ( "bufio" "io/ioutil" "net/http" "os" "fmt" "strconv" "strings" "time")func getCPUSample() (idle, total uint64) { //读取/proc/stat内容 contents, err := ioutil.ReadFile("/proc/stat") if err != nil { return } //读取内容转化为字符串 lines := strings.Split(string(contents), "\n") for _, line := range(lines) { //将字符串以空白字符(\t, \n, \v, \f, \r, ’ ‘, U+0085 (NEL), U+00A0 (NBSP) 。)进行分割多个子串 fields := strings.Fields(line) //如果第一列字符为“cpu” if fields[0] == "cpu" { //统计子串数量 numFields := len(fields) for i := 1; i < numFields; i++ { val, err := strconv.ParseUint(fields[i], 10, 64) if err != nil { fmt.Println("Error: ", i, fields[i], err) } //将是CPU字符的所有子串相加 total += val // tally up all the numbers to get total ticks if i == 4 { // idle is the 5th field in the cpu line //第五列的数据赋值给idle idle = val } } return } } return}func ReadLine(lineNumber int) string{ //读取/proc/meminfo内容 file, _ := os.Open("/proc/meminfo") //按行读取所有内容 fileScanner := bufio.NewScanner(file) lineCount := 1 for fileScanner.Scan(){ if lineCount == lineNumber{ return fileScanner.Text() } lineCount++ } defer file.Close() return ""}func handler(w http.ResponseWriter, r *http.Request) { //定义一个整数型切片 var s []int //读取/proc/meminfo的第二行内容 MemFree := ReadLine(2) //将读取的内容转化为字符串 MemFree_lines := strings.Split(string(MemFree), "\n") //将字符串以空白字符(\t, \n, \v, \f, \r, ’ ‘, U+0085 (NEL), U+00A0 (NBSP) 。)进行分割多个子串 for _, MemFree_line := range (MemFree_lines) { fields := strings.Fields(MemFree_line) //将第二列的内容转化为整数,并将这个整数追加到s切片中 if MemFree_line, err := strconv.Atoi(fields[1]); err == nil { //fmt.Printf("%T, %v", MemFree_line, MemFree_line) s = append(s, MemFree_line) } } Buffers := ReadLine(4) Buffers_lines := strings.Split(string(Buffers), "\n") for _, Buffers_line := range (Buffers_lines) { fields := strings.Fields(Buffers_line) if Buffers_line, err := strconv.Atoi(fields[1]); err == nil { //fmt.Printf("%T, %v", Buffers_line, Buffers_line) s = append(s, Buffers_line) } } Cached := ReadLine(4) Cached_lines := strings.Split(string(Cached), "\n") for _, Cached_line := range (Cached_lines) { fields := strings.Fields(Cached_line) if Cached_line, err := strconv.Atoi(fields[1]); err == nil { //fmt.Printf("%T, %v", Cached_line, Cached_line) s = append(s, Cached_line) } } MemTotal := ReadLine(1) MemTotal_lines := strings.Split(string(MemTotal), "\n") for _, MemTotal_line := range (MemTotal_lines) { fields := strings.Fields(MemTotal_line) if MemTotal_line, err := strconv.Atoi(fields[1]); err == nil { //fmt.Printf("%T, %v", MemTotal_line, MemTotal_line) s = append(s, MemTotal_line) } } idle0, total0 := getCPUSample() time.Sleep(3 * time.Second) idle1, total1 := getCPUSample() idleTicks := float64(idle1 - idle0) totalTicks := float64(total1 - total0) //计算cpu利用率 cpuUsage := 100 * (totalTicks - idleTicks) / totalTicks //计算内存的使用率及剩余量 memoryused := (s[0] + s[1] + s[2]) memoryfreeused:=(s[3]-memoryused) //页面显示内容 fmt.Fprintf(w,"#HELP node_memory_guest_seconds\n node_memory{key=\"used\"}\t%v\n node_memory{key=\"free\"}\t%v\n#node_CPU_guest_seconds\n node_cpu{key=\"usage\"}\t%v\n",memoryused,memoryfreeused,cpuUsage)}func main(){//调用handler函数 http.HandleFunc("/", handler) //端口为8006 http.ListenAndServe(":8006", nil)}
执行并打开页面(每次加载页面会自动刷新数据值):
[root@localhost ~]# go run exporter_cpu_memory.go[root@localhost ~]# curl 127.0.0.1:8006#HELP node_memory_guest_seconds node_memory{key="used"} 117864 node_memory{key="free"} 878060#node_CPU_guest_seconds node_cpu{key="usage"} 0
©著作权归作者所有:来自51CTO博客作者上古杰作的原创作品,如需转载,请注明出处,否则将追究法律责任每一份赞赏源于懂得
赞赏
0人进行了赞赏支持
更多相关文章
- 宝塔面板非https站点使用https访问跳转其他网站内容的处理办法
- 编程题三:使用指针来打印数组内容
- 求解磁盘结构损坏且无法读取咋找回???
- Python_学习之文件读写
- 《从0到1学习Flink》—— Data Source 介绍
- 存储卡出现“文件或目录结构损坏且无法读取”的解决办法
- Markdown基本语法解析
- Python爬取小说
- js文件中如何读取app.ux中的全局变量