diff --git a/plugins/system/mock_PS.go b/plugins/system/mock_PS.go index e3d142347..4731c6d50 100644 --- a/plugins/system/mock_PS.go +++ b/plugins/system/mock_PS.go @@ -4,6 +4,7 @@ import "github.com/stretchr/testify/mock" import "github.com/influxdb/tivan/plugins/system/ps/cpu" import "github.com/influxdb/tivan/plugins/system/ps/disk" + import "github.com/influxdb/tivan/plugins/system/ps/load" import "github.com/influxdb/tivan/plugins/system/ps/mem" import "github.com/influxdb/tivan/plugins/system/ps/net" @@ -68,3 +69,11 @@ func (m *MockPS) SwapStat() (*mem.SwapMemoryStat, error) { return r0, r1 } +func (m *MockPS) DockerStat() ([]*DockerContainerStat, error) { + ret := m.Called() + + r0 := ret.Get(0).([]*DockerContainerStat) + r1 := ret.Error(1) + + return r0, r1 +} diff --git a/plugins/system/system.go b/plugins/system/system.go index 94dbef8af..afa8d6701 100644 --- a/plugins/system/system.go +++ b/plugins/system/system.go @@ -7,11 +7,18 @@ import ( "github.com/influxdb/tivan/plugins/system/ps/common" "github.com/influxdb/tivan/plugins/system/ps/cpu" "github.com/influxdb/tivan/plugins/system/ps/disk" + "github.com/influxdb/tivan/plugins/system/ps/docker" "github.com/influxdb/tivan/plugins/system/ps/load" "github.com/influxdb/tivan/plugins/system/ps/mem" "github.com/influxdb/tivan/plugins/system/ps/net" ) +type DockerContainerStat struct { + Name string + CPU *cpu.CPUTimesStat + Mem *docker.CgroupMemStat +} + type PS interface { LoadAvg() (*load.LoadAvgStat, error) CPUTimes() ([]cpu.CPUTimesStat, error) @@ -20,6 +27,7 @@ type PS interface { DiskIO() (map[string]disk.DiskIOCountersStat, error) VMStat() (*mem.VirtualMemoryStat, error) SwapStat() (*mem.SwapMemoryStat, error) + DockerStat() ([]*DockerContainerStat, error) } type SystemStats struct { @@ -156,6 +164,59 @@ func (s *SystemStats) Gather(acc plugins.Accumulator) error { acc.Add("swap_in", swap.Sin, swaptags) acc.Add("swap_out", swap.Sout, swaptags) + containers, err := s.ps.DockerStat() + if err != nil { + return err + } + + for _, cont := range containers { + tags := map[string]string{ + "docker": cont.Name, + } + + 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 } @@ -210,6 +271,35 @@ func (s *systemPS) SwapStat() (*mem.SwapMemoryStat, error) { return mem.SwapMemory() } +func (s *systemPS) DockerStat() ([]*DockerContainerStat, error) { + list, err := docker.GetDockerIDList() + if err != nil { + if err == common.NotImplementedError { + return nil, nil + } + + return nil, err + } + + var stats []*DockerContainerStat + + for _, cont := range list { + ctu, err := docker.CgroupCPUDocker(cont) + if err != nil { + return nil, err + } + + mem, err := docker.CgroupMemDocker(cont) + if err != nil { + return nil, err + } + + stats = append(stats, &DockerContainerStat{cont, ctu, mem}) + } + + return stats, nil +} + func init() { plugins.Add("system", func() plugins.Plugin { return &SystemStats{ps: &systemPS{}} diff --git a/plugins/system/system_test.go b/plugins/system/system_test.go index 5c002d7a5..d885f3752 100644 --- a/plugins/system/system_test.go +++ b/plugins/system/system_test.go @@ -5,6 +5,7 @@ import ( "github.com/influxdb/tivan/plugins/system/ps/cpu" "github.com/influxdb/tivan/plugins/system/ps/disk" + "github.com/influxdb/tivan/plugins/system/ps/docker" "github.com/influxdb/tivan/plugins/system/ps/load" "github.com/influxdb/tivan/plugins/system/ps/mem" "github.com/influxdb/tivan/plugins/system/ps/net" @@ -112,6 +113,56 @@ func TestSystemStats_GenerateStats(t *testing.T) { mps.On("SwapStat").Return(sms, nil) + ds := &DockerContainerStat{ + Name: "blah", + CPU: &cpu.CPUTimesStat{ + CPU: "all", + User: 3.1, + System: 8.2, + Idle: 80.1, + Nice: 1.3, + Iowait: 0.2, + Irq: 0.1, + Softirq: 0.11, + Steal: 0.0001, + Guest: 8.1, + GuestNice: 0.324, + Stolen: 0.051, + }, + Mem: &docker.CgroupMemStat{ + ContainerID: "blah", + Cache: 1, + RSS: 2, + RSSHuge: 3, + MappedFile: 4, + Pgpgin: 5, + Pgpgout: 6, + Pgfault: 7, + Pgmajfault: 8, + InactiveAnon: 9, + ActiveAnon: 10, + InactiveFile: 11, + ActiveFile: 12, + Unevictable: 13, + HierarchicalMemoryLimit: 14, + TotalCache: 15, + TotalRSS: 16, + TotalRSSHuge: 17, + TotalMappedFile: 18, + TotalPgpgIn: 19, + TotalPgpgOut: 20, + TotalPgFault: 21, + TotalPgMajFault: 22, + TotalInactiveAnon: 23, + TotalActiveAnon: 24, + TotalInactiveFile: 25, + TotalActiveFile: 26, + TotalUnevictable: 27, + }, + } + + mps.On("DockerStat").Return([]*DockerContainerStat{ds}, nil) + err := ss.Gather(&acc) require.NoError(t, err) @@ -172,7 +223,6 @@ func TestSystemStats_GenerateStats(t *testing.T) { "memory": "virtual", } - assert.NoError(t, acc.ValidateTaggedValue("total", uint64(12400), vmtags)) assert.True(t, acc.CheckTaggedValue("total", uint64(12400), vmtags)) assert.True(t, acc.CheckTaggedValue("available", uint64(7600), vmtags)) assert.True(t, acc.CheckTaggedValue("used", uint64(5000), vmtags)) @@ -195,4 +245,48 @@ func TestSystemStats_GenerateStats(t *testing.T) { assert.True(t, acc.CheckTaggedValue("free", uint64(6412), swaptags)) assert.True(t, acc.CheckTaggedValue("swap_in", uint64(7), swaptags)) assert.True(t, acc.CheckTaggedValue("swap_out", uint64(830), swaptags)) + + dockertags := map[string]string{ + "docker": "blah", + } + + assert.True(t, acc.CheckTaggedValue("user", 3.1, dockertags)) + assert.True(t, acc.CheckTaggedValue("system", 8.2, dockertags)) + assert.True(t, acc.CheckTaggedValue("idle", 80.1, dockertags)) + assert.True(t, acc.CheckTaggedValue("nice", 1.3, dockertags)) + assert.True(t, acc.CheckTaggedValue("iowait", 0.2, dockertags)) + assert.True(t, acc.CheckTaggedValue("irq", 0.1, dockertags)) + assert.True(t, acc.CheckTaggedValue("softirq", 0.11, dockertags)) + assert.True(t, acc.CheckTaggedValue("steal", 0.0001, dockertags)) + assert.True(t, acc.CheckTaggedValue("guest", 8.1, dockertags)) + assert.True(t, acc.CheckTaggedValue("guestNice", 0.324, dockertags)) + assert.True(t, acc.CheckTaggedValue("stolen", 0.051, dockertags)) + + assert.True(t, acc.CheckTaggedValue("cache", uint64(1), dockertags)) + assert.True(t, acc.CheckTaggedValue("rss", uint64(2), dockertags)) + assert.True(t, acc.CheckTaggedValue("rss_huge", uint64(3), dockertags)) + assert.True(t, acc.CheckTaggedValue("mapped_file", uint64(4), dockertags)) + assert.True(t, acc.CheckTaggedValue("swap_in", uint64(5), dockertags)) + assert.True(t, acc.CheckTaggedValue("swap_out", uint64(6), dockertags)) + assert.True(t, acc.CheckTaggedValue("page_fault", uint64(7), dockertags)) + assert.True(t, acc.CheckTaggedValue("page_major_fault", uint64(8), dockertags)) + assert.True(t, acc.CheckTaggedValue("inactive_anon", uint64(9), dockertags)) + assert.True(t, acc.CheckTaggedValue("active_anon", uint64(10), dockertags)) + assert.True(t, acc.CheckTaggedValue("inactive_file", uint64(11), dockertags)) + assert.True(t, acc.CheckTaggedValue("active_file", uint64(12), dockertags)) + assert.True(t, acc.CheckTaggedValue("unevictable", uint64(13), dockertags)) + assert.True(t, acc.CheckTaggedValue("memory_limit", uint64(14), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_cache", uint64(15), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_rss", uint64(16), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_rss_huge", uint64(17), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_mapped_file", uint64(18), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_swap_in", uint64(19), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_swap_out", uint64(20), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_page_fault", uint64(21), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_page_major_fault", uint64(22), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_inactive_anon", uint64(23), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_active_anon", uint64(24), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_inactive_file", uint64(25), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_active_file", uint64(26), dockertags)) + assert.True(t, acc.CheckTaggedValue("total_unevictable", uint64(27), dockertags)) }