server/admin/api/monitor.go

99 lines
2.0 KiB
Go

package api
import (
"bufio"
"io/ioutil"
"net/http"
"os"
"strconv"
"strings"
"github.com/gin-gonic/gin"
)
func declareMonitorRoutes(router *gin.RouterGroup) {
router.GET("/monitor", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"localhost": genLocalConstants(),
})
})
}
func readLoadAvg(fd *os.File) (ret map[string]float64) {
if s, err := ioutil.ReadAll(fd); err == nil {
f := strings.Fields(strings.TrimSpace(string(s)))
if len(f) >= 3 {
ret = map[string]float64{}
ret["1m"], _ = strconv.ParseFloat(f[0], 64)
ret["5m"], _ = strconv.ParseFloat(f[1], 64)
ret["15m"], _ = strconv.ParseFloat(f[2], 64)
}
}
return
}
func readMeminfo(fd *os.File) (ret map[string]uint64) {
ret = map[string]uint64{}
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
f := strings.Fields(strings.TrimSpace(scanner.Text()))
if len(f) >= 2 {
if v, err := strconv.ParseUint(f[1], 10, 64); err == nil {
ret[strings.ToLower(strings.TrimSuffix(f[0], ":"))] = v * 1024
}
}
}
return
}
func readCPUStats(fd *os.File) (ret map[string]map[string]uint64) {
ret = map[string]map[string]uint64{}
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
f := strings.Fields(strings.TrimSpace(scanner.Text()))
if len(f[0]) >= 4 && f[0][0:3] == "cpu" && len(f) >= 8 {
ret[f[0]] = map[string]uint64{}
var total uint64 = 0
for i, k := range []string{"user", "nice", "system", "idle", "iowait", "irq", "softirq"} {
if v, err := strconv.ParseUint(f[i+1], 10, 64); err == nil {
ret[f[0]][k] = v
total += v
}
}
ret[f[0]]["total"] = total
}
}
return
}
func genLocalConstants() interface{} {
ret := map[string]interface{}{}
fi, err := os.Open("/proc/loadavg")
if err != nil {
return err
}
defer fi.Close()
ret["loadavg"] = readLoadAvg(fi)
fi, err = os.Open("/proc/meminfo")
if err != nil {
return err
}
defer fi.Close()
ret["meminfo"] = readMeminfo(fi)
fi, err = os.Open("/proc/stat")
if err != nil {
return err
}
defer fi.Close()
ret["cpustat"] = readCPUStats(fi)
return ret
}