From cca41809724152588e5a528c18c66755df12d086 Mon Sep 17 00:00:00 2001 From: Fabrizio Furnari Date: Tue, 1 Dec 2020 22:31:10 +0100 Subject: [PATCH] Added other stats and json serialization --- main.go | 50 +++++++++++++++++++--- stats.go | 121 +++++++++++++++++++++++++++++++++++++++--------------- struct.go | 73 ++++++++++++++++++++++---------- 3 files changed, 185 insertions(+), 59 deletions(-) diff --git a/main.go b/main.go index 974b057..2c72330 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "flag" "fmt" "log" @@ -20,11 +21,37 @@ var ( // TODO: bench test with pointer func getMetrics() (Metric, error) { log.Println("Started getMetrics") - var s = Stat{} m := Metric{} - cpustats := s.CPUStats() - m.Load1m = cpustats.LoadMin1 - log.Printf("Metric: %v\n", m) + err := m.getMemory() + if err != nil { + log.Printf("Cannot get memory: %s\n", err) + return m, err + } + + err = m.getLoadAvg() + if err != nil { + log.Printf("Cannot get load average: %s\n", err) + return m, err + } + + err = m.getCpuMetric() + if err != nil { + log.Printf("Cannot get CPU metrics: %s\n", err) + return m, err + } + + err = m.getDiskMetrics() + if err != nil { + log.Printf("Cannot get disk metrics: %s\n", err) + return m, err + } + + err = m.getNetworkMetrics() + if err != nil { + log.Printf("Cannot get network metrics: %s\n", err) + return m, err + } + return m, nil } @@ -131,8 +158,19 @@ func (t *Test) stopTest(w http.ResponseWriter, req *http.Request) { } func (t *Test) testStatus(w http.ResponseWriter, req *http.Request) { - fmt.Fprintf(w, "%v\n", t.Result) - fmt.Fprintf(w, "Test %s, status: %s\n", t.Name, t.Status) + qFormat := req.URL.Query().Get("format") + if qFormat == "json" { + b, err := json.Marshal(t.Result) + if err != nil { + log.Printf("Cannot marshal json: %s\n", err) + http.Error(w, err.Error(), 500) + return + } + fmt.Fprintf(w, "%s\n", b) + } else { + fmt.Fprintf(w, "%v\n", t.Result) + fmt.Fprintf(w, "Test %s, status: %s\n", t.Name, t.Status) + } } func newTest() *Test { diff --git a/stats.go b/stats.go index 90a2576..075baf1 100644 --- a/stats.go +++ b/stats.go @@ -1,43 +1,100 @@ package main -// #cgo LDFLAGS: -lstatgrab -// #include -import "C" -import "time" +import ( + "log" -var mainfunc = make(chan func()) + "github.com/mackerelio/go-osstat/cpu" + "github.com/mackerelio/go-osstat/disk" + "github.com/mackerelio/go-osstat/loadavg" + "github.com/mackerelio/go-osstat/memory" + "github.com/mackerelio/go-osstat/network" +) -func do(f func()) { - done := make(chan bool, 1) - mainfunc <- func() { - f() - done <- true +func (m *Metric) getMemory() error { + memory, err := memory.Get() + if err != nil { + log.Printf("Cannot get memory: %s\n", err) + return err } - <-done + m.MemMetrics.FreeMem = memory.Free + m.MemMetrics.TotalMem = memory.Total + m.MemMetrics.UsedMem = memory.Used + m.MemMetrics.BuffersMem = memory.Buffers + m.MemMetrics.CachedMem = memory.Cached + m.MemMetrics.AvailableMem = memory.Available + m.MemMetrics.ActiveMem = memory.Active + m.MemMetrics.InactiveMem = memory.Inactive + m.MemMetrics.SwapTotal = memory.SwapTotal + m.MemMetrics.SwapUsed = memory.SwapUsed + m.MemMetrics.SwapCached = memory.SwapCached + m.MemMetrics.SwapFree = memory.SwapFree + return nil } -func (s *Stat) CPUStats() *CPUStats { - s.Lock() - defer s.Unlock() +func (m *Metric) getLoadAvg() error { + loadAvg, err := loadavg.Get() + if err != nil { + log.Printf("Cannot get loadAvg(): %s\n", err) + return err + } + m.LoadMetrics.Load1m = loadAvg.Loadavg1 + m.LoadMetrics.Load5m = loadAvg.Loadavg5 + m.LoadMetrics.Load15m = loadAvg.Loadavg15 + return nil +} - var cpu *CPUStats +func (m *Metric) getCpuMetric() error { + cpu, err := cpu.Get() + if err != nil { + log.Printf("Cannot get cpu(): %s\n", err) + return err + } + m.CPUMetrics.User = cpu.User + m.CPUMetrics.Nice = cpu.Nice + m.CPUMetrics.System = cpu.System + m.CPUMetrics.Idle = cpu.Idle + m.CPUMetrics.Iowait = cpu.Iowait + m.CPUMetrics.Irq = cpu.Irq + m.CPUMetrics.Softirq = cpu.Softirq + m.CPUMetrics.Steal = cpu.Steal + m.CPUMetrics.Guest = cpu.Guest + m.CPUMetrics.GuestNice = cpu.GuestNice + m.CPUMetrics.Total = cpu.Total + m.CPUMetrics.CPUCount = cpu.CPUCount + m.CPUMetrics.StatCount = cpu.StatCount + return nil +} - do(func() { - cpup := C.sg_get_cpu_percents_of(C.sg_new_diff_cpu_percent, nil) - loadStat := C.sg_get_load_stats(nil) - cpu = &CPUStats{ - User: float64(cpup.user), - Kernel: float64(cpup.kernel), - Idle: float64(cpup.idle), - IOWait: float64(cpup.iowait), - Swap: float64(cpup.swap), - Nice: float64(cpup.nice), - LoadMin1: float64(loadStat.min1), - LoadMin5: float64(loadStat.min5), - LoadMin15: float64(loadStat.min15), - Period: time.Duration(int(cpup.time_taken)) * time.Second, - TimeTaken: time.Now(), +func (m *Metric) getDiskMetrics() error { + disk, err := disk.Get() + if err != nil { + log.Printf("Cannot get disk(): %s\n", err) + return err + } + for i, _ := range disk { + tmpM := DiskMetric{ + Name: disk[i].Name, + WritesCompleted: disk[i].WritesCompleted, + ReadsCompleted: disk[i].ReadsCompleted, } - }) - return cpu + m.DiskMetrics = append(m.DiskMetrics, tmpM) + } + return nil +} + +func (m *Metric) getNetworkMetrics() error { + network, err := network.Get() + if err != nil { + log.Printf("Cannot get network(): %s\n", err) + return err + } + for i, _ := range network { + tmpM := NetworkMetric{ + Name: network[i].Name, + TxBytes: network[i].TxBytes, + RxBytes: network[i].RxBytes, + } + m.NetworkMetrics = append(m.NetworkMetrics, tmpM) + } + return nil } diff --git a/struct.go b/struct.go index bb50153..0cda143 100644 --- a/struct.go +++ b/struct.go @@ -16,29 +16,60 @@ type Test struct { Timeout time.Duration } -type Metric struct { - Timestamp time.Time `json:"timestamp"` - Load1m float64 - Load5m float64 - Load15m float64 - FreeMem int +type LoadMetric struct { + Load1m float64 `json:"load1m"` + Load5m float64 `json:"load5m"` + Load15m float64 `json:"load15m"` } -type CPUStats struct { - User float64 - Kernel float64 - Idle float64 - IOWait float64 - Swap float64 - Nice float64 - LoadMin1 float64 - LoadMin5 float64 - LoadMin15 float64 - Period time.Duration - TimeTaken time.Time +type MemMetric struct { + FreeMem uint64 `json:"freemem"` + TotalMem uint64 `json:"totalmem"` + UsedMem uint64 `json:"usedmem"` + BuffersMem uint64 `json:"buffersmem"` + CachedMem uint64 `json:"cachedmem"` + AvailableMem uint64 `json:"availablemem"` + ActiveMem uint64 `json:"activemem"` + InactiveMem uint64 `json:"inactivemem"` + SwapTotal uint64 `json:"swaptotal"` + SwapUsed uint64 `json:"swapused"` + SwapCached uint64 `json:"swapcached"` + SwapFree uint64 `json:"swapfree"` } -type Stat struct { - sync.Mutex - exitMessage chan bool +type CpuMetric struct { + User uint64 `json:"user"` + Nice uint64 `json:"nice"` + System uint64 `json:"system"` + Idle uint64 `json:"idle"` + Iowait uint64 `json:"iowait"` + Irq uint64 `json:"irq"` + Softirq uint64 `json:"softirq"` + Steal uint64 `json:"steal"` + Guest uint64 `json:"guest"` + GuestNice uint64 `json:"guestnice"` + Total uint64 `json:"total"` + CPUCount int `json:"cpucount"` + StatCount int `json:"statcount"` +} + +type DiskMetric struct { + Name string `json:"name"` + WritesCompleted uint64 `json:"writes_completed"` + ReadsCompleted uint64 `json:"reads_completed"` +} + +type NetworkMetric struct { + Name string `json:"name"` + RxBytes uint64 `json:"rx_bytes"` + TxBytes uint64 `json:"tx_bytes"` +} + +type Metric struct { + LoadMetrics LoadMetric `json:"load_metrics"` + Timestamp time.Time `json:"timestamp"` + MemMetrics MemMetric `json:"mem_metrics"` + CPUMetrics CpuMetric `json:"cpu_metrics"` + DiskMetrics []DiskMetric `json:"disk_metrics"` + NetworkMetrics []NetworkMetric `json:"network_metrics"` }