telegraf/plugins/inputs/system/ps.go

169 lines
3.6 KiB
Go

package system
import (
gonet "net"
"os"
"strings"
"github.com/influxdb/telegraf/internal"
"github.com/influxdb/telegraf/plugins/inputs"
dc "github.com/fsouza/go-dockerclient"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/docker"
"github.com/shirou/gopsutil/mem"
"github.com/shirou/gopsutil/net"
)
type DockerContainerStat struct {
Id string
Name string
Command string
Labels map[string]string
CPU *cpu.CPUTimesStat
Mem *docker.CgroupMemStat
}
type PS interface {
CPUTimes(perCPU, totalCPU bool) ([]cpu.CPUTimesStat, error)
DiskUsage() ([]*disk.DiskUsageStat, error)
NetIO() ([]net.NetIOCountersStat, error)
NetProto() ([]net.NetProtoCountersStat, error)
DiskIO() (map[string]disk.DiskIOCountersStat, error)
VMStat() (*mem.VirtualMemoryStat, error)
SwapStat() (*mem.SwapMemoryStat, error)
DockerStat() ([]*DockerContainerStat, error)
NetConnections() ([]net.NetConnectionStat, error)
}
func add(acc inputs.Accumulator,
name string, val float64, tags map[string]string) {
if val >= 0 {
acc.Add(name, val, tags)
}
}
type systemPS struct {
dockerClient *dc.Client
}
func (s *systemPS) CPUTimes(perCPU, totalCPU bool) ([]cpu.CPUTimesStat, error) {
var cpuTimes []cpu.CPUTimesStat
if perCPU {
if perCPUTimes, err := cpu.CPUTimes(true); err == nil {
cpuTimes = append(cpuTimes, perCPUTimes...)
} else {
return nil, err
}
}
if totalCPU {
if totalCPUTimes, err := cpu.CPUTimes(false); err == nil {
cpuTimes = append(cpuTimes, totalCPUTimes...)
} else {
return nil, err
}
}
return cpuTimes, nil
}
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 {
if _, err := os.Stat(p.Mountpoint); err == nil {
du, err := disk.DiskUsage(p.Mountpoint)
if err != nil {
return nil, err
}
du.Fstype = p.Fstype
usage = append(usage, du)
}
}
return usage, nil
}
func (s *systemPS) NetProto() ([]net.NetProtoCountersStat, error) {
return net.NetProtoCounters(nil)
}
func (s *systemPS) NetIO() ([]net.NetIOCountersStat, error) {
return net.NetIOCounters(true)
}
func (s *systemPS) NetConnections() ([]net.NetConnectionStat, error) {
return net.NetConnections("all")
}
func (s *systemPS) DiskIO() (map[string]disk.DiskIOCountersStat, error) {
m, err := disk.DiskIOCounters()
if err == internal.NotImplementedError {
return nil, nil
}
return m, err
}
func (s *systemPS) VMStat() (*mem.VirtualMemoryStat, error) {
return mem.VirtualMemory()
}
func (s *systemPS) SwapStat() (*mem.SwapMemoryStat, error) {
return mem.SwapMemory()
}
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
}
s.dockerClient = c
}
opts := dc.ListContainersOptions{}
containers, err := s.dockerClient.ListContainers(opts)
if err != nil {
if _, ok := err.(*gonet.OpError); ok {
return nil, nil
}
return nil, err
}
var stats []*DockerContainerStat
for _, container := range containers {
ctu, err := docker.CgroupCPUDocker(container.ID)
if err != nil {
return nil, err
}
mem, err := docker.CgroupMemDocker(container.ID)
if err != nil {
return nil, err
}
name := strings.Join(container.Names, " ")
stats = append(stats, &DockerContainerStat{
Id: container.ID,
Name: name,
Command: container.Command,
Labels: container.Labels,
CPU: ctu,
Mem: mem,
})
}
return stats, nil
}