telegraf/plugins/system/system.go

428 lines
10 KiB
Go
Raw Normal View History

package system
import (
"fmt"
gonet "net"
"strings"
dc "github.com/fsouza/go-dockerclient"
"github.com/influxdb/tivan/plugins"
2015-04-06 17:59:05 +00:00
"github.com/influxdb/tivan/plugins/system/ps/common"
"github.com/influxdb/tivan/plugins/system/ps/cpu"
2015-04-06 17:34:55 +00:00
"github.com/influxdb/tivan/plugins/system/ps/disk"
2015-04-06 23:03:09 +00:00
"github.com/influxdb/tivan/plugins/system/ps/docker"
2015-04-04 00:22:31 +00:00
"github.com/influxdb/tivan/plugins/system/ps/load"
2015-04-06 21:53:43 +00:00
"github.com/influxdb/tivan/plugins/system/ps/mem"
2015-04-06 17:44:32 +00:00
"github.com/influxdb/tivan/plugins/system/ps/net"
)
2015-04-06 23:03:09 +00:00
type DockerContainerStat struct {
Id string
Name string
Command string
CPU *cpu.CPUTimesStat
Mem *docker.CgroupMemStat
2015-04-06 23:03:09 +00:00
}
type PS interface {
LoadAvg() (*load.LoadAvgStat, error)
CPUTimes() ([]cpu.CPUTimesStat, error)
2015-04-06 17:34:55 +00:00
DiskUsage() ([]*disk.DiskUsageStat, error)
2015-04-06 17:44:32 +00:00
NetIO() ([]net.NetIOCountersStat, error)
2015-04-06 17:59:05 +00:00
DiskIO() (map[string]disk.DiskIOCountersStat, error)
2015-04-06 21:53:43 +00:00
VMStat() (*mem.VirtualMemoryStat, error)
SwapStat() (*mem.SwapMemoryStat, error)
2015-04-06 23:03:09 +00:00
DockerStat() ([]*DockerContainerStat, error)
}
func add(acc plugins.Accumulator,
2015-04-07 00:23:15 +00:00
name string, val float64, tags map[string]string) {
if val >= 0 {
2015-04-07 00:23:15 +00:00
acc.Add(name, val, tags)
}
}
type CPUStats struct {
ps PS
}
func (s *CPUStats) Gather(acc plugins.Accumulator) error {
times, err := s.ps.CPUTimes()
if err != nil {
return fmt.Errorf("error getting CPU info: %s", err)
}
for _, cts := range times {
2015-04-07 00:23:15 +00:00
tags := map[string]string{
"cpu": cts.CPU,
}
add(acc, "user", cts.User, tags)
add(acc, "system", cts.System, tags)
add(acc, "idle", cts.Idle, tags)
add(acc, "nice", cts.Nice, tags)
add(acc, "iowait", cts.Iowait, tags)
add(acc, "irq", cts.Irq, tags)
add(acc, "softirq", cts.Softirq, tags)
add(acc, "steal", cts.Steal, tags)
add(acc, "guest", cts.Guest, tags)
add(acc, "guestNice", cts.GuestNice, tags)
add(acc, "stolen", cts.Stolen, tags)
}
return nil
}
type DiskStats struct {
ps PS
}
func (s *DiskStats) Gather(acc plugins.Accumulator) error {
2015-04-06 17:34:55 +00:00
disks, err := s.ps.DiskUsage()
if err != nil {
return fmt.Errorf("error getting disk usage info: %s", err)
2015-04-06 17:34:55 +00:00
}
for _, du := range disks {
tags := map[string]string{
"path": du.Path,
}
acc.Add("total", du.Total, tags)
acc.Add("free", du.Free, tags)
acc.Add("used", du.Total-du.Free, tags)
acc.Add("inodes_total", du.InodesTotal, tags)
acc.Add("inodes_free", du.InodesFree, tags)
acc.Add("inodes_used", du.InodesTotal-du.InodesFree, tags)
2015-04-06 17:34:55 +00:00
}
return nil
}
type DiskIOStats struct {
ps PS
}
func (s *DiskIOStats) Gather(acc plugins.Accumulator) error {
2015-04-06 17:59:05 +00:00
diskio, err := s.ps.DiskIO()
if err != nil {
return fmt.Errorf("error getting disk io info: %s", err)
2015-04-06 17:59:05 +00:00
}
for _, io := range diskio {
tags := map[string]string{
"name": io.Name,
"serial": io.SerialNumber,
}
acc.Add("reads", io.ReadCount, tags)
acc.Add("writes", io.WriteCount, tags)
acc.Add("read_bytes", io.ReadBytes, tags)
acc.Add("write_bytes", io.WriteBytes, tags)
acc.Add("read_time", io.ReadTime, tags)
acc.Add("write_time", io.WriteTime, tags)
acc.Add("io_time", io.IoTime, tags)
2015-04-06 17:59:05 +00:00
}
return nil
}
type NetIOStats struct {
ps PS
}
func (s *NetIOStats) Gather(acc plugins.Accumulator) error {
2015-04-06 17:44:32 +00:00
netio, err := s.ps.NetIO()
if err != nil {
return fmt.Errorf("error getting net io info: %s", err)
2015-04-06 17:44:32 +00:00
}
for _, io := range netio {
tags := map[string]string{
"interface": io.Name,
}
acc.Add("bytes_sent", io.BytesSent, tags)
acc.Add("bytes_recv", io.BytesRecv, tags)
acc.Add("packets_sent", io.PacketsSent, tags)
acc.Add("packets_recv", io.PacketsRecv, tags)
acc.Add("err_in", io.Errin, tags)
acc.Add("err_out", io.Errout, tags)
acc.Add("drop_in", io.Dropin, tags)
acc.Add("drop_out", io.Dropout, tags)
2015-04-06 17:44:32 +00:00
}
return nil
}
type MemStats struct {
ps PS
}
func (s *MemStats) Gather(acc plugins.Accumulator) error {
2015-04-06 21:53:43 +00:00
vm, err := s.ps.VMStat()
if err != nil {
return fmt.Errorf("error getting virtual memory info: %s", err)
2015-04-06 21:53:43 +00:00
}
2015-04-07 17:25:05 +00:00
vmtags := map[string]string(nil)
2015-04-06 21:53:43 +00:00
acc.Add("total", vm.Total, vmtags)
acc.Add("available", vm.Available, vmtags)
acc.Add("used", vm.Used, vmtags)
acc.Add("used_prec", vm.UsedPercent, vmtags)
acc.Add("free", vm.Free, vmtags)
acc.Add("active", vm.Active, vmtags)
acc.Add("inactive", vm.Inactive, vmtags)
acc.Add("buffers", vm.Buffers, vmtags)
acc.Add("cached", vm.Cached, vmtags)
acc.Add("wired", vm.Wired, vmtags)
acc.Add("shared", vm.Shared, vmtags)
return nil
}
type SwapStats struct {
ps PS
}
2015-04-06 21:53:43 +00:00
func (s *SwapStats) Gather(acc plugins.Accumulator) error {
2015-04-06 21:53:43 +00:00
swap, err := s.ps.SwapStat()
if err != nil {
return fmt.Errorf("error getting swap memory info: %s", err)
2015-04-06 21:53:43 +00:00
}
2015-04-07 17:25:05 +00:00
swaptags := map[string]string(nil)
2015-04-06 21:53:43 +00:00
acc.Add("total", swap.Total, swaptags)
acc.Add("used", swap.Used, swaptags)
acc.Add("free", swap.Free, swaptags)
acc.Add("used_perc", swap.UsedPercent, swaptags)
acc.Add("in", swap.Sin, swaptags)
acc.Add("out", swap.Sout, swaptags)
return nil
}
2015-04-06 21:53:43 +00:00
type DockerStats struct {
ps PS
}
func (s *DockerStats) Gather(acc plugins.Accumulator) error {
2015-04-06 23:03:09 +00:00
containers, err := s.ps.DockerStat()
if err != nil {
return fmt.Errorf("error getting docker info: %s", err)
2015-04-06 23:03:09 +00:00
}
for _, cont := range containers {
tags := map[string]string{
2015-04-07 17:25:05 +00:00
"id": cont.Id,
"name": cont.Name,
"command": cont.Command,
2015-04-06 23:03:09 +00:00
}
cts := cont.CPU
acc.Add("user", cts.User, tags)
acc.Add("system", cts.System, tags)
acc.Add("idle", cts.Idle, tags)
acc.Add("nice", cts.Nice, tags)
acc.Add("iowait", cts.Iowait, tags)
acc.Add("irq", cts.Irq, tags)
acc.Add("softirq", cts.Softirq, tags)
acc.Add("steal", cts.Steal, tags)
acc.Add("guest", cts.Guest, tags)
acc.Add("guestNice", cts.GuestNice, tags)
acc.Add("stolen", cts.Stolen, tags)
acc.Add("cache", cont.Mem.Cache, tags)
acc.Add("rss", cont.Mem.RSS, tags)
acc.Add("rss_huge", cont.Mem.RSSHuge, tags)
acc.Add("mapped_file", cont.Mem.MappedFile, tags)
acc.Add("swap_in", cont.Mem.Pgpgin, tags)
acc.Add("swap_out", cont.Mem.Pgpgout, tags)
acc.Add("page_fault", cont.Mem.Pgfault, tags)
acc.Add("page_major_fault", cont.Mem.Pgmajfault, tags)
acc.Add("inactive_anon", cont.Mem.InactiveAnon, tags)
acc.Add("active_anon", cont.Mem.ActiveAnon, tags)
acc.Add("inactive_file", cont.Mem.InactiveFile, tags)
acc.Add("active_file", cont.Mem.ActiveFile, tags)
acc.Add("unevictable", cont.Mem.Unevictable, tags)
acc.Add("memory_limit", cont.Mem.HierarchicalMemoryLimit, tags)
acc.Add("total_cache", cont.Mem.TotalCache, tags)
acc.Add("total_rss", cont.Mem.TotalRSS, tags)
acc.Add("total_rss_huge", cont.Mem.TotalRSSHuge, tags)
acc.Add("total_mapped_file", cont.Mem.TotalMappedFile, tags)
acc.Add("total_swap_in", cont.Mem.TotalPgpgIn, tags)
acc.Add("total_swap_out", cont.Mem.TotalPgpgOut, tags)
acc.Add("total_page_fault", cont.Mem.TotalPgFault, tags)
acc.Add("total_page_major_fault", cont.Mem.TotalPgMajFault, tags)
acc.Add("total_inactive_anon", cont.Mem.TotalInactiveAnon, tags)
acc.Add("total_active_anon", cont.Mem.TotalActiveAnon, tags)
acc.Add("total_inactive_file", cont.Mem.TotalInactiveFile, tags)
acc.Add("total_active_file", cont.Mem.TotalActiveFile, tags)
acc.Add("total_unevictable", cont.Mem.TotalUnevictable, tags)
}
return nil
}
type SystemStats struct {
ps PS
}
func (s *SystemStats) add(acc plugins.Accumulator,
name string, val float64, tags map[string]string) {
if val >= 0 {
acc.Add(name, val, tags)
}
}
func (s *SystemStats) Gather(acc plugins.Accumulator) error {
lv, err := s.ps.LoadAvg()
if err != nil {
return err
2015-04-06 23:03:09 +00:00
}
acc.Add("load1", lv.Load1, nil)
acc.Add("load5", lv.Load5, nil)
acc.Add("load15", lv.Load15, nil)
return nil
}
type systemPS struct {
dockerClient *dc.Client
}
func (s *systemPS) LoadAvg() (*load.LoadAvgStat, error) {
return load.LoadAvg()
}
func (s *systemPS) CPUTimes() ([]cpu.CPUTimesStat, error) {
return cpu.CPUTimes(true)
}
2015-04-06 17:34:55 +00:00
func (s *systemPS) DiskUsage() ([]*disk.DiskUsageStat, error) {
parts, err := disk.DiskPartitions(true)
if err != nil {
return nil, err
}
var usage []*disk.DiskUsageStat
for _, p := range parts {
du, err := disk.DiskUsage(p.Mountpoint)
if err != nil {
return nil, err
}
usage = append(usage, du)
}
return usage, nil
}
2015-04-06 17:44:32 +00:00
func (s *systemPS) NetIO() ([]net.NetIOCountersStat, error) {
return net.NetIOCounters(true)
}
2015-04-06 17:59:05 +00:00
func (s *systemPS) DiskIO() (map[string]disk.DiskIOCountersStat, error) {
m, err := disk.DiskIOCounters()
if err == common.NotImplementedError {
return nil, nil
}
return m, err
}
2015-04-06 21:53:43 +00:00
func (s *systemPS) VMStat() (*mem.VirtualMemoryStat, error) {
return mem.VirtualMemory()
}
func (s *systemPS) SwapStat() (*mem.SwapMemoryStat, error) {
return mem.SwapMemory()
}
2015-04-06 23:03:09 +00:00
func (s *systemPS) DockerStat() ([]*DockerContainerStat, error) {
if s.dockerClient == nil {
c, err := dc.NewClient("unix:///var/run/docker.sock")
if err != nil {
return nil, err
2015-04-06 23:03:09 +00:00
}
s.dockerClient = c
}
opts := dc.ListContainersOptions{}
list, err := s.dockerClient.ListContainers(opts)
if err != nil {
if _, ok := err.(*gonet.OpError); ok {
return nil, nil
}
return nil, err
2015-04-06 23:03:09 +00:00
}
var stats []*DockerContainerStat
for _, cont := range list {
ctu, err := docker.CgroupCPUDocker(cont.ID)
2015-04-06 23:03:09 +00:00
if err != nil {
return nil, err
}
mem, err := docker.CgroupMemDocker(cont.ID)
2015-04-06 23:03:09 +00:00
if err != nil {
return nil, err
}
name := strings.Join(cont.Names, " ")
stats = append(stats, &DockerContainerStat{
Id: cont.ID,
Name: name,
Command: cont.Command,
CPU: ctu,
Mem: mem,
})
2015-04-06 23:03:09 +00:00
}
return stats, nil
}
func init() {
plugins.Add("cpu", func() plugins.Plugin {
return &CPUStats{ps: &systemPS{}}
})
plugins.Add("disk", func() plugins.Plugin {
return &DiskStats{ps: &systemPS{}}
})
plugins.Add("io", func() plugins.Plugin {
return &DiskIOStats{ps: &systemPS{}}
})
plugins.Add("net", func() plugins.Plugin {
return &NetIOStats{ps: &systemPS{}}
})
plugins.Add("mem", func() plugins.Plugin {
return &MemStats{ps: &systemPS{}}
})
plugins.Add("swap", func() plugins.Plugin {
return &SwapStats{ps: &systemPS{}}
})
plugins.Add("docker", func() plugins.Plugin {
return &DockerStats{ps: &systemPS{}}
})
plugins.Add("system", func() plugins.Plugin {
return &SystemStats{ps: &systemPS{}}
})
}