1
0
Fork 0
cpu_ctrl/producer/os_darwin.go

328 lines
8.4 KiB
Go

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"
"runtime"
)
type NetIOInfo struct {
Name string `json:"name"`
RxBytes uint64 `json:"rx_bytes"`
TxBytes uint64 `json:"tx_bytes"`
}
type MemoryInfo struct {
Total uint64 `json:"total_bytes"`
Active uint64 `json:"active_bytes"`
Cached uint64 `json:"cached_bytes"`
Free uint64 `json:"free_bytes"`
Inactive uint64 `json:"inactive_bytes"`
SwapFree uint64 `json:"swap_free_bytes"`
SwapTotal uint64 `json:"swap_total_bytes"`
SwapUsed uint64 `json:"swap_used_bytes"`
Used uint64 `json:"used_bytes"`
}
type LoadInfo struct {
Avg1 float64 `json:"avg_1"`
Avg5 float64 `json:"avg_5"`
Avg15 float64 `json:"avg_15"`
}
type CPUInfo struct {
Idle float64 `json:"idle"`
Nice float64 `json:"nice"`
System float64 `json:"system"`
User float64 `json:"user"`
}
type OSMetricInfo struct {
Memory MemoryInfo `json:"memory"`
Load LoadInfo `json:"load"`
NetIO map[string]NetIOInfo `json:"net_io"`
Uptime time.Duration `json:"uptime"`
CPU CPUInfo `json:"cpu"`
Host string `json:"host"`
At time.Time `json:"at"`
}
func (p *OSMetricInfo) MarshalUptime() (name string, tags []map[string]string, fields []map[string]interface{}) {
name, tags, fields =
"uptime",
[]map[string]string{
{
"os": runtime.GOOS,
},
},
[]map[string]interface{}{
{
"duration": p.Uptime,
},
}
return
}
func (p *OSMetricInfo) MarshalLoad() (name string, tags []map[string]string, fields []map[string]interface{}) {
name, tags, fields =
"load",
[]map[string]string{
{
"os": runtime.GOOS,
},
},
[]map[string]interface{}{
{
"avg_1": p.Load.Avg1,
"avg_5": p.Load.Avg5,
"avg_15": p.Load.Avg15,
},
}
return
}
func (p *OSMetricInfo) MarshalCPU() (name string, tags []map[string]string, fields []map[string]interface{}) {
name, tags, fields =
"cpu",
[]map[string]string{
{
"os": runtime.GOOS,
},
},
[]map[string]interface{}{
{
"idle": p.CPU.Idle,
"nice": p.CPU.Nice,
"system": p.CPU.System,
"user": p.CPU.User,
},
}
return
}
func (p *OSMetricInfo) MarshalNetworks() (name string, tags []map[string]string, fields []map[string]interface{}) {
name = "network"
tags = make([]map[string]string, 0)
fields = make([]map[string]interface{}, 0)
for name, info := range p.NetIO {
tags, fields =
append(tags, map[string]string{
"os": runtime.GOOS,
"name": name,
}),
append(fields, map[string]interface{}{
"rx_bytes": info.RxBytes,
"tx_bytes": info.TxBytes,
})
}
return
}
func (p *OSMetricInfo) MarshalMemory() (name string, tags []map[string]string, fields []map[string]interface{}) {
name, tags, fields =
"memory",
[]map[string]string{
{
"os": runtime.GOOS,
},
},
[]map[string]interface{}{
{
"total_bytes": p.Memory.Total,
"active_bytes": p.Memory.Active,
"cached_bytes": p.Memory.Cached,
"free_bytes": p.Memory.Free,
"inactive_bytes": p.Memory.Inactive,
"swap_free_bytes": p.Memory.SwapFree,
"swap_total_bytes": p.Memory.SwapTotal,
"swap_used_bytes": p.Memory.SwapUsed,
"used_bytes": p.Memory.Used,
},
}
return
}
func (p *OSMetricInfo) Applier() (generator []OSMetricPointGen) {
generator = append(
generator,
p.MarshalLoad,
p.MarshalCPU,
p.MarshalMemory,
p.MarshalNetworks,
p.MarshalUptime,
)
return
}
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.Debug("memory total: ", misc.FileSizeIEC(memoryInfo.Total))
p.logger.Debug("memory active: ", misc.FileSizeIEC(memoryInfo.Active))
p.logger.Debug("memory cached: ", misc.FileSizeIEC(memoryInfo.Cached))
p.logger.Debug("memory free: ", misc.FileSizeIEC(memoryInfo.Free))
p.logger.Debug("memory inactive: ", misc.FileSizeIEC(memoryInfo.Inactive))
p.logger.Debug("memory swapFree: ", misc.FileSizeIEC(memoryInfo.SwapFree))
p.logger.Debug("memory swapTotal: ", misc.FileSizeIEC(memoryInfo.SwapTotal))
p.logger.Debug("memory swapUsed: ", misc.FileSizeIEC(memoryInfo.SwapUsed))
p.logger.Debug("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", load.Loadavg1)
p.logger.Debugf("load Loadavg5: %f", load.Loadavg5)
p.logger.Debugf("load Loadavg15: %f", 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.Debug("netio name: ", netio.Name)
p.logger.Debug("netio rxBytes: ", misc.FileSizeIEC(netio.RxBytes))
p.logger.Debug("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", 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", ct.Idle)
p.logger.Debugf("readCpuStat: nice=%d", ct.Nice)
p.logger.Debugf("readCpuStat: system=%d", ct.System)
p.logger.Debugf("readCpuStat: total=%d", ct.Total)
p.logger.Debugf("readCpuStat: user=%d", ct.User)
p.logger.Debugf("readCpuStat: idle=%f%%", float64(ct.Idle*100)/float64(ct.Total))
p.logger.Debugf("readCpuStat: nice=%f%%", float64(ct.Nice*100)/float64(ct.Total))
p.logger.Debugf("readCpuStat: system=%f%%", float64(ct.System*100)/float64(ct.Total))
p.logger.Debugf("readCpuStat: user=%f%%", 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
}