Godep update: gopsutil

This commit is contained in:
Cameron Sparr 2015-11-10 14:59:01 -07:00
parent acf9c1141a
commit 92fb51026a
44 changed files with 2503 additions and 281 deletions

39
Godeps/Godeps.json generated
View File

@ -1,9 +1,6 @@
{
"ImportPath": "github.com/influxdb/telegraf",
"GoVersion": "go1.5.1",
"Packages": [
"./..."
],
"Deps": [
{
"ImportPath": "bitbucket.org/ww/goautoneg",
@ -172,39 +169,9 @@
"Rev": "5bb5cfc093ad18a28148c578f8632cfdb4d802e4"
},
{
"ImportPath": "github.com/shirou/gopsutil/cpu",
"Comment": "1.0.0-161-g3303647",
"Rev": "3303647209557312e5db51450ea8bbdef56d5176"
},
{
"ImportPath": "github.com/shirou/gopsutil/disk",
"Comment": "1.0.0-161-g3303647",
"Rev": "3303647209557312e5db51450ea8bbdef56d5176"
},
{
"ImportPath": "github.com/shirou/gopsutil/docker",
"Comment": "1.0.0-161-g3303647",
"Rev": "3303647209557312e5db51450ea8bbdef56d5176"
},
{
"ImportPath": "github.com/shirou/gopsutil/load",
"Comment": "1.0.0-161-g3303647",
"Rev": "3303647209557312e5db51450ea8bbdef56d5176"
},
{
"ImportPath": "github.com/shirou/gopsutil/mem",
"Comment": "1.0.0-161-g3303647",
"Rev": "3303647209557312e5db51450ea8bbdef56d5176"
},
{
"ImportPath": "github.com/shirou/gopsutil/net",
"Comment": "1.0.0-161-g3303647",
"Rev": "3303647209557312e5db51450ea8bbdef56d5176"
},
{
"ImportPath": "github.com/shirou/gopsutil/process",
"Comment": "1.0.0-161-g3303647",
"Rev": "3303647209557312e5db51450ea8bbdef56d5176"
"ImportPath": "github.com/shirou/gopsutil",
"Comment": "1.0.0-173-g1e9aabb",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
},
{
"ImportPath": "github.com/streadway/amqp",

View File

@ -0,0 +1,4 @@
*~
#*
_obj
*.tmp

View File

@ -0,0 +1,27 @@
gopsutil is distributed under BSD license reproduced below.
Copyright (c) 2014, WAKAYAMA Shirou
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the gopsutil authors nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,270 @@
gopsutil: psutil for golang
==============================
.. image:: https://drone.io/github.com/shirou/gopsutil/status.png
:target: https://drone.io/github.com/shirou/gopsutil
.. image:: https://coveralls.io/repos/shirou/gopsutil/badge.png?branch=master
:target: https://coveralls.io/r/shirou/gopsutil?branch=master
This is a port of psutil (http://pythonhosted.org/psutil/). The challenge is porting all
psutil functions on some architectures...
.. highlights:: Package Structure Changed!
Package (a.k.a. directory) structure has been changed!! see `issue 24 <https://github.com/shirou/gopsutil/issues/24>`_
.. highlights:: golang 1.4 will become REQUIRED!
Since syscall package becomes frozen, we should use golang/x/sys of golang 1.4 as soon as possible.
Available Architectures
------------------------------------
- FreeBSD i386/amd64
- Linux i386/amd64/arm(raspberry pi)
- Windows/amd64
- Darwin/amd64
All works are implemented without cgo by porting c struct to golang struct.
Usage
---------
.. code:: go
import (
"fmt"
"github.com/shirou/gopsutil/mem"
)
func main() {
v, _ := mem.VirtualMemory()
// almost every return value is a struct
fmt.Printf("Total: %v, Free:%v, UsedPercent:%f%%\n", v.Total, v.Free, v.UsedPercent)
// convert to JSON. String() is also implemented
fmt.Println(v)
}
The output is below.
::
Total: 3179569152, Free:284233728, UsedPercent:84.508194%
{"total":3179569152,"available":492572672,"used":2895335424,"usedPercent":84.50819439828305, (snip)}
You can set an alternative location to /proc by setting the HOST_PROC environment variable.
Documentation
------------------------
see http://godoc.org/github.com/shirou/gopsutil
More Info
--------------------
Several methods have been added which are not present in psutil, but will provide useful information.
- host/HostInfo() (linux)
- Hostname
- Uptime
- Procs
- OS (ex: "linux")
- Platform (ex: "ubuntu", "arch")
- PlatformFamily (ex: "debian")
- PlatformVersion (ex: "Ubuntu 13.10")
- VirtualizationSystem (ex: "LXC")
- VirtualizationRole (ex: "guest"/"host")
- cpu/CPUInfo() (linux, freebsd)
- CPU (ex: 0, 1, ...)
- VendorID (ex: "GenuineIntel")
- Family
- Model
- Stepping
- PhysicalID
- CoreID
- Cores (ex: 2)
- ModelName (ex: "Intel(R) Core(TM) i7-2640M CPU @ 2.80GHz")
- Mhz
- CacheSize
- Flags (ex: "fpu vme de pse tsc msr pae mce cx8 ...")
- load/LoadAvg() (linux, freebsd)
- Load1
- Load5
- Load15
- docker/GetDockerIDList() (linux only)
- container id list ([]string)
- docker/CgroupCPU() (linux only)
- user
- system
- docker/CgroupMem() (linux only)
- various status
Some codes are ported from Ohai. many thanks.
Current Status
------------------
- x: work
- b: almost work but something broken
================= ====== ======= ====== =======
name Linux FreeBSD MacOSX Windows
cpu_times x x x x
cpu_count x x x x
cpu_percent x x x x
cpu_times_percent x x x x
virtual_memory x x x x
swap_memory x x x
disk_partitions x x x x
disk_io_counters x x
disk_usage x x x x
net_io_counters x x b x
boot_time x x x x
users x x x x
pids x x x x
pid_exists x x x x
net_connections x x
net_if_addrs
net_if_stats
================= ====== ======= ====== =======
Process class
^^^^^^^^^^^^^^^
================ ===== ======= ====== =======
name Linux FreeBSD MacOSX Windows
pid x x x x
ppid x x x x
name x x x x
cmdline x x x
create_time x
status x x x
cwd x
exe x x x
uids x x x
gids x x x
terminal x x x
io_counters x
nice x x x
num_fds x
num_ctx_switches x
num_threads x x x x
cpu_times x
memory_info x x x
memory_info_ex x
memory_maps x
open_files x
send_signal x x x
suspend x x x
resume x x x
terminate x x x
kill x x x
username x
ionice
rlimit
num_handlres
threads
cpu_percent x x
cpu_affinity
memory_percent
parent x x
children
connections x x
is_running
================ ===== ======= ====== =======
Original Metrics
^^^^^^^^^^^^^^^^^^^
================== ===== ======= ====== =======
item Linux FreeBSD MacOSX Windows
**HostInfo**
hostname x x x x
uptime x x x
proces x x
os x x x x
platform x x x
platformfamiliy x x x
virtualization x
**CPU**
VendorID x x x x
Family x x x x
Model x x x x
Stepping x x x x
PhysicalID x
CoreID x
Cores x x
ModelName x x x x
**LoadAvg**
Load1 x x x
Load5 x x x
Load15 x x x
**GetDockerID**
container id x no no no
**CgroupsCPU**
user x no no no
system x no no no
**CgroupsMem**
various x no no no
================== ===== ======= ====== =======
- future work
- process_iter
- wait_procs
- Process class
- as_dict
- wait
License
------------
New BSD License (same as psutil)
Related Works
-----------------------
I have been influenced by the following great works:
- psutil: http://pythonhosted.org/psutil/
- dstat: https://github.com/dagwieers/dstat
- gosigar: https://github.com/cloudfoundry/gosigar/
- goprocinfo: https://github.com/c9s/goprocinfo
- go-ps: https://github.com/mitchellh/go-ps
- ohai: https://github.com/opscode/ohai/
- bosun: https://github.com/bosun-monitor/bosun/tree/master/cmd/scollector/collectors
- mackerel: https://github.com/mackerelio/mackerel-agent/tree/master/metrics
How to Contribute
---------------------------
1. Fork it
2. Create your feature branch (git checkout -b my-new-feature)
3. Commit your changes (git commit -am 'Add some feature')
4. Push to the branch (git push origin my-new-feature)
5. Create new Pull Request
My English is terrible, so documentation or correcting comments are also
welcome.

View File

@ -0,0 +1,218 @@
//
// gopsutil is a port of psutil(http://pythonhosted.org/psutil/).
// This covers these architectures.
// - linux (amd64, arm)
// - freebsd (amd64)
// - windows (amd64)
package common
import (
"bufio"
"errors"
"io/ioutil"
"net/url"
"os"
"os/exec"
"path"
"reflect"
"runtime"
"strconv"
"strings"
)
type Invoker interface {
Command(string, ...string) ([]byte, error)
}
type Invoke struct{}
func (i Invoke) Command(name string, arg ...string) ([]byte, error) {
return exec.Command(name, arg...).Output()
}
type FakeInvoke struct {
CommandExpectedDir string // CommandExpectedDir specifies dir which includes expected outputs.
Suffix string // Suffix species expected file name suffix such as "fail"
Error error // If Error specfied, return the error.
}
// Command in FakeInvoke returns from expected file if exists.
func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) {
if i.Error != nil {
return []byte{}, i.Error
}
arch := runtime.GOOS
fname := strings.Join(append([]string{name}, arg...), "")
fname = url.QueryEscape(fname)
var dir string
if i.CommandExpectedDir == "" {
dir = "expected"
} else {
dir = i.CommandExpectedDir
}
fpath := path.Join(dir, arch, fname)
if i.Suffix != "" {
fpath += "_" + i.Suffix
}
if PathExists(fpath) {
return ioutil.ReadFile(fpath)
} else {
return exec.Command(name, arg...).Output()
}
}
var NotImplementedError = errors.New("not implemented yet")
// ReadLines reads contents from a file and splits them by new lines.
// A convenience wrapper to ReadLinesOffsetN(filename, 0, -1).
func ReadLines(filename string) ([]string, error) {
return ReadLinesOffsetN(filename, 0, -1)
}
// ReadLines reads contents from file and splits them by new line.
// The offset tells at which line number to start.
// The count determines the number of lines to read (starting from offset):
// n >= 0: at most n lines
// n < 0: whole file
func ReadLinesOffsetN(filename string, offset uint, n int) ([]string, error) {
f, err := os.Open(filename)
if err != nil {
return []string{""}, err
}
defer f.Close()
var ret []string
r := bufio.NewReader(f)
for i := 0; i < n+int(offset) || n < 0; i++ {
line, err := r.ReadString('\n')
if err != nil {
break
}
if i < int(offset) {
continue
}
ret = append(ret, strings.Trim(line, "\n"))
}
return ret, nil
}
func IntToString(orig []int8) string {
ret := make([]byte, len(orig))
size := -1
for i, o := range orig {
if o == 0 {
size = i
break
}
ret[i] = byte(o)
}
if size == -1 {
size = len(orig)
}
return string(ret[0:size])
}
func ByteToString(orig []byte) string {
n := -1
l := -1
for i, b := range orig {
// skip left side null
if l == -1 && b == 0 {
continue
}
if l == -1 {
l = i
}
if b == 0 {
break
}
n = i + 1
}
if n == -1 {
return string(orig)
}
return string(orig[l:n])
}
// Parse to int32 without error
func mustParseInt32(val string) int32 {
vv, _ := strconv.ParseInt(val, 10, 32)
return int32(vv)
}
// Parse to uint64 without error
func mustParseUint64(val string) uint64 {
vv, _ := strconv.ParseInt(val, 10, 64)
return uint64(vv)
}
// Parse to Float64 without error
func mustParseFloat64(val string) float64 {
vv, _ := strconv.ParseFloat(val, 64)
return vv
}
// StringsHas checks the target string slice containes src or not
func StringsHas(target []string, src string) bool {
for _, t := range target {
if strings.TrimSpace(t) == src {
return true
}
}
return false
}
// StringsContains checks the src in any string of the target string slice
func StringsContains(target []string, src string) bool {
for _, t := range target {
if strings.Contains(t, src) {
return true
}
}
return false
}
// get struct attributes.
// This method is used only for debugging platform dependent code.
func attributes(m interface{}) map[string]reflect.Type {
typ := reflect.TypeOf(m)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
attrs := make(map[string]reflect.Type)
if typ.Kind() != reflect.Struct {
return nil
}
for i := 0; i < typ.NumField(); i++ {
p := typ.Field(i)
if !p.Anonymous {
attrs[p.Name] = p.Type
}
}
return attrs
}
func PathExists(filename string) bool {
if _, err := os.Stat(filename); err == nil {
return true
}
return false
}
//GetEnv retreives the environment variable key. If it does not exist it returns the default.
func GetEnv(key string, dfault string) string {
value := os.Getenv(key)
if value == "" {
value = dfault
}
return value
}

View File

@ -0,0 +1,60 @@
// +build darwin
package common
import (
"os/exec"
"strings"
"syscall"
"unsafe"
)
func DoSysctrl(mib string) ([]string, error) {
out, err := exec.Command("/usr/sbin/sysctl", "-n", mib).Output()
if err != nil {
return []string{}, err
}
v := strings.Replace(string(out), "{ ", "", 1)
v = strings.Replace(string(v), " }", "", 1)
values := strings.Fields(string(v))
return values, nil
}
func CallSyscall(mib []int32) ([]byte, uint64, error) {
miblen := uint64(len(mib))
// get required buffer size
length := uint64(0)
_, _, err := syscall.Syscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
0,
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
var b []byte
return b, length, err
}
if length == 0 {
var b []byte
return b, length, err
}
// get proc info itself
buf := make([]byte, length)
_, _, err = syscall.Syscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
return buf, length, err
}
return buf, length, nil
}

View File

@ -0,0 +1,61 @@
// +build freebsd
package common
import (
"syscall"
"os/exec"
"strings"
"unsafe"
)
func DoSysctrl(mib string) ([]string, error) {
out, err := exec.Command("/sbin/sysctl", "-n", mib).Output()
if err != nil {
return []string{}, err
}
v := strings.Replace(string(out), "{ ", "", 1)
v = strings.Replace(string(v), " }", "", 1)
values := strings.Fields(string(v))
return values, nil
}
func CallSyscall(mib []int32) ([]byte, uint64, error) {
miblen := uint64(len(mib))
// get required buffer size
length := uint64(0)
_, _, err := syscall.Syscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
0,
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
var b []byte
return b, length, err
}
if length == 0 {
var b []byte
return b, length, err
}
// get proc info itself
buf := make([]byte, length)
_, _, err = syscall.Syscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
return buf, length, err
}
return buf, length, nil
}

View File

@ -0,0 +1,3 @@
// +build linux
package common

View File

@ -0,0 +1,90 @@
package common
import (
"fmt"
"strings"
"testing"
)
func TestReadlines(t *testing.T) {
ret, err := ReadLines("common_test.go")
if err != nil {
t.Error(err)
}
if !strings.Contains(ret[0], "package common") {
t.Error("could not read correctly")
}
}
func TestReadLinesOffsetN(t *testing.T) {
ret, err := ReadLinesOffsetN("common_test.go", 2, 1)
if err != nil {
t.Error(err)
}
fmt.Println(ret[0])
if !strings.Contains(ret[0], `import (`) {
t.Error("could not read correctly")
}
}
func TestIntToString(t *testing.T) {
src := []int8{65, 66, 67}
dst := IntToString(src)
if dst != "ABC" {
t.Error("could not convert")
}
}
func TestByteToString(t *testing.T) {
src := []byte{65, 66, 67}
dst := ByteToString(src)
if dst != "ABC" {
t.Error("could not convert")
}
src = []byte{0, 65, 66, 67}
dst = ByteToString(src)
if dst != "ABC" {
t.Error("could not convert")
}
}
func TestmustParseInt32(t *testing.T) {
ret := mustParseInt32("11111")
if ret != int32(11111) {
t.Error("could not parse")
}
}
func TestmustParseUint64(t *testing.T) {
ret := mustParseUint64("11111")
if ret != uint64(11111) {
t.Error("could not parse")
}
}
func TestmustParseFloat64(t *testing.T) {
ret := mustParseFloat64("11111.11")
if ret != float64(11111.11) {
t.Error("could not parse")
}
ret = mustParseFloat64("11111")
if ret != float64(11111) {
t.Error("could not parse")
}
}
func TestStringsContains(t *testing.T) {
target, err := ReadLines("common_test.go")
if err != nil {
t.Error(err)
}
if !StringsContains(target, "func TestStringsContains(t *testing.T) {") {
t.Error("cloud not test correctly")
}
}
func TestPathExists(t *testing.T) {
if !PathExists("common_test.go") {
t.Error("exists but return not exists")
}
if PathExists("should_not_exists.go") {
t.Error("not exists but return exists")
}
}

View File

@ -0,0 +1,40 @@
// +build linux freebsd darwin
package common
import (
"os/exec"
"strconv"
"strings"
)
func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) {
var cmd []string
if pid == 0 { // will get from all processes.
cmd = []string{"-a", "-n", "-P"}
} else {
cmd = []string{"-a", "-n", "-P", "-p", strconv.Itoa(int(pid))}
}
cmd = append(cmd, args...)
lsof, err := exec.LookPath("lsof")
if err != nil {
return []string{}, err
}
out, err := invoke.Command(lsof, cmd...)
if err != nil {
// if no pid found, lsof returnes code 1.
if err.Error() == "exit status 1" && len(out) == 0 {
return []string{}, nil
}
}
lines := strings.Split(string(out), "\n")
var ret []string
for _, l := range lines[1:] {
if len(l) == 0 {
continue
}
ret = append(ret, l)
}
return ret, nil
}

View File

@ -0,0 +1,110 @@
// +build windows
package common
import (
"syscall"
"unsafe"
)
// for double values
type PDH_FMT_COUNTERVALUE_DOUBLE struct {
CStatus uint32
DoubleValue float64
}
// for 64 bit integer values
type PDH_FMT_COUNTERVALUE_LARGE struct {
CStatus uint32
LargeValue int64
}
// for long values
type PDH_FMT_COUNTERVALUE_LONG struct {
CStatus uint32
LongValue int32
padding [4]byte
}
// windows system const
const (
ERROR_SUCCESS = 0
ERROR_FILE_NOT_FOUND = 2
DRIVE_REMOVABLE = 2
DRIVE_FIXED = 3
HKEY_LOCAL_MACHINE = 0x80000002
RRF_RT_REG_SZ = 0x00000002
RRF_RT_REG_DWORD = 0x00000010
PDH_FMT_LONG = 0x00000100
PDH_FMT_DOUBLE = 0x00000200
PDH_FMT_LARGE = 0x00000400
PDH_INVALID_DATA = 0xc0000bc6
PDH_INVALID_HANDLE = 0xC0000bbc
PDH_NO_DATA = 0x800007d5
)
var (
Modkernel32 = syscall.NewLazyDLL("kernel32.dll")
ModNt = syscall.NewLazyDLL("ntdll.dll")
ModPdh = syscall.NewLazyDLL("pdh.dll")
ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes")
ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation")
PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery")
PdhAddCounter = ModPdh.NewProc("PdhAddCounterW")
PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
)
type FILETIME struct {
DwLowDateTime uint32
DwHighDateTime uint32
}
// borrowed from net/interface_windows.go
func BytePtrToString(p *uint8) string {
a := (*[10000]uint8)(unsafe.Pointer(p))
i := 0
for a[i] != 0 {
i++
}
return string(a[:i])
}
// CounterInfo
// copied from https://github.com/mackerelio/mackerel-agent/
type CounterInfo struct {
PostName string
CounterName string
Counter syscall.Handle
}
// CreateQuery XXX
// copied from https://github.com/mackerelio/mackerel-agent/
func CreateQuery() (syscall.Handle, error) {
var query syscall.Handle
r, _, err := PdhOpenQuery.Call(0, 0, uintptr(unsafe.Pointer(&query)))
if r != 0 {
return 0, err
}
return query, nil
}
// CreateCounter XXX
func CreateCounter(query syscall.Handle, pname, cname string) (*CounterInfo, error) {
var counter syscall.Handle
r, _, err := PdhAddCounter.Call(
uintptr(query),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(cname))),
0,
uintptr(unsafe.Pointer(&counter)))
if r != 0 {
return nil, err
}
return &CounterInfo{
PostName: pname,
CounterName: cname,
Counter: counter,
}, nil
}

View File

@ -0,0 +1,26 @@
#/bin/sh
# see http://www.songmu.jp/riji/entry/2015-01-15-goveralls-multi-package.html
set -e
# cleanup
cleanup() {
if [ $tmpprof != "" ] && [ -f $tmpprof ]; then
rm -f $tmpprof
fi
exit
}
trap cleanup INT QUIT TERM EXIT
# メインの処理
prof=${1:-".profile.cov"}
echo "mode: count" > $prof
gopath1=$(echo $GOPATH | cut -d: -f1)
for pkg in $(go list ./...); do
tmpprof=$gopath1/src/$pkg/profile.tmp
go test -covermode=count -coverprofile=$tmpprof $pkg
if [ -f $tmpprof ]; then
cat $tmpprof | tail -n +2 >> $prof
rm $tmpprof
fi
done

View File

@ -2,27 +2,10 @@
package cpu
/*
#include <stdlib.h>
#include <sys/sysctl.h>
#include <sys/mount.h>
#include <mach/mach_init.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <libproc.h>
#include <mach/processor_info.h>
#include <mach/vm_map.h>
*/
import "C"
import (
"bytes"
"encoding/binary"
"fmt"
"os/exec"
"strconv"
"strings"
"unsafe"
)
// sys/resource.h
@ -38,89 +21,6 @@ const (
// default value. from time.h
var ClocksPerSec = float64(128)
// these CPU times for darwin is borrowed from influxdb/telegraf.
func perCPUTimes() ([]CPUTimesStat, error) {
var (
count C.mach_msg_type_number_t
cpuload *C.processor_cpu_load_info_data_t
ncpu C.natural_t
)
status := C.host_processor_info(C.host_t(C.mach_host_self()),
C.PROCESSOR_CPU_LOAD_INFO,
&ncpu,
(*C.processor_info_array_t)(unsafe.Pointer(&cpuload)),
&count)
if status != C.KERN_SUCCESS {
return nil, fmt.Errorf("host_processor_info error=%d", status)
}
// jump through some cgo casting hoops and ensure we properly free
// the memory that cpuload points to
target := C.vm_map_t(C.mach_task_self_)
address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload)))
defer C.vm_deallocate(target, address, C.vm_size_t(ncpu))
// the body of struct processor_cpu_load_info
// aka processor_cpu_load_info_data_t
var cpu_ticks [C.CPU_STATE_MAX]uint32
// copy the cpuload array to a []byte buffer
// where we can binary.Read the data
size := int(ncpu) * binary.Size(cpu_ticks)
buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size))
bbuf := bytes.NewBuffer(buf)
var ret []CPUTimesStat
for i := 0; i < int(ncpu); i++ {
err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks)
if err != nil {
return nil, err
}
c := CPUTimesStat{
CPU: fmt.Sprintf("cpu%d", i),
User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec,
System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec,
Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec,
Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec,
}
ret = append(ret, c)
}
return ret, nil
}
func allCPUTimes() ([]CPUTimesStat, error) {
var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT
var cpuload C.host_cpu_load_info_data_t
status := C.host_statistics(C.host_t(C.mach_host_self()),
C.HOST_CPU_LOAD_INFO,
C.host_info_t(unsafe.Pointer(&cpuload)),
&count)
if status != C.KERN_SUCCESS {
return nil, fmt.Errorf("host_statistics error=%d", status)
}
c := CPUTimesStat{
CPU: "cpu-total",
User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec,
System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec,
Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec,
Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec,
}
return []CPUTimesStat{c}, nil
}
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
if percpu {
return perCPUTimes()

View File

@ -0,0 +1,107 @@
// +build darwin
// +build cgo
package cpu
/*
#include <stdlib.h>
#include <sys/sysctl.h>
#include <sys/mount.h>
#include <mach/mach_init.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <libproc.h>
#include <mach/processor_info.h>
#include <mach/vm_map.h>
*/
import "C"
import (
"bytes"
"encoding/binary"
"fmt"
"unsafe"
)
// these CPU times for darwin is borrowed from influxdb/telegraf.
func perCPUTimes() ([]CPUTimesStat, error) {
var (
count C.mach_msg_type_number_t
cpuload *C.processor_cpu_load_info_data_t
ncpu C.natural_t
)
status := C.host_processor_info(C.host_t(C.mach_host_self()),
C.PROCESSOR_CPU_LOAD_INFO,
&ncpu,
(*C.processor_info_array_t)(unsafe.Pointer(&cpuload)),
&count)
if status != C.KERN_SUCCESS {
return nil, fmt.Errorf("host_processor_info error=%d", status)
}
// jump through some cgo casting hoops and ensure we properly free
// the memory that cpuload points to
target := C.vm_map_t(C.mach_task_self_)
address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload)))
defer C.vm_deallocate(target, address, C.vm_size_t(ncpu))
// the body of struct processor_cpu_load_info
// aka processor_cpu_load_info_data_t
var cpu_ticks [C.CPU_STATE_MAX]uint32
// copy the cpuload array to a []byte buffer
// where we can binary.Read the data
size := int(ncpu) * binary.Size(cpu_ticks)
buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size))
bbuf := bytes.NewBuffer(buf)
var ret []CPUTimesStat
for i := 0; i < int(ncpu); i++ {
err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks)
if err != nil {
return nil, err
}
c := CPUTimesStat{
CPU: fmt.Sprintf("cpu%d", i),
User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec,
System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec,
Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec,
Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec,
}
ret = append(ret, c)
}
return ret, nil
}
func allCPUTimes() ([]CPUTimesStat, error) {
var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT
var cpuload C.host_cpu_load_info_data_t
status := C.host_statistics(C.host_t(C.mach_host_self()),
C.HOST_CPU_LOAD_INFO,
C.host_info_t(unsafe.Pointer(&cpuload)),
&count)
if status != C.KERN_SUCCESS {
return nil, fmt.Errorf("host_statistics error=%d", status)
}
c := CPUTimesStat{
CPU: "cpu-total",
User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec,
System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec,
Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec,
Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec,
}
return []CPUTimesStat{c}, nil
}

View File

@ -0,0 +1,14 @@
// +build darwin
// +build !cgo
package cpu
import "github.com/shirou/gopsutil/common"
func perCPUTimes() ([]CPUTimesStat, error) {
return []CPUTimesStat{}, common.NotImplementedError
}
func allCPUTimes() ([]CPUTimesStat, error) {
return []CPUTimesStat{}, common.NotImplementedError
}

View File

@ -25,7 +25,7 @@ func init() {
}
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
filename := "/proc/stat"
filename := common.GetEnv("HOST_PROC", "/proc") + "/stat"
var lines = []string{}
if percpu {
var startIdx uint = 1
@ -56,7 +56,7 @@ func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
}
func CPUInfo() ([]CPUInfoStat, error) {
filename := "/proc/cpuinfo"
filename := common.GetEnv("HOST_PROC", "/proc") + "cpuinfo"
lines, _ := common.ReadLines(filename)
var ret []CPUInfoStat

View File

@ -238,7 +238,7 @@ func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
}
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
filename := "/proc/diskstats"
filename := common.GetEnv("HOST_PROC", "/proc") + "/diskstats"
lines, err := common.ReadLines(filename)
if err != nil {
return nil, err

View File

@ -0,0 +1 @@
package gopsutil

View File

@ -0,0 +1,37 @@
package host
import (
"encoding/json"
)
// A HostInfoStat describes the host status.
// This is not in the psutil but it useful.
type HostInfoStat struct {
Hostname string `json:"hostname"`
Uptime uint64 `json:"uptime"`
Procs uint64 `json:"procs"` // number of processes
OS string `json:"os"` // ex: freebsd, linux
Platform string `json:"platform"` // ex: ubuntu, linuxmint
PlatformFamily string `json:"platform_family"` // ex: debian, rhel
PlatformVersion string `json:"platform_version"`
VirtualizationSystem string `json:"virtualization_system"`
VirtualizationRole string `json:"virtualization_role"` // guest or host
}
type UserStat struct {
User string `json:"user"`
Terminal string `json:"terminal"`
Host string `json:"host"`
Started int `json:"started"`
}
func (h HostInfoStat) String() string {
s, _ := json.Marshal(h)
return string(s)
}
func (u UserStat) String() string {
s, _ := json.Marshal(u)
return string(s)
}

View File

@ -0,0 +1,137 @@
// +build darwin
package host
import (
"bytes"
"encoding/binary"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"unsafe"
common "github.com/shirou/gopsutil/common"
)
func HostInfo() (*HostInfoStat, error) {
ret := &HostInfoStat{
OS: runtime.GOOS,
PlatformFamily: "darwin",
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
platform, family, version, err := GetPlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
}
system, role, err := GetVirtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
values, err := common.DoSysctrl("kern.boottime")
if err == nil {
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
v := strings.Replace(values[2], ",", "", 1)
t, err := strconv.ParseUint(v, 10, 64)
if err != nil {
ret.Uptime = t
}
}
return ret, nil
}
func BootTime() (uint64, error) {
values, err := common.DoSysctrl("kern.boottime")
if err != nil {
return 0, err
}
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
v := strings.Replace(values[2], ",", "", 1)
boottime, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return 0, err
}
return uint64(boottime), nil
}
func Users() ([]UserStat, error) {
utmpfile := "/var/run/utmpx"
var ret []UserStat
file, err := os.Open(utmpfile)
if err != nil {
return ret, err
}
buf, err := ioutil.ReadAll(file)
if err != nil {
return ret, err
}
u := Utmpx{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u Utmpx
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil {
continue
}
if u.Type != 7 { // skip if not USERPROCESS
continue
}
user := UserStat{
User: common.IntToString(u.User[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(u.Tv.Sec),
}
ret = append(ret, user)
}
return ret, nil
}
func GetPlatformInformation() (string, string, string, error) {
platform := ""
family := ""
version := ""
out, err := exec.Command("uname", "-s").Output()
if err == nil {
platform = strings.ToLower(strings.TrimSpace(string(out)))
}
out, err = exec.Command("uname", "-r").Output()
if err == nil {
version = strings.ToLower(strings.TrimSpace(string(out)))
}
return platform, family, version, nil
}
func GetVirtualization() (string, string, error) {
system := ""
role := ""
return system, role, nil
}

View File

@ -0,0 +1,19 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_darwin.go
package host
type Utmpx struct {
User [256]int8
Id [4]int8
Line [32]int8
Pid int32
Type int16
Pad_cgo_0 [6]byte
Tv Timeval
Host [256]int8
Pad [16]uint32
}
type Timeval struct {
Sec int32
}

View File

@ -0,0 +1,183 @@
// +build freebsd
package host
import (
"bytes"
"encoding/binary"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"unsafe"
common "github.com/shirou/gopsutil/common"
)
const (
UTNameSize = 16 /* see MAXLOGNAME in <sys/param.h> */
UTLineSize = 8
UTHostSize = 16
)
func HostInfo() (*HostInfoStat, error) {
ret := &HostInfoStat{
OS: runtime.GOOS,
PlatformFamily: "freebsd",
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
platform, family, version, err := GetPlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
}
system, role, err := GetVirtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
values, err := common.DoSysctrl("kern.boottime")
if err == nil {
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
v := strings.Replace(values[2], ",", "", 1)
t, err := strconv.ParseUint(v, 10, 64)
if err == nil {
ret.Uptime = t
}
}
return ret, nil
}
func BootTime() (int64, error) {
values, err := common.DoSysctrl("kern.boottime")
if err != nil {
return 0, err
}
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
v := strings.Replace(values[2], ",", "", 1)
boottime, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return 0, err
}
return boottime, nil
}
func Users() ([]UserStat, error) {
utmpfile := "/var/run/utx.active"
if !common.PathExists(utmpfile) {
utmpfile = "/var/run/utmp" // before 9.0
return getUsersFromUtmp(utmpfile)
}
var ret []UserStat
file, err := os.Open(utmpfile)
if err != nil {
return ret, err
}
buf, err := ioutil.ReadAll(file)
if err != nil {
return ret, err
}
u := Utmpx{}
entrySize := int(unsafe.Sizeof(u)) - 3
entrySize = 197 // TODO: why should 197
count := len(buf) / entrySize
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u Utmpx
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil || u.Type != 4 {
continue
}
sec := (binary.LittleEndian.Uint32(u.Tv.Sec[:])) / 2 // TODO:
user := UserStat{
User: common.IntToString(u.User[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(sec),
}
ret = append(ret, user)
}
return ret, nil
}
func GetPlatformInformation() (string, string, string, error) {
platform := ""
family := ""
version := ""
out, err := exec.Command("uname", "-s").Output()
if err == nil {
platform = strings.ToLower(strings.TrimSpace(string(out)))
}
out, err = exec.Command("uname", "-r").Output()
if err == nil {
version = strings.ToLower(strings.TrimSpace(string(out)))
}
return platform, family, version, nil
}
func GetVirtualization() (string, string, error) {
system := ""
role := ""
return system, role, nil
}
// before 9.0
func getUsersFromUtmp(utmpfile string) ([]UserStat, error) {
var ret []UserStat
file, err := os.Open(utmpfile)
if err != nil {
return ret, err
}
buf, err := ioutil.ReadAll(file)
if err != nil {
return ret, err
}
u := Utmp{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u Utmp
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil || u.Time == 0 {
continue
}
user := UserStat{
User: common.IntToString(u.Name[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(u.Time),
}
ret = append(ret, user)
}
return ret, nil
}

View File

@ -0,0 +1,41 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_freebsd.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type Utmp struct {
Line [8]int8
Name [16]int8
Host [16]int8
Time int32
}
type Utmpx struct {
Type int16
Tv Timeval
Id [8]int8
Pid int32
User [32]int8
Line [16]int8
Host [125]int8
// Host [128]int8
// X__ut_spare [64]int8
}
type Timeval struct {
Sec [4]byte
Usec [3]byte
}

View File

@ -0,0 +1,406 @@
// +build linux
package host
import (
"bytes"
"encoding/binary"
"fmt"
"io/ioutil"
"os"
"os/exec"
"regexp"
"runtime"
"strconv"
"strings"
"unsafe"
common "github.com/shirou/gopsutil/common"
)
type LSB struct {
ID string
Release string
Codename string
Description string
}
func HostInfo() (*HostInfoStat, error) {
ret := &HostInfoStat{
OS: runtime.GOOS,
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
platform, family, version, err := GetPlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
}
system, role, err := GetVirtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
uptime, err := BootTime()
if err == nil {
ret.Uptime = uptime
}
return ret, nil
}
// BootTime returns the system boot time expressed in seconds since the epoch.
func BootTime() (uint64, error) {
filename := common.GetEnv("HOST_PROC", "/proc") + "/stat"
lines, err := common.ReadLines(filename)
if err != nil {
return 0, err
}
for _, line := range lines {
if strings.HasPrefix(line, "btime") {
f := strings.Fields(line)
if len(f) != 2 {
return 0, fmt.Errorf("wrong btime format")
}
b, err := strconv.ParseInt(f[1], 10, 64)
if err != nil {
return 0, err
}
return uint64(b), nil
}
}
return 0, fmt.Errorf("could not find btime")
}
func Users() ([]UserStat, error) {
utmpfile := "/var/run/utmp"
file, err := os.Open(utmpfile)
if err != nil {
return nil, err
}
buf, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
u := utmp{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
ret := make([]UserStat, 0, count)
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u utmp
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil {
continue
}
user := UserStat{
User: common.IntToString(u.User[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(u.Tv.TvSec),
}
ret = append(ret, user)
}
return ret, nil
}
func getLSB() (*LSB, error) {
ret := &LSB{}
if common.PathExists("/etc/lsb-release") {
contents, err := common.ReadLines("/etc/lsb-release")
if err != nil {
return ret, err // return empty
}
for _, line := range contents {
field := strings.Split(line, "=")
if len(field) < 2 {
continue
}
switch field[0] {
case "DISTRIB_ID":
ret.ID = field[1]
case "DISTRIB_RELEASE":
ret.Release = field[1]
case "DISTRIB_CODENAME":
ret.Codename = field[1]
case "DISTRIB_DESCRIPTION":
ret.Description = field[1]
}
}
} else if common.PathExists("/usr/bin/lsb_release") {
out, err := exec.Command("/usr/bin/lsb_release").Output()
if err != nil {
return ret, err
}
for _, line := range strings.Split(string(out), "\n") {
field := strings.Split(line, ":")
if len(field) < 2 {
continue
}
switch field[0] {
case "Distributor ID":
ret.ID = field[1]
case "Release":
ret.Release = field[1]
case "Codename":
ret.Codename = field[1]
case "Description":
ret.Description = field[1]
}
}
}
return ret, nil
}
func GetPlatformInformation() (platform string, family string, version string, err error) {
lsb, err := getLSB()
if err != nil {
lsb = &LSB{}
}
if common.PathExists("/etc/oracle-release") {
platform = "oracle"
contents, err := common.ReadLines("/etc/oracle-release")
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExists("/etc/enterprise-release") {
platform = "oracle"
contents, err := common.ReadLines("/etc/enterprise-release")
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExists("/etc/debian_version") {
if lsb.ID == "Ubuntu" {
platform = "ubuntu"
version = lsb.Release
} else if lsb.ID == "LinuxMint" {
platform = "linuxmint"
version = lsb.Release
} else {
if common.PathExists("/usr/bin/raspi-config") {
platform = "raspbian"
} else {
platform = "debian"
}
contents, err := common.ReadLines("/etc/debian_version")
if err == nil {
version = contents[0]
}
}
} else if common.PathExists("/etc/redhat-release") {
contents, err := common.ReadLines("/etc/redhat-release")
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists("/etc/system-release") {
contents, err := common.ReadLines("/etc/system-release")
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists("/etc/gentoo-release") {
platform = "gentoo"
contents, err := common.ReadLines("/etc/gentoo-release")
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExists("/etc/SuSE-release") {
contents, err := common.ReadLines("/etc/SuSE-release")
if err == nil {
version = getSuseVersion(contents)
platform = getSusePlatform(contents)
}
// TODO: slackware detecion
} else if common.PathExists("/etc/arch-release") {
platform = "arch"
// TODO: exherbo detection
} else if lsb.ID == "RedHat" {
platform = "redhat"
version = lsb.Release
} else if lsb.ID == "Amazon" {
platform = "amazon"
version = lsb.Release
} else if lsb.ID == "ScientificSL" {
platform = "scientific"
version = lsb.Release
} else if lsb.ID == "XenServer" {
platform = "xenserver"
version = lsb.Release
} else if lsb.ID != "" {
platform = strings.ToLower(lsb.ID)
version = lsb.Release
}
switch platform {
case "debian", "ubuntu", "linuxmint", "raspbian":
family = "debian"
case "fedora":
family = "fedora"
case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm":
family = "rhel"
case "suse", "opensuse":
family = "suse"
case "gentoo":
family = "gentoo"
case "slackware":
family = "slackware"
case "arch":
family = "arch"
case "exherbo":
family = "exherbo"
}
return platform, family, version, nil
}
func getRedhatishVersion(contents []string) string {
c := strings.ToLower(strings.Join(contents, ""))
if strings.Contains(c, "rawhide") {
return "rawhide"
}
if matches := regexp.MustCompile(`release (\d[\d.]*)`).FindStringSubmatch(c); matches != nil {
return matches[1]
}
return ""
}
func getRedhatishPlatform(contents []string) string {
c := strings.ToLower(strings.Join(contents, ""))
if strings.Contains(c, "red hat") {
return "redhat"
}
f := strings.Split(c, " ")
return f[0]
}
func getSuseVersion(contents []string) string {
version := ""
for _, line := range contents {
if matches := regexp.MustCompile(`VERSION = ([\d.]+)`).FindStringSubmatch(line); matches != nil {
version = matches[1]
} else if matches := regexp.MustCompile(`PATCHLEVEL = ([\d]+)`).FindStringSubmatch(line); matches != nil {
version = version + "." + matches[1]
}
}
return version
}
func getSusePlatform(contents []string) string {
c := strings.ToLower(strings.Join(contents, ""))
if strings.Contains(c, "opensuse") {
return "opensuse"
}
return "suse"
}
func GetVirtualization() (string, string, error) {
var system string
var role string
filename := common.GetEnv("HOST_PROC", "/proc") + "/xen"
if common.PathExists(filename) {
system = "xen"
role = "guest" // assume guest
if common.PathExists(filename + "/capabilities") {
contents, err := common.ReadLines(filename + "/capabilities")
if err == nil {
if common.StringsHas(contents, "control_d") {
role = "host"
}
}
}
}
filename = common.GetEnv("HOST_PROC", "/proc") + "/modules"
if common.PathExists(filename) {
contents, err := common.ReadLines(filename)
if err == nil {
if common.StringsContains(contents, "kvm") {
system = "kvm"
role = "host"
} else if common.StringsContains(contents, "vboxdrv") {
system = "vbox"
role = "host"
} else if common.StringsContains(contents, "vboxguest") {
system = "vbox"
role = "guest"
}
}
}
filename = common.GetEnv("HOST_PROC", "/proc") + "/cpuinfo"
if common.PathExists(filename) {
contents, err := common.ReadLines(filename)
if err == nil {
if common.StringsHas(contents, "QEMU Virtual CPU") ||
common.StringsHas(contents, "Common KVM processor") ||
common.StringsHas(contents, "Common 32-bit KVM processor") {
system = "kvm"
role = "guest"
}
}
}
filename = common.GetEnv("HOST_PROC", "/proc")
if common.PathExists(filename + "/bc/0") {
system = "openvz"
role = "host"
} else if common.PathExists(filename + "/vz") {
system = "openvz"
role = "guest"
}
// not use dmidecode because it requires root
if common.PathExists(filename + "/self/status") {
contents, err := common.ReadLines(filename + "/self/status")
if err == nil {
if common.StringsHas(contents, "s_context:") ||
common.StringsHas(contents, "VxID:") {
system = "linux-vserver"
}
// TODO: guest or host
}
}
if common.PathExists(filename + "/self/cgroup") {
contents, err := common.ReadLines(filename + "/self/cgroup")
if err == nil {
if common.StringsHas(contents, "lxc") ||
common.StringsHas(contents, "docker") {
system = "lxc"
role = "guest"
} else if common.PathExists("/usr/bin/lxc-version") { // TODO: which
system = "lxc"
role = "host"
}
}
}
return system, role, nil
}

View File

@ -0,0 +1,44 @@
// ATTENTION - FILE MANUAL FIXED AFTER CGO.
// Fixed line: Tv _Ctype_struct_timeval -> Tv UtTv
// Created by cgo -godefs, MANUAL FIXED
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv UtTv
Addr_v6 [4]int32
X__unused [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type UtTv struct {
TvSec int32
TvUsec int32
}

View File

@ -0,0 +1,42 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_linux.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv UtTv
Addr_v6 [4]int32
X__glibc_reserved [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type UtTv struct {
TvSec int32
TvUsec int32
}

View File

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

View File

@ -0,0 +1,61 @@
// +build linux
package host
import (
"testing"
)
func TestGetRedhatishVersion(t *testing.T) {
var ret string
c := []string{"Rawhide"}
ret = getRedhatishVersion(c)
if ret != "rawhide" {
t.Errorf("Could not get version rawhide: %v", ret)
}
c = []string{"Fedora release 15 (Lovelock)"}
ret = getRedhatishVersion(c)
if ret != "15" {
t.Errorf("Could not get version fedora: %v", ret)
}
c = []string{"Enterprise Linux Server release 5.5 (Carthage)"}
ret = getRedhatishVersion(c)
if ret != "5.5" {
t.Errorf("Could not get version redhat enterprise: %v", ret)
}
c = []string{""}
ret = getRedhatishVersion(c)
if ret != "" {
t.Errorf("Could not get version with no value: %v", ret)
}
}
func TestGetRedhatishPlatform(t *testing.T) {
var ret string
c := []string{"red hat"}
ret = getRedhatishPlatform(c)
if ret != "redhat" {
t.Errorf("Could not get platform redhat: %v", ret)
}
c = []string{"Fedora release 15 (Lovelock)"}
ret = getRedhatishPlatform(c)
if ret != "fedora" {
t.Errorf("Could not get platform fedora: %v", ret)
}
c = []string{"Enterprise Linux Server release 5.5 (Carthage)"}
ret = getRedhatishPlatform(c)
if ret != "enterprise" {
t.Errorf("Could not get platform redhat enterprise: %v", ret)
}
c = []string{""}
ret = getRedhatishPlatform(c)
if ret != "" {
t.Errorf("Could not get platform with no value: %v", ret)
}
}

View File

@ -0,0 +1,67 @@
package host
import (
"fmt"
"testing"
)
func TestHostInfo(t *testing.T) {
v, err := HostInfo()
if err != nil {
t.Errorf("error %v", err)
}
empty := &HostInfoStat{}
if v == empty {
t.Errorf("Could not get hostinfo %v", v)
}
}
func TestBoot_time(t *testing.T) {
v, err := BootTime()
if err != nil {
t.Errorf("error %v", err)
}
if v == 0 {
t.Errorf("Could not get boot time %v", v)
}
}
func TestUsers(t *testing.T) {
v, err := Users()
if err != nil {
t.Errorf("error %v", err)
}
empty := UserStat{}
for _, u := range v {
if u == empty {
t.Errorf("Could not Users %v", v)
}
}
}
func TestHostInfoStat_String(t *testing.T) {
v := HostInfoStat{
Hostname: "test",
Uptime: 3000,
Procs: 100,
OS: "linux",
Platform: "ubuntu",
}
e := `{"hostname":"test","uptime":3000,"procs":100,"os":"linux","platform":"ubuntu","platform_family":"","platform_version":"","virtualization_system":"","virtualization_role":""}`
if e != fmt.Sprintf("%v", v) {
t.Errorf("HostInfoStat string is invalid: %v", v)
}
}
func TestUserStat_String(t *testing.T) {
v := UserStat{
User: "user",
Terminal: "term",
Host: "host",
Started: 100,
}
e := `{"user":"user","terminal":"term","host":"host","started":100}`
if e != fmt.Sprintf("%v", v) {
t.Errorf("UserStat string is invalid: %v", v)
}
}

View File

@ -0,0 +1,122 @@
// +build windows
package host
import (
"fmt"
"os"
"runtime"
"strings"
"time"
"github.com/StackExchange/wmi"
common "github.com/shirou/gopsutil/common"
process "github.com/shirou/gopsutil/common/process"
)
var (
procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime")
osInfo *Win32_OperatingSystem
)
type Win32_OperatingSystem struct {
Version string
Caption string
ProductType uint32
BuildNumber string
LastBootUpTime time.Time
}
func HostInfo() (*HostInfoStat, error) {
ret := &HostInfoStat{
OS: runtime.GOOS,
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
platform, family, version, err := GetPlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
} else {
return ret, err
}
ret.Uptime, err = BootTime()
if err != nil {
return ret, err
}
procs, err := process.Pids()
if err != nil {
return ret, err
}
ret.Procs = uint64(len(procs))
return ret, nil
}
func GetOSInfo() (Win32_OperatingSystem, error) {
var dst []Win32_OperatingSystem
q := wmi.CreateQuery(&dst, "")
err := wmi.Query(q, &dst)
if err != nil {
return Win32_OperatingSystem{}, err
}
osInfo = &dst[0]
return dst[0], nil
}
func BootTime() (uint64, error) {
if osInfo == nil {
_, err := GetOSInfo()
if err != nil {
return 0, err
}
}
now := time.Now()
t := osInfo.LastBootUpTime.Local()
return uint64(now.Sub(t).Seconds()), nil
}
func GetPlatformInformation() (platform string, family string, version string, err error) {
if osInfo == nil {
_, err = GetOSInfo()
if err != nil {
return
}
}
// Platform
platform = strings.Trim(osInfo.Caption, " ")
// PlatformFamily
switch osInfo.ProductType {
case 1:
family = "Standalone Workstation"
case 2:
family = "Server (Domain Controller)"
case 3:
family = "Server"
}
// Platform Version
version = fmt.Sprintf("%s Build %s", osInfo.Version, osInfo.BuildNumber)
return
}
func Users() ([]UserStat, error) {
var ret []UserStat
return ret, nil
}

View File

@ -0,0 +1,17 @@
// +build ignore
// plus hand editing about timeval
/*
Input to cgo -godefs.
*/
package host
/*
#include <sys/time.h>
#include <utmpx.h>
*/
import "C"
type Utmpx C.struct_utmpx
type Timeval C.struct_timeval

View File

@ -0,0 +1,43 @@
// +build ignore
/*
Input to cgo -godefs.
*/
package host
/*
#define KERNEL
#include <sys/types.h>
#include <sys/time.h>
#include <utmpx.h>
enum {
sizeofPtr = sizeof(void*),
};
*/
import "C"
// Machine characteristics; for internal use.
const (
sizeofPtr = C.sizeofPtr
sizeofShort = C.sizeof_short
sizeofInt = C.sizeof_int
sizeofLong = C.sizeof_long
sizeofLongLong = C.sizeof_longlong
)
// Basic types
type (
_C_short C.short
_C_int C.int
_C_long C.long
_C_long_long C.longlong
)
type Utmp C.struct_utmp
type Utmpx C.struct_utmpx
type Timeval C.struct_timeval

View File

@ -0,0 +1,45 @@
// +build ignore
/*
Input to cgo -godefs.
*/
package host
/*
#define KERNEL
#include <sys/types.h>
#include <utmp.h>
enum {
sizeofPtr = sizeof(void*),
};
*/
import "C"
// Machine characteristics; for internal use.
const (
sizeofPtr = C.sizeofPtr
sizeofShort = C.sizeof_short
sizeofInt = C.sizeof_int
sizeofLong = C.sizeof_long
sizeofLongLong = C.sizeof_longlong
)
// Basic types
type (
_C_short C.short
_C_int C.int
_C_long C.long
_C_long_long C.longlong
)
type utmp C.struct_utmp
type exit_status C.struct_exit_status
type UtTv struct {
TvSec int32
TvUsec int32
}

View File

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

View File

@ -61,7 +61,7 @@ func TestParseVmStat(t *testing.T) {
}
if ret.Cached != uint64(128967*4096+449242.*4096) {
t.Errorf("Cached pages, actual: %d, expected: %d", ret.Cached,
t.Errorf("Cached pages, actual: %d, expected: %f", ret.Cached,
128967*4096+449242.*4096)
}
}

View File

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

View File

@ -0,0 +1,37 @@
DIRS="cpu disk docker host load mem net process"
GOOS=`uname | tr '[:upper:]' '[:lower:]'`
ARCH=`uname -m`
case $ARCH in
amd64)
GOARCH="amd64"
;;
x86_64)
GOARCH="amd64"
;;
i386)
GOARCH="386"
;;
i686)
GOARCH="386"
;;
arm)
GOARCH="arm"
;;
*)
echo "unknown arch: $ARCH"
exit 1
esac
for DIR in $DIRS
do
if [ -e ${DIR}/types_${GOOS}.go ]; then
echo "// +build $GOOS" > ${DIR}/${DIR}_${GOOS}_${GOARCH}.go
echo "// +build $GOARCH" >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go
go tool cgo -godefs ${DIR}/types_${GOOS}.go >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go
fi
done

View File

@ -90,63 +90,3 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
return ret, nil
}
// Return a list of network connections opened.
func NetConnections(kind string) ([]NetConnectionStat, error) {
return NetConnectionsPid(kind, 0)
}
// Return a list of network connections opened by a process.
func NetConnectionsPid(kind string, pid int32) ([]NetConnectionStat, error) {
var ret []NetConnectionStat
args := []string{"-i"}
switch strings.ToLower(kind) {
default:
fallthrough
case "":
fallthrough
case "all":
fallthrough
case "inet":
args = append(args, "tcp")
case "inet4":
args = append(args, "4")
case "inet6":
args = append(args, "6")
case "tcp":
args = append(args, "tcp")
case "tcp4":
args = append(args, "4tcp")
case "tcp6":
args = append(args, "6tcp")
case "udp":
args = append(args, "udp")
case "udp4":
args = append(args, "6udp")
case "udp6":
args = append(args, "6udp")
case "unix":
return ret, common.NotImplementedError
}
// we can not use -F filter to get all of required information at once.
r, err := common.CallLsof(invoke, pid, args...)
if err != nil {
return nil, err
}
for _, rr := range r {
if strings.HasPrefix(rr, "COMMAND") {
continue
}
n, err := parseNetLine(rr)
if err != nil {
// fmt.Println(err) // TODO: should debug print?
continue
}
ret = append(ret, n)
}
return ret, nil
}

View File

@ -81,9 +81,3 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
return ret, nil
}
func NetConnections(kind string) ([]NetConnectionStat, error) {
var ret []NetConnectionStat
return ret, common.NotImplementedError
}

View File

@ -15,7 +15,7 @@ import (
// every network interface installed on the system is returned
// separately.
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
filename := "/proc/net/dev"
filename := common.GetEnv("HOST_PROC", "/proc") + "/net/dev"
lines, err := common.ReadLines(filename)
if err != nil {
return nil, err
@ -89,63 +89,3 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
return ret, nil
}
// Return a list of network connections opened.
func NetConnections(kind string) ([]NetConnectionStat, error) {
return NetConnectionsPid(kind, 0)
}
// Return a list of network connections opened by a process.
func NetConnectionsPid(kind string, pid int32) ([]NetConnectionStat, error) {
var ret []NetConnectionStat
args := []string{"-i"}
switch strings.ToLower(kind) {
default:
fallthrough
case "":
fallthrough
case "all":
fallthrough
case "inet":
args = append(args, "tcp")
case "inet4":
args = append(args, "4")
case "inet6":
args = append(args, "6")
case "tcp":
args = append(args, "tcp")
case "tcp4":
args = append(args, "4tcp")
case "tcp6":
args = append(args, "6tcp")
case "udp":
args = append(args, "udp")
case "udp4":
args = append(args, "6udp")
case "udp6":
args = append(args, "6udp")
case "unix":
return ret, common.NotImplementedError
}
// we can not use -F filter to get all of required information at once.
r, err := common.CallLsof(invoke, pid, args...)
if err != nil {
return nil, err
}
for _, rr := range r {
if strings.HasPrefix(rr, "COMMAND") {
continue
}
n, err := parseNetLine(rr)
if err != nil {
// fmt.Println(err) // TODO: should debug print?
continue
}
ret = append(ret, n)
}
return ret, nil
}

View File

@ -0,0 +1,68 @@
// +build linux freebsd darwin
package net
import (
"strings"
"github.com/shirou/gopsutil/common"
)
// Return a list of network connections opened.
func NetConnections(kind string) ([]NetConnectionStat, error) {
return NetConnectionsPid(kind, 0)
}
// Return a list of network connections opened by a process.
func NetConnectionsPid(kind string, pid int32) ([]NetConnectionStat, error) {
var ret []NetConnectionStat
args := []string{"-i"}
switch strings.ToLower(kind) {
default:
fallthrough
case "":
fallthrough
case "all":
fallthrough
case "inet":
args = append(args, "tcp", "-i", "udp")
case "inet4":
args = append(args, "4")
case "inet6":
args = append(args, "6")
case "tcp":
args = append(args, "tcp")
case "tcp4":
args = append(args, "4tcp")
case "tcp6":
args = append(args, "6tcp")
case "udp":
args = append(args, "udp")
case "udp4":
args = append(args, "6udp")
case "udp6":
args = append(args, "6udp")
case "unix":
return ret, common.NotImplementedError
}
r, err := common.CallLsof(invoke, pid, args...)
if err != nil {
return nil, err
}
for _, rr := range r {
if strings.HasPrefix(rr, "COMMAND") {
continue
}
n, err := parseNetLine(rr)
if err != nil {
continue
}
ret = append(ret, n)
}
return ret, nil
}

View File

@ -222,7 +222,7 @@ func (p *Process) IsRunning() (bool, error) {
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
pid := p.Pid
var ret []MemoryMapsStat
smapsPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "smaps")
smapsPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "smaps")
contents, err := ioutil.ReadFile(smapsPath)
if err != nil {
return nil, err
@ -303,7 +303,7 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
// Get num_fds from /proc/(pid)/fd
func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) {
pid := p.Pid
statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "fd")
statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "fd")
d, err := os.Open(statPath)
if err != nil {
return 0, nil, err
@ -336,7 +336,7 @@ func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) {
// Get cwd from /proc/(pid)/cwd
func (p *Process) fillFromCwd() (string, error) {
pid := p.Pid
cwdPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "cwd")
cwdPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "cwd")
cwd, err := os.Readlink(cwdPath)
if err != nil {
return "", err
@ -347,7 +347,7 @@ func (p *Process) fillFromCwd() (string, error) {
// Get exe from /proc/(pid)/exe
func (p *Process) fillFromExe() (string, error) {
pid := p.Pid
exePath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "exe")
exePath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "exe")
exe, err := os.Readlink(exePath)
if err != nil {
return "", err
@ -358,7 +358,7 @@ func (p *Process) fillFromExe() (string, error) {
// Get cmdline from /proc/(pid)/cmdline
func (p *Process) fillFromCmdline() (string, error) {
pid := p.Pid
cmdPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "cmdline")
cmdPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil {
return "", err
@ -376,7 +376,7 @@ func (p *Process) fillFromCmdline() (string, error) {
// Get IO status from /proc/(pid)/io
func (p *Process) fillFromIO() (*IOCountersStat, error) {
pid := p.Pid
ioPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "io")
ioPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "io")
ioline, err := ioutil.ReadFile(ioPath)
if err != nil {
return nil, err
@ -415,7 +415,7 @@ func (p *Process) fillFromIO() (*IOCountersStat, error) {
// Get memory info from /proc/(pid)/statm
func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
pid := p.Pid
memPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "statm")
memPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "statm")
contents, err := ioutil.ReadFile(memPath)
if err != nil {
return nil, nil, err
@ -467,7 +467,7 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
// Get various status from /proc/(pid)/status
func (p *Process) fillFromStatus() error {
pid := p.Pid
statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "status")
statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath)
if err != nil {
return err
@ -554,7 +554,7 @@ func (p *Process) fillFromStatus() error {
func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32, error) {
pid := p.Pid
statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "stat")
statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "stat")
contents, err := ioutil.ReadFile(statPath)
if err != nil {
return "", 0, nil, 0, 0, err
@ -610,7 +610,7 @@ func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32
func Pids() ([]int32, error) {
var ret []int32
d, err := os.Open("/proc")
d, err := os.Open(common.GetEnv("HOST_PROC", "/proc"))
if err != nil {
return nil, err
}

View File

@ -0,0 +1,36 @@
Windows memo
=====================
Size
----------
DWORD
32-bit unsigned integer
DWORDLONG
64-bit unsigned integer
DWORD_PTR
unsigned long type for pointer precision
DWORD32
32-bit unsigned integer
DWORD64
64-bit unsigned integer
HALF_PTR
_WIN64 = int, else short
INT
32-bit signed integer
INT_PTR
_WIN64 = __int64 else int
LONG
32-bit signed integer
LONGLONG
64-bit signed integer
LONG_PTR
_WIN64 = __int64 else long
SHORT
16-bit integer
SIZE_T
maximum number of bytes to which a pointer can point. typedef ULONG_PTR SIZE_T;
SSIZE_T
signed version of SIZE_T. typedef LONG_PTR SSIZE_T;
WORD
16-bit unsigned integer

View File

@ -39,7 +39,7 @@ func MockBatchPoints() client.BatchPoints {
// Create a point and add to batch
tags := map[string]string{"tag1": "value1"}
fields := map[string]interface{}{"value": 1.0}
pt := client.NewPoint("test_point", tags, fields)
pt, _ := client.NewPoint("test_point", tags, fields)
bp.AddPoint(pt)
return bp