Added other stats and json serialization

master
Fabrizio Furnari 5 years ago
parent 67233fa2be
commit cca4180972

@ -1,6 +1,7 @@
package main package main
import ( import (
"encoding/json"
"flag" "flag"
"fmt" "fmt"
"log" "log"
@ -20,11 +21,37 @@ var (
// TODO: bench test with pointer // TODO: bench test with pointer
func getMetrics() (Metric, error) { func getMetrics() (Metric, error) {
log.Println("Started getMetrics") log.Println("Started getMetrics")
var s = Stat{}
m := Metric{} m := Metric{}
cpustats := s.CPUStats() err := m.getMemory()
m.Load1m = cpustats.LoadMin1 if err != nil {
log.Printf("Metric: %v\n", m) 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 return m, nil
} }
@ -131,9 +158,20 @@ func (t *Test) stopTest(w http.ResponseWriter, req *http.Request) {
} }
func (t *Test) testStatus(w http.ResponseWriter, req *http.Request) { func (t *Test) testStatus(w http.ResponseWriter, req *http.Request) {
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, "%v\n", t.Result)
fmt.Fprintf(w, "Test %s, status: %s\n", t.Name, t.Status) fmt.Fprintf(w, "Test %s, status: %s\n", t.Name, t.Status)
} }
}
func newTest() *Test { func newTest() *Test {
log.Println("Creating new test") log.Println("Creating new test")

@ -1,43 +1,100 @@
package main package main
// #cgo LDFLAGS: -lstatgrab import (
// #include <statgrab.h> "log"
import "C"
import "time"
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()) { func (m *Metric) getMemory() error {
done := make(chan bool, 1) memory, err := memory.Get()
mainfunc <- func() { if err != nil {
f() log.Printf("Cannot get memory: %s\n", err)
done <- true 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 { func (m *Metric) getLoadAvg() error {
s.Lock() loadAvg, err := loadavg.Get()
defer s.Unlock() 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
}
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
}
var cpu *CPUStats 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,
}
m.DiskMetrics = append(m.DiskMetrics, tmpM)
}
return nil
}
do(func() { func (m *Metric) getNetworkMetrics() error {
cpup := C.sg_get_cpu_percents_of(C.sg_new_diff_cpu_percent, nil) network, err := network.Get()
loadStat := C.sg_get_load_stats(nil) if err != nil {
cpu = &CPUStats{ log.Printf("Cannot get network(): %s\n", err)
User: float64(cpup.user), return err
Kernel: float64(cpup.kernel), }
Idle: float64(cpup.idle), for i, _ := range network {
IOWait: float64(cpup.iowait), tmpM := NetworkMetric{
Swap: float64(cpup.swap), Name: network[i].Name,
Nice: float64(cpup.nice), TxBytes: network[i].TxBytes,
LoadMin1: float64(loadStat.min1), RxBytes: network[i].RxBytes,
LoadMin5: float64(loadStat.min5), }
LoadMin15: float64(loadStat.min15), m.NetworkMetrics = append(m.NetworkMetrics, tmpM)
Period: time.Duration(int(cpup.time_taken)) * time.Second, }
TimeTaken: time.Now(), return nil
}
})
return cpu
} }

@ -16,29 +16,60 @@ type Test struct {
Timeout time.Duration Timeout time.Duration
} }
type Metric struct { type LoadMetric struct {
Timestamp time.Time `json:"timestamp"` Load1m float64 `json:"load1m"`
Load1m float64 Load5m float64 `json:"load5m"`
Load5m float64 Load15m float64 `json:"load15m"`
Load15m float64
FreeMem int
} }
type CPUStats struct { type MemMetric struct {
User float64 FreeMem uint64 `json:"freemem"`
Kernel float64 TotalMem uint64 `json:"totalmem"`
Idle float64 UsedMem uint64 `json:"usedmem"`
IOWait float64 BuffersMem uint64 `json:"buffersmem"`
Swap float64 CachedMem uint64 `json:"cachedmem"`
Nice float64 AvailableMem uint64 `json:"availablemem"`
LoadMin1 float64 ActiveMem uint64 `json:"activemem"`
LoadMin5 float64 InactiveMem uint64 `json:"inactivemem"`
LoadMin15 float64 SwapTotal uint64 `json:"swaptotal"`
Period time.Duration SwapUsed uint64 `json:"swapused"`
TimeTaken time.Time SwapCached uint64 `json:"swapcached"`
SwapFree uint64 `json:"swapfree"`
} }
type Stat struct { type CpuMetric struct {
sync.Mutex User uint64 `json:"user"`
exitMessage chan bool 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"`
} }

Loading…
Cancel
Save