package producer import ( "github.com/mackerelio/go-osstat/memory" "github.com/mackerelio/go-osstat/loadavg" "github.com/mackerelio/go-osstat/network" "github.com/mackerelio/go-osstat/uptime" "github.com/mackerelio/go-osstat/cpu" "github.com/hako/durafmt" "amuz.es/src/infra/goutils/misc" "time" "go.uber.org/multierr" "sync" ) type NetIOInfo struct { Name string RxBytes, TxBytes uint64 } type MemoryInfo struct { Total, Active, Cached, Free, Inactive, SwapFree, SwapTotal, SwapUsed, Used uint64 } type LoadInfo struct { Avg1, Avg5, Avg15 float64 } type CPUInfo struct { Idle, Nice, System, User float64 } type OSMetricInfo struct { Memory MemoryInfo Load LoadInfo NetIO map[string]NetIOInfo Uptime time.Duration CPU CPUInfo At time.Time } func (p *osMetric) readMemoryStat(info *OSMetricInfo, errChan chan<- error, waiter *sync.WaitGroup) { memoryInfo, err := memory.Get() defer func() { defer waiter.Done() if panicErr := recover(); panicErr != nil { err = multierr.Append(err, panicErr.(error)) } if err != nil { p.logger.Error("unable to retrieve readMemoryStat: ", err) errChan <- err } }() if err !=nil{ return } p.logger.Debugf("memory total: ", misc.FileSizeIEC(memoryInfo.Total)) p.logger.Debugf("memory active: ", misc.FileSizeIEC(memoryInfo.Active)) p.logger.Debugf("memory cached: ", misc.FileSizeIEC(memoryInfo.Cached)) p.logger.Debugf("memory free: ", misc.FileSizeIEC(memoryInfo.Free)) p.logger.Debugf("memory inactive: ", misc.FileSizeIEC(memoryInfo.Inactive)) p.logger.Debugf("memory swapFree: ", misc.FileSizeIEC(memoryInfo.SwapFree)) p.logger.Debugf("memory swapTotal: ", misc.FileSizeIEC(memoryInfo.SwapTotal)) p.logger.Debugf("memory swapUsed: ", misc.FileSizeIEC(memoryInfo.SwapUsed)) p.logger.Debugf("memory used: ", misc.FileSizeIEC(memoryInfo.Used)) info.Memory.Total = memoryInfo.Total info.Memory.Active = memoryInfo.Active info.Memory.Cached = memoryInfo.Cached info.Memory.Free = memoryInfo.Free info.Memory.Inactive = memoryInfo.Inactive info.Memory.SwapFree = memoryInfo.SwapFree info.Memory.SwapTotal = memoryInfo.SwapTotal info.Memory.SwapUsed = memoryInfo.SwapUsed info.Memory.Used = memoryInfo.Used return } func (p *osMetric) readLoadStat(info *OSMetricInfo, errChan chan<- error, waiter *sync.WaitGroup) { load, err := loadavg.Get() defer func() { defer waiter.Done() if panicErr := recover(); panicErr != nil { err = multierr.Append(err, panicErr.(error)) } if err != nil { p.logger.Error("unable to retrieve readLoadStat: ", err) errChan <- err } }() if err !=nil{ return } p.logger.Debugf("load Loadavg1: %f \n", load.Loadavg1) p.logger.Debugf("load Loadavg5: %f \n", load.Loadavg5) p.logger.Debugf("load Loadavg15: %f \n", load.Loadavg15) info.Load.Avg1 = load.Loadavg1 info.Load.Avg5 = load.Loadavg5 info.Load.Avg15 = load.Loadavg15 return } func (p *osMetric) readNetworkStat(info *OSMetricInfo, errChan chan<- error, waiter *sync.WaitGroup) { netios, err := network.Get() defer func() { defer waiter.Done() if panicErr := recover(); panicErr != nil { err = multierr.Append(err, panicErr.(error)) } if err != nil { p.logger.Error("unable to retrieve readNetworkStat: ", err) errChan <- err } }() if err !=nil{ return } netIoMap := make(map[string]NetIOInfo) for _, netio := range netios { p.logger.Debugf("netio name: ", netio.Name) p.logger.Debugf("netio rxBytes: ", misc.FileSizeIEC(netio.RxBytes)) p.logger.Debugf("netio txBytes: ", misc.FileSizeIEC(netio.TxBytes)) netIoMap[netio.Name] = NetIOInfo{ Name: netio.Name, RxBytes: netio.RxBytes, TxBytes: netio.TxBytes, } } info.NetIO = netIoMap return } func (p *osMetric) readUptimeStat(info *OSMetricInfo, errChan chan<- error, waiter *sync.WaitGroup) { ut, err := uptime.Get() defer func() { defer waiter.Done() if panicErr := recover(); panicErr != nil { err = multierr.Append(err, panicErr.(error)) } if err != nil { p.logger.Error("unable to retrieve readUptimeStat: ", err) errChan <- err } }() if err !=nil{ return } p.logger.Debugf("readUptimeStat: %s\n", durafmt.Parse(ut).String()) info.Uptime = ut return } func (p *osMetric) readCpuStat(info *OSMetricInfo, errChan chan<- error, waiter *sync.WaitGroup) { ct, err := cpu.Get() defer func() { defer waiter.Done() if panicErr := recover(); panicErr != nil { err = multierr.Append(err, panicErr.(error)) } if err != nil { p.logger.Error("unable to retrieve readCpuStat: ", err) errChan <- err } }() if err !=nil{ return } p.logger.Debugf("readCpuStat: idle=%d\n", ct.Idle) p.logger.Debugf("readCpuStat: nice=%d\n", ct.Nice) p.logger.Debugf("readCpuStat: system=%d\n", ct.System) p.logger.Debugf("readCpuStat: total=%d\n", ct.Total) p.logger.Debugf("readCpuStat: user=%d\n", ct.User) p.logger.Debugf("readCpuStat: idle=%f%%\n", float64(ct.Idle*100)/float64(ct.Total)) p.logger.Debugf("readCpuStat: nice=%f%%\n", float64(ct.Nice*100)/float64(ct.Total)) p.logger.Debugf("readCpuStat: system=%f%%\n", float64(ct.System*100)/float64(ct.Total)) p.logger.Debugf("readCpuStat: user=%f%%\n", float64(ct.User*100)/float64(ct.Total)) info.CPU.Idle = float64(ct.Idle*100) / float64(ct.Total) info.CPU.Nice = float64(ct.Nice*100) / float64(ct.Total) info.CPU.System = float64(ct.System*100) / float64(ct.Total) info.CPU.User = float64(ct.User*100) / float64(ct.Total) return } func (p *osMetric) availableMetrics() (appliers []osMetricApplier) { appliers = append(appliers, p.readLoadStat, p.readMemoryStat, p.readCpuStat, p.readNetworkStat, p.readUptimeStat, ) return }