Update gopsutil godep dependency. Dont use godep go build anymore

godep seems to have a problem when dependencies have `internal`
packages. So removing `godep go build` and `godep go test` from the
build process in favor of just checking out the correct revisions using
`godep restore` into the regular GOPATH.

This basically means that we are not actually using anything within the
Godeps directory except Godeps.json. I should probably make a separate
go dependency management system that does this.
This commit is contained in:
Cameron Sparr 2015-12-04 11:44:56 -07:00
parent 00a6dbbe97
commit e6517d4140
52 changed files with 762 additions and 218 deletions

37
Godeps/Godeps.json generated
View File

@ -167,50 +167,45 @@
"ImportPath": "github.com/samuel/go-zookeeper/zk", "ImportPath": "github.com/samuel/go-zookeeper/zk",
"Rev": "5bb5cfc093ad18a28148c578f8632cfdb4d802e4" "Rev": "5bb5cfc093ad18a28148c578f8632cfdb4d802e4"
}, },
{
"ImportPath": "github.com/shirou/gopsutil/common",
"Comment": "1.0.0-173-g1e9aabb",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
},
{ {
"ImportPath": "github.com/shirou/gopsutil/cpu", "ImportPath": "github.com/shirou/gopsutil/cpu",
"Comment": "1.0.0-173-g1e9aabb", "Comment": "1.0.0-208-g759e96e",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617" "Rev": "759e96ebaffb01c3cba0e8b129ef29f56507b323"
}, },
{ {
"ImportPath": "github.com/shirou/gopsutil/disk", "ImportPath": "github.com/shirou/gopsutil/disk",
"Comment": "1.0.0-173-g1e9aabb", "Comment": "1.0.0-208-g759e96e",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617" "Rev": "759e96ebaffb01c3cba0e8b129ef29f56507b323"
}, },
{ {
"ImportPath": "github.com/shirou/gopsutil/docker", "ImportPath": "github.com/shirou/gopsutil/docker",
"Comment": "1.0.0-173-g1e9aabb", "Comment": "1.0.0-208-g759e96e",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617" "Rev": "759e96ebaffb01c3cba0e8b129ef29f56507b323"
}, },
{ {
"ImportPath": "github.com/shirou/gopsutil/host", "ImportPath": "github.com/shirou/gopsutil/host",
"Comment": "1.0.0-173-g1e9aabb", "Comment": "1.0.0-208-g759e96e",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617" "Rev": "759e96ebaffb01c3cba0e8b129ef29f56507b323"
}, },
{ {
"ImportPath": "github.com/shirou/gopsutil/load", "ImportPath": "github.com/shirou/gopsutil/load",
"Comment": "1.0.0-173-g1e9aabb", "Comment": "1.0.0-208-g759e96e",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617" "Rev": "759e96ebaffb01c3cba0e8b129ef29f56507b323"
}, },
{ {
"ImportPath": "github.com/shirou/gopsutil/mem", "ImportPath": "github.com/shirou/gopsutil/mem",
"Comment": "1.0.0-173-g1e9aabb", "Comment": "1.0.0-208-g759e96e",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617" "Rev": "759e96ebaffb01c3cba0e8b129ef29f56507b323"
}, },
{ {
"ImportPath": "github.com/shirou/gopsutil/net", "ImportPath": "github.com/shirou/gopsutil/net",
"Comment": "1.0.0-173-g1e9aabb", "Comment": "1.0.0-208-g759e96e",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617" "Rev": "759e96ebaffb01c3cba0e8b129ef29f56507b323"
}, },
{ {
"ImportPath": "github.com/shirou/gopsutil/process", "ImportPath": "github.com/shirou/gopsutil/process",
"Comment": "1.0.0-173-g1e9aabb", "Comment": "1.0.0-208-g759e96e",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617" "Rev": "759e96ebaffb01c3cba0e8b129ef29f56507b323"
}, },
{ {
"ImportPath": "github.com/streadway/amqp", "ImportPath": "github.com/streadway/amqp",

View File

@ -3,7 +3,7 @@
package cpu package cpu
import "github.com/shirou/gopsutil/common" import "github.com/shirou/gopsutil/internal/common"
func perCPUTimes() ([]CPUTimesStat, error) { func perCPUTimes() ([]CPUTimesStat, error) {
return []CPUTimesStat{}, common.NotImplementedError return []CPUTimesStat{}, common.NotImplementedError

View File

@ -9,7 +9,7 @@ import (
"strconv" "strconv"
"strings" "strings"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
// sys/resource.h // sys/resource.h

View File

@ -4,11 +4,12 @@ package cpu
import ( import (
"errors" "errors"
"fmt"
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
var cpu_tick = float64(100) var cpu_tick = float64(100)
@ -25,7 +26,7 @@ func init() {
} }
func CPUTimes(percpu bool) ([]CPUTimesStat, error) { func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
filename := common.GetEnv("HOST_PROC", "/proc") + "/stat" filename := common.HostProc("stat")
var lines = []string{} var lines = []string{}
if percpu { if percpu {
var startIdx uint = 1 var startIdx uint = 1
@ -55,19 +56,47 @@ func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
return ret, nil return ret, nil
} }
func sysCpuPath(cpu int32, relPath string) string {
return common.HostSys(fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath)
}
func finishCPUInfo(c *CPUInfoStat) error {
if c.Mhz == 0 {
lines, err := common.ReadLines(sysCpuPath(c.CPU, "cpufreq/cpuinfo_max_freq"))
if err == nil {
value, err := strconv.ParseFloat(lines[0], 64)
if err != nil {
return err
}
c.Mhz = value
}
}
if len(c.CoreID) == 0 {
lines, err := common.ReadLines(sysCpuPath(c.CPU, "topology/core_id"))
if err == nil {
c.CoreID = lines[0]
}
}
return nil
}
// CPUInfo on linux will return 1 item per physical thread.
//
// CPUs have three levels of counting: sockets, cores, threads.
// Cores with HyperThreading count as having 2 threads per core.
// Sockets often come with many physical CPU cores.
// For example a single socket board with two cores each with HT will
// return 4 CPUInfoStat structs on Linux and the "Cores" field set to 1.
func CPUInfo() ([]CPUInfoStat, error) { func CPUInfo() ([]CPUInfoStat, error) {
filename := common.GetEnv("HOST_PROC", "/proc") + "cpuinfo" filename := common.HostProc("cpuinfo")
lines, _ := common.ReadLines(filename) lines, _ := common.ReadLines(filename)
var ret []CPUInfoStat var ret []CPUInfoStat
var c CPUInfoStat c := CPUInfoStat{CPU: -1, Cores: 1}
for _, line := range lines { for _, line := range lines {
fields := strings.Split(line, ":") fields := strings.Split(line, ":")
if len(fields) < 2 { if len(fields) < 2 {
if c.VendorID != "" {
ret = append(ret, c)
}
continue continue
} }
key := strings.TrimSpace(fields[0]) key := strings.TrimSpace(fields[0])
@ -75,7 +104,14 @@ func CPUInfo() ([]CPUInfoStat, error) {
switch key { switch key {
case "processor": case "processor":
c = CPUInfoStat{} if c.CPU >= 0 {
err := finishCPUInfo(&c)
if err != nil {
return ret, err
}
ret = append(ret, c)
}
c = CPUInfoStat{Cores: 1}
t, err := strconv.ParseInt(value, 10, 64) t, err := strconv.ParseInt(value, 10, 64)
if err != nil { if err != nil {
return ret, err return ret, err
@ -111,16 +147,19 @@ func CPUInfo() ([]CPUInfoStat, error) {
c.PhysicalID = value c.PhysicalID = value
case "core id": case "core id":
c.CoreID = value c.CoreID = value
case "cpu cores": case "flags", "Features":
t, err := strconv.ParseInt(value, 10, 64) c.Flags = strings.FieldsFunc(value, func(r rune) bool {
if err != nil { return r == ',' || r == ' '
return ret, err })
}
c.Cores = int32(t)
case "flags":
c.Flags = strings.Split(value, ",")
} }
} }
if c.CPU >= 0 {
err := finishCPUInfo(&c)
if err != nil {
return ret, err
}
ret = append(ret, c)
}
return ret, nil return ret, nil
} }

View File

@ -82,7 +82,8 @@ func testCPUPercent(t *testing.T, percpu bool) {
t.Errorf("error %v", err) t.Errorf("error %v", err)
} }
for _, percent := range v { for _, percent := range v {
if percent < 0.0 || percent > 100.0*float64(numcpu) { // Check for slightly greater then 100% to account for any rounding issues.
if percent < 0.0 || percent > 100.0001*float64(numcpu) {
t.Fatalf("CPUPercent value is invalid: %f", percent) t.Fatalf("CPUPercent value is invalid: %f", percent)
} }
} }

View File

@ -10,7 +10,7 @@ import (
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
type Win32_Processor struct { type Win32_Processor struct {

View File

@ -6,7 +6,7 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func DiskPartitions(all bool) ([]DiskPartitionStat, error) { func DiskPartitions(all bool) ([]DiskPartitionStat, error) {

View File

@ -9,7 +9,7 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
const ( const (

View File

@ -0,0 +1,108 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_freebsd.go
package disk
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
sizeofLongDouble = 0x8
DEVSTAT_NO_DATA = 0x00
DEVSTAT_READ = 0x01
DEVSTAT_WRITE = 0x02
DEVSTAT_FREE = 0x03
MNT_RDONLY = 0x00000001
MNT_SYNCHRONOUS = 0x00000002
MNT_NOEXEC = 0x00000004
MNT_NOSUID = 0x00000008
MNT_UNION = 0x00000020
MNT_ASYNC = 0x00000040
MNT_SUIDDIR = 0x00100000
MNT_SOFTDEP = 0x00200000
MNT_NOSYMFOLLOW = 0x00400000
MNT_GJOURNAL = 0x02000000
MNT_MULTILABEL = 0x04000000
MNT_ACLS = 0x08000000
MNT_NOATIME = 0x10000000
MNT_NOCLUSTERR = 0x40000000
MNT_NOCLUSTERW = 0x80000000
MNT_NFS4ACLS = 0x00000010
MNT_WAIT = 1
MNT_NOWAIT = 2
MNT_LAZY = 3
MNT_SUSPEND = 4
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
_C_long_double int64
)
type Statfs struct {
Version uint32
Type uint32
Flags uint64
Bsize uint64
Iosize uint64
Blocks uint64
Bfree uint64
Bavail int64
Files uint64
Ffree int64
Syncwrites uint64
Asyncwrites uint64
Syncreads uint64
Asyncreads uint64
Spare [10]uint64
Namemax uint32
Owner uint32
Fsid Fsid
Charspare [80]int8
Fstypename [16]int8
Mntfromname [88]int8
Mntonname [88]int8
}
type Fsid struct {
Val [2]int32
}
type Devstat struct {
Sequence0 uint32
Allocated int32
Start_count uint32
End_count uint32
Busy_from Bintime
Dev_links _Ctype_struct___0
Device_number uint32
Device_name [16]int8
Unit_number int32
Bytes [4]uint64
Operations [4]uint64
Duration [4]Bintime
Busy_time Bintime
Creation_time Bintime
Block_size uint32
Tag_types [3]uint64
Flags uint32
Device_type uint32
Priority uint32
Id *byte
Sequence1 uint32
}
type Bintime struct {
Sec int32
Frac uint64
}
type _Ctype_struct___0 struct {
Empty uint32
}

View File

@ -9,7 +9,7 @@ import (
"strings" "strings"
"syscall" "syscall"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
const ( const (
@ -238,7 +238,7 @@ func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
} }
func DiskIOCounters() (map[string]DiskIOCountersStat, error) { func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
filename := common.GetEnv("HOST_PROC", "/proc") + "/diskstats" filename := common.HostProc("diskstats")
lines, err := common.ReadLines(filename) lines, err := common.ReadLines(filename)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -16,7 +16,7 @@ func DiskUsage(path string) (*DiskUsageStat, error) {
Path: path, Path: path,
Fstype: getFsType(stat), Fstype: getFsType(stat),
Total: (uint64(stat.Blocks) * uint64(bsize)), Total: (uint64(stat.Blocks) * uint64(bsize)),
Free: (uint64(stat.Bfree) * uint64(bsize)), Free: (uint64(stat.Bavail) * uint64(bsize)),
InodesTotal: (uint64(stat.Files)), InodesTotal: (uint64(stat.Files)),
InodesFree: (uint64(stat.Ffree)), InodesFree: (uint64(stat.Ffree)),
} }

View File

@ -9,7 +9,7 @@ import (
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
var ( var (

View File

@ -34,4 +34,8 @@ type CgroupMemStat struct {
TotalInactiveFile uint64 `json:"total_inactive_file"` TotalInactiveFile uint64 `json:"total_inactive_file"`
TotalActiveFile uint64 `json:"total_active_file"` TotalActiveFile uint64 `json:"total_active_file"`
TotalUnevictable uint64 `json:"total_unevictable"` TotalUnevictable uint64 `json:"total_unevictable"`
MemUsageInBytes uint64 `json:"mem_usage_in_bytes"`
MemMaxUsageInBytes uint64 `json:"mem_max_usage_in_bytes"`
MemLimitInBytes uint64 `json:"memory.limit_in_bytes"`
MemFailCnt uint64 `json:"memory.failcnt"`
} }

View File

@ -4,14 +4,15 @@ package docker
import ( import (
"encoding/json" "encoding/json"
"os" "fmt"
"os"
"os/exec" "os/exec"
"path" "path"
"strconv" "strconv"
"strings" "strings"
common "github.com/shirou/gopsutil/common"
cpu "github.com/shirou/gopsutil/cpu" cpu "github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common"
) )
// GetDockerIDList returnes a list of DockerID. // GetDockerIDList returnes a list of DockerID.
@ -40,28 +41,20 @@ func GetDockerIDList() ([]string, error) {
} }
// CgroupCPU returnes specified cgroup id CPU status. // CgroupCPU returnes specified cgroup id CPU status.
// containerid is same as docker id if you use docker. // containerId is same as docker id if you use docker.
// If you use container via systemd.slice, you could use // If you use container via systemd.slice, you could use
// containerid = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/ // containerId = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
func CgroupCPU(containerid string, base string) (*cpu.CPUTimesStat, error) { func CgroupCPU(containerId string, base string) (*cpu.CPUTimesStat, error) {
if len(base) == 0 { statfile := getCgroupFilePath(containerId, base, "cpuacct", "cpuacct.stat")
base = "/sys/fs/cgroup/cpuacct/docker"
}
statfile := path.Join(base, containerid, "cpuacct.stat")
if _, err := os.Stat(statfile); os.IsNotExist(err) {
statfile = path.Join("/sys/fs/cgroup/cpuacct/system.slice", "docker-" + containerid + ".scope", "cpuacct.stat")
}
lines, err := common.ReadLines(statfile) lines, err := common.ReadLines(statfile)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// empty containerid means all cgroup // empty containerId means all cgroup
if len(containerid) == 0 { if len(containerId) == 0 {
containerid = "all" containerId = "all"
} }
ret := &cpu.CPUTimesStat{CPU: containerid} ret := &cpu.CPUTimesStat{CPU: containerId}
for _, line := range lines { for _, line := range lines {
fields := strings.Split(line, " ") fields := strings.Split(line, " ")
if fields[0] == "user" { if fields[0] == "user" {
@ -82,28 +75,21 @@ func CgroupCPU(containerid string, base string) (*cpu.CPUTimesStat, error) {
} }
func CgroupCPUDocker(containerid string) (*cpu.CPUTimesStat, error) { func CgroupCPUDocker(containerid string) (*cpu.CPUTimesStat, error) {
return CgroupCPU(containerid, "/sys/fs/cgroup/cpuacct/docker") return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
} }
func CgroupMem(containerid string, base string) (*CgroupMemStat, error) { func CgroupMem(containerId string, base string) (*CgroupMemStat, error) {
if len(base) == 0 { statfile := getCgroupFilePath(containerId, base, "memory", "memory.stat")
base = "/sys/fs/cgroup/memory/docker"
}
statfile := path.Join(base, containerid, "memory.stat")
if _, err := os.Stat(statfile); os.IsNotExist(err) { // empty containerId means all cgroup
statfile = path.Join("/sys/fs/cgroup/memory/system.slice", "docker-" + containerid + ".scope", "memory.stat") if len(containerId) == 0 {
} containerId = "all"
// empty containerid means all cgroup
if len(containerid) == 0 {
containerid = "all"
} }
lines, err := common.ReadLines(statfile) lines, err := common.ReadLines(statfile)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ret := &CgroupMemStat{ContainerID: containerid} ret := &CgroupMemStat{ContainerID: containerId}
for _, line := range lines { for _, line := range lines {
fields := strings.Split(line, " ") fields := strings.Split(line, " ")
v, err := strconv.ParseUint(fields[1], 10, 64) v, err := strconv.ParseUint(fields[1], 10, 64)
@ -167,14 +153,61 @@ func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
ret.TotalUnevictable = v ret.TotalUnevictable = v
} }
} }
r, err := getCgroupMemFile(containerId, base, "memory.usage_in_bytes")
if err == nil {
ret.MemUsageInBytes = r
}
r, err = getCgroupMemFile(containerId, base, "memory.max_usage_in_bytes")
if err == nil {
ret.MemMaxUsageInBytes = r
}
r, err = getCgroupMemFile(containerId, base, "memory.limit_in_bytes")
if err == nil {
ret.MemLimitInBytes = r
}
r, err = getCgroupMemFile(containerId, base, "memory.failcnt")
if err == nil {
ret.MemFailCnt = r
}
return ret, nil return ret, nil
} }
func CgroupMemDocker(containerid string) (*CgroupMemStat, error) { func CgroupMemDocker(containerId string) (*CgroupMemStat, error) {
return CgroupMem(containerid, "/sys/fs/cgroup/memory/docker") return CgroupMem(containerId, common.HostSys("fs/cgroup/memory/docker"))
} }
func (m CgroupMemStat) String() string { func (m CgroupMemStat) String() string {
s, _ := json.Marshal(m) s, _ := json.Marshal(m)
return string(s) return string(s)
} }
// getCgroupFilePath constructs file path to get targetted stats file.
func getCgroupFilePath(containerId, base, target, file string) string {
if len(base) == 0 {
base = common.HostSys(fmt.Sprintf("fs/cgroup/%s/docker", target))
}
statfile := path.Join(base, containerId, file)
if _, err := os.Stat(statfile); os.IsNotExist(err) {
statfile = path.Join(
common.HostSys(fmt.Sprintf("fs/cgroup/%s/system.slice", target)), "docker-"+containerId+".scope", file)
}
return statfile
}
// getCgroupMemFile reads a cgroup file and return the contents as uint64.
func getCgroupMemFile(containerId, base, file string) (uint64, error) {
statfile := getCgroupFilePath(containerId, base, "memory", file)
lines, err := common.ReadLines(statfile)
if err != nil {
return 0, err
}
if len(lines) != 1 {
return 0, fmt.Errorf("wrong format file: %s", statfile)
}
return strconv.ParseUint(lines[0], 10, 64)
}

View File

@ -2,9 +2,7 @@
package docker package docker
import ( import "testing"
"testing"
)
func TestGetDockerIDList(t *testing.T) { func TestGetDockerIDList(t *testing.T) {
// If there is not docker environment, this test always fail. // If there is not docker environment, this test always fail.

View File

@ -6,6 +6,7 @@ import (
"encoding/json" "encoding/json"
"github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common"
) )
// GetDockerIDList returnes a list of DockerID. // GetDockerIDList returnes a list of DockerID.
@ -23,7 +24,7 @@ func CgroupCPU(containerid string, base string) (*cpu.CPUTimesStat, error) {
} }
func CgroupCPUDocker(containerid string) (*cpu.CPUTimesStat, error) { func CgroupCPUDocker(containerid string) (*cpu.CPUTimesStat, error) {
return CgroupCPU(containerid, "/sys/fs/cgroup/cpuacct/docker") return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
} }
func CgroupMem(containerid string, base string) (*CgroupMemStat, error) { func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
@ -31,7 +32,7 @@ func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
} }
func CgroupMemDocker(containerid string) (*CgroupMemStat, error) { func CgroupMemDocker(containerid string) (*CgroupMemStat, error) {
return CgroupMem(containerid, "/sys/fs/cgroup/memory/docker") return CgroupMem(containerid, common.HostSys("fs/cgroup/memory/docker"))
} }
func (m CgroupMemStat) String() string { func (m CgroupMemStat) String() string {

View File

@ -9,6 +9,7 @@ import (
type HostInfoStat struct { type HostInfoStat struct {
Hostname string `json:"hostname"` Hostname string `json:"hostname"`
Uptime uint64 `json:"uptime"` Uptime uint64 `json:"uptime"`
BootTime uint64 `json:"boot_time"`
Procs uint64 `json:"procs"` // number of processes Procs uint64 `json:"procs"` // number of processes
OS string `json:"os"` // ex: freebsd, linux OS string `json:"os"` // ex: freebsd, linux
Platform string `json:"platform"` // ex: ubuntu, linuxmint Platform string `json:"platform"` // ex: ubuntu, linuxmint

View File

@ -11,9 +11,10 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"time"
"unsafe" "unsafe"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func HostInfo() (*HostInfoStat, error) { func HostInfo() (*HostInfoStat, error) {
@ -39,14 +40,10 @@ func HostInfo() (*HostInfoStat, error) {
ret.VirtualizationRole = role ret.VirtualizationRole = role
} }
values, err := common.DoSysctrl("kern.boottime") boot, err := BootTime()
if err == nil { if err == nil {
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 ret.BootTime = boot
v := strings.Replace(values[2], ",", "", 1) ret.Uptime = uptime(boot)
t, err := strconv.ParseUint(v, 10, 64)
if err != nil {
ret.Uptime = t
}
} }
return ret, nil return ret, nil
@ -59,7 +56,6 @@ func BootTime() (uint64, error) {
} }
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 // ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
v := strings.Replace(values[2], ",", "", 1) v := strings.Replace(values[2], ",", "", 1)
boottime, err := strconv.ParseInt(v, 10, 64) boottime, err := strconv.ParseInt(v, 10, 64)
if err != nil { if err != nil {
return 0, err return 0, err
@ -68,6 +64,18 @@ func BootTime() (uint64, error) {
return uint64(boottime), nil return uint64(boottime), nil
} }
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) { func Users() ([]UserStat, error) {
utmpfile := "/var/run/utmpx" utmpfile := "/var/run/utmpx"
var ret []UserStat var ret []UserStat

View File

@ -11,9 +11,10 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"time"
"unsafe" "unsafe"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
const ( const (
@ -45,20 +46,16 @@ func HostInfo() (*HostInfoStat, error) {
ret.VirtualizationRole = role ret.VirtualizationRole = role
} }
values, err := common.DoSysctrl("kern.boottime") boot, err := BootTime()
if err == nil { if err == nil {
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 ret.BootTime = boot
v := strings.Replace(values[2], ",", "", 1) ret.Uptime = uptime(boot)
t, err := strconv.ParseUint(v, 10, 64)
if err == nil {
ret.Uptime = t
}
} }
return ret, nil return ret, nil
} }
func BootTime() (int64, error) { func BootTime() (uint64, error) {
values, err := common.DoSysctrl("kern.boottime") values, err := common.DoSysctrl("kern.boottime")
if err != nil { if err != nil {
return 0, err return 0, err
@ -66,7 +63,7 @@ func BootTime() (int64, error) {
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 // ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
v := strings.Replace(values[2], ",", "", 1) v := strings.Replace(values[2], ",", "", 1)
boottime, err := strconv.ParseInt(v, 10, 64) boottime, err := strconv.ParseUint(v, 10, 64)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -74,6 +71,18 @@ func BootTime() (int64, error) {
return boottime, nil return boottime, nil
} }
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) { func Users() ([]UserStat, error) {
utmpfile := "/var/run/utx.active" utmpfile := "/var/run/utx.active"
if !common.PathExists(utmpfile) { if !common.PathExists(utmpfile) {

View File

@ -13,9 +13,10 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"time"
"unsafe" "unsafe"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
type LSB struct { type LSB struct {
@ -46,9 +47,10 @@ func HostInfo() (*HostInfoStat, error) {
ret.VirtualizationSystem = system ret.VirtualizationSystem = system
ret.VirtualizationRole = role ret.VirtualizationRole = role
} }
uptime, err := BootTime() boot, err := BootTime()
if err == nil { if err == nil {
ret.Uptime = uptime ret.BootTime = boot
ret.Uptime = uptime(boot)
} }
return ret, nil return ret, nil
@ -56,7 +58,7 @@ func HostInfo() (*HostInfoStat, error) {
// BootTime returns the system boot time expressed in seconds since the epoch. // BootTime returns the system boot time expressed in seconds since the epoch.
func BootTime() (uint64, error) { func BootTime() (uint64, error) {
filename := common.GetEnv("HOST_PROC", "/proc") + "/stat" filename := common.HostProc("stat")
lines, err := common.ReadLines(filename) lines, err := common.ReadLines(filename)
if err != nil { if err != nil {
return 0, err return 0, err
@ -78,6 +80,18 @@ func BootTime() (uint64, error) {
return 0, fmt.Errorf("could not find btime") return 0, fmt.Errorf("could not find btime")
} }
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) { func Users() ([]UserStat, error) {
utmpfile := "/var/run/utmp" utmpfile := "/var/run/utmp"
@ -321,7 +335,7 @@ func GetVirtualization() (string, string, error) {
var system string var system string
var role string var role string
filename := common.GetEnv("HOST_PROC", "/proc") + "/xen" filename := common.HostProc("xen")
if common.PathExists(filename) { if common.PathExists(filename) {
system = "xen" system = "xen"
role = "guest" // assume guest role = "guest" // assume guest
@ -336,7 +350,7 @@ func GetVirtualization() (string, string, error) {
} }
} }
filename = common.GetEnv("HOST_PROC", "/proc") + "/modules" filename = common.HostProc("modules")
if common.PathExists(filename) { if common.PathExists(filename) {
contents, err := common.ReadLines(filename) contents, err := common.ReadLines(filename)
if err == nil { if err == nil {
@ -353,7 +367,7 @@ func GetVirtualization() (string, string, error) {
} }
} }
filename = common.GetEnv("HOST_PROC", "/proc") + "/cpuinfo" filename = common.HostProc("cpuinfo")
if common.PathExists(filename) { if common.PathExists(filename) {
contents, err := common.ReadLines(filename) contents, err := common.ReadLines(filename)
if err == nil { if err == nil {
@ -366,7 +380,7 @@ func GetVirtualization() (string, string, error) {
} }
} }
filename = common.GetEnv("HOST_PROC", "/proc") filename = common.HostProc()
if common.PathExists(filename + "/bc/0") { if common.PathExists(filename + "/bc/0") {
system = "openvz" system = "openvz"
role = "host" role = "host"

View File

@ -6,39 +6,39 @@
package host package host
const ( const (
sizeofPtr = 0x4 sizeofPtr = 0x4
sizeofShort = 0x2 sizeofShort = 0x2
sizeofInt = 0x4 sizeofInt = 0x4
sizeofLong = 0x4 sizeofLong = 0x4
sizeofLongLong = 0x8 sizeofLongLong = 0x8
) )
type ( type (
_C_short int16 _C_short int16
_C_int int32 _C_int int32
_C_long int32 _C_long int32
_C_long_long int64 _C_long_long int64
) )
type utmp struct { type utmp struct {
Type int16 Type int16
Pad_cgo_0 [2]byte Pad_cgo_0 [2]byte
Pid int32 Pid int32
Line [32]int8 Line [32]int8
Id [4]int8 Id [4]int8
User [32]int8 User [32]int8
Host [256]int8 Host [256]int8
Exit exit_status Exit exit_status
Session int32 Session int32
Tv UtTv Tv UtTv
Addr_v6 [4]int32 Addr_v6 [4]int32
X__unused [20]int8 X__unused [20]int8
} }
type exit_status struct { type exit_status struct {
Termination int16 Termination int16
Exit int16 Exit int16
} }
type UtTv struct { type UtTv struct {
TvSec int32 TvSec int32
TvUsec int32 TvUsec int32
} }

View File

@ -46,8 +46,9 @@ func TestHostInfoStat_String(t *testing.T) {
Procs: 100, Procs: 100,
OS: "linux", OS: "linux",
Platform: "ubuntu", Platform: "ubuntu",
BootTime: 1447040000,
} }
e := `{"hostname":"test","uptime":3000,"procs":100,"os":"linux","platform":"ubuntu","platform_family":"","platform_version":"","virtualization_system":"","virtualization_role":""}` e := `{"hostname":"test","uptime":3000,"boot_time":1447040000,"procs":100,"os":"linux","platform":"ubuntu","platform_family":"","platform_version":"","virtualization_system":"","virtualization_role":""}`
if e != fmt.Sprintf("%v", v) { if e != fmt.Sprintf("%v", v) {
t.Errorf("HostInfoStat string is invalid: %v", v) t.Errorf("HostInfoStat string is invalid: %v", v)
} }

View File

@ -11,8 +11,8 @@ import (
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
process "github.com/shirou/gopsutil/common/process" process "github.com/shirou/gopsutil/process"
) )
var ( var (
@ -47,9 +47,10 @@ func HostInfo() (*HostInfoStat, error) {
return ret, err return ret, err
} }
ret.Uptime, err = BootTime() boot, err := BootTime()
if err != nil { if err == nil {
return ret, err ret.BootTime = boot
ret.Uptime = uptime(boot)
} }
procs, err := process.Pids() procs, err := process.Pids()
@ -87,6 +88,18 @@ func BootTime() (uint64, error) {
return uint64(now.Sub(t).Seconds()), nil return uint64(now.Sub(t).Seconds()), nil
} }
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func GetPlatformInformation() (platform string, family string, version string, err error) { func GetPlatformInformation() (platform string, family string, version string, err error) {
if osInfo == nil { if osInfo == nil {
_, err = GetOSInfo() _, err = GetOSInfo()

View File

@ -5,7 +5,7 @@ package load
import ( import (
"strconv" "strconv"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func LoadAvg() (*LoadAvgStat, error) { func LoadAvg() (*LoadAvgStat, error) {

View File

@ -5,7 +5,7 @@ package load
import ( import (
"strconv" "strconv"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func LoadAvg() (*LoadAvgStat, error) { func LoadAvg() (*LoadAvgStat, error) {

View File

@ -7,11 +7,11 @@ import (
"strconv" "strconv"
"strings" "strings"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func LoadAvg() (*LoadAvgStat, error) { func LoadAvg() (*LoadAvgStat, error) {
filename := common.GetEnv("HOST_PROC", "/proc") + "/loadavg" filename := common.HostProc("loadavg")
line, err := ioutil.ReadFile(filename) line, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -3,7 +3,7 @@
package load package load
import ( import (
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func LoadAvg() (*LoadAvgStat, error) { func LoadAvg() (*LoadAvgStat, error) {

View File

@ -7,7 +7,7 @@ import (
"strconv" "strconv"
"strings" "strings"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func getPageSize() (uint64, error) { func getPageSize() (uint64, error) {

View File

@ -6,8 +6,8 @@ import (
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"
"errors"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func VirtualMemory() (*VirtualMemoryStat, error) { func VirtualMemory() (*VirtualMemoryStat, error) {
@ -91,7 +91,6 @@ func SwapMemory() (*SwapMemoryStat, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
var ret *SwapMemoryStat
for _, line := range strings.Split(string(out), "\n") { for _, line := range strings.Split(string(out), "\n") {
values := strings.Fields(line) values := strings.Fields(line)
// skip title line // skip title line
@ -117,13 +116,13 @@ func SwapMemory() (*SwapMemoryStat, error) {
return nil, err return nil, err
} }
ret = &SwapMemoryStat{ return &SwapMemoryStat{
Total: total_v, Total: total_v,
Used: used_v, Used: used_v,
Free: free_v, Free: free_v,
UsedPercent: up_v, UsedPercent: up_v,
} }, nil
} }
return ret, nil return nil, errors.New("no swap devices found")
} }

View File

@ -7,11 +7,11 @@ import (
"strings" "strings"
"syscall" "syscall"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func VirtualMemory() (*VirtualMemoryStat, error) { func VirtualMemory() (*VirtualMemoryStat, error) {
filename := common.GetEnv("HOST_PROC", "/proc") + "/meminfo" filename := common.HostProc("meminfo")
lines, _ := common.ReadLines(filename) lines, _ := common.ReadLines(filename)
// flag if MemAvailable is in /proc/meminfo (kernel 3.14+) // flag if MemAvailable is in /proc/meminfo (kernel 3.14+)
memavail := false memavail := false
@ -74,7 +74,7 @@ func SwapMemory() (*SwapMemoryStat, error) {
} else { } else {
ret.UsedPercent = 0 ret.UsedPercent = 0
} }
filename := common.GetEnv("HOST_PROC", "/proc") + "/vmstat" filename := common.HostProc("vmstat")
lines, _ := common.ReadLines(filename) lines, _ := common.ReadLines(filename)
for _, l := range lines { for _, l := range lines {
fields := strings.Fields(l) fields := strings.Fields(l)

View File

@ -6,7 +6,7 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
var ( var (

View File

@ -8,7 +8,7 @@ import (
"strings" "strings"
"syscall" "syscall"
"github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
var invoke common.Invoker var invoke common.Invoker
@ -45,6 +45,12 @@ type NetConnectionStat struct {
Pid int32 `json:"pid"` Pid int32 `json:"pid"`
} }
// System wide stats about different network protocols
type NetProtoCountersStat struct {
Protocol string `json:"protocol"`
Stats map[string]int64 `json:"stats"`
}
// NetInterfaceAddr is designed for represent interface addresses // NetInterfaceAddr is designed for represent interface addresses
type NetInterfaceAddr struct { type NetInterfaceAddr struct {
Addr string `json:"addr"` Addr string `json:"addr"`
@ -75,6 +81,11 @@ func (n NetConnectionStat) String() string {
return string(s) return string(s)
} }
func (n NetProtoCountersStat) String() string {
s, _ := json.Marshal(n)
return string(s)
}
func (a Addr) String() string { func (a Addr) String() string {
s, _ := json.Marshal(a) s, _ := json.Marshal(a)
return string(s) return string(s)

View File

@ -3,11 +3,12 @@
package net package net
import ( import (
"errors"
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"
"github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
// example of netstat -idbn output on yosemite // example of netstat -idbn output on yosemite
@ -90,3 +91,11 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
return ret, nil return ret, nil
} }
// NetProtoCounters returns network statistics for the entire system
// If protocols is empty then all protocols are returned, otherwise
// just the protocols in the list are returned.
// Not Implemented for Darwin
func NetProtoCounters(protocols []string) ([]NetProtoCountersStat, error) {
return nil, errors.New("NetProtoCounters not implemented for darwin")
}

View File

@ -3,11 +3,12 @@
package net package net
import ( import (
"errors"
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"
"github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
@ -81,3 +82,11 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
return ret, nil return ret, nil
} }
// NetProtoCounters returns network statistics for the entire system
// If protocols is empty then all protocols are returned, otherwise
// just the protocols in the list are returned.
// Not Implemented for FreeBSD
func NetProtoCounters(protocols []string) ([]NetProtoCountersStat, error) {
return nil, errors.New("NetProtoCounters not implemented for freebsd")
}

View File

@ -3,10 +3,11 @@
package net package net
import ( import (
"errors"
"strconv" "strconv"
"strings" "strings"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
// NetIOCounters returnes network I/O statistics for every network // NetIOCounters returnes network I/O statistics for every network
@ -15,7 +16,7 @@ import (
// every network interface installed on the system is returned // every network interface installed on the system is returned
// separately. // separately.
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
filename := common.GetEnv("HOST_PROC", "/proc") + "/net/dev" filename := common.HostProc("net/dev")
lines, err := common.ReadLines(filename) lines, err := common.ReadLines(filename)
if err != nil { if err != nil {
return nil, err return nil, err
@ -89,3 +90,73 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
return ret, nil return ret, nil
} }
var netProtocols = []string{
"ip",
"icmp",
"icmpmsg",
"tcp",
"udp",
"udplite",
}
// NetProtoCounters returns network statistics for the entire system
// If protocols is empty then all protocols are returned, otherwise
// just the protocols in the list are returned.
// Available protocols:
// ip,icmp,icmpmsg,tcp,udp,udplite
func NetProtoCounters(protocols []string) ([]NetProtoCountersStat, error) {
if len(protocols) == 0 {
protocols = netProtocols
}
stats := make([]NetProtoCountersStat, 0, len(protocols))
protos := make(map[string]bool, len(protocols))
for _, p := range protocols {
protos[p] = true
}
filename := "/proc/net/snmp"
lines, err := common.ReadLines(filename)
if err != nil {
return nil, err
}
linecount := len(lines)
for i := 0; i < linecount; i++ {
line := lines[i]
r := strings.IndexRune(line, ':')
if r == -1 {
return nil, errors.New(filename + " is not fomatted correctly, expected ':'.")
}
proto := strings.ToLower(line[:r])
if !protos[proto] {
// skip protocol and data line
i++
continue
}
// Read header line
statNames := strings.Split(line[r+2:], " ")
// Read data line
i++
statValues := strings.Split(lines[i][r+2:], " ")
if len(statNames) != len(statValues) {
return nil, errors.New(filename + " is not fomatted correctly, expected same number of columns.")
}
stat := NetProtoCountersStat{
Protocol: proto,
Stats: make(map[string]int64, len(statNames)),
}
for j := range statNames {
value, err := strconv.ParseInt(statValues[j], 10, 64)
if err != nil {
return nil, err
}
stat.Stats[statNames[j]] = value
}
stats = append(stats, stat)
}
return stats, nil
}

View File

@ -26,6 +26,22 @@ func TestNetIOCountersStatString(t *testing.T) {
} }
} }
func TestNetProtoCountersStatString(t *testing.T) {
v := NetProtoCountersStat{
Protocol: "tcp",
Stats: map[string]int64{
"MaxConn": -1,
"ActiveOpens": 4000,
"PassiveOpens": 3000,
},
}
e := `{"protocol":"tcp","stats":{"ActiveOpens":4000,"MaxConn":-1,"PassiveOpens":3000}}`
if e != fmt.Sprintf("%v", v) {
t.Errorf("NetProtoCountersStat string is invalid: %v", v)
}
}
func TestNetConnectionStatString(t *testing.T) { func TestNetConnectionStatString(t *testing.T) {
v := NetConnectionStat{ v := NetConnectionStat{
Fd: 10, Fd: 10,
@ -122,6 +138,45 @@ func TestNetInterfaces(t *testing.T) {
} }
} }
func TestNetProtoCountersStatsAll(t *testing.T) {
v, err := NetProtoCounters(nil)
if err != nil {
t.Fatalf("Could not get NetProtoCounters: %v", err)
}
if len(v) == 0 {
t.Fatalf("Could not get NetProtoCounters: %v", err)
}
for _, vv := range v {
if vv.Protocol == "" {
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
}
if len(vv.Stats) == 0 {
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
}
}
}
func TestNetProtoCountersStats(t *testing.T) {
v, err := NetProtoCounters([]string{"tcp", "ip"})
if err != nil {
t.Fatalf("Could not get NetProtoCounters: %v", err)
}
if len(v) == 0 {
t.Fatalf("Could not get NetProtoCounters: %v", err)
}
if len(v) != 2 {
t.Fatalf("Go incorrect number of NetProtoCounters: %v", err)
}
for _, vv := range v {
if vv.Protocol != "tcp" && vv.Protocol != "ip" {
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
}
if len(vv.Stats) == 0 {
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
}
}
}
func TestNetConnections(t *testing.T) { func TestNetConnections(t *testing.T) {
if ci := os.Getenv("CI"); ci != "" { // skip if test on drone.io if ci := os.Getenv("CI"); ci != "" { // skip if test on drone.io
return return

View File

@ -5,7 +5,7 @@ package net
import ( import (
"strings" "strings"
"github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
// Return a list of network connections opened. // Return a list of network connections opened.

View File

@ -3,12 +3,13 @@
package net package net
import ( import (
"errors"
"net" "net"
"os" "os"
"syscall" "syscall"
"unsafe" "unsafe"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
var ( var (
@ -96,3 +97,11 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) {
} }
return a, nil return a, nil
} }
// NetProtoCounters returns network statistics for the entire system
// If protocols is empty then all protocols are returned, otherwise
// just the protocols in the list are returned.
// Not Implemented for Windows
func NetProtoCounters(protocols []string) ([]NetProtoCountersStat, error) {
return nil, errors.New("NetProtoCounters not implemented for windows")
}

View File

@ -5,8 +5,8 @@ import (
"runtime" "runtime"
"time" "time"
"github.com/shirou/gopsutil/common"
"github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common"
) )
var invoke common.Invoker var invoke common.Invoker

View File

@ -10,8 +10,8 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/shirou/gopsutil/common"
"github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common"
"github.com/shirou/gopsutil/net" "github.com/shirou/gopsutil/net"
) )
@ -278,7 +278,19 @@ func (p *Process) MemoryPercent() (float32, error) {
} }
func (p *Process) Children() ([]*Process, error) { func (p *Process) Children() ([]*Process, error) {
return nil, common.NotImplementedError pids, err := common.CallPgrep(invoke, p.Pid)
if err != nil {
return nil, err
}
ret := make([]*Process, 0, len(pids))
for _, pid := range pids {
np, err := NewProcess(pid)
if err != nil {
return nil, err
}
ret = append(ret, np)
}
return ret, nil
} }
func (p *Process) OpenFiles() ([]OpenFilesStat, error) { func (p *Process) OpenFiles() ([]OpenFilesStat, error) {

View File

@ -6,9 +6,11 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"unsafe" "unsafe"
"strings"
"syscall"
common "github.com/shirou/gopsutil/common"
cpu "github.com/shirou/gopsutil/cpu" cpu "github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common"
net "github.com/shirou/gopsutil/net" net "github.com/shirou/gopsutil/net"
) )
@ -53,7 +55,19 @@ func (p *Process) Exe() (string, error) {
return "", common.NotImplementedError return "", common.NotImplementedError
} }
func (p *Process) Cmdline() (string, error) { func (p *Process) Cmdline() (string, error) {
return "", common.NotImplementedError mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return "", err
}
ret := strings.FieldsFunc(string(buf), func(r rune) bool {
if r == '\u0000' {
return true
}
return false
})
return strings.Join(ret, " "), nil
} }
func (p *Process) CreateTime() (int64, error) { func (p *Process) CreateTime() (int64, error) {
return 0, common.NotImplementedError return 0, common.NotImplementedError
@ -121,7 +135,14 @@ func (p *Process) Rlimit() ([]RlimitStat, error) {
return rlimit, common.NotImplementedError return rlimit, common.NotImplementedError
} }
func (p *Process) IOCounters() (*IOCountersStat, error) { func (p *Process) IOCounters() (*IOCountersStat, error) {
return nil, common.NotImplementedError k, err := p.getKProc()
if err != nil {
return nil, err
}
return &IOCountersStat{
ReadCount: uint64(k.KiRusage.Inblock),
WriteCount: uint64(k.KiRusage.Oublock),
}, nil
} }
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
return nil, common.NotImplementedError return nil, common.NotImplementedError
@ -142,7 +163,15 @@ func (p *Process) Threads() (map[string]string, error) {
return ret, common.NotImplementedError return ret, common.NotImplementedError
} }
func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) { func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
return nil, common.NotImplementedError k, err := p.getKProc()
if err != nil {
return nil, err
}
return &cpu.CPUTimesStat{
CPU: "cpu",
User: float64(k.KiRusage.Utime.Sec) + float64(k.KiRusage.Utime.Usec)/1000000,
System: float64(k.KiRusage.Stime.Sec) + float64(k.KiRusage.Stime.Usec)/1000000,
}, nil
} }
func (p *Process) CPUAffinity() ([]int32, error) { func (p *Process) CPUAffinity() ([]int32, error) {
return nil, common.NotImplementedError return nil, common.NotImplementedError
@ -152,13 +181,16 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
v, err := syscall.Sysctl("vm.stats.vm.v_page_size")
ret := &MemoryInfoStat{ if err != nil {
RSS: uint64(k.KiRssize), return nil, err
VMS: uint64(k.KiSize),
} }
pageSize := binary.LittleEndian.Uint16([]byte(v))
return ret, nil return &MemoryInfoStat{
RSS: uint64(k.KiRssize) * uint64(pageSize),
VMS: uint64(k.KiSize),
}, nil
} }
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
return nil, common.NotImplementedError return nil, common.NotImplementedError
@ -168,7 +200,19 @@ func (p *Process) MemoryPercent() (float32, error) {
} }
func (p *Process) Children() ([]*Process, error) { func (p *Process) Children() ([]*Process, error) {
return nil, common.NotImplementedError pids, err := common.CallPgrep(invoke, p.Pid)
if err != nil {
return nil, err
}
ret := make([]*Process, 0, len(pids))
for _, pid := range pids {
np, err := NewProcess(pid)
if err != nil {
return nil, err
}
ret = append(ret, np)
}
return ret, nil
} }
func (p *Process) OpenFiles() ([]OpenFilesStat, error) { func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
@ -229,11 +273,7 @@ func parseKinfoProc(buf []byte) (KinfoProc, error) {
var k KinfoProc var k KinfoProc
br := bytes.NewReader(buf) br := bytes.NewReader(buf)
err := binary.Read(br, binary.LittleEndian, &k) err := binary.Read(br, binary.LittleEndian, &k)
if err != nil { return k, err
return k, err
}
return k, nil
} }
func (p *Process) getKProc() (*KinfoProc, error) { func (p *Process) getKProc() (*KinfoProc, error) {

View File

@ -10,8 +10,38 @@ const (
KernProcPID = 1 // by process id KernProcPID = 1 // by process id
KernProcProc = 8 // only return procs KernProcProc = 8 // only return procs
KernProcPathname = 12 // path to executable KernProcPathname = 12 // path to executable
KernProcArgs = 7 // get/set arguments/proctitle
) )
type Timespec struct {
Sec int32
Nsec int32
}
type Timeval struct {
Sec int32
Usec int32
}
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int32
Ixrss int32
Idrss int32
Isrss int32
Minflt int32
Majflt int32
Nswap int32
Inblock int32
Oublock int32
Msgsnd int32
Msgrcv int32
Nsignals int32
Nvcsw int32
Nivcsw int32
}
// copied from sys/user.h // copied from sys/user.h
type KinfoProc struct { type KinfoProc struct {
KiStructsize int32 KiStructsize int32
@ -83,7 +113,7 @@ type KinfoProc struct {
KiNumthreads int32 KiNumthreads int32
KiTid int32 KiTid int32
KiPri int32 KiPri int32
KiRusage [72]byte KiRusage Rusage
KiRusageCh [72]byte KiRusageCh [72]byte
KiPcb int32 KiPcb int32
KiKstack int32 KiKstack int32

View File

@ -1,6 +1,5 @@
// +build freebsd // +build freebsd
// +build amd64 // +build amd64
package process package process
// copied from sys/sysctl.h // copied from sys/sysctl.h
@ -10,8 +9,38 @@ const (
KernProcPID = 1 // by process id KernProcPID = 1 // by process id
KernProcProc = 8 // only return procs KernProcProc = 8 // only return procs
KernProcPathname = 12 // path to executable KernProcPathname = 12 // path to executable
KernProcArgs = 7 // get/set arguments/proctitle
) )
type Timespec struct {
Sec int64
Nsec int64
}
type Timeval struct {
Sec int64
Usec int64
}
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int64
Ixrss int64
Idrss int64
Isrss int64
Minflt int64
Majflt int64
Nswap int64
Inblock int64
Oublock int64
Msgsnd int64
Msgrcv int64
Nsignals int64
Nvcsw int64
Nivcsw int64
}
// copied from sys/user.h // copied from sys/user.h
type KinfoProc struct { type KinfoProc struct {
KiStructsize int32 KiStructsize int32
@ -83,7 +112,7 @@ type KinfoProc struct {
KiNumthreads int32 KiNumthreads int32
KiTid int32 KiTid int32
KiPri int32 KiPri int32
KiRusage [144]byte KiRusage Rusage
KiRusageCh [144]byte KiRusageCh [144]byte
KiPcb int64 KiPcb int64
KiKstack int64 KiKstack int64

View File

@ -12,9 +12,9 @@ import (
"strings" "strings"
"syscall" "syscall"
"github.com/shirou/gopsutil/common"
"github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/host" "github.com/shirou/gopsutil/host"
"github.com/shirou/gopsutil/internal/common"
"github.com/shirou/gopsutil/net" "github.com/shirou/gopsutil/net"
) )
@ -203,11 +203,32 @@ func (p *Process) MemoryPercent() (float32, error) {
} }
func (p *Process) Children() ([]*Process, error) { func (p *Process) Children() ([]*Process, error) {
return nil, common.NotImplementedError pids, err := common.CallPgrep(invoke, p.Pid)
if err != nil {
return nil, err
}
ret := make([]*Process, 0, len(pids))
for _, pid := range pids {
np, err := NewProcess(pid)
if err != nil {
return nil, err
}
ret = append(ret, np)
}
return ret, nil
} }
func (p *Process) OpenFiles() ([]OpenFilesStat, error) { func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
return nil, common.NotImplementedError _, ofs, err := p.fillFromfd()
if err != nil {
return nil, err
}
ret := make([]OpenFilesStat, 0, len(ofs))
for i, o := range ofs {
ret[i] = *o
}
return ret, nil
} }
func (p *Process) Connections() ([]net.NetConnectionStat, error) { func (p *Process) Connections() ([]net.NetConnectionStat, error) {
@ -222,7 +243,7 @@ func (p *Process) IsRunning() (bool, error) {
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
pid := p.Pid pid := p.Pid
var ret []MemoryMapsStat var ret []MemoryMapsStat
smapsPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "smaps") smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps")
contents, err := ioutil.ReadFile(smapsPath) contents, err := ioutil.ReadFile(smapsPath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -303,7 +324,7 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
// Get num_fds from /proc/(pid)/fd // Get num_fds from /proc/(pid)/fd
func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) { func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) {
pid := p.Pid pid := p.Pid
statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "fd") statPath := common.HostProc(strconv.Itoa(int(pid)), "fd")
d, err := os.Open(statPath) d, err := os.Open(statPath)
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
@ -336,7 +357,7 @@ func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) {
// Get cwd from /proc/(pid)/cwd // Get cwd from /proc/(pid)/cwd
func (p *Process) fillFromCwd() (string, error) { func (p *Process) fillFromCwd() (string, error) {
pid := p.Pid pid := p.Pid
cwdPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "cwd") cwdPath := common.HostProc(strconv.Itoa(int(pid)), "cwd")
cwd, err := os.Readlink(cwdPath) cwd, err := os.Readlink(cwdPath)
if err != nil { if err != nil {
return "", err return "", err
@ -347,7 +368,7 @@ func (p *Process) fillFromCwd() (string, error) {
// Get exe from /proc/(pid)/exe // Get exe from /proc/(pid)/exe
func (p *Process) fillFromExe() (string, error) { func (p *Process) fillFromExe() (string, error) {
pid := p.Pid pid := p.Pid
exePath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "exe") exePath := common.HostProc(strconv.Itoa(int(pid)), "exe")
exe, err := os.Readlink(exePath) exe, err := os.Readlink(exePath)
if err != nil { if err != nil {
return "", err return "", err
@ -358,7 +379,7 @@ func (p *Process) fillFromExe() (string, error) {
// Get cmdline from /proc/(pid)/cmdline // Get cmdline from /proc/(pid)/cmdline
func (p *Process) fillFromCmdline() (string, error) { func (p *Process) fillFromCmdline() (string, error) {
pid := p.Pid pid := p.Pid
cmdPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "cmdline") cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath) cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil { if err != nil {
return "", err return "", err
@ -376,7 +397,7 @@ func (p *Process) fillFromCmdline() (string, error) {
// Get IO status from /proc/(pid)/io // Get IO status from /proc/(pid)/io
func (p *Process) fillFromIO() (*IOCountersStat, error) { func (p *Process) fillFromIO() (*IOCountersStat, error) {
pid := p.Pid pid := p.Pid
ioPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "io") ioPath := common.HostProc(strconv.Itoa(int(pid)), "io")
ioline, err := ioutil.ReadFile(ioPath) ioline, err := ioutil.ReadFile(ioPath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -415,7 +436,7 @@ func (p *Process) fillFromIO() (*IOCountersStat, error) {
// Get memory info from /proc/(pid)/statm // Get memory info from /proc/(pid)/statm
func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
pid := p.Pid pid := p.Pid
memPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "statm") memPath := common.HostProc(strconv.Itoa(int(pid)), "statm")
contents, err := ioutil.ReadFile(memPath) contents, err := ioutil.ReadFile(memPath)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -467,7 +488,7 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
// Get various status from /proc/(pid)/status // Get various status from /proc/(pid)/status
func (p *Process) fillFromStatus() error { func (p *Process) fillFromStatus() error {
pid := p.Pid pid := p.Pid
statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "status") statPath := common.HostProc(strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath) contents, err := ioutil.ReadFile(statPath)
if err != nil { if err != nil {
return err return err
@ -554,7 +575,7 @@ func (p *Process) fillFromStatus() error {
func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32, error) { func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32, error) {
pid := p.Pid pid := p.Pid
statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "stat") statPath := common.HostProc(strconv.Itoa(int(pid)), "stat")
contents, err := ioutil.ReadFile(statPath) contents, err := ioutil.ReadFile(statPath)
if err != nil { if err != nil {
return "", 0, nil, 0, 0, err return "", 0, nil, 0, 0, err
@ -610,7 +631,7 @@ func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32
func Pids() ([]int32, error) { func Pids() ([]int32, error) {
var ret []int32 var ret []int32
d, err := os.Open(common.GetEnv("HOST_PROC", "/proc")) d, err := os.Open(common.HostProc())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -8,7 +8,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
) )
var mu sync.Mutex var mu sync.Mutex
@ -312,3 +312,19 @@ func Test_Connections(t *testing.T) {
t.Fatalf("wrong connections") t.Fatalf("wrong connections")
} }
} }
func Test_Children(t *testing.T) {
p, err := NewProcess(1)
if err != nil {
t.Fatalf("new process error %v", err)
}
c, err := p.Children()
if err != nil {
t.Fatalf("error %v", err)
}
if len(c) == 0 {
t.Fatalf("children is empty")
}
}

View File

@ -12,7 +12,7 @@ import (
"github.com/StackExchange/wmi" "github.com/StackExchange/wmi"
"github.com/shirou/w32" "github.com/shirou/w32"
common "github.com/shirou/gopsutil/common" "github.com/shirou/gopsutil/internal/common"
cpu "github.com/shirou/gopsutil/cpu" cpu "github.com/shirou/gopsutil/cpu"
net "github.com/shirou/gopsutil/net" net "github.com/shirou/gopsutil/net"
) )

View File

@ -7,32 +7,37 @@ PATH := $(subst :,/bin:,$(GOPATH))/bin:$(PATH)
endif endif
# Standard Telegraf build # Standard Telegraf build
build: prepare default: prepare build
godep go build -o telegraf -ldflags \
# Only run the build (no dependency grabbing)
build:
go build -o telegraf -ldflags \
"-X main.Version=$(VERSION)" \ "-X main.Version=$(VERSION)" \
./cmd/telegraf/telegraf.go ./cmd/telegraf/telegraf.go
# Build with race detector # Build with race detector
dev: prepare dev: prepare
godep go build -race -o telegraf -ldflags \ go build -race -o telegraf -ldflags \
"-X main.Version=$(VERSION)" \ "-X main.Version=$(VERSION)" \
./cmd/telegraf/telegraf.go ./cmd/telegraf/telegraf.go
# Build linux 64-bit, 32-bit and arm architectures # Build linux 64-bit, 32-bit and arm architectures
build-linux-bins: prepare build-linux-bins: prepare
GOARCH=amd64 GOOS=linux godep go build -o telegraf_linux_amd64 \ GOARCH=amd64 GOOS=linux go build -o telegraf_linux_amd64 \
-ldflags "-X main.Version=$(VERSION)" \ -ldflags "-X main.Version=$(VERSION)" \
./cmd/telegraf/telegraf.go ./cmd/telegraf/telegraf.go
GOARCH=386 GOOS=linux godep go build -o telegraf_linux_386 \ GOARCH=386 GOOS=linux go build -o telegraf_linux_386 \
-ldflags "-X main.Version=$(VERSION)" \ -ldflags "-X main.Version=$(VERSION)" \
./cmd/telegraf/telegraf.go ./cmd/telegraf/telegraf.go
GOARCH=arm GOOS=linux godep go build -o telegraf_linux_arm \ GOARCH=arm GOOS=linux go build -o telegraf_linux_arm \
-ldflags "-X main.Version=$(VERSION)" \ -ldflags "-X main.Version=$(VERSION)" \
./cmd/telegraf/telegraf.go ./cmd/telegraf/telegraf.go
# Get godep # Get dependencies and use godep to checkout changesets
prepare: prepare:
go get ./...
go get github.com/tools/godep go get github.com/tools/godep
godep restore
# Run all docker containers necessary for unit tests # Run all docker containers necessary for unit tests
docker-run: docker-run:
@ -84,10 +89,10 @@ test: docker-kill prepare docker-run
# Sleeping for kafka leadership election, TSDB setup, etc. # Sleeping for kafka leadership election, TSDB setup, etc.
sleep 60 sleep 60
# SUCCESS, running tests # SUCCESS, running tests
godep go test -race ./... go test -race ./...
# Run "short" unit tests # Run "short" unit tests
test-short: prepare test-short: prepare
godep go test -short ./... go test -short ./...
.PHONY: test .PHONY: test

View File

@ -10,6 +10,8 @@ machine:
- go version - go version
dependencies: dependencies:
cache_directories:
- "~/telegraf-build/src"
override: override:
- docker info - docker info

View File

@ -35,11 +35,11 @@ func NewConfig() *Config {
c := &Config{ c := &Config{
// Agent defaults: // Agent defaults:
Agent: &AgentConfig{ Agent: &AgentConfig{
Interval: internal.Duration{10 * time.Second}, Interval: internal.Duration{Duration: 10 * time.Second},
RoundInterval: true, RoundInterval: true,
FlushInterval: internal.Duration{10 * time.Second}, FlushInterval: internal.Duration{Duration: 10 * time.Second},
FlushRetries: 2, FlushRetries: 2,
FlushJitter: internal.Duration{5 * time.Second}, FlushJitter: internal.Duration{Duration: 5 * time.Second},
}, },
Tags: make(map[string]string), Tags: make(map[string]string),

View File

@ -10,7 +10,7 @@ import (
// Duration just wraps time.Duration // Duration just wraps time.Duration
type Duration struct { type Duration struct {
time.Duration Duration time.Duration
} }
// UnmarshalTOML parses the duration from the TOML config file // UnmarshalTOML parses the duration from the TOML config file

View File

@ -57,7 +57,7 @@ exit_if_fail make
exit_if_fail godep go vet ./... exit_if_fail godep go vet ./...
exit_if_fail make docker-run-circle exit_if_fail make docker-run-circle
sleep 10 sleep 10
exit_if_fail godep go test -race ./... exit_if_fail go test -race ./...
# Simple Integration Tests # Simple Integration Tests
# check that version was properly set # check that version was properly set

View File

@ -134,7 +134,8 @@ do_build() {
rm -f $GOPATH_INSTALL/bin/$b rm -f $GOPATH_INSTALL/bin/$b
done done
godep go install -ldflags="-X main.Version $version" ./... godep restore
go install -ldflags="-X main.Version $version" ./...
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Build failed, unable to create package -- aborting" echo "Build failed, unable to create package -- aborting"
cleanup_exit 1 cleanup_exit 1