需求:利用go語言獲取linux主機的cpu利用率及內存使用量和剩餘量,並將其製做成exporter
編寫go代碼及註解以下:
package main
import (
"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