Delete 'vendored' gopsutil directory
This commit is contained in:
parent
94a623c00e
commit
dd7a3b37b0
|
@ -14,7 +14,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins"
|
"github.com/influxdb/telegraf/plugins"
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
common "github.com/shirou/gopsutil/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Lustre proc files can change between versions, so we want to future-proof
|
// Lustre proc files can change between versions, so we want to future-proof
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins"
|
"github.com/influxdb/telegraf/plugins"
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
"github.com/shirou/gopsutil/cpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CPUStats struct {
|
type CPUStats struct {
|
||||||
|
|
|
@ -5,9 +5,9 @@ package system
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/docker"
|
|
||||||
"github.com/influxdb/telegraf/testutil"
|
"github.com/influxdb/telegraf/testutil"
|
||||||
|
"github.com/shirou/gopsutil/cpu"
|
||||||
|
"github.com/shirou/gopsutil/docker"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
|
@ -2,12 +2,12 @@ package system
|
||||||
|
|
||||||
import "github.com/stretchr/testify/mock"
|
import "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
import "github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
import "github.com/shirou/gopsutil/cpu"
|
||||||
import "github.com/influxdb/telegraf/plugins/system/ps/disk"
|
import "github.com/shirou/gopsutil/disk"
|
||||||
|
|
||||||
import "github.com/influxdb/telegraf/plugins/system/ps/load"
|
import "github.com/shirou/gopsutil/load"
|
||||||
import "github.com/influxdb/telegraf/plugins/system/ps/mem"
|
import "github.com/shirou/gopsutil/mem"
|
||||||
import "github.com/influxdb/telegraf/plugins/system/ps/net"
|
import "github.com/shirou/gopsutil/net"
|
||||||
|
|
||||||
type MockPS struct {
|
type MockPS struct {
|
||||||
mock.Mock
|
mock.Mock
|
||||||
|
|
|
@ -7,12 +7,12 @@ import (
|
||||||
|
|
||||||
dc "github.com/fsouza/go-dockerclient"
|
dc "github.com/fsouza/go-dockerclient"
|
||||||
"github.com/influxdb/telegraf/plugins"
|
"github.com/influxdb/telegraf/plugins"
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/common"
|
"github.com/shirou/gopsutil/common"
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
"github.com/shirou/gopsutil/cpu"
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/disk"
|
"github.com/shirou/gopsutil/disk"
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/docker"
|
"github.com/shirou/gopsutil/docker"
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/mem"
|
"github.com/shirou/gopsutil/mem"
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/net"
|
"github.com/shirou/gopsutil/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DockerContainerStat struct {
|
type DockerContainerStat struct {
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
*~
|
|
||||||
#*
|
|
||||||
_obj
|
|
|
@ -1,27 +0,0 @@
|
||||||
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 psutil 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.
|
|
|
@ -1,267 +0,0 @@
|
||||||
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)}
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
cpu_count x x x x
|
|
||||||
cpu_percent x x x
|
|
||||||
cpu_times_percent 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
|
|
||||||
================= ====== ======= ====== =======
|
|
||||||
|
|
||||||
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
|
|
||||||
cpu_affinity
|
|
||||||
memory_percent
|
|
||||||
children
|
|
||||||
connections
|
|
||||||
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
|
|
||||||
|
|
||||||
- parent (use ppid instead)
|
|
||||||
- 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
|
|
||||||
- gosiger: 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.
|
|
|
@ -1,151 +0,0 @@
|
||||||
//
|
|
||||||
// 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"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var NotImplementedError = errors.New("not implemented yet")
|
|
||||||
|
|
||||||
// ReadLines reads contents from file and splits them by new line.
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the target string slice containes src or not
|
|
||||||
func StringContains(target []string, src string) bool {
|
|
||||||
for _, t := range target {
|
|
||||||
if strings.TrimSpace(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
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
// +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
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"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
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
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 TestStringContains(t *testing.T) {
|
|
||||||
target, err := ReadLines("common_test.go")
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
if !StringContains(target, "func TestStringContains(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")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,144 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"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])
|
|
||||||
}
|
|
||||||
|
|
||||||
// exec wmic and return lines splited by newline
|
|
||||||
func GetWmic(target string, query ...string) ([][]string, error) {
|
|
||||||
cmd := []string{target}
|
|
||||||
cmd = append(cmd, query...)
|
|
||||||
cmd = append(cmd, "/format:csv")
|
|
||||||
out, err := exec.Command("wmic", cmd...).Output()
|
|
||||||
if err != nil {
|
|
||||||
return [][]string{}, err
|
|
||||||
}
|
|
||||||
lines := strings.Split(string(out), "\r\r\n")
|
|
||||||
if len(lines) <= 2 {
|
|
||||||
return [][]string{}, fmt.Errorf("wmic result malformed: [%q]", lines)
|
|
||||||
}
|
|
||||||
var ret [][]string
|
|
||||||
for _, l := range lines[2:] { // skip first two lines
|
|
||||||
var lr []string
|
|
||||||
for _, r := range strings.Split(l, ",") {
|
|
||||||
if r == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lr = append(lr, strings.TrimSpace(r))
|
|
||||||
}
|
|
||||||
if len(lr) != 0 {
|
|
||||||
ret = append(ret, lr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#/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
|
|
|
@ -1,74 +0,0 @@
|
||||||
package cpu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CPUTimesStat struct {
|
|
||||||
CPU string `json:"cpu"`
|
|
||||||
User float64 `json:"user"`
|
|
||||||
System float64 `json:"system"`
|
|
||||||
Idle float64 `json:"idle"`
|
|
||||||
Nice float64 `json:"nice"`
|
|
||||||
Iowait float64 `json:"iowait"`
|
|
||||||
Irq float64 `json:"irq"`
|
|
||||||
Softirq float64 `json:"softirq"`
|
|
||||||
Steal float64 `json:"steal"`
|
|
||||||
Guest float64 `json:"guest"`
|
|
||||||
GuestNice float64 `json:"guest_nice"`
|
|
||||||
Stolen float64 `json:"stolen"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CPUInfoStat struct {
|
|
||||||
CPU int32 `json:"cpu"`
|
|
||||||
VendorID string `json:"vendor_id"`
|
|
||||||
Family string `json:"family"`
|
|
||||||
Model string `json:"model"`
|
|
||||||
Stepping int32 `json:"stepping"`
|
|
||||||
PhysicalID string `json:"physical_id"`
|
|
||||||
CoreID string `json:"core_id"`
|
|
||||||
Cores int32 `json:"cores"`
|
|
||||||
ModelName string `json:"model_name"`
|
|
||||||
Mhz float64 `json:"mhz"`
|
|
||||||
CacheSize int32 `json:"cache_size"`
|
|
||||||
Flags []string `json:"flags"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastCPUTimes []CPUTimesStat
|
|
||||||
var lastPerCPUTimes []CPUTimesStat
|
|
||||||
|
|
||||||
func CPUCounts(logical bool) (int, error) {
|
|
||||||
return runtime.NumCPU(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CPUTimesStat) String() string {
|
|
||||||
v := []string{
|
|
||||||
`"cpu":"` + c.CPU + `"`,
|
|
||||||
`"user":` + strconv.FormatFloat(c.User, 'f', 1, 64),
|
|
||||||
`"system":` + strconv.FormatFloat(c.System, 'f', 1, 64),
|
|
||||||
`"idle":` + strconv.FormatFloat(c.Idle, 'f', 1, 64),
|
|
||||||
`"nice":` + strconv.FormatFloat(c.Nice, 'f', 1, 64),
|
|
||||||
`"iowait":` + strconv.FormatFloat(c.Iowait, 'f', 1, 64),
|
|
||||||
`"irq":` + strconv.FormatFloat(c.Irq, 'f', 1, 64),
|
|
||||||
`"softirq":` + strconv.FormatFloat(c.Softirq, 'f', 1, 64),
|
|
||||||
`"steal":` + strconv.FormatFloat(c.Steal, 'f', 1, 64),
|
|
||||||
`"guest":` + strconv.FormatFloat(c.Guest, 'f', 1, 64),
|
|
||||||
`"guest_nice":` + strconv.FormatFloat(c.GuestNice, 'f', 1, 64),
|
|
||||||
`"stolen":` + strconv.FormatFloat(c.Stolen, 'f', 1, 64),
|
|
||||||
}
|
|
||||||
|
|
||||||
return `{` + strings.Join(v, ",") + `}`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CPUInfoStat) String() string {
|
|
||||||
s, _ := json.Marshal(c)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
lastCPUTimes, _ = CPUTimes(false)
|
|
||||||
lastPerCPUTimes, _ = CPUTimes(true)
|
|
||||||
}
|
|
|
@ -1,254 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
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"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
// sys/resource.h
|
|
||||||
const (
|
|
||||||
CPUser = 0
|
|
||||||
CPNice = 1
|
|
||||||
CPSys = 2
|
|
||||||
CPIntr = 3
|
|
||||||
CPIdle = 4
|
|
||||||
CPUStates = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
// time.h
|
|
||||||
const (
|
|
||||||
ClocksPerSec = 128
|
|
||||||
)
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
return allCPUTimes()
|
|
||||||
}
|
|
||||||
|
|
||||||
func sysctrlCPUTimes(percpu bool) ([]CPUTimesStat, error) {
|
|
||||||
var ret []CPUTimesStat
|
|
||||||
|
|
||||||
var sysctlCall string
|
|
||||||
var ncpu int
|
|
||||||
if percpu {
|
|
||||||
sysctlCall = "kern.cp_times"
|
|
||||||
ncpu, _ = CPUCounts(true)
|
|
||||||
} else {
|
|
||||||
sysctlCall = "kern.cp_time"
|
|
||||||
ncpu = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuTimes, err := common.DoSysctrl(sysctlCall)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < ncpu; i++ {
|
|
||||||
offset := CPUStates * i
|
|
||||||
user, err := strconv.ParseFloat(cpuTimes[CPUser+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
nice, err := strconv.ParseFloat(cpuTimes[CPNice+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
sys, err := strconv.ParseFloat(cpuTimes[CPSys+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
idle, err := strconv.ParseFloat(cpuTimes[CPIdle+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
intr, err := strconv.ParseFloat(cpuTimes[CPIntr+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
c := CPUTimesStat{
|
|
||||||
User: float64(user / ClocksPerSec),
|
|
||||||
Nice: float64(nice / ClocksPerSec),
|
|
||||||
System: float64(sys / ClocksPerSec),
|
|
||||||
Idle: float64(idle / ClocksPerSec),
|
|
||||||
Irq: float64(intr / ClocksPerSec),
|
|
||||||
}
|
|
||||||
if !percpu {
|
|
||||||
c.CPU = "cpu-total"
|
|
||||||
} else {
|
|
||||||
c.CPU = fmt.Sprintf("cpu%d", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = append(ret, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns only one CPUInfoStat on FreeBSD
|
|
||||||
func CPUInfo() ([]CPUInfoStat, error) {
|
|
||||||
var ret []CPUInfoStat
|
|
||||||
|
|
||||||
out, err := exec.Command("/usr/sbin/sysctl", "machdep.cpu").Output()
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
c := CPUInfoStat{}
|
|
||||||
for _, line := range strings.Split(string(out), "\n") {
|
|
||||||
values := strings.Fields(line)
|
|
||||||
if len(values) < 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
t, err := strconv.ParseInt(values[1], 10, 64)
|
|
||||||
// err is not checked here because some value is string.
|
|
||||||
if strings.HasPrefix(line, "machdep.cpu.brand_string") {
|
|
||||||
c.ModelName = strings.Join(values[1:], " ")
|
|
||||||
} else if strings.HasPrefix(line, "machdep.cpu.family") {
|
|
||||||
c.Family = values[1]
|
|
||||||
} else if strings.HasPrefix(line, "machdep.cpu.model") {
|
|
||||||
c.Model = values[1]
|
|
||||||
} else if strings.HasPrefix(line, "machdep.cpu.stepping") {
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
c.Stepping = int32(t)
|
|
||||||
} else if strings.HasPrefix(line, "machdep.cpu.features") {
|
|
||||||
for _, v := range values[1:] {
|
|
||||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
|
||||||
}
|
|
||||||
} else if strings.HasPrefix(line, "machdep.cpu.leaf7_features") {
|
|
||||||
for _, v := range values[1:] {
|
|
||||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
|
||||||
}
|
|
||||||
} else if strings.HasPrefix(line, "machdep.cpu.extfeatures") {
|
|
||||||
for _, v := range values[1:] {
|
|
||||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
|
||||||
}
|
|
||||||
} else if strings.HasPrefix(line, "machdep.cpu.core_count") {
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
c.Cores = int32(t)
|
|
||||||
} else if strings.HasPrefix(line, "machdep.cpu.cache.size") {
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
c.CacheSize = int32(t)
|
|
||||||
} else if strings.HasPrefix(line, "machdep.cpu.vendor") {
|
|
||||||
c.VendorID = values[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// c.Mhz = mustParseFloat64(values[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(ret, c), nil
|
|
||||||
}
|
|
|
@ -1,134 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package cpu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
// sys/resource.h
|
|
||||||
const (
|
|
||||||
CPUser = 0
|
|
||||||
CPNice = 1
|
|
||||||
CPSys = 2
|
|
||||||
CPIntr = 3
|
|
||||||
CPIdle = 4
|
|
||||||
CPUStates = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
// time.h
|
|
||||||
const (
|
|
||||||
ClocksPerSec = 128
|
|
||||||
)
|
|
||||||
|
|
||||||
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
|
|
||||||
var ret []CPUTimesStat
|
|
||||||
|
|
||||||
var sysctlCall string
|
|
||||||
var ncpu int
|
|
||||||
if percpu {
|
|
||||||
sysctlCall = "kern.cp_times"
|
|
||||||
ncpu, _ = CPUCounts(true)
|
|
||||||
} else {
|
|
||||||
sysctlCall = "kern.cp_time"
|
|
||||||
ncpu = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuTimes, err := common.DoSysctrl(sysctlCall)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < ncpu; i++ {
|
|
||||||
offset := CPUStates * i
|
|
||||||
user, err := strconv.ParseFloat(cpuTimes[CPUser+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
nice, err := strconv.ParseFloat(cpuTimes[CPNice+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
sys, err := strconv.ParseFloat(cpuTimes[CPSys+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
idle, err := strconv.ParseFloat(cpuTimes[CPIdle+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
intr, err := strconv.ParseFloat(cpuTimes[CPIntr+offset], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
c := CPUTimesStat{
|
|
||||||
User: float64(user / ClocksPerSec),
|
|
||||||
Nice: float64(nice / ClocksPerSec),
|
|
||||||
System: float64(sys / ClocksPerSec),
|
|
||||||
Idle: float64(idle / ClocksPerSec),
|
|
||||||
Irq: float64(intr / ClocksPerSec),
|
|
||||||
}
|
|
||||||
if !percpu {
|
|
||||||
c.CPU = "cpu-total"
|
|
||||||
} else {
|
|
||||||
c.CPU = fmt.Sprintf("cpu%d", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = append(ret, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns only one CPUInfoStat on FreeBSD
|
|
||||||
func CPUInfo() ([]CPUInfoStat, error) {
|
|
||||||
filename := "/var/run/dmesg.boot"
|
|
||||||
lines, _ := common.ReadLines(filename)
|
|
||||||
|
|
||||||
var ret []CPUInfoStat
|
|
||||||
|
|
||||||
c := CPUInfoStat{}
|
|
||||||
for _, line := range lines {
|
|
||||||
if matches := regexp.MustCompile(`CPU:\s+(.+) \(([\d.]+).+\)`).FindStringSubmatch(line); matches != nil {
|
|
||||||
c.ModelName = matches[1]
|
|
||||||
t, err := strconv.ParseFloat(matches[2], 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
c.Mhz = t
|
|
||||||
} else if matches := regexp.MustCompile(`Origin = "(.+)" Id = (.+) Family = (.+) Model = (.+) Stepping = (.+)`).FindStringSubmatch(line); matches != nil {
|
|
||||||
c.VendorID = matches[1]
|
|
||||||
c.Family = matches[3]
|
|
||||||
c.Model = matches[4]
|
|
||||||
t, err := strconv.ParseInt(matches[5], 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
c.Stepping = int32(t)
|
|
||||||
} else if matches := regexp.MustCompile(`Features=.+<(.+)>`).FindStringSubmatch(line); matches != nil {
|
|
||||||
for _, v := range strings.Split(matches[1], ",") {
|
|
||||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
|
||||||
}
|
|
||||||
} else if matches := regexp.MustCompile(`Features2=[a-f\dx]+<(.+)>`).FindStringSubmatch(line); matches != nil {
|
|
||||||
for _, v := range strings.Split(matches[1], ",") {
|
|
||||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
|
||||||
}
|
|
||||||
} else if matches := regexp.MustCompile(`Logical CPUs per core: (\d+)`).FindStringSubmatch(line); matches != nil {
|
|
||||||
// FIXME: no this line?
|
|
||||||
t, err := strconv.ParseInt(matches[1], 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
c.Cores = int32(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(ret, c), nil
|
|
||||||
}
|
|
|
@ -1,206 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package cpu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
|
|
||||||
filename := "/proc/stat"
|
|
||||||
var lines = []string{}
|
|
||||||
if percpu {
|
|
||||||
var startIdx uint = 1
|
|
||||||
for {
|
|
||||||
linen, _ := common.ReadLinesOffsetN(filename, startIdx, 1)
|
|
||||||
line := linen[0]
|
|
||||||
if !strings.HasPrefix(line, "cpu") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
lines = append(lines, line)
|
|
||||||
startIdx += 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lines, _ = common.ReadLinesOffsetN(filename, 0, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := make([]CPUTimesStat, 0, len(lines))
|
|
||||||
|
|
||||||
for _, line := range lines {
|
|
||||||
ct, err := parseStatLine(line)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ret = append(ret, *ct)
|
|
||||||
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CPUInfo() ([]CPUInfoStat, error) {
|
|
||||||
filename := "/proc/cpuinfo"
|
|
||||||
lines, _ := common.ReadLines(filename)
|
|
||||||
|
|
||||||
var ret []CPUInfoStat
|
|
||||||
|
|
||||||
var c CPUInfoStat
|
|
||||||
for _, line := range lines {
|
|
||||||
fields := strings.Split(line, ":")
|
|
||||||
if len(fields) < 2 {
|
|
||||||
if c.VendorID != "" {
|
|
||||||
ret = append(ret, c)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
key := strings.TrimSpace(fields[0])
|
|
||||||
value := strings.TrimSpace(fields[1])
|
|
||||||
|
|
||||||
switch key {
|
|
||||||
case "processor":
|
|
||||||
c = CPUInfoStat{}
|
|
||||||
t, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
c.CPU = int32(t)
|
|
||||||
case "vendor_id":
|
|
||||||
c.VendorID = value
|
|
||||||
case "cpu family":
|
|
||||||
c.Family = value
|
|
||||||
case "model":
|
|
||||||
c.Model = value
|
|
||||||
case "model name":
|
|
||||||
c.ModelName = value
|
|
||||||
case "stepping":
|
|
||||||
t, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
c.Stepping = int32(t)
|
|
||||||
case "cpu MHz":
|
|
||||||
t, err := strconv.ParseFloat(value, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
c.Mhz = t
|
|
||||||
case "cache size":
|
|
||||||
t, err := strconv.ParseInt(strings.Replace(value, " KB", "", 1), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
c.CacheSize = int32(t)
|
|
||||||
case "physical id":
|
|
||||||
c.PhysicalID = value
|
|
||||||
case "core id":
|
|
||||||
c.CoreID = value
|
|
||||||
case "cpu cores":
|
|
||||||
t, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
c.Cores = int32(t)
|
|
||||||
case "flags":
|
|
||||||
c.Flags = strings.Split(value, ",")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var CLK_TCK = 100
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
out, err := exec.Command("getconf", "CLK_TCK").CombinedOutput()
|
|
||||||
if err == nil {
|
|
||||||
i, err := strconv.Atoi(strings.TrimSpace(string(out)))
|
|
||||||
if err == nil {
|
|
||||||
CLK_TCK = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseStatLine(line string) (*CPUTimesStat, error) {
|
|
||||||
fields := strings.Fields(line)
|
|
||||||
|
|
||||||
if strings.HasPrefix(fields[0], "cpu") == false {
|
|
||||||
// return CPUTimesStat{}, e
|
|
||||||
return nil, errors.New("not contain cpu")
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu := fields[0]
|
|
||||||
if cpu == "cpu" {
|
|
||||||
cpu = "cpu-total"
|
|
||||||
}
|
|
||||||
user, err := strconv.ParseFloat(fields[1], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
nice, err := strconv.ParseFloat(fields[2], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
system, err := strconv.ParseFloat(fields[3], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
idle, err := strconv.ParseFloat(fields[4], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
iowait, err := strconv.ParseFloat(fields[5], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
irq, err := strconv.ParseFloat(fields[6], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
softirq, err := strconv.ParseFloat(fields[7], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
stolen, err := strconv.ParseFloat(fields[8], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu_tick := float64(CLK_TCK)
|
|
||||||
ct := &CPUTimesStat{
|
|
||||||
CPU: cpu,
|
|
||||||
User: float64(user) / cpu_tick,
|
|
||||||
Nice: float64(nice) / cpu_tick,
|
|
||||||
System: float64(system) / cpu_tick,
|
|
||||||
Idle: float64(idle) / cpu_tick,
|
|
||||||
Iowait: float64(iowait) / cpu_tick,
|
|
||||||
Irq: float64(irq) / cpu_tick,
|
|
||||||
Softirq: float64(softirq) / cpu_tick,
|
|
||||||
Stolen: float64(stolen) / cpu_tick,
|
|
||||||
}
|
|
||||||
if len(fields) > 9 { // Linux >= 2.6.11
|
|
||||||
steal, err := strconv.ParseFloat(fields[9], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ct.Steal = float64(steal)
|
|
||||||
}
|
|
||||||
if len(fields) > 10 { // Linux >= 2.6.24
|
|
||||||
guest, err := strconv.ParseFloat(fields[10], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ct.Guest = float64(guest)
|
|
||||||
}
|
|
||||||
if len(fields) > 11 { // Linux >= 3.2.0
|
|
||||||
guestNice, err := strconv.ParseFloat(fields[11], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ct.GuestNice = float64(guestNice)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ct, nil
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
package cpu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCpu_times(t *testing.T) {
|
|
||||||
v, err := CPUTimes(false)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
if len(v) == 0 {
|
|
||||||
t.Error("could not get CPUs ", err)
|
|
||||||
}
|
|
||||||
empty := CPUTimesStat{}
|
|
||||||
for _, vv := range v {
|
|
||||||
if vv == empty {
|
|
||||||
t.Errorf("could not get CPU User: %v", vv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCpu_counts(t *testing.T) {
|
|
||||||
v, err := CPUCounts(true)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
if v == 0 {
|
|
||||||
t.Errorf("could not get CPU counts: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCPUTimeStat_String(t *testing.T) {
|
|
||||||
v := CPUTimesStat{
|
|
||||||
CPU: "cpu0",
|
|
||||||
User: 100.1,
|
|
||||||
System: 200.1,
|
|
||||||
Idle: 300.1,
|
|
||||||
}
|
|
||||||
e := `{"cpu":"cpu0","user":100.1,"system":200.1,"idle":300.1,"nice":0.0,"iowait":0.0,"irq":0.0,"softirq":0.0,"steal":0.0,"guest":0.0,"guest_nice":0.0,"stolen":0.0}`
|
|
||||||
if e != fmt.Sprintf("%v", v) {
|
|
||||||
t.Errorf("CPUTimesStat string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCpuInfo(t *testing.T) {
|
|
||||||
v, err := CPUInfo()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
if len(v) == 0 {
|
|
||||||
t.Errorf("could not get CPU Info")
|
|
||||||
}
|
|
||||||
for _, vv := range v {
|
|
||||||
if vv.ModelName == "" {
|
|
||||||
t.Errorf("could not get CPU Info: %v", vv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testCPUPercent(t *testing.T, percpu bool) {
|
|
||||||
numcpu := runtime.NumCPU()
|
|
||||||
testCount := 3
|
|
||||||
|
|
||||||
if runtime.GOOS != "windows" {
|
|
||||||
testCount = 100
|
|
||||||
v, err := CPUPercent(time.Millisecond, percpu)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
if (percpu && len(v) != numcpu) || (!percpu && len(v) != 1) {
|
|
||||||
t.Fatalf("wrong number of entries from CPUPercent: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < testCount; i++ {
|
|
||||||
duration := time.Duration(10) * time.Microsecond
|
|
||||||
v, err := CPUPercent(duration, percpu)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
for _, percent := range v {
|
|
||||||
if percent < 0.0 || int(percent) > 100*numcpu {
|
|
||||||
t.Fatalf("CPUPercent value is invalid: %f", percent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCPUPercent(t *testing.T) {
|
|
||||||
testCPUPercent(t, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCPUPercentPerCpu(t *testing.T) {
|
|
||||||
// Skip Per-CPU tests when running from a Circle CI container,
|
|
||||||
// see: https://github.com/golang/go/issues/11609
|
|
||||||
if os.Getenv("CIRCLE_BUILD_NUM") != "" {
|
|
||||||
t.Skip("Detected that we are in a circleci container, skipping Per-CPU tests")
|
|
||||||
}
|
|
||||||
testCPUPercent(t, true)
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
// +build linux freebsd darwin
|
|
||||||
|
|
||||||
package cpu
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
lastCPUTimes, _ = CPUTimes(false)
|
|
||||||
lastPerCPUTimes, _ = CPUTimes(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CPUPercent(interval time.Duration, percpu bool) ([]float64, error) {
|
|
||||||
getAllBusy := func(t CPUTimesStat) (float64, float64) {
|
|
||||||
busy := t.User + t.System + t.Nice + t.Iowait + t.Irq +
|
|
||||||
t.Softirq + t.Steal + t.Guest + t.GuestNice + t.Stolen
|
|
||||||
return busy + t.Idle, busy
|
|
||||||
}
|
|
||||||
|
|
||||||
calculate := func(t1, t2 CPUTimesStat) float64 {
|
|
||||||
t1All, t1Busy := getAllBusy(t1)
|
|
||||||
t2All, t2Busy := getAllBusy(t2)
|
|
||||||
|
|
||||||
if t2Busy <= t1Busy {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if t2All <= t1All {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return (t2Busy - t1Busy) / (t2All - t1All) * 100
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuTimes, err := CPUTimes(percpu)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if interval > 0 {
|
|
||||||
if !percpu {
|
|
||||||
lastCPUTimes = cpuTimes
|
|
||||||
} else {
|
|
||||||
lastPerCPUTimes = cpuTimes
|
|
||||||
}
|
|
||||||
time.Sleep(interval)
|
|
||||||
cpuTimes, err = CPUTimes(percpu)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := make([]float64, len(cpuTimes))
|
|
||||||
if !percpu {
|
|
||||||
ret[0] = calculate(lastCPUTimes[0], cpuTimes[0])
|
|
||||||
lastCPUTimes = cpuTimes
|
|
||||||
} else {
|
|
||||||
for i, t := range cpuTimes {
|
|
||||||
ret[i] = calculate(lastPerCPUTimes[i], t)
|
|
||||||
}
|
|
||||||
lastPerCPUTimes = cpuTimes
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package cpu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: Get percpu
|
|
||||||
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
|
|
||||||
var ret []CPUTimesStat
|
|
||||||
|
|
||||||
var lpIdleTime common.FILETIME
|
|
||||||
var lpKernelTime common.FILETIME
|
|
||||||
var lpUserTime common.FILETIME
|
|
||||||
r, _, _ := common.ProcGetSystemTimes.Call(
|
|
||||||
uintptr(unsafe.Pointer(&lpIdleTime)),
|
|
||||||
uintptr(unsafe.Pointer(&lpKernelTime)),
|
|
||||||
uintptr(unsafe.Pointer(&lpUserTime)))
|
|
||||||
if r == 0 {
|
|
||||||
return ret, syscall.GetLastError()
|
|
||||||
}
|
|
||||||
|
|
||||||
LOT := float64(0.0000001)
|
|
||||||
HIT := (LOT * 4294967296.0)
|
|
||||||
idle := ((HIT * float64(lpIdleTime.DwHighDateTime)) + (LOT * float64(lpIdleTime.DwLowDateTime)))
|
|
||||||
user := ((HIT * float64(lpUserTime.DwHighDateTime)) + (LOT * float64(lpUserTime.DwLowDateTime)))
|
|
||||||
kernel := ((HIT * float64(lpKernelTime.DwHighDateTime)) + (LOT * float64(lpKernelTime.DwLowDateTime)))
|
|
||||||
system := (kernel - idle)
|
|
||||||
|
|
||||||
ret = append(ret, CPUTimesStat{
|
|
||||||
Idle: float64(idle),
|
|
||||||
User: float64(user),
|
|
||||||
System: float64(system),
|
|
||||||
})
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CPUInfo() ([]CPUInfoStat, error) {
|
|
||||||
var ret []CPUInfoStat
|
|
||||||
lines, err := common.GetWmic("cpu", "get", "Family,L2CacheSize,Manufacturer,Name,NumberOfLogicalProcessors,ProcessorId,Stepping")
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
for i, t := range lines {
|
|
||||||
cache, err := strconv.Atoi(t[2])
|
|
||||||
if err != nil {
|
|
||||||
cache = 0
|
|
||||||
}
|
|
||||||
cores, err := strconv.Atoi(t[5])
|
|
||||||
if err != nil {
|
|
||||||
cores = 0
|
|
||||||
}
|
|
||||||
stepping := 0
|
|
||||||
if len(t) > 7 {
|
|
||||||
stepping, err = strconv.Atoi(t[6])
|
|
||||||
if err != nil {
|
|
||||||
stepping = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cpu := CPUInfoStat{
|
|
||||||
CPU: int32(i),
|
|
||||||
Family: t[1],
|
|
||||||
CacheSize: int32(cache),
|
|
||||||
VendorID: t[3],
|
|
||||||
ModelName: t[4],
|
|
||||||
Cores: int32(cores),
|
|
||||||
PhysicalID: t[6],
|
|
||||||
Stepping: int32(stepping),
|
|
||||||
Flags: []string{},
|
|
||||||
}
|
|
||||||
ret = append(ret, cpu)
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CPUPercent(interval time.Duration, percpu bool) ([]float64, error) {
|
|
||||||
ret := []float64{}
|
|
||||||
|
|
||||||
lines, err := common.GetWmic("cpu", "get", "loadpercentage")
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
for _, l := range lines {
|
|
||||||
if len(l) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p, err := strconv.Atoi(l[1])
|
|
||||||
if err != nil {
|
|
||||||
p = 0
|
|
||||||
}
|
|
||||||
// but windows can only get one percent.
|
|
||||||
ret = append(ret, float64(p)/100.0)
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,634 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package binary implements simple translation between numbers and byte
|
|
||||||
// sequences and encoding and decoding of varints.
|
|
||||||
//
|
|
||||||
// Numbers are translated by reading and writing fixed-size values.
|
|
||||||
// A fixed-size value is either a fixed-size arithmetic
|
|
||||||
// type (int8, uint8, int16, float32, complex64, ...)
|
|
||||||
// or an array or struct containing only fixed-size values.
|
|
||||||
//
|
|
||||||
// The varint functions encode and decode single integer values using
|
|
||||||
// a variable-length encoding; smaller values require fewer bytes.
|
|
||||||
// For a specification, see
|
|
||||||
// http://code.google.com/apis/protocolbuffers/docs/encoding.html.
|
|
||||||
//
|
|
||||||
// This package favors simplicity over efficiency. Clients that require
|
|
||||||
// high-performance serialization, especially for large data structures,
|
|
||||||
// should look at more advanced solutions such as the encoding/gob
|
|
||||||
// package or protocol buffers.
|
|
||||||
package disk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A ByteOrder specifies how to convert byte sequences into
|
|
||||||
// 16-, 32-, or 64-bit unsigned integers.
|
|
||||||
type ByteOrder interface {
|
|
||||||
Uint16([]byte) uint16
|
|
||||||
Uint32([]byte) uint32
|
|
||||||
Uint64([]byte) uint64
|
|
||||||
PutUint16([]byte, uint16)
|
|
||||||
PutUint32([]byte, uint32)
|
|
||||||
PutUint64([]byte, uint64)
|
|
||||||
String() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// LittleEndian is the little-endian implementation of ByteOrder.
|
|
||||||
var LittleEndian littleEndian
|
|
||||||
|
|
||||||
// BigEndian is the big-endian implementation of ByteOrder.
|
|
||||||
var BigEndian bigEndian
|
|
||||||
|
|
||||||
type littleEndian struct{}
|
|
||||||
|
|
||||||
func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
|
|
||||||
|
|
||||||
func (littleEndian) PutUint16(b []byte, v uint16) {
|
|
||||||
b[0] = byte(v)
|
|
||||||
b[1] = byte(v >> 8)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) Uint32(b []byte) uint32 {
|
|
||||||
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) PutUint32(b []byte, v uint32) {
|
|
||||||
b[0] = byte(v)
|
|
||||||
b[1] = byte(v >> 8)
|
|
||||||
b[2] = byte(v >> 16)
|
|
||||||
b[3] = byte(v >> 24)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) Uint64(b []byte) uint64 {
|
|
||||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
|
||||||
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) PutUint64(b []byte, v uint64) {
|
|
||||||
b[0] = byte(v)
|
|
||||||
b[1] = byte(v >> 8)
|
|
||||||
b[2] = byte(v >> 16)
|
|
||||||
b[3] = byte(v >> 24)
|
|
||||||
b[4] = byte(v >> 32)
|
|
||||||
b[5] = byte(v >> 40)
|
|
||||||
b[6] = byte(v >> 48)
|
|
||||||
b[7] = byte(v >> 56)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) String() string { return "LittleEndian" }
|
|
||||||
|
|
||||||
func (littleEndian) GoString() string { return "binary.LittleEndian" }
|
|
||||||
|
|
||||||
type bigEndian struct{}
|
|
||||||
|
|
||||||
func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 }
|
|
||||||
|
|
||||||
func (bigEndian) PutUint16(b []byte, v uint16) {
|
|
||||||
b[0] = byte(v >> 8)
|
|
||||||
b[1] = byte(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) Uint32(b []byte) uint32 {
|
|
||||||
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) PutUint32(b []byte, v uint32) {
|
|
||||||
b[0] = byte(v >> 24)
|
|
||||||
b[1] = byte(v >> 16)
|
|
||||||
b[2] = byte(v >> 8)
|
|
||||||
b[3] = byte(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) Uint64(b []byte) uint64 {
|
|
||||||
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
|
||||||
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) PutUint64(b []byte, v uint64) {
|
|
||||||
b[0] = byte(v >> 56)
|
|
||||||
b[1] = byte(v >> 48)
|
|
||||||
b[2] = byte(v >> 40)
|
|
||||||
b[3] = byte(v >> 32)
|
|
||||||
b[4] = byte(v >> 24)
|
|
||||||
b[5] = byte(v >> 16)
|
|
||||||
b[6] = byte(v >> 8)
|
|
||||||
b[7] = byte(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) String() string { return "BigEndian" }
|
|
||||||
|
|
||||||
func (bigEndian) GoString() string { return "binary.BigEndian" }
|
|
||||||
|
|
||||||
// Read reads structured binary data from r into data.
|
|
||||||
// Data must be a pointer to a fixed-size value or a slice
|
|
||||||
// of fixed-size values.
|
|
||||||
// Bytes read from r are decoded using the specified byte order
|
|
||||||
// and written to successive fields of the data.
|
|
||||||
// When reading into structs, the field data for fields with
|
|
||||||
// blank (_) field names is skipped; i.e., blank field names
|
|
||||||
// may be used for padding.
|
|
||||||
// When reading into a struct, all non-blank fields must be exported.
|
|
||||||
func Read(r io.Reader, order ByteOrder, data interface{}) error {
|
|
||||||
// Fast path for basic types and slices.
|
|
||||||
if n := intDataSize(data); n != 0 {
|
|
||||||
var b [8]byte
|
|
||||||
var bs []byte
|
|
||||||
if n > len(b) {
|
|
||||||
bs = make([]byte, n)
|
|
||||||
} else {
|
|
||||||
bs = b[:n]
|
|
||||||
}
|
|
||||||
if _, err := io.ReadFull(r, bs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch data := data.(type) {
|
|
||||||
case *int8:
|
|
||||||
*data = int8(b[0])
|
|
||||||
case *uint8:
|
|
||||||
*data = b[0]
|
|
||||||
case *int16:
|
|
||||||
*data = int16(order.Uint16(bs))
|
|
||||||
case *uint16:
|
|
||||||
*data = order.Uint16(bs)
|
|
||||||
case *int32:
|
|
||||||
*data = int32(order.Uint32(bs))
|
|
||||||
case *uint32:
|
|
||||||
*data = order.Uint32(bs)
|
|
||||||
case *int64:
|
|
||||||
*data = int64(order.Uint64(bs))
|
|
||||||
case *uint64:
|
|
||||||
*data = order.Uint64(bs)
|
|
||||||
case []int8:
|
|
||||||
for i, x := range bs { // Easier to loop over the input for 8-bit values.
|
|
||||||
data[i] = int8(x)
|
|
||||||
}
|
|
||||||
case []uint8:
|
|
||||||
copy(data, bs)
|
|
||||||
case []int16:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = int16(order.Uint16(bs[2*i:]))
|
|
||||||
}
|
|
||||||
case []uint16:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = order.Uint16(bs[2*i:])
|
|
||||||
}
|
|
||||||
case []int32:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = int32(order.Uint32(bs[4*i:]))
|
|
||||||
}
|
|
||||||
case []uint32:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = order.Uint32(bs[4*i:])
|
|
||||||
}
|
|
||||||
case []int64:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = int64(order.Uint64(bs[8*i:]))
|
|
||||||
}
|
|
||||||
case []uint64:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = order.Uint64(bs[8*i:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to reflect-based decoding.
|
|
||||||
v := reflect.ValueOf(data)
|
|
||||||
size := -1
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
v = v.Elem()
|
|
||||||
size = dataSize(v)
|
|
||||||
case reflect.Slice:
|
|
||||||
size = dataSize(v)
|
|
||||||
}
|
|
||||||
if size < 0 {
|
|
||||||
return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String())
|
|
||||||
}
|
|
||||||
d := &decoder{order: order, buf: make([]byte, size)}
|
|
||||||
if _, err := io.ReadFull(r, d.buf); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.value(v)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write writes the binary representation of data into w.
|
|
||||||
// Data must be a fixed-size value or a slice of fixed-size
|
|
||||||
// values, or a pointer to such data.
|
|
||||||
// Bytes written to w are encoded using the specified byte order
|
|
||||||
// and read from successive fields of the data.
|
|
||||||
// When writing structs, zero values are written for fields
|
|
||||||
// with blank (_) field names.
|
|
||||||
func Write(w io.Writer, order ByteOrder, data interface{}) error {
|
|
||||||
// Fast path for basic types and slices.
|
|
||||||
if n := intDataSize(data); n != 0 {
|
|
||||||
var b [8]byte
|
|
||||||
var bs []byte
|
|
||||||
if n > len(b) {
|
|
||||||
bs = make([]byte, n)
|
|
||||||
} else {
|
|
||||||
bs = b[:n]
|
|
||||||
}
|
|
||||||
switch v := data.(type) {
|
|
||||||
case *int8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = byte(*v)
|
|
||||||
case int8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = byte(v)
|
|
||||||
case []int8:
|
|
||||||
for i, x := range v {
|
|
||||||
bs[i] = byte(x)
|
|
||||||
}
|
|
||||||
case *uint8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = *v
|
|
||||||
case uint8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = byte(v)
|
|
||||||
case []uint8:
|
|
||||||
bs = v
|
|
||||||
case *int16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, uint16(*v))
|
|
||||||
case int16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, uint16(v))
|
|
||||||
case []int16:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint16(bs[2*i:], uint16(x))
|
|
||||||
}
|
|
||||||
case *uint16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, *v)
|
|
||||||
case uint16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, v)
|
|
||||||
case []uint16:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint16(bs[2*i:], x)
|
|
||||||
}
|
|
||||||
case *int32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, uint32(*v))
|
|
||||||
case int32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, uint32(v))
|
|
||||||
case []int32:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint32(bs[4*i:], uint32(x))
|
|
||||||
}
|
|
||||||
case *uint32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, *v)
|
|
||||||
case uint32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, v)
|
|
||||||
case []uint32:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint32(bs[4*i:], x)
|
|
||||||
}
|
|
||||||
case *int64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, uint64(*v))
|
|
||||||
case int64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, uint64(v))
|
|
||||||
case []int64:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint64(bs[8*i:], uint64(x))
|
|
||||||
}
|
|
||||||
case *uint64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, *v)
|
|
||||||
case uint64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, v)
|
|
||||||
case []uint64:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint64(bs[8*i:], x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err := w.Write(bs)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to reflect-based encoding.
|
|
||||||
v := reflect.Indirect(reflect.ValueOf(data))
|
|
||||||
size := dataSize(v)
|
|
||||||
if size < 0 {
|
|
||||||
return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String())
|
|
||||||
}
|
|
||||||
buf := make([]byte, size)
|
|
||||||
e := &encoder{order: order, buf: buf}
|
|
||||||
e.value(v)
|
|
||||||
_, err := w.Write(buf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns how many bytes Write would generate to encode the value v, which
|
|
||||||
// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
|
|
||||||
// If v is neither of these, Size returns -1.
|
|
||||||
func Size(v interface{}) int {
|
|
||||||
return dataSize(reflect.Indirect(reflect.ValueOf(v)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// dataSize returns the number of bytes the actual data represented by v occupies in memory.
|
|
||||||
// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
|
|
||||||
// it returns the length of the slice times the element size and does not count the memory
|
|
||||||
// occupied by the header. If the type of v is not acceptable, dataSize returns -1.
|
|
||||||
func dataSize(v reflect.Value) int {
|
|
||||||
if v.Kind() == reflect.Slice {
|
|
||||||
if s := sizeof(v.Type().Elem()); s >= 0 {
|
|
||||||
return s * v.Len()
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
return sizeof(v.Type())
|
|
||||||
}
|
|
||||||
|
|
||||||
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
|
|
||||||
func sizeof(t reflect.Type) int {
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Array:
|
|
||||||
if s := sizeof(t.Elem()); s >= 0 {
|
|
||||||
return s * t.Len()
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
sum := 0
|
|
||||||
for i, n := 0, t.NumField(); i < n; i++ {
|
|
||||||
s := sizeof(t.Field(i).Type)
|
|
||||||
if s < 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
sum += s
|
|
||||||
}
|
|
||||||
return sum
|
|
||||||
|
|
||||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
|
||||||
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
|
||||||
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr:
|
|
||||||
return int(t.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
type coder struct {
|
|
||||||
order ByteOrder
|
|
||||||
buf []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type decoder coder
|
|
||||||
type encoder coder
|
|
||||||
|
|
||||||
func (d *decoder) uint8() uint8 {
|
|
||||||
x := d.buf[0]
|
|
||||||
d.buf = d.buf[1:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint8(x uint8) {
|
|
||||||
e.buf[0] = x
|
|
||||||
e.buf = e.buf[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) uint16() uint16 {
|
|
||||||
x := d.order.Uint16(d.buf[0:2])
|
|
||||||
d.buf = d.buf[2:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint16(x uint16) {
|
|
||||||
e.order.PutUint16(e.buf[0:2], x)
|
|
||||||
e.buf = e.buf[2:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) uint32() uint32 {
|
|
||||||
x := d.order.Uint32(d.buf[0:4])
|
|
||||||
d.buf = d.buf[4:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint32(x uint32) {
|
|
||||||
e.order.PutUint32(e.buf[0:4], x)
|
|
||||||
e.buf = e.buf[4:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) uint64() uint64 {
|
|
||||||
x := d.order.Uint64(d.buf[0:8])
|
|
||||||
d.buf = d.buf[8:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint64(x uint64) {
|
|
||||||
e.order.PutUint64(e.buf[0:8], x)
|
|
||||||
e.buf = e.buf[8:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) int8() int8 { return int8(d.uint8()) }
|
|
||||||
|
|
||||||
func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) int16() int16 { return int16(d.uint16()) }
|
|
||||||
|
|
||||||
func (e *encoder) int16(x int16) { e.uint16(uint16(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) int32() int32 { return int32(d.uint32()) }
|
|
||||||
|
|
||||||
func (e *encoder) int32(x int32) { e.uint32(uint32(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) int64() int64 { return int64(d.uint64()) }
|
|
||||||
|
|
||||||
func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) value(v reflect.Value) {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Array:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
d.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
t := v.Type()
|
|
||||||
l := v.NumField()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
// Note: Calling v.CanSet() below is an optimization.
|
|
||||||
// It would be sufficient to check the field name,
|
|
||||||
// but creating the StructField info for each field is
|
|
||||||
// costly (run "go test -bench=ReadStruct" and compare
|
|
||||||
// results when making changes to this code).
|
|
||||||
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
|
||||||
d.value(v)
|
|
||||||
} else {
|
|
||||||
d.skip(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
d.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Int8:
|
|
||||||
v.SetInt(int64(d.int8()))
|
|
||||||
case reflect.Int16:
|
|
||||||
v.SetInt(int64(d.int16()))
|
|
||||||
case reflect.Int32:
|
|
||||||
v.SetInt(int64(d.int32()))
|
|
||||||
case reflect.Int64:
|
|
||||||
v.SetInt(d.int64())
|
|
||||||
|
|
||||||
case reflect.Uint8:
|
|
||||||
v.SetUint(uint64(d.uint8()))
|
|
||||||
case reflect.Uint16:
|
|
||||||
v.SetUint(uint64(d.uint16()))
|
|
||||||
case reflect.Uint32:
|
|
||||||
v.SetUint(uint64(d.uint32()))
|
|
||||||
case reflect.Uint64:
|
|
||||||
v.SetUint(d.uint64())
|
|
||||||
|
|
||||||
case reflect.Float32:
|
|
||||||
v.SetFloat(float64(math.Float32frombits(d.uint32())))
|
|
||||||
case reflect.Float64:
|
|
||||||
v.SetFloat(math.Float64frombits(d.uint64()))
|
|
||||||
|
|
||||||
case reflect.Complex64:
|
|
||||||
v.SetComplex(complex(
|
|
||||||
float64(math.Float32frombits(d.uint32())),
|
|
||||||
float64(math.Float32frombits(d.uint32())),
|
|
||||||
))
|
|
||||||
case reflect.Complex128:
|
|
||||||
v.SetComplex(complex(
|
|
||||||
math.Float64frombits(d.uint64()),
|
|
||||||
math.Float64frombits(d.uint64()),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) value(v reflect.Value) {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Array:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
e.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
t := v.Type()
|
|
||||||
l := v.NumField()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
// see comment for corresponding code in decoder.value()
|
|
||||||
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
|
||||||
e.value(v)
|
|
||||||
} else {
|
|
||||||
e.skip(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
e.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Int8:
|
|
||||||
e.int8(int8(v.Int()))
|
|
||||||
case reflect.Int16:
|
|
||||||
e.int16(int16(v.Int()))
|
|
||||||
case reflect.Int32:
|
|
||||||
e.int32(int32(v.Int()))
|
|
||||||
case reflect.Int64:
|
|
||||||
e.int64(v.Int())
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Uint8:
|
|
||||||
e.uint8(uint8(v.Uint()))
|
|
||||||
case reflect.Uint16:
|
|
||||||
e.uint16(uint16(v.Uint()))
|
|
||||||
case reflect.Uint32:
|
|
||||||
e.uint32(uint32(v.Uint()))
|
|
||||||
case reflect.Uint64:
|
|
||||||
e.uint64(v.Uint())
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Float32:
|
|
||||||
e.uint32(math.Float32bits(float32(v.Float())))
|
|
||||||
case reflect.Float64:
|
|
||||||
e.uint64(math.Float64bits(v.Float()))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Complex64, reflect.Complex128:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Complex64:
|
|
||||||
x := v.Complex()
|
|
||||||
e.uint32(math.Float32bits(float32(real(x))))
|
|
||||||
e.uint32(math.Float32bits(float32(imag(x))))
|
|
||||||
case reflect.Complex128:
|
|
||||||
x := v.Complex()
|
|
||||||
e.uint64(math.Float64bits(real(x)))
|
|
||||||
e.uint64(math.Float64bits(imag(x)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) skip(v reflect.Value) {
|
|
||||||
d.buf = d.buf[dataSize(v):]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) skip(v reflect.Value) {
|
|
||||||
n := dataSize(v)
|
|
||||||
for i := range e.buf[0:n] {
|
|
||||||
e.buf[i] = 0
|
|
||||||
}
|
|
||||||
e.buf = e.buf[n:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// intDataSize returns the size of the data required to represent the data when encoded.
|
|
||||||
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
|
|
||||||
func intDataSize(data interface{}) int {
|
|
||||||
switch data := data.(type) {
|
|
||||||
case int8, *int8, *uint8:
|
|
||||||
return 1
|
|
||||||
case []int8:
|
|
||||||
return len(data)
|
|
||||||
case []uint8:
|
|
||||||
return len(data)
|
|
||||||
case int16, *int16, *uint16:
|
|
||||||
return 2
|
|
||||||
case []int16:
|
|
||||||
return 2 * len(data)
|
|
||||||
case []uint16:
|
|
||||||
return 2 * len(data)
|
|
||||||
case int32, *int32, *uint32:
|
|
||||||
return 4
|
|
||||||
case []int32:
|
|
||||||
return 4 * len(data)
|
|
||||||
case []uint32:
|
|
||||||
return 4 * len(data)
|
|
||||||
case int64, *int64, *uint64:
|
|
||||||
return 8
|
|
||||||
case []int64:
|
|
||||||
return 8 * len(data)
|
|
||||||
case []uint64:
|
|
||||||
return 8 * len(data)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
package disk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DiskUsageStat struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Fstype string `json:"fstype"`
|
|
||||||
Total uint64 `json:"total"`
|
|
||||||
Free uint64 `json:"free"`
|
|
||||||
Used uint64 `json:"used"`
|
|
||||||
UsedPercent float64 `json:"used_percent"`
|
|
||||||
InodesTotal uint64 `json:"inodes_total"`
|
|
||||||
InodesUsed uint64 `json:"inodes_used"`
|
|
||||||
InodesFree uint64 `json:"inodes_free"`
|
|
||||||
InodesUsedPercent float64 `json:"inodes_used_percent"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DiskPartitionStat struct {
|
|
||||||
Device string `json:"device"`
|
|
||||||
Mountpoint string `json:"mountpoint"`
|
|
||||||
Fstype string `json:"fstype"`
|
|
||||||
Opts string `json:"opts"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DiskIOCountersStat struct {
|
|
||||||
ReadCount uint64 `json:"read_count"`
|
|
||||||
WriteCount uint64 `json:"write_count"`
|
|
||||||
ReadBytes uint64 `json:"read_bytes"`
|
|
||||||
WriteBytes uint64 `json:"write_bytes"`
|
|
||||||
ReadTime uint64 `json:"read_time"`
|
|
||||||
WriteTime uint64 `json:"write_time"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
IoTime uint64 `json:"io_time"`
|
|
||||||
SerialNumber string `json:"serial_number"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d DiskUsageStat) String() string {
|
|
||||||
s, _ := json.Marshal(d)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d DiskPartitionStat) String() string {
|
|
||||||
s, _ := json.Marshal(d)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d DiskIOCountersStat) String() string {
|
|
||||||
s, _ := json.Marshal(d)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package disk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
|
|
||||||
var ret []DiskPartitionStat
|
|
||||||
|
|
||||||
count, err := Getfsstat(nil, MntWait)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
fs := make([]Statfs_t, count)
|
|
||||||
_, err = Getfsstat(fs, MntWait)
|
|
||||||
for _, stat := range fs {
|
|
||||||
opts := "rw"
|
|
||||||
if stat.Flags&MntReadOnly != 0 {
|
|
||||||
opts = "ro"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntSynchronous != 0 {
|
|
||||||
opts += ",sync"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntNoExec != 0 {
|
|
||||||
opts += ",noexec"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntNoSuid != 0 {
|
|
||||||
opts += ",nosuid"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntUnion != 0 {
|
|
||||||
opts += ",union"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntAsync != 0 {
|
|
||||||
opts += ",async"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntSuidDir != 0 {
|
|
||||||
opts += ",suiddir"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntSoftDep != 0 {
|
|
||||||
opts += ",softdep"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntNoSymFollow != 0 {
|
|
||||||
opts += ",nosymfollow"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntGEOMJournal != 0 {
|
|
||||||
opts += ",gjounalc"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntMultilabel != 0 {
|
|
||||||
opts += ",multilabel"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntACLs != 0 {
|
|
||||||
opts += ",acls"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntNoATime != 0 {
|
|
||||||
opts += ",noattime"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntClusterRead != 0 {
|
|
||||||
opts += ",nocluster"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntClusterWrite != 0 {
|
|
||||||
opts += ",noclusterw"
|
|
||||||
}
|
|
||||||
if stat.Flags&MntNFS4ACLs != 0 {
|
|
||||||
opts += ",nfs4acls"
|
|
||||||
}
|
|
||||||
d := DiskPartitionStat{
|
|
||||||
Device: common.IntToString(stat.Mntfromname[:]),
|
|
||||||
Mountpoint: common.IntToString(stat.Mntonname[:]),
|
|
||||||
Fstype: common.IntToString(stat.Fstypename[:]),
|
|
||||||
Opts: opts,
|
|
||||||
}
|
|
||||||
ret = append(ret, d)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
|
||||||
var _p0 unsafe.Pointer
|
|
||||||
var bufsize uintptr
|
|
||||||
if len(buf) > 0 {
|
|
||||||
_p0 = unsafe.Pointer(&buf[0])
|
|
||||||
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
|
|
||||||
}
|
|
||||||
r0, _, e1 := syscall.Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
|
|
||||||
n = int(r0)
|
|
||||||
if e1 != 0 {
|
|
||||||
err = e1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
// +build amd64
|
|
||||||
|
|
||||||
package disk
|
|
||||||
|
|
||||||
const (
|
|
||||||
MntWait = 1
|
|
||||||
MfsNameLen = 15 /* length of fs type name, not inc. nul */
|
|
||||||
MNameLen = 90 /* length of buffer for returned name */
|
|
||||||
|
|
||||||
MFSTYPENAMELEN = 16 /* length of fs type name including null */
|
|
||||||
MAXPATHLEN = 1024
|
|
||||||
MNAMELEN = MAXPATHLEN
|
|
||||||
|
|
||||||
SYS_GETFSSTAT64 = 347
|
|
||||||
)
|
|
||||||
|
|
||||||
type Fsid struct{ val [2]int32 } /* file system id type */
|
|
||||||
type uid_t int32
|
|
||||||
|
|
||||||
// sys/mount.h
|
|
||||||
const (
|
|
||||||
MntReadOnly = 0x00000001 /* read only filesystem */
|
|
||||||
MntSynchronous = 0x00000002 /* filesystem written synchronously */
|
|
||||||
MntNoExec = 0x00000004 /* can't exec from filesystem */
|
|
||||||
MntNoSuid = 0x00000008 /* don't honor setuid bits on fs */
|
|
||||||
MntUnion = 0x00000020 /* union with underlying filesystem */
|
|
||||||
MntAsync = 0x00000040 /* filesystem written asynchronously */
|
|
||||||
MntSuidDir = 0x00100000 /* special handling of SUID on dirs */
|
|
||||||
MntSoftDep = 0x00200000 /* soft updates being done */
|
|
||||||
MntNoSymFollow = 0x00400000 /* do not follow symlinks */
|
|
||||||
MntGEOMJournal = 0x02000000 /* GEOM journal support enabled */
|
|
||||||
MntMultilabel = 0x04000000 /* MAC support for individual objects */
|
|
||||||
MntACLs = 0x08000000 /* ACL support enabled */
|
|
||||||
MntNoATime = 0x10000000 /* disable update of file access time */
|
|
||||||
MntClusterRead = 0x40000000 /* disable cluster read */
|
|
||||||
MntClusterWrite = 0x80000000 /* disable cluster write */
|
|
||||||
MntNFS4ACLs = 0x00000010
|
|
||||||
)
|
|
||||||
|
|
||||||
type Statfs_t struct {
|
|
||||||
Bsize uint32
|
|
||||||
Iosize int32
|
|
||||||
Blocks uint64
|
|
||||||
Bfree uint64
|
|
||||||
Bavail uint64
|
|
||||||
Files uint64
|
|
||||||
Ffree uint64
|
|
||||||
Fsid Fsid
|
|
||||||
Owner uint32
|
|
||||||
Type uint32
|
|
||||||
Flags uint32
|
|
||||||
Fssubtype uint32
|
|
||||||
Fstypename [16]int8
|
|
||||||
Mntonname [1024]int8
|
|
||||||
Mntfromname [1024]int8
|
|
||||||
Reserved [8]uint32
|
|
||||||
}
|
|
|
@ -1,173 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package disk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"strconv"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
CTLKern = 1
|
|
||||||
KernDevstat = 773
|
|
||||||
KernDevstatAll = 772
|
|
||||||
)
|
|
||||||
|
|
||||||
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
|
|
||||||
var ret []DiskPartitionStat
|
|
||||||
|
|
||||||
// get length
|
|
||||||
count, err := syscall.Getfsstat(nil, MNT_WAIT)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fs := make([]Statfs, count)
|
|
||||||
_, err = Getfsstat(fs, MNT_WAIT)
|
|
||||||
|
|
||||||
for _, stat := range fs {
|
|
||||||
opts := "rw"
|
|
||||||
if stat.Flags&MNT_RDONLY != 0 {
|
|
||||||
opts = "ro"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_SYNCHRONOUS != 0 {
|
|
||||||
opts += ",sync"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_NOEXEC != 0 {
|
|
||||||
opts += ",noexec"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_NOSUID != 0 {
|
|
||||||
opts += ",nosuid"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_UNION != 0 {
|
|
||||||
opts += ",union"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_ASYNC != 0 {
|
|
||||||
opts += ",async"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_SUIDDIR != 0 {
|
|
||||||
opts += ",suiddir"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_SOFTDEP != 0 {
|
|
||||||
opts += ",softdep"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_NOSYMFOLLOW != 0 {
|
|
||||||
opts += ",nosymfollow"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_GJOURNAL != 0 {
|
|
||||||
opts += ",gjounalc"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_MULTILABEL != 0 {
|
|
||||||
opts += ",multilabel"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_ACLS != 0 {
|
|
||||||
opts += ",acls"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_NOATIME != 0 {
|
|
||||||
opts += ",noattime"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_NOCLUSTERR != 0 {
|
|
||||||
opts += ",nocluster"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_NOCLUSTERW != 0 {
|
|
||||||
opts += ",noclusterw"
|
|
||||||
}
|
|
||||||
if stat.Flags&MNT_NFS4ACLS != 0 {
|
|
||||||
opts += ",nfs4acls"
|
|
||||||
}
|
|
||||||
|
|
||||||
d := DiskPartitionStat{
|
|
||||||
Device: common.IntToString(stat.Mntfromname[:]),
|
|
||||||
Mountpoint: common.IntToString(stat.Mntonname[:]),
|
|
||||||
Fstype: common.IntToString(stat.Fstypename[:]),
|
|
||||||
Opts: opts,
|
|
||||||
}
|
|
||||||
ret = append(ret, d)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
|
|
||||||
// statinfo->devinfo->devstat
|
|
||||||
// /usr/include/devinfo.h
|
|
||||||
|
|
||||||
// sysctl.sysctl ('kern.devstat.all', 0)
|
|
||||||
ret := make(map[string]DiskIOCountersStat)
|
|
||||||
mib := []int32{CTLKern, KernDevstat, KernDevstatAll}
|
|
||||||
|
|
||||||
buf, length, err := common.CallSyscall(mib)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ds := Devstat{}
|
|
||||||
devstatLen := int(unsafe.Sizeof(ds))
|
|
||||||
count := int(length / uint64(devstatLen))
|
|
||||||
|
|
||||||
buf = buf[8:] // devstat.all has version in the head.
|
|
||||||
// parse buf to Devstat
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
b := buf[i*devstatLen : i*devstatLen+devstatLen]
|
|
||||||
d, err := parseDevstat(b)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
un := strconv.Itoa(int(d.Unit_number))
|
|
||||||
name := common.IntToString(d.Device_name[:]) + un
|
|
||||||
|
|
||||||
ds := DiskIOCountersStat{
|
|
||||||
ReadCount: d.Operations[DEVSTAT_READ],
|
|
||||||
WriteCount: d.Operations[DEVSTAT_WRITE],
|
|
||||||
ReadBytes: d.Bytes[DEVSTAT_READ],
|
|
||||||
WriteBytes: d.Bytes[DEVSTAT_WRITE],
|
|
||||||
ReadTime: d.Duration[DEVSTAT_READ].Compute(),
|
|
||||||
WriteTime: d.Duration[DEVSTAT_WRITE].Compute(),
|
|
||||||
Name: name,
|
|
||||||
}
|
|
||||||
ret[name] = ds
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b Bintime) Compute() uint64 {
|
|
||||||
BINTIME_SCALE := 5.42101086242752217003726400434970855712890625e-20
|
|
||||||
return uint64(b.Sec) + b.Frac*uint64(BINTIME_SCALE)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BT2LD(time) ((long double)(time).sec + (time).frac * BINTIME_SCALE)
|
|
||||||
|
|
||||||
// Getfsstat is borrowed from pkg/syscall/syscall_freebsd.go
|
|
||||||
// change Statfs_t to Statfs in order to get more information
|
|
||||||
func Getfsstat(buf []Statfs, flags int) (n int, err error) {
|
|
||||||
var _p0 unsafe.Pointer
|
|
||||||
var bufsize uintptr
|
|
||||||
if len(buf) > 0 {
|
|
||||||
_p0 = unsafe.Pointer(&buf[0])
|
|
||||||
bufsize = unsafe.Sizeof(Statfs{}) * uintptr(len(buf))
|
|
||||||
}
|
|
||||||
r0, _, e1 := syscall.Syscall(syscall.SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
|
||||||
n = int(r0)
|
|
||||||
if e1 != 0 {
|
|
||||||
err = e1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseDevstat(buf []byte) (Devstat, error) {
|
|
||||||
var ds Devstat
|
|
||||||
br := bytes.NewReader(buf)
|
|
||||||
// err := binary.Read(br, binary.LittleEndian, &ds)
|
|
||||||
err := Read(br, binary.LittleEndian, &ds)
|
|
||||||
if err != nil {
|
|
||||||
return ds, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ds, nil
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
// Created by cgo -godefs - DO NOT EDIT
|
|
||||||
// cgo -godefs types_freebsd.go
|
|
||||||
|
|
||||||
package disk
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofPtr = 0x8
|
|
||||||
sizeofShort = 0x2
|
|
||||||
sizeofInt = 0x4
|
|
||||||
sizeofLong = 0x8
|
|
||||||
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 int64
|
|
||||||
_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
|
|
||||||
Pad_cgo_0 [4]byte
|
|
||||||
Tag_types [3]uint64
|
|
||||||
Flags uint32
|
|
||||||
Device_type uint32
|
|
||||||
Priority uint32
|
|
||||||
Pad_cgo_1 [4]byte
|
|
||||||
Id *byte
|
|
||||||
Sequence1 uint32
|
|
||||||
Pad_cgo_2 [4]byte
|
|
||||||
}
|
|
||||||
type Bintime struct {
|
|
||||||
Sec int64
|
|
||||||
Frac uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
type _Ctype_struct___0 struct {
|
|
||||||
Empty uint64
|
|
||||||
}
|
|
|
@ -1,122 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package disk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
SectorSize = 512
|
|
||||||
)
|
|
||||||
|
|
||||||
// Get disk partitions.
|
|
||||||
// should use setmntent(3) but this implement use /etc/mtab file
|
|
||||||
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
|
|
||||||
|
|
||||||
filename := "/etc/mtab"
|
|
||||||
lines, err := common.ReadLines(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := make([]DiskPartitionStat, 0, len(lines))
|
|
||||||
|
|
||||||
for _, line := range lines {
|
|
||||||
fields := strings.Fields(line)
|
|
||||||
d := DiskPartitionStat{
|
|
||||||
Device: fields[0],
|
|
||||||
Mountpoint: fields[1],
|
|
||||||
Fstype: fields[2],
|
|
||||||
Opts: fields[3],
|
|
||||||
}
|
|
||||||
ret = append(ret, d)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
|
|
||||||
filename := "/proc/diskstats"
|
|
||||||
lines, err := common.ReadLines(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ret := make(map[string]DiskIOCountersStat, 0)
|
|
||||||
empty := DiskIOCountersStat{}
|
|
||||||
|
|
||||||
for _, line := range lines {
|
|
||||||
fields := strings.Fields(line)
|
|
||||||
name := fields[2]
|
|
||||||
reads, err := strconv.ParseUint((fields[3]), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
rbytes, err := strconv.ParseUint((fields[5]), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
rtime, err := strconv.ParseUint((fields[6]), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
writes, err := strconv.ParseUint((fields[7]), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
wbytes, err := strconv.ParseUint((fields[9]), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
wtime, err := strconv.ParseUint((fields[10]), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
iotime, err := strconv.ParseUint((fields[12]), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
d := DiskIOCountersStat{
|
|
||||||
ReadBytes: rbytes * SectorSize,
|
|
||||||
WriteBytes: wbytes * SectorSize,
|
|
||||||
ReadCount: reads,
|
|
||||||
WriteCount: writes,
|
|
||||||
ReadTime: rtime,
|
|
||||||
WriteTime: wtime,
|
|
||||||
IoTime: iotime,
|
|
||||||
}
|
|
||||||
if d == empty {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
d.Name = name
|
|
||||||
|
|
||||||
d.SerialNumber = GetDiskSerialNumber(name)
|
|
||||||
ret[name] = d
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDiskSerialNumber(name string) string {
|
|
||||||
n := fmt.Sprintf("--name=%s", name)
|
|
||||||
out, err := exec.Command("/sbin/udevadm", "info", "--query=property", n).Output()
|
|
||||||
|
|
||||||
// does not return error, just an empty string
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
lines := strings.Split(string(out), "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
values := strings.Split(line, "=")
|
|
||||||
if len(values) < 2 || values[0] != "ID_SERIAL" {
|
|
||||||
// only get ID_SERIAL, not ID_SERIAL_SHORT
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return values[1]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
package disk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDisk_usage(t *testing.T) {
|
|
||||||
path := "/"
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
path = "C:"
|
|
||||||
}
|
|
||||||
v, err := DiskUsage(path)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
if v.Path != path {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDisk_partitions(t *testing.T) {
|
|
||||||
ret, err := DiskPartitions(false)
|
|
||||||
if err != nil || len(ret) == 0 {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
empty := DiskPartitionStat{}
|
|
||||||
for _, disk := range ret {
|
|
||||||
if disk == empty {
|
|
||||||
t.Errorf("Could not get device info %v", disk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDisk_io_counters(t *testing.T) {
|
|
||||||
ret, err := DiskIOCounters()
|
|
||||||
if err != nil {
|
|
||||||
if err == common.NotImplementedError {
|
|
||||||
t.SkipNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
if len(ret) == 0 {
|
|
||||||
t.Errorf("ret is empty: %s", ret)
|
|
||||||
}
|
|
||||||
empty := DiskIOCountersStat{}
|
|
||||||
for part, io := range ret {
|
|
||||||
fmt.Println(io)
|
|
||||||
if io == empty {
|
|
||||||
t.Errorf("io_counter error %v, %v", part, io)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiskUsageStat_String(t *testing.T) {
|
|
||||||
v := DiskUsageStat{
|
|
||||||
Path: "/",
|
|
||||||
Fstype: "ext4",
|
|
||||||
Total: 1000,
|
|
||||||
Free: 2000,
|
|
||||||
Used: 3000,
|
|
||||||
UsedPercent: 50.1,
|
|
||||||
InodesTotal: 4000,
|
|
||||||
InodesUsed: 5000,
|
|
||||||
InodesFree: 6000,
|
|
||||||
InodesUsedPercent: 49.1,
|
|
||||||
}
|
|
||||||
e := `{"path":"/","fstype":"ext4","total":1000,"free":2000,"used":3000,"used_percent":50.1,"inodes_total":4000,"inodes_used":5000,"inodes_free":6000,"inodes_used_percent":49.1}`
|
|
||||||
if e != fmt.Sprintf("%v", v) {
|
|
||||||
t.Errorf("DiskUsageStat string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiskPartitionStat_String(t *testing.T) {
|
|
||||||
v := DiskPartitionStat{
|
|
||||||
Device: "sd01",
|
|
||||||
Mountpoint: "/",
|
|
||||||
Fstype: "ext4",
|
|
||||||
Opts: "ro",
|
|
||||||
}
|
|
||||||
e := `{"device":"sd01","mountpoint":"/","fstype":"ext4","opts":"ro"}`
|
|
||||||
if e != fmt.Sprintf("%v", v) {
|
|
||||||
t.Errorf("DiskUsageStat string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiskIOCountersStat_String(t *testing.T) {
|
|
||||||
v := DiskIOCountersStat{
|
|
||||||
Name: "sd01",
|
|
||||||
ReadCount: 100,
|
|
||||||
WriteCount: 200,
|
|
||||||
ReadBytes: 300,
|
|
||||||
WriteBytes: 400,
|
|
||||||
SerialNumber: "SERIAL",
|
|
||||||
}
|
|
||||||
e := `{"read_count":100,"write_count":200,"read_bytes":300,"write_bytes":400,"read_time":0,"write_time":0,"name":"sd01","io_time":0,"serial_number":"SERIAL"}`
|
|
||||||
if e != fmt.Sprintf("%v", v) {
|
|
||||||
t.Errorf("DiskUsageStat string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
// +build freebsd linux darwin
|
|
||||||
|
|
||||||
package disk
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
func DiskUsage(path string) (*DiskUsageStat, error) {
|
|
||||||
stat := syscall.Statfs_t{}
|
|
||||||
err := syscall.Statfs(path, &stat)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
bsize := stat.Bsize
|
|
||||||
|
|
||||||
ret := &DiskUsageStat{
|
|
||||||
Path: path,
|
|
||||||
Total: (uint64(stat.Blocks) * uint64(bsize)),
|
|
||||||
Free: (uint64(stat.Bfree) * uint64(bsize)),
|
|
||||||
InodesTotal: (uint64(stat.Files)),
|
|
||||||
InodesFree: (uint64(stat.Ffree)),
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.InodesUsed = (ret.InodesTotal - ret.InodesFree)
|
|
||||||
ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0
|
|
||||||
ret.Used = (ret.Total - ret.Free)
|
|
||||||
ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,196 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package disk
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
procGetDiskFreeSpaceExW = common.Modkernel32.NewProc("GetDiskFreeSpaceExW")
|
|
||||||
procGetLogicalDriveStringsW = common.Modkernel32.NewProc("GetLogicalDriveStringsW")
|
|
||||||
procGetDriveType = common.Modkernel32.NewProc("GetDriveTypeW")
|
|
||||||
provGetVolumeInformation = common.Modkernel32.NewProc("GetVolumeInformationW")
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
FileFileCompression = int64(16) // 0x00000010
|
|
||||||
FileReadOnlyVolume = int64(524288) // 0x00080000
|
|
||||||
)
|
|
||||||
|
|
||||||
const WaitMSec = 500
|
|
||||||
|
|
||||||
func DiskUsage(path string) (*DiskUsageStat, error) {
|
|
||||||
|
|
||||||
lpFreeBytesAvailable := int64(0)
|
|
||||||
lpTotalNumberOfBytes := int64(0)
|
|
||||||
lpTotalNumberOfFreeBytes := int64(0)
|
|
||||||
diskret, _, err := procGetDiskFreeSpaceExW.Call(
|
|
||||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
|
|
||||||
uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
|
|
||||||
uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
|
|
||||||
uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)))
|
|
||||||
if diskret == 0 {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &DiskUsageStat{
|
|
||||||
Path: path,
|
|
||||||
Total: uint64(lpTotalNumberOfBytes),
|
|
||||||
Free: uint64(lpTotalNumberOfFreeBytes),
|
|
||||||
// Used: uint64(lpTotalNumberOfBytes) - uint64(lpTotalNumberOfFreeBytes)
|
|
||||||
// UsedPercent: (float64(lpTotalNumberOfBytes) - float64(lpTotalNumberOfFreeBytes)) / float64(lpTotalNumberOfBytes) * 100
|
|
||||||
// InodesTotal: 0,
|
|
||||||
// InodesFree: 0,
|
|
||||||
// InodesUsed: 0,
|
|
||||||
// InodesUsedPercent: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
|
|
||||||
var ret []DiskPartitionStat
|
|
||||||
lpBuffer := make([]byte, 254)
|
|
||||||
diskret, _, err := procGetLogicalDriveStringsW.Call(
|
|
||||||
uintptr(len(lpBuffer)),
|
|
||||||
uintptr(unsafe.Pointer(&lpBuffer[0])))
|
|
||||||
if diskret == 0 {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
for _, v := range lpBuffer {
|
|
||||||
if v >= 65 && v <= 90 {
|
|
||||||
path := string(v) + ":"
|
|
||||||
if path == "A:" || path == "B:" { // skip floppy drives
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
typepath, _ := syscall.UTF16PtrFromString(path)
|
|
||||||
typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath)))
|
|
||||||
if typeret == 0 {
|
|
||||||
return ret, syscall.GetLastError()
|
|
||||||
}
|
|
||||||
// 2: DRIVE_REMOVABLE 3: DRIVE_FIXED 5: DRIVE_CDROM
|
|
||||||
|
|
||||||
if typeret == 2 || typeret == 3 || typeret == 5 {
|
|
||||||
lpVolumeNameBuffer := make([]byte, 256)
|
|
||||||
lpVolumeSerialNumber := int64(0)
|
|
||||||
lpMaximumComponentLength := int64(0)
|
|
||||||
lpFileSystemFlags := int64(0)
|
|
||||||
lpFileSystemNameBuffer := make([]byte, 256)
|
|
||||||
volpath, _ := syscall.UTF16PtrFromString(string(v) + ":/")
|
|
||||||
driveret, _, err := provGetVolumeInformation.Call(
|
|
||||||
uintptr(unsafe.Pointer(volpath)),
|
|
||||||
uintptr(unsafe.Pointer(&lpVolumeNameBuffer[0])),
|
|
||||||
uintptr(len(lpVolumeNameBuffer)),
|
|
||||||
uintptr(unsafe.Pointer(&lpVolumeSerialNumber)),
|
|
||||||
uintptr(unsafe.Pointer(&lpMaximumComponentLength)),
|
|
||||||
uintptr(unsafe.Pointer(&lpFileSystemFlags)),
|
|
||||||
uintptr(unsafe.Pointer(&lpFileSystemNameBuffer[0])),
|
|
||||||
uintptr(len(lpFileSystemNameBuffer)))
|
|
||||||
if driveret == 0 {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
opts := "rw"
|
|
||||||
if lpFileSystemFlags&FileReadOnlyVolume != 0 {
|
|
||||||
opts = "ro"
|
|
||||||
}
|
|
||||||
if lpFileSystemFlags&FileFileCompression != 0 {
|
|
||||||
opts += ".compress"
|
|
||||||
}
|
|
||||||
|
|
||||||
d := DiskPartitionStat{
|
|
||||||
Mountpoint: path,
|
|
||||||
Device: path,
|
|
||||||
Fstype: string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)),
|
|
||||||
Opts: opts,
|
|
||||||
}
|
|
||||||
ret = append(ret, d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
|
|
||||||
ret := make(map[string]DiskIOCountersStat, 0)
|
|
||||||
query, err := common.CreateQuery()
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
drivebuf := make([]byte, 256)
|
|
||||||
r, _, err := procGetLogicalDriveStringsW.Call(
|
|
||||||
uintptr(len(drivebuf)),
|
|
||||||
uintptr(unsafe.Pointer(&drivebuf[0])))
|
|
||||||
|
|
||||||
if r == 0 {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
drivemap := make(map[string][]*common.CounterInfo, 0)
|
|
||||||
for _, v := range drivebuf {
|
|
||||||
if v >= 65 && v <= 90 {
|
|
||||||
drive := string(v)
|
|
||||||
r, _, err = procGetDriveType.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(drive + `:\`))))
|
|
||||||
if r != common.DRIVE_FIXED {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
drivemap[drive] = make([]*common.CounterInfo, 0, 2)
|
|
||||||
var counter *common.CounterInfo
|
|
||||||
|
|
||||||
counter, err = common.CreateCounter(query,
|
|
||||||
"read",
|
|
||||||
fmt.Sprintf(`\PhysicalDisk(0 %s:)\Disk Reads/sec`, drive))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
drivemap[drive] = append(drivemap[drive], counter)
|
|
||||||
counter, err = common.CreateCounter(query,
|
|
||||||
"write",
|
|
||||||
fmt.Sprintf(`\PhysicalDisk(0 %s:)\Disk Writes/sec`, drive))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
drivemap[drive] = append(drivemap[drive], counter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r, _, err = common.PdhCollectQueryData.Call(uintptr(query))
|
|
||||||
if r != 0 && err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
time.Sleep(time.Duration(WaitMSec) * time.Millisecond)
|
|
||||||
r, _, err = common.PdhCollectQueryData.Call(uintptr(query))
|
|
||||||
if r != 0 && err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for drive, counters := range drivemap {
|
|
||||||
stat := DiskIOCountersStat{}
|
|
||||||
for _, v := range counters {
|
|
||||||
var fmtValue common.PDH_FMT_COUNTERVALUE_LARGE
|
|
||||||
r, _, err := common.PdhGetFormattedCounterValue.Call(uintptr(v.Counter), common.PDH_FMT_LARGE, uintptr(0), uintptr(unsafe.Pointer(&fmtValue)))
|
|
||||||
if r != 0 && r != common.PDH_INVALID_DATA {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch v.PostName {
|
|
||||||
case "read":
|
|
||||||
stat.ReadCount = uint64(fmtValue.LargeValue)
|
|
||||||
case "write":
|
|
||||||
stat.WriteCount = uint64(fmtValue.LargeValue)
|
|
||||||
default:
|
|
||||||
return ret, fmt.Errorf("unknown postname: %s", v.PostName)
|
|
||||||
}
|
|
||||||
stat.Name = drive
|
|
||||||
}
|
|
||||||
ret[drive] = stat
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
// +build ignore
|
|
||||||
// Hand writing: _Ctype_struct___0
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input to cgo -godefs.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
package disk
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <devstat.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
sizeofPtr = sizeof(void*),
|
|
||||||
};
|
|
||||||
|
|
||||||
// because statinfo has long double snap_time, redefine with changing long long
|
|
||||||
struct statinfo2 {
|
|
||||||
long cp_time[CPUSTATES];
|
|
||||||
long tk_nin;
|
|
||||||
long tk_nout;
|
|
||||||
struct devinfo *dinfo;
|
|
||||||
long long snap_time;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
sizeofLongDouble = C.sizeof_longlong
|
|
||||||
|
|
||||||
DEVSTAT_NO_DATA = 0x00
|
|
||||||
DEVSTAT_READ = 0x01
|
|
||||||
DEVSTAT_WRITE = 0x02
|
|
||||||
DEVSTAT_FREE = 0x03
|
|
||||||
|
|
||||||
// from sys/mount.h
|
|
||||||
MNT_RDONLY = 0x00000001 /* read only filesystem */
|
|
||||||
MNT_SYNCHRONOUS = 0x00000002 /* filesystem written synchronously */
|
|
||||||
MNT_NOEXEC = 0x00000004 /* can't exec from filesystem */
|
|
||||||
MNT_NOSUID = 0x00000008 /* don't honor setuid bits on fs */
|
|
||||||
MNT_UNION = 0x00000020 /* union with underlying filesystem */
|
|
||||||
MNT_ASYNC = 0x00000040 /* filesystem written asynchronously */
|
|
||||||
MNT_SUIDDIR = 0x00100000 /* special handling of SUID on dirs */
|
|
||||||
MNT_SOFTDEP = 0x00200000 /* soft updates being done */
|
|
||||||
MNT_NOSYMFOLLOW = 0x00400000 /* do not follow symlinks */
|
|
||||||
MNT_GJOURNAL = 0x02000000 /* GEOM journal support enabled */
|
|
||||||
MNT_MULTILABEL = 0x04000000 /* MAC support for individual objects */
|
|
||||||
MNT_ACLS = 0x08000000 /* ACL support enabled */
|
|
||||||
MNT_NOATIME = 0x10000000 /* disable update of file access time */
|
|
||||||
MNT_NOCLUSTERR = 0x40000000 /* disable cluster read */
|
|
||||||
MNT_NOCLUSTERW = 0x80000000 /* disable cluster write */
|
|
||||||
MNT_NFS4ACLS = 0x00000010
|
|
||||||
|
|
||||||
MNT_WAIT = 1 /* synchronously wait for I/O to complete */
|
|
||||||
MNT_NOWAIT = 2 /* start all I/O, but do not wait for it */
|
|
||||||
MNT_LAZY = 3 /* push data not written by filesystem syncer */
|
|
||||||
MNT_SUSPEND = 4 /* Suspend file system after sync */
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
// Basic types
|
|
||||||
|
|
||||||
type (
|
|
||||||
_C_short C.short
|
|
||||||
_C_int C.int
|
|
||||||
_C_long C.long
|
|
||||||
_C_long_long C.longlong
|
|
||||||
_C_long_double C.longlong
|
|
||||||
)
|
|
||||||
|
|
||||||
type Statfs C.struct_statfs
|
|
||||||
type Fsid C.struct_fsid
|
|
||||||
|
|
||||||
type Devstat C.struct_devstat
|
|
||||||
type Bintime C.struct_bintime
|
|
|
@ -1 +0,0 @@
|
||||||
package gopsutil
|
|
|
@ -1,36 +0,0 @@
|
||||||
package docker
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
var ErrNotAvailable = errors.New("docker not available")
|
|
||||||
|
|
||||||
type CgroupMemStat struct {
|
|
||||||
ContainerID string `json:"container_id"`
|
|
||||||
Cache uint64 `json:"cache"`
|
|
||||||
RSS uint64 `json:"rss"`
|
|
||||||
RSSHuge uint64 `json:"rss_huge"`
|
|
||||||
MappedFile uint64 `json:"mapped_file"`
|
|
||||||
Pgpgin uint64 `json:"pgpgin"`
|
|
||||||
Pgpgout uint64 `json:"pgpgout"`
|
|
||||||
Pgfault uint64 `json:"pgfault"`
|
|
||||||
Pgmajfault uint64 `json:"pgmajfault"`
|
|
||||||
InactiveAnon uint64 `json:"inactive_anon"`
|
|
||||||
ActiveAnon uint64 `json:"active_anon"`
|
|
||||||
InactiveFile uint64 `json:"inactive_file"`
|
|
||||||
ActiveFile uint64 `json:"active_file"`
|
|
||||||
Unevictable uint64 `json:"unevictable"`
|
|
||||||
HierarchicalMemoryLimit uint64 `json:"hierarchical_memory_limit"`
|
|
||||||
TotalCache uint64 `json:"total_cache"`
|
|
||||||
TotalRSS uint64 `json:"total_rss"`
|
|
||||||
TotalRSSHuge uint64 `json:"total_rss_huge"`
|
|
||||||
TotalMappedFile uint64 `json:"total_mapped_file"`
|
|
||||||
TotalPgpgIn uint64 `json:"total_pgpgin"`
|
|
||||||
TotalPgpgOut uint64 `json:"total_pgpgout"`
|
|
||||||
TotalPgFault uint64 `json:"total_pgfault"`
|
|
||||||
TotalPgMajFault uint64 `json:"total_pgmajfault"`
|
|
||||||
TotalInactiveAnon uint64 `json:"total_inactive_anon"`
|
|
||||||
TotalActiveAnon uint64 `json:"total_active_anon"`
|
|
||||||
TotalInactiveFile uint64 `json:"total_inactive_file"`
|
|
||||||
TotalActiveFile uint64 `json:"total_active_file"`
|
|
||||||
TotalUnevictable uint64 `json:"total_unevictable"`
|
|
||||||
}
|
|
|
@ -1,182 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package docker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetDockerIDList returnes a list of DockerID.
|
|
||||||
// This requires certain permission.
|
|
||||||
func GetDockerIDList() ([]string, error) {
|
|
||||||
path, err := exec.LookPath("docker")
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrNotAvailable
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := exec.Command(path, "ps", "-q", "--no-trunc").Output()
|
|
||||||
if err != nil {
|
|
||||||
return []string{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(string(out), "\n")
|
|
||||||
ret := make([]string, 0, len(lines))
|
|
||||||
|
|
||||||
for _, l := range lines {
|
|
||||||
if l == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = append(ret, l)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CgroupCPU returnes specified cgroup id CPU status.
|
|
||||||
// containerid is same as docker id if you use docker.
|
|
||||||
// If you use container via systemd.slice, you could use
|
|
||||||
// containerid = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
|
|
||||||
func CgroupCPU(containerid string, base string) (*cpu.CPUTimesStat, error) {
|
|
||||||
if len(base) == 0 {
|
|
||||||
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)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// empty containerid means all cgroup
|
|
||||||
if len(containerid) == 0 {
|
|
||||||
containerid = "all"
|
|
||||||
}
|
|
||||||
ret := &cpu.CPUTimesStat{CPU: containerid}
|
|
||||||
for _, line := range lines {
|
|
||||||
fields := strings.Split(line, " ")
|
|
||||||
if fields[0] == "user" {
|
|
||||||
user, err := strconv.ParseFloat(fields[1], 64)
|
|
||||||
if err == nil {
|
|
||||||
ret.User = float64(user)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if fields[0] == "system" {
|
|
||||||
system, err := strconv.ParseFloat(fields[1], 64)
|
|
||||||
if err == nil {
|
|
||||||
ret.System = float64(system)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CgroupCPUDocker(containerid string) (*cpu.CPUTimesStat, error) {
|
|
||||||
return CgroupCPU(containerid, "/sys/fs/cgroup/cpuacct/docker")
|
|
||||||
}
|
|
||||||
|
|
||||||
func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
|
|
||||||
if len(base) == 0 {
|
|
||||||
base = "/sys/fs/cgroup/memory/docker"
|
|
||||||
}
|
|
||||||
statfile := path.Join(base, containerid, "memory.stat")
|
|
||||||
|
|
||||||
if _, err := os.Stat(statfile); os.IsNotExist(err) {
|
|
||||||
statfile = path.Join("/sys/fs/cgroup/memory/system.slice", "docker-" + containerid + ".scope", "memory.stat")
|
|
||||||
}
|
|
||||||
|
|
||||||
// empty containerid means all cgroup
|
|
||||||
if len(containerid) == 0 {
|
|
||||||
containerid = "all"
|
|
||||||
}
|
|
||||||
lines, err := common.ReadLines(statfile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ret := &CgroupMemStat{ContainerID: containerid}
|
|
||||||
for _, line := range lines {
|
|
||||||
fields := strings.Split(line, " ")
|
|
||||||
v, err := strconv.ParseUint(fields[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch fields[0] {
|
|
||||||
case "cache":
|
|
||||||
ret.Cache = v
|
|
||||||
case "rss":
|
|
||||||
ret.RSS = v
|
|
||||||
case "rss_huge":
|
|
||||||
ret.RSSHuge = v
|
|
||||||
case "mapped_file":
|
|
||||||
ret.MappedFile = v
|
|
||||||
case "pgpgin":
|
|
||||||
ret.Pgpgin = v
|
|
||||||
case "pgpgout":
|
|
||||||
ret.Pgpgout = v
|
|
||||||
case "pgfault":
|
|
||||||
ret.Pgfault = v
|
|
||||||
case "pgmajfault":
|
|
||||||
ret.Pgmajfault = v
|
|
||||||
case "inactive_anon":
|
|
||||||
ret.InactiveAnon = v
|
|
||||||
case "active_anon":
|
|
||||||
ret.ActiveAnon = v
|
|
||||||
case "inactive_file":
|
|
||||||
ret.InactiveFile = v
|
|
||||||
case "active_file":
|
|
||||||
ret.ActiveFile = v
|
|
||||||
case "unevictable":
|
|
||||||
ret.Unevictable = v
|
|
||||||
case "hierarchical_memory_limit":
|
|
||||||
ret.HierarchicalMemoryLimit = v
|
|
||||||
case "total_cache":
|
|
||||||
ret.TotalCache = v
|
|
||||||
case "total_rss":
|
|
||||||
ret.TotalRSS = v
|
|
||||||
case "total_rss_huge":
|
|
||||||
ret.TotalRSSHuge = v
|
|
||||||
case "total_mapped_file":
|
|
||||||
ret.TotalMappedFile = v
|
|
||||||
case "total_pgpgin":
|
|
||||||
ret.TotalPgpgIn = v
|
|
||||||
case "total_pgpgout":
|
|
||||||
ret.TotalPgpgOut = v
|
|
||||||
case "total_pgfault":
|
|
||||||
ret.TotalPgFault = v
|
|
||||||
case "total_pgmajfault":
|
|
||||||
ret.TotalPgMajFault = v
|
|
||||||
case "total_inactive_anon":
|
|
||||||
ret.TotalInactiveAnon = v
|
|
||||||
case "total_active_anon":
|
|
||||||
ret.TotalActiveAnon = v
|
|
||||||
case "total_inactive_file":
|
|
||||||
ret.TotalInactiveFile = v
|
|
||||||
case "total_active_file":
|
|
||||||
ret.TotalActiveFile = v
|
|
||||||
case "total_unevictable":
|
|
||||||
ret.TotalUnevictable = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CgroupMemDocker(containerid string) (*CgroupMemStat, error) {
|
|
||||||
return CgroupMem(containerid, "/sys/fs/cgroup/memory/docker")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m CgroupMemStat) String() string {
|
|
||||||
s, _ := json.Marshal(m)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package docker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetDockerIDList(t *testing.T) {
|
|
||||||
// If there is not docker environment, this test always fail.
|
|
||||||
// not tested here
|
|
||||||
/*
|
|
||||||
_, err := GetDockerIDList()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCgroupCPU(t *testing.T) {
|
|
||||||
v, _ := GetDockerIDList()
|
|
||||||
for _, id := range v {
|
|
||||||
v, err := CgroupCPUDocker(id)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
if v.CPU == "" {
|
|
||||||
t.Errorf("could not get CgroupCPU %v", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCgroupCPUInvalidId(t *testing.T) {
|
|
||||||
_, err := CgroupCPUDocker("bad id")
|
|
||||||
if err == nil {
|
|
||||||
t.Error("Expected path does not exist error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCgroupMem(t *testing.T) {
|
|
||||||
v, _ := GetDockerIDList()
|
|
||||||
for _, id := range v {
|
|
||||||
v, err := CgroupMemDocker(id)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
empty := &CgroupMemStat{}
|
|
||||||
if v == empty {
|
|
||||||
t.Errorf("Could not CgroupMemStat %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCgroupMemInvalidId(t *testing.T) {
|
|
||||||
_, err := CgroupMemDocker("bad id")
|
|
||||||
if err == nil {
|
|
||||||
t.Error("Expected path does not exist error")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
// +build !linux
|
|
||||||
|
|
||||||
package docker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetDockerIDList returnes a list of DockerID.
|
|
||||||
// This requires certain permission.
|
|
||||||
func GetDockerIDList() ([]string, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
// CgroupCPU returnes specified cgroup id CPU status.
|
|
||||||
// containerid is same as docker id if you use docker.
|
|
||||||
// If you use container via systemd.slice, you could use
|
|
||||||
// containerid = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
|
|
||||||
func CgroupCPU(containerid string, base string) (*cpu.CPUTimesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func CgroupCPUDocker(containerid string) (*cpu.CPUTimesStat, error) {
|
|
||||||
return CgroupCPU(containerid, "/sys/fs/cgroup/cpuacct/docker")
|
|
||||||
}
|
|
||||||
|
|
||||||
func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func CgroupMemDocker(containerid string) (*CgroupMemStat, error) {
|
|
||||||
return CgroupMem(containerid, "/sys/fs/cgroup/memory/docker")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m CgroupMemStat) String() string {
|
|
||||||
s, _ := json.Marshal(m)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
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)
|
|
||||||
}
|
|
|
@ -1,139 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func HostInfo() (*HostInfoStat, error) {
|
|
||||||
ret := &HostInfoStat{
|
|
||||||
OS: runtime.GOOS,
|
|
||||||
PlatformFamily: "darwin",
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
// 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
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/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 {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
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/utmp"
|
|
||||||
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
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
// +build amd64
|
|
||||||
// Created by cgo -godefs - DO NOT EDIT
|
|
||||||
// cgo -godefs host/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
|
|
||||||
}
|
|
|
@ -1,362 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
type LSB struct {
|
|
||||||
ID string
|
|
||||||
Release string
|
|
||||||
Codename string
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
func HostInfo() (*HostInfoStat, error) {
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &HostInfoStat{
|
|
||||||
Hostname: hostname,
|
|
||||||
OS: runtime.GOOS,
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
func BootTime() (uint64, error) {
|
|
||||||
sysinfo := &syscall.Sysinfo_t{}
|
|
||||||
if err := syscall.Sysinfo(sysinfo); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uint64(sysinfo.Uptime), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
// TODO: suse detection
|
|
||||||
// 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":
|
|
||||||
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 GetVirtualization() (string, string, error) {
|
|
||||||
var system string
|
|
||||||
var role string
|
|
||||||
|
|
||||||
if common.PathExists("/proc/xen") {
|
|
||||||
system = "xen"
|
|
||||||
role = "guest" // assume guest
|
|
||||||
|
|
||||||
if common.PathExists("/proc/xen/capabilities") {
|
|
||||||
contents, err := common.ReadLines("/proc/xen/capabilities")
|
|
||||||
if err == nil {
|
|
||||||
if common.StringContains(contents, "control_d") {
|
|
||||||
role = "host"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if common.PathExists("/proc/modules") {
|
|
||||||
contents, err := common.ReadLines("/proc/modules")
|
|
||||||
if err == nil {
|
|
||||||
if common.StringContains(contents, "kvm") {
|
|
||||||
system = "kvm"
|
|
||||||
role = "host"
|
|
||||||
} else if common.StringContains(contents, "vboxdrv") {
|
|
||||||
system = "vbox"
|
|
||||||
role = "host"
|
|
||||||
} else if common.StringContains(contents, "vboxguest") {
|
|
||||||
system = "vbox"
|
|
||||||
role = "guest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if common.PathExists("/proc/cpuinfo") {
|
|
||||||
contents, err := common.ReadLines("/proc/cpuinfo")
|
|
||||||
if err == nil {
|
|
||||||
if common.StringContains(contents, "QEMU Virtual CPU") ||
|
|
||||||
common.StringContains(contents, "Common KVM processor") ||
|
|
||||||
common.StringContains(contents, "Common 32-bit KVM processor") {
|
|
||||||
system = "kvm"
|
|
||||||
role = "guest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if common.PathExists("/proc/bc/0") {
|
|
||||||
system = "openvz"
|
|
||||||
role = "host"
|
|
||||||
} else if common.PathExists("/proc/vz") {
|
|
||||||
system = "openvz"
|
|
||||||
role = "guest"
|
|
||||||
}
|
|
||||||
|
|
||||||
// not use dmidecode because it requires root
|
|
||||||
|
|
||||||
if common.PathExists("/proc/self/status") {
|
|
||||||
contents, err := common.ReadLines("/proc/self/status")
|
|
||||||
if err == nil {
|
|
||||||
|
|
||||||
if common.StringContains(contents, "s_context:") ||
|
|
||||||
common.StringContains(contents, "VxID:") {
|
|
||||||
system = "linux-vserver"
|
|
||||||
}
|
|
||||||
// TODO: guest or host
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if common.PathExists("/proc/self/cgroup") {
|
|
||||||
contents, err := common.ReadLines("/proc/self/cgroup")
|
|
||||||
if err == nil {
|
|
||||||
|
|
||||||
if common.StringContains(contents, "lxc") ||
|
|
||||||
common.StringContains(contents, "docker") {
|
|
||||||
system = "lxc"
|
|
||||||
role = "guest"
|
|
||||||
} else if common.PathExists("/usr/bin/lxc-version") { // TODO: which
|
|
||||||
system = "lxc"
|
|
||||||
role = "host"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return system, role, nil
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
// 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
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
// 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
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// +build linux
|
|
||||||
// +build arm
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
type exitStatus struct {
|
|
||||||
Etermination int16 // Process termination status.
|
|
||||||
Eexit int16 // Process exit status.
|
|
||||||
}
|
|
||||||
type timeval struct {
|
|
||||||
TvSec uint32 // Seconds.
|
|
||||||
TvUsec uint32 // Microseconds.
|
|
||||||
}
|
|
||||||
|
|
||||||
type utmp struct {
|
|
||||||
Type int16 // Type of login.
|
|
||||||
Pid int32 // Process ID of login process.
|
|
||||||
Line [32]byte // Devicename.
|
|
||||||
ID [4]byte // Inittab ID.
|
|
||||||
User [32]byte // Username.
|
|
||||||
Host [256]byte // Hostname for remote login.
|
|
||||||
Exit exitStatus // Exit status of a process marked
|
|
||||||
Session int32 // Session ID, used for windowing.
|
|
||||||
Tv timeval // Time entry was made.
|
|
||||||
AddrV6 [16]byte // Internet address of remote host.
|
|
||||||
Unused [20]byte // Reserved for future use. // original is 20
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
// +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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
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 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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
process "github.com/influxdb/telegraf/plugins/system/ps/process"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime")
|
|
||||||
)
|
|
||||||
|
|
||||||
func HostInfo() (*HostInfoStat, error) {
|
|
||||||
ret := &HostInfoStat{}
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.Hostname = hostname
|
|
||||||
uptime, err := BootTime()
|
|
||||||
if err == nil {
|
|
||||||
ret.Uptime = uptime
|
|
||||||
}
|
|
||||||
|
|
||||||
procs, err := process.Pids()
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.Procs = uint64(len(procs))
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BootTime() (uint64, error) {
|
|
||||||
lines, err := common.GetWmic("os", "get", "LastBootUpTime")
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if len(lines) == 0 || len(lines[0]) != 2 {
|
|
||||||
return 0, fmt.Errorf("could not get LastBootUpTime")
|
|
||||||
}
|
|
||||||
format := "20060102150405"
|
|
||||||
t, err := time.Parse(format, strings.Split(lines[0][1], ".")[0])
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
now := time.Now()
|
|
||||||
return uint64(now.Sub(t).Seconds()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Users() ([]UserStat, error) {
|
|
||||||
|
|
||||||
var ret []UserStat
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
// +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
|
|
|
@ -1,40 +0,0 @@
|
||||||
// +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
|
|
|
@ -1,45 +0,0 @@
|
||||||
// +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
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package load
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type LoadAvgStat struct {
|
|
||||||
Load1 float64 `json:"load1"`
|
|
||||||
Load5 float64 `json:"load5"`
|
|
||||||
Load15 float64 `json:"load15"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l LoadAvgStat) String() string {
|
|
||||||
s, _ := json.Marshal(l)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package load
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func LoadAvg() (*LoadAvgStat, error) {
|
|
||||||
values, err := common.DoSysctrl("vm.loadavg")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
load1, err := strconv.ParseFloat(values[0], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
load5, err := strconv.ParseFloat(values[1], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
load15, err := strconv.ParseFloat(values[2], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &LoadAvgStat{
|
|
||||||
Load1: float64(load1),
|
|
||||||
Load5: float64(load5),
|
|
||||||
Load15: float64(load15),
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package load
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func LoadAvg() (*LoadAvgStat, error) {
|
|
||||||
values, err := common.DoSysctrl("vm.loadavg")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
load1, err := strconv.ParseFloat(values[0], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
load5, err := strconv.ParseFloat(values[1], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
load15, err := strconv.ParseFloat(values[2], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &LoadAvgStat{
|
|
||||||
Load1: float64(load1),
|
|
||||||
Load5: float64(load5),
|
|
||||||
Load15: float64(load15),
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package load
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func LoadAvg() (*LoadAvgStat, error) {
|
|
||||||
filename := "/proc/loadavg"
|
|
||||||
line, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
values := strings.Fields(string(line))
|
|
||||||
|
|
||||||
load1, err := strconv.ParseFloat(values[0], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
load5, err := strconv.ParseFloat(values[1], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
load15, err := strconv.ParseFloat(values[2], 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &LoadAvgStat{
|
|
||||||
Load1: load1,
|
|
||||||
Load5: load5,
|
|
||||||
Load15: load15,
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package load
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLoad(t *testing.T) {
|
|
||||||
v, err := LoadAvg()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
empty := &LoadAvgStat{}
|
|
||||||
if v == empty {
|
|
||||||
t.Errorf("error load: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLoadAvgStat_String(t *testing.T) {
|
|
||||||
v := LoadAvgStat{
|
|
||||||
Load1: 10.1,
|
|
||||||
Load5: 20.1,
|
|
||||||
Load15: 30.1,
|
|
||||||
}
|
|
||||||
e := `{"load1":10.1,"load5":20.1,"load15":30.1}`
|
|
||||||
if e != fmt.Sprintf("%v", v) {
|
|
||||||
t.Errorf("LoadAvgStat string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package load
|
|
||||||
|
|
||||||
import (
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func LoadAvg() (*LoadAvgStat, error) {
|
|
||||||
ret := LoadAvgStat{}
|
|
||||||
|
|
||||||
return &ret, common.NotImplementedError
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package mem
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type VirtualMemoryStat struct {
|
|
||||||
Total uint64 `json:"total"`
|
|
||||||
Available uint64 `json:"available"`
|
|
||||||
Used uint64 `json:"used"`
|
|
||||||
UsedPercent float64 `json:"used_percent"`
|
|
||||||
Free uint64 `json:"free"`
|
|
||||||
Active uint64 `json:"active"`
|
|
||||||
Inactive uint64 `json:"inactive"`
|
|
||||||
Buffers uint64 `json:"buffers"`
|
|
||||||
Cached uint64 `json:"cached"`
|
|
||||||
Wired uint64 `json:"wired"`
|
|
||||||
Shared uint64 `json:"shared"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SwapMemoryStat struct {
|
|
||||||
Total uint64 `json:"total"`
|
|
||||||
Used uint64 `json:"used"`
|
|
||||||
Free uint64 `json:"free"`
|
|
||||||
UsedPercent float64 `json:"used_percent"`
|
|
||||||
Sin uint64 `json:"sin"`
|
|
||||||
Sout uint64 `json:"sout"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m VirtualMemoryStat) String() string {
|
|
||||||
s, _ := json.Marshal(m)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m SwapMemoryStat) String() string {
|
|
||||||
s, _ := json.Marshal(m)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package mem
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getPageSize() (uint64, error) {
|
|
||||||
out, err := exec.Command("pagesize").Output()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
o := strings.TrimSpace(string(out))
|
|
||||||
p, err := strconv.ParseUint(o, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// VirtualMemory returns VirtualmemoryStat.
|
|
||||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
|
||||||
p, err := getPageSize()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
total, err := common.DoSysctrl("hw.memsize")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
free, err := common.DoSysctrl("vm.page_free_count")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
parsed := make([]uint64, 0, 7)
|
|
||||||
vv := []string{
|
|
||||||
total[0],
|
|
||||||
free[0],
|
|
||||||
}
|
|
||||||
for _, target := range vv {
|
|
||||||
t, err := strconv.ParseUint(target, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
parsed = append(parsed, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &VirtualMemoryStat{
|
|
||||||
Total: parsed[0],
|
|
||||||
Free: parsed[1] * p,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: platform independent (worked freebsd?)
|
|
||||||
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
|
||||||
|
|
||||||
ret.Used = ret.Total - ret.Free
|
|
||||||
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwapMemory returns swapinfo.
|
|
||||||
func SwapMemory() (*SwapMemoryStat, error) {
|
|
||||||
var ret *SwapMemoryStat
|
|
||||||
|
|
||||||
swapUsage, err := common.DoSysctrl("vm.swapusage")
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
total := strings.Replace(swapUsage[2], "M", "", 1)
|
|
||||||
used := strings.Replace(swapUsage[5], "M", "", 1)
|
|
||||||
free := strings.Replace(swapUsage[8], "M", "", 1)
|
|
||||||
|
|
||||||
total_v, err := strconv.ParseFloat(total, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
used_v, err := strconv.ParseFloat(used, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
free_v, err := strconv.ParseFloat(free, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
u := float64(0)
|
|
||||||
if total_v != 0 {
|
|
||||||
u = ((total_v - free_v) / total_v) * 100.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// vm.swapusage shows "M", multiply 1000
|
|
||||||
ret = &SwapMemoryStat{
|
|
||||||
Total: uint64(total_v * 1000),
|
|
||||||
Used: uint64(used_v * 1000),
|
|
||||||
Free: uint64(free_v * 1000),
|
|
||||||
UsedPercent: u,
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package mem
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
|
||||||
pageSize, err := common.DoSysctrl("vm.stats.vm.v_page_size")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p, err := strconv.ParseUint(pageSize[0], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pageCount, err := common.DoSysctrl("vm.stats.vm.v_page_count")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
free, err := common.DoSysctrl("vm.stats.vm.v_free_count")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
active, err := common.DoSysctrl("vm.stats.vm.v_active_count")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
inactive, err := common.DoSysctrl("vm.stats.vm.v_inactive_count")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cache, err := common.DoSysctrl("vm.stats.vm.v_cache_count")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
buffer, err := common.DoSysctrl("vfs.bufspace")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
wired, err := common.DoSysctrl("vm.stats.vm.v_wire_count")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed := make([]uint64, 0, 7)
|
|
||||||
vv := []string{
|
|
||||||
pageCount[0],
|
|
||||||
free[0],
|
|
||||||
active[0],
|
|
||||||
inactive[0],
|
|
||||||
cache[0],
|
|
||||||
buffer[0],
|
|
||||||
wired[0],
|
|
||||||
}
|
|
||||||
for _, target := range vv {
|
|
||||||
t, err := strconv.ParseUint(target, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
parsed = append(parsed, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &VirtualMemoryStat{
|
|
||||||
Total: parsed[0] * p,
|
|
||||||
Free: parsed[1] * p,
|
|
||||||
Active: parsed[2] * p,
|
|
||||||
Inactive: parsed[3] * p,
|
|
||||||
Cached: parsed[4] * p,
|
|
||||||
Buffers: parsed[5],
|
|
||||||
Wired: parsed[6] * p,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: platform independent (worked freebsd?)
|
|
||||||
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
|
||||||
|
|
||||||
ret.Used = ret.Total - ret.Free
|
|
||||||
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return swapinfo
|
|
||||||
// FreeBSD can have multiple swap devices. but use only first device
|
|
||||||
func SwapMemory() (*SwapMemoryStat, error) {
|
|
||||||
out, err := exec.Command("swapinfo").Output()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var ret *SwapMemoryStat
|
|
||||||
for _, line := range strings.Split(string(out), "\n") {
|
|
||||||
values := strings.Fields(line)
|
|
||||||
// skip title line
|
|
||||||
if len(values) == 0 || values[0] == "Device" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
u := strings.Replace(values[4], "%", "", 1)
|
|
||||||
total_v, err := strconv.ParseUint(values[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
used_v, err := strconv.ParseUint(values[2], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
free_v, err := strconv.ParseUint(values[3], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
up_v, err := strconv.ParseFloat(u, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = &SwapMemoryStat{
|
|
||||||
Total: total_v,
|
|
||||||
Used: used_v,
|
|
||||||
Free: free_v,
|
|
||||||
UsedPercent: up_v,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package mem
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
|
||||||
filename := "/proc/meminfo"
|
|
||||||
lines, _ := common.ReadLines(filename)
|
|
||||||
|
|
||||||
ret := &VirtualMemoryStat{}
|
|
||||||
for _, line := range lines {
|
|
||||||
fields := strings.Split(line, ":")
|
|
||||||
if len(fields) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
key := strings.TrimSpace(fields[0])
|
|
||||||
value := strings.TrimSpace(fields[1])
|
|
||||||
value = strings.Replace(value, " kB", "", -1)
|
|
||||||
|
|
||||||
t, err := strconv.ParseUint(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
switch key {
|
|
||||||
case "MemTotal":
|
|
||||||
ret.Total = t * 1024
|
|
||||||
case "MemFree":
|
|
||||||
ret.Free = t * 1024
|
|
||||||
case "Buffers":
|
|
||||||
ret.Buffers = t * 1024
|
|
||||||
case "Cached":
|
|
||||||
ret.Cached = t * 1024
|
|
||||||
case "Active":
|
|
||||||
ret.Active = t * 1024
|
|
||||||
case "Inactive":
|
|
||||||
ret.Inactive = t * 1024
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
|
||||||
ret.Used = ret.Total - ret.Free
|
|
||||||
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func SwapMemory() (*SwapMemoryStat, error) {
|
|
||||||
sysinfo := &syscall.Sysinfo_t{}
|
|
||||||
|
|
||||||
if err := syscall.Sysinfo(sysinfo); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ret := &SwapMemoryStat{
|
|
||||||
Total: uint64(sysinfo.Totalswap),
|
|
||||||
Free: uint64(sysinfo.Freeswap),
|
|
||||||
}
|
|
||||||
ret.Used = ret.Total - ret.Free
|
|
||||||
//check Infinity
|
|
||||||
if ret.Total != 0 {
|
|
||||||
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
|
|
||||||
} else {
|
|
||||||
ret.UsedPercent = 0
|
|
||||||
}
|
|
||||||
lines, _ := common.ReadLines("/proc/vmstat")
|
|
||||||
for _, l := range lines {
|
|
||||||
fields := strings.Fields(l)
|
|
||||||
if len(fields) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch fields[0] {
|
|
||||||
case "pswpin":
|
|
||||||
value, err := strconv.ParseUint(fields[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ret.Sin = value * 4 * 1024
|
|
||||||
case "pswpout":
|
|
||||||
value, err := strconv.ParseUint(fields[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ret.Sout = value * 4 * 1024
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
package mem
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestVirtual_memory(t *testing.T) {
|
|
||||||
v, err := VirtualMemory()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
empty := &VirtualMemoryStat{}
|
|
||||||
if v == empty {
|
|
||||||
t.Errorf("error %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSwap_memory(t *testing.T) {
|
|
||||||
v, err := SwapMemory()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
empty := &SwapMemoryStat{}
|
|
||||||
if v == empty {
|
|
||||||
t.Errorf("error %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVirtualMemoryStat_String(t *testing.T) {
|
|
||||||
v := VirtualMemoryStat{
|
|
||||||
Total: 10,
|
|
||||||
Available: 20,
|
|
||||||
Used: 30,
|
|
||||||
UsedPercent: 30.1,
|
|
||||||
Free: 40,
|
|
||||||
}
|
|
||||||
e := `{"total":10,"available":20,"used":30,"used_percent":30.1,"free":40,"active":0,"inactive":0,"buffers":0,"cached":0,"wired":0,"shared":0}`
|
|
||||||
if e != fmt.Sprintf("%v", v) {
|
|
||||||
t.Errorf("VirtualMemoryStat string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSwapMemoryStat_String(t *testing.T) {
|
|
||||||
v := SwapMemoryStat{
|
|
||||||
Total: 10,
|
|
||||||
Used: 30,
|
|
||||||
Free: 40,
|
|
||||||
UsedPercent: 30.1,
|
|
||||||
}
|
|
||||||
e := `{"total":10,"used":30,"free":40,"used_percent":30.1,"sin":0,"sout":0}`
|
|
||||||
if e != fmt.Sprintf("%v", v) {
|
|
||||||
t.Errorf("SwapMemoryStat string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package mem
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
procGlobalMemoryStatusEx = common.Modkernel32.NewProc("GlobalMemoryStatusEx")
|
|
||||||
)
|
|
||||||
|
|
||||||
type MEMORYSTATUSEX struct {
|
|
||||||
cbSize uint32
|
|
||||||
dwMemoryLoad uint32
|
|
||||||
ullTotalPhys uint64 // in bytes
|
|
||||||
ullAvailPhys uint64
|
|
||||||
ullTotalPageFile uint64
|
|
||||||
ullAvailPageFile uint64
|
|
||||||
ullTotalVirtual uint64
|
|
||||||
ullAvailVirtual uint64
|
|
||||||
ullAvailExtendedVirtual uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
|
||||||
var memInfo MEMORYSTATUSEX
|
|
||||||
memInfo.cbSize = uint32(unsafe.Sizeof(memInfo))
|
|
||||||
mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo)))
|
|
||||||
if mem == 0 {
|
|
||||||
return nil, syscall.GetLastError()
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &VirtualMemoryStat{
|
|
||||||
Total: memInfo.ullTotalPhys,
|
|
||||||
Available: memInfo.ullAvailPhys,
|
|
||||||
UsedPercent: float64(memInfo.dwMemoryLoad),
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.Used = ret.Total - ret.Available
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func SwapMemory() (*SwapMemoryStat, error) {
|
|
||||||
ret := &SwapMemoryStat{}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
|
@ -1,137 +0,0 @@
|
||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
type NetIOCountersStat struct {
|
|
||||||
Name string `json:"name"` // interface name
|
|
||||||
BytesSent uint64 `json:"bytes_sent"` // number of bytes sent
|
|
||||||
BytesRecv uint64 `json:"bytes_recv"` // number of bytes received
|
|
||||||
PacketsSent uint64 `json:"packets_sent"` // number of packets sent
|
|
||||||
PacketsRecv uint64 `json:"packets_recv"` // number of packets received
|
|
||||||
Errin uint64 `json:"errin"` // total number of errors while receiving
|
|
||||||
Errout uint64 `json:"errout"` // total number of errors while sending
|
|
||||||
Dropin uint64 `json:"dropin"` // total number of incoming packets which were dropped
|
|
||||||
Dropout uint64 `json:"dropout"` // total number of outgoing packets which were dropped (always 0 on OSX and BSD)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Addr is implemented compatibility to psutil
|
|
||||||
type Addr struct {
|
|
||||||
IP string `json:"ip"`
|
|
||||||
Port uint32 `json:"port"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type NetConnectionStat struct {
|
|
||||||
Fd uint32 `json:"fd"`
|
|
||||||
Family uint32 `json:"family"`
|
|
||||||
Type uint32 `json:"type"`
|
|
||||||
Laddr Addr `json:"localaddr"`
|
|
||||||
Raddr Addr `json:"remoteaddr"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
Pid int32 `json:"pid"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetInterfaceAddr is designed for represent interface addresses
|
|
||||||
type NetInterfaceAddr struct {
|
|
||||||
Addr string `json:"addr"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type NetInterfaceStat struct {
|
|
||||||
MTU int `json:"mtu"` // maximum transmission unit
|
|
||||||
Name string `json:"name"` // e.g., "en0", "lo0", "eth0.100"
|
|
||||||
HardwareAddr string `json:"hardwareaddr"` // IEEE MAC-48, EUI-48 and EUI-64 form
|
|
||||||
Flags []string `json:"flags"` // e.g., FlagUp, FlagLoopback, FlagMulticast
|
|
||||||
Addrs []NetInterfaceAddr `json:"addrs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n NetIOCountersStat) String() string {
|
|
||||||
s, _ := json.Marshal(n)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n NetConnectionStat) String() string {
|
|
||||||
s, _ := json.Marshal(n)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a Addr) String() string {
|
|
||||||
s, _ := json.Marshal(a)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n NetInterfaceStat) String() string {
|
|
||||||
s, _ := json.Marshal(n)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n NetInterfaceAddr) String() string {
|
|
||||||
s, _ := json.Marshal(n)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NetInterfaces() ([]NetInterfaceStat, error) {
|
|
||||||
is, err := net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ret := make([]NetInterfaceStat, 0, len(is))
|
|
||||||
for _, ifi := range is {
|
|
||||||
|
|
||||||
var flags []string
|
|
||||||
if ifi.Flags&net.FlagUp != 0 {
|
|
||||||
flags = append(flags, "up")
|
|
||||||
}
|
|
||||||
if ifi.Flags&net.FlagBroadcast != 0 {
|
|
||||||
flags = append(flags, "broadcast")
|
|
||||||
}
|
|
||||||
if ifi.Flags&net.FlagLoopback != 0 {
|
|
||||||
flags = append(flags, "loopback")
|
|
||||||
}
|
|
||||||
if ifi.Flags&net.FlagPointToPoint != 0 {
|
|
||||||
flags = append(flags, "pointtopoint")
|
|
||||||
}
|
|
||||||
if ifi.Flags&net.FlagMulticast != 0 {
|
|
||||||
flags = append(flags, "multicast")
|
|
||||||
}
|
|
||||||
|
|
||||||
r := NetInterfaceStat{
|
|
||||||
Name: ifi.Name,
|
|
||||||
MTU: ifi.MTU,
|
|
||||||
HardwareAddr: ifi.HardwareAddr.String(),
|
|
||||||
Flags: flags,
|
|
||||||
}
|
|
||||||
addrs, err := ifi.Addrs()
|
|
||||||
if err == nil {
|
|
||||||
r.Addrs = make([]NetInterfaceAddr, 0, len(addrs))
|
|
||||||
for _, addr := range addrs {
|
|
||||||
r.Addrs = append(r.Addrs, NetInterfaceAddr{
|
|
||||||
Addr: addr.String(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
ret = append(ret, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNetIOCountersAll(n []NetIOCountersStat) ([]NetIOCountersStat, error) {
|
|
||||||
r := NetIOCountersStat{
|
|
||||||
Name: "all",
|
|
||||||
}
|
|
||||||
for _, nic := range n {
|
|
||||||
r.BytesRecv += nic.BytesRecv
|
|
||||||
r.PacketsRecv += nic.PacketsRecv
|
|
||||||
r.Errin += nic.Errin
|
|
||||||
r.Dropin += nic.Dropin
|
|
||||||
r.BytesSent += nic.BytesSent
|
|
||||||
r.PacketsSent += nic.PacketsSent
|
|
||||||
r.Errout += nic.Errout
|
|
||||||
r.Dropout += nic.Dropout
|
|
||||||
}
|
|
||||||
|
|
||||||
return []NetIOCountersStat{r}, nil
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
|
||||||
out, err := exec.Command("/usr/sbin/netstat", "-ibdn").Output()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(string(out), "\n")
|
|
||||||
ret := make([]NetIOCountersStat, 0, len(lines)-1)
|
|
||||||
exists := make([]string, 0, len(ret))
|
|
||||||
|
|
||||||
for _, line := range lines {
|
|
||||||
values := strings.Fields(line)
|
|
||||||
if len(values) < 1 || values[0] == "Name" {
|
|
||||||
// skip first line
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if common.StringContains(exists, values[0]) {
|
|
||||||
// skip if already get
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
exists = append(exists, values[0])
|
|
||||||
|
|
||||||
base := 1
|
|
||||||
// sometimes Address is ommitted
|
|
||||||
if len(values) < 11 {
|
|
||||||
base = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed := make([]uint64, 0, 6)
|
|
||||||
vv := []string{
|
|
||||||
values[base+3], // Ipkts == PacketsRecv
|
|
||||||
values[base+4], // Ierrs == Errin
|
|
||||||
values[base+5], // Ibytes == BytesRecv
|
|
||||||
values[base+6], // Opkts == PacketsSent
|
|
||||||
values[base+7], // Oerrs == Errout
|
|
||||||
values[base+8], // Obytes == BytesSent
|
|
||||||
}
|
|
||||||
for _, target := range vv {
|
|
||||||
if target == "-" {
|
|
||||||
parsed = append(parsed, 0)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
t, err := strconv.ParseUint(target, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
parsed = append(parsed, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
n := NetIOCountersStat{
|
|
||||||
Name: values[0],
|
|
||||||
PacketsRecv: parsed[0],
|
|
||||||
Errin: parsed[1],
|
|
||||||
BytesRecv: parsed[2],
|
|
||||||
PacketsSent: parsed[3],
|
|
||||||
Errout: parsed[4],
|
|
||||||
BytesSent: parsed[5],
|
|
||||||
}
|
|
||||||
ret = append(ret, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
if pernic == false {
|
|
||||||
return getNetIOCountersAll(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
|
||||||
out, err := exec.Command("/usr/bin/netstat", "-ibdn").Output()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(string(out), "\n")
|
|
||||||
ret := make([]NetIOCountersStat, 0, len(lines)-1)
|
|
||||||
exists := make([]string, 0, len(ret))
|
|
||||||
|
|
||||||
for _, line := range lines {
|
|
||||||
values := strings.Fields(line)
|
|
||||||
if len(values) < 1 || values[0] == "Name" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if common.StringContains(exists, values[0]) {
|
|
||||||
// skip if already get
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
exists = append(exists, values[0])
|
|
||||||
|
|
||||||
base := 1
|
|
||||||
// sometimes Address is ommitted
|
|
||||||
if len(values) < 13 {
|
|
||||||
base = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed := make([]uint64, 0, 8)
|
|
||||||
vv := []string{
|
|
||||||
values[base+3], // PacketsRecv
|
|
||||||
values[base+4], // Errin
|
|
||||||
values[base+5], // Dropin
|
|
||||||
values[base+6], // BytesRecvn
|
|
||||||
values[base+7], // PacketSent
|
|
||||||
values[base+8], // Errout
|
|
||||||
values[base+9], // BytesSent
|
|
||||||
values[base+11], // Dropout
|
|
||||||
}
|
|
||||||
for _, target := range vv {
|
|
||||||
if target == "-" {
|
|
||||||
parsed = append(parsed, 0)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
t, err := strconv.ParseUint(target, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
parsed = append(parsed, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
n := NetIOCountersStat{
|
|
||||||
Name: values[0],
|
|
||||||
PacketsRecv: parsed[0],
|
|
||||||
Errin: parsed[1],
|
|
||||||
Dropin: parsed[2],
|
|
||||||
BytesRecv: parsed[3],
|
|
||||||
PacketsSent: parsed[4],
|
|
||||||
Errout: parsed[5],
|
|
||||||
BytesSent: parsed[6],
|
|
||||||
Dropout: parsed[7],
|
|
||||||
}
|
|
||||||
ret = append(ret, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
if pernic == false {
|
|
||||||
return getNetIOCountersAll(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NetIOCounters returnes network I/O statistics for every network
|
|
||||||
// interface installed on the system. If pernic argument is false,
|
|
||||||
// return only sum of all information (which name is 'all'). If true,
|
|
||||||
// every network interface installed on the system is returned
|
|
||||||
// separately.
|
|
||||||
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
|
||||||
filename := "/proc/net/dev"
|
|
||||||
lines, err := common.ReadLines(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
statlen := len(lines) - 1
|
|
||||||
|
|
||||||
ret := make([]NetIOCountersStat, 0, statlen)
|
|
||||||
|
|
||||||
for _, line := range lines[2:] {
|
|
||||||
parts := strings.SplitN(line, ":", 2)
|
|
||||||
if len(parts) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
interfaceName := strings.TrimSpace(parts[0])
|
|
||||||
if interfaceName == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fields := strings.Fields(strings.TrimSpace(parts[1]))
|
|
||||||
bytesRecv, err := strconv.ParseUint(fields[0], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
packetsRecv, err := strconv.ParseUint(fields[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
errIn, err := strconv.ParseUint(fields[2], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
dropIn, err := strconv.ParseUint(fields[3], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
bytesSent, err := strconv.ParseUint(fields[8], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
packetsSent, err := strconv.ParseUint(fields[9], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
errOut, err := strconv.ParseUint(fields[10], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
dropOut, err := strconv.ParseUint(fields[13], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
nic := NetIOCountersStat{
|
|
||||||
Name: interfaceName,
|
|
||||||
BytesRecv: bytesRecv,
|
|
||||||
PacketsRecv: packetsRecv,
|
|
||||||
Errin: errIn,
|
|
||||||
Dropin: dropIn,
|
|
||||||
BytesSent: bytesSent,
|
|
||||||
PacketsSent: packetsSent,
|
|
||||||
Errout: errOut,
|
|
||||||
Dropout: dropOut,
|
|
||||||
}
|
|
||||||
ret = append(ret, nic)
|
|
||||||
}
|
|
||||||
|
|
||||||
if pernic == false {
|
|
||||||
return getNetIOCountersAll(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,122 +0,0 @@
|
||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAddrString(t *testing.T) {
|
|
||||||
v := Addr{IP: "192.168.0.1", Port: 8000}
|
|
||||||
|
|
||||||
s := fmt.Sprintf("%v", v)
|
|
||||||
if s != "{\"ip\":\"192.168.0.1\",\"port\":8000}" {
|
|
||||||
t.Errorf("Addr string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNetIOCountersStatString(t *testing.T) {
|
|
||||||
v := NetIOCountersStat{
|
|
||||||
Name: "test",
|
|
||||||
BytesSent: 100,
|
|
||||||
}
|
|
||||||
e := `{"name":"test","bytes_sent":100,"bytes_recv":0,"packets_sent":0,"packets_recv":0,"errin":0,"errout":0,"dropin":0,"dropout":0}`
|
|
||||||
if e != fmt.Sprintf("%v", v) {
|
|
||||||
t.Errorf("NetIOCountersStat string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNetConnectionStatString(t *testing.T) {
|
|
||||||
v := NetConnectionStat{
|
|
||||||
Fd: 10,
|
|
||||||
Family: 10,
|
|
||||||
Type: 10,
|
|
||||||
}
|
|
||||||
e := `{"fd":10,"family":10,"type":10,"localaddr":{"ip":"","port":0},"remoteaddr":{"ip":"","port":0},"status":"","pid":0}`
|
|
||||||
if e != fmt.Sprintf("%v", v) {
|
|
||||||
t.Errorf("NetConnectionStat string is invalid: %v", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNetIOCountersAll(t *testing.T) {
|
|
||||||
v, err := NetIOCounters(false)
|
|
||||||
per, err := NetIOCounters(true)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Could not get NetIOCounters: %v", err)
|
|
||||||
}
|
|
||||||
if len(v) != 1 {
|
|
||||||
t.Errorf("Could not get NetIOCounters: %v", v)
|
|
||||||
}
|
|
||||||
if v[0].Name != "all" {
|
|
||||||
t.Errorf("Invalid NetIOCounters: %v", v)
|
|
||||||
}
|
|
||||||
var pr uint64
|
|
||||||
for _, p := range per {
|
|
||||||
pr += p.PacketsRecv
|
|
||||||
}
|
|
||||||
if v[0].PacketsRecv != pr {
|
|
||||||
t.Errorf("invalid sum value: %v, %v", v[0].PacketsRecv, pr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNetIOCountersPerNic(t *testing.T) {
|
|
||||||
v, err := NetIOCounters(true)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Could not get NetIOCounters: %v", err)
|
|
||||||
}
|
|
||||||
if len(v) == 0 {
|
|
||||||
t.Errorf("Could not get NetIOCounters: %v", v)
|
|
||||||
}
|
|
||||||
for _, vv := range v {
|
|
||||||
if vv.Name == "" {
|
|
||||||
t.Errorf("Invalid NetIOCounters: %v", vv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_getNetIOCountersAll(t *testing.T) {
|
|
||||||
n := []NetIOCountersStat{
|
|
||||||
NetIOCountersStat{
|
|
||||||
Name: "a",
|
|
||||||
BytesRecv: 10,
|
|
||||||
PacketsRecv: 10,
|
|
||||||
},
|
|
||||||
NetIOCountersStat{
|
|
||||||
Name: "b",
|
|
||||||
BytesRecv: 10,
|
|
||||||
PacketsRecv: 10,
|
|
||||||
Errin: 10,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
ret, err := getNetIOCountersAll(n)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
if len(ret) != 1 {
|
|
||||||
t.Errorf("invalid return count")
|
|
||||||
}
|
|
||||||
if ret[0].Name != "all" {
|
|
||||||
t.Errorf("invalid return name")
|
|
||||||
}
|
|
||||||
if ret[0].BytesRecv != 20 {
|
|
||||||
t.Errorf("invalid count bytesrecv")
|
|
||||||
}
|
|
||||||
if ret[0].Errin != 10 {
|
|
||||||
t.Errorf("invalid count errin")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNetInterfaces(t *testing.T) {
|
|
||||||
v, err := NetInterfaces()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Could not get NetInterfaceStat: %v", err)
|
|
||||||
}
|
|
||||||
if len(v) == 0 {
|
|
||||||
t.Errorf("Could not get NetInterfaceStat: %v", err)
|
|
||||||
}
|
|
||||||
for _, vv := range v {
|
|
||||||
if vv.Name == "" {
|
|
||||||
t.Errorf("Invalid NetInterface: %v", vv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
modiphlpapi = syscall.NewLazyDLL("iphlpapi.dll")
|
|
||||||
procGetExtendedTcpTable = modiphlpapi.NewProc("GetExtendedTcpTable")
|
|
||||||
procGetExtendedUdpTable = modiphlpapi.NewProc("GetExtendedUdpTable")
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
TCPTableBasicListener = iota
|
|
||||||
TCPTableBasicConnections
|
|
||||||
TCPTableBasicAll
|
|
||||||
TCPTableOwnerPIDListener
|
|
||||||
TCPTableOwnerPIDConnections
|
|
||||||
TCPTableOwnerPIDAll
|
|
||||||
TCPTableOwnerModuleListener
|
|
||||||
TCPTableOwnerModuleConnections
|
|
||||||
TCPTableOwnerModuleAll
|
|
||||||
)
|
|
||||||
|
|
||||||
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
|
||||||
ifs, err := net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ai, err := getAdapterList()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var ret []NetIOCountersStat
|
|
||||||
|
|
||||||
for _, ifi := range ifs {
|
|
||||||
name := ifi.Name
|
|
||||||
for ; ai != nil; ai = ai.Next {
|
|
||||||
name = common.BytePtrToString(&ai.Description[0])
|
|
||||||
c := NetIOCountersStat{
|
|
||||||
Name: name,
|
|
||||||
}
|
|
||||||
|
|
||||||
row := syscall.MibIfRow{Index: ai.Index}
|
|
||||||
e := syscall.GetIfEntry(&row)
|
|
||||||
if e != nil {
|
|
||||||
return nil, os.NewSyscallError("GetIfEntry", e)
|
|
||||||
}
|
|
||||||
c.BytesSent = uint64(row.OutOctets)
|
|
||||||
c.BytesRecv = uint64(row.InOctets)
|
|
||||||
c.PacketsSent = uint64(row.OutUcastPkts)
|
|
||||||
c.PacketsRecv = uint64(row.InUcastPkts)
|
|
||||||
c.Errin = uint64(row.InErrors)
|
|
||||||
c.Errout = uint64(row.OutErrors)
|
|
||||||
c.Dropin = uint64(row.InDiscards)
|
|
||||||
c.Dropout = uint64(row.OutDiscards)
|
|
||||||
|
|
||||||
ret = append(ret, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pernic == false {
|
|
||||||
return getNetIOCountersAll(ret)
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a list of network connections opened by a process
|
|
||||||
func NetConnections(kind string) ([]NetConnectionStat, error) {
|
|
||||||
var ret []NetConnectionStat
|
|
||||||
|
|
||||||
return ret, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
// borrowed from src/pkg/net/interface_windows.go
|
|
||||||
func getAdapterList() (*syscall.IpAdapterInfo, error) {
|
|
||||||
b := make([]byte, 1000)
|
|
||||||
l := uint32(len(b))
|
|
||||||
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
|
|
||||||
err := syscall.GetAdaptersInfo(a, &l)
|
|
||||||
if err == syscall.ERROR_BUFFER_OVERFLOW {
|
|
||||||
b = make([]byte, l)
|
|
||||||
a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
|
|
||||||
err = syscall.GetAdaptersInfo(a, &l)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, os.NewSyscallError("GetAdaptersInfo", err)
|
|
||||||
}
|
|
||||||
return a, nil
|
|
||||||
}
|
|
|
@ -1,634 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package binary implements simple translation between numbers and byte
|
|
||||||
// sequences and encoding and decoding of varints.
|
|
||||||
//
|
|
||||||
// Numbers are translated by reading and writing fixed-size values.
|
|
||||||
// A fixed-size value is either a fixed-size arithmetic
|
|
||||||
// type (int8, uint8, int16, float32, complex64, ...)
|
|
||||||
// or an array or struct containing only fixed-size values.
|
|
||||||
//
|
|
||||||
// The varint functions encode and decode single integer values using
|
|
||||||
// a variable-length encoding; smaller values require fewer bytes.
|
|
||||||
// For a specification, see
|
|
||||||
// http://code.google.com/apis/protocolbuffers/docs/encoding.html.
|
|
||||||
//
|
|
||||||
// This package favors simplicity over efficiency. Clients that require
|
|
||||||
// high-performance serialization, especially for large data structures,
|
|
||||||
// should look at more advanced solutions such as the encoding/gob
|
|
||||||
// package or protocol buffers.
|
|
||||||
package process
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A ByteOrder specifies how to convert byte sequences into
|
|
||||||
// 16-, 32-, or 64-bit unsigned integers.
|
|
||||||
type ByteOrder interface {
|
|
||||||
Uint16([]byte) uint16
|
|
||||||
Uint32([]byte) uint32
|
|
||||||
Uint64([]byte) uint64
|
|
||||||
PutUint16([]byte, uint16)
|
|
||||||
PutUint32([]byte, uint32)
|
|
||||||
PutUint64([]byte, uint64)
|
|
||||||
String() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// LittleEndian is the little-endian implementation of ByteOrder.
|
|
||||||
var LittleEndian littleEndian
|
|
||||||
|
|
||||||
// BigEndian is the big-endian implementation of ByteOrder.
|
|
||||||
var BigEndian bigEndian
|
|
||||||
|
|
||||||
type littleEndian struct{}
|
|
||||||
|
|
||||||
func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
|
|
||||||
|
|
||||||
func (littleEndian) PutUint16(b []byte, v uint16) {
|
|
||||||
b[0] = byte(v)
|
|
||||||
b[1] = byte(v >> 8)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) Uint32(b []byte) uint32 {
|
|
||||||
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) PutUint32(b []byte, v uint32) {
|
|
||||||
b[0] = byte(v)
|
|
||||||
b[1] = byte(v >> 8)
|
|
||||||
b[2] = byte(v >> 16)
|
|
||||||
b[3] = byte(v >> 24)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) Uint64(b []byte) uint64 {
|
|
||||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
|
||||||
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) PutUint64(b []byte, v uint64) {
|
|
||||||
b[0] = byte(v)
|
|
||||||
b[1] = byte(v >> 8)
|
|
||||||
b[2] = byte(v >> 16)
|
|
||||||
b[3] = byte(v >> 24)
|
|
||||||
b[4] = byte(v >> 32)
|
|
||||||
b[5] = byte(v >> 40)
|
|
||||||
b[6] = byte(v >> 48)
|
|
||||||
b[7] = byte(v >> 56)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) String() string { return "LittleEndian" }
|
|
||||||
|
|
||||||
func (littleEndian) GoString() string { return "binary.LittleEndian" }
|
|
||||||
|
|
||||||
type bigEndian struct{}
|
|
||||||
|
|
||||||
func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 }
|
|
||||||
|
|
||||||
func (bigEndian) PutUint16(b []byte, v uint16) {
|
|
||||||
b[0] = byte(v >> 8)
|
|
||||||
b[1] = byte(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) Uint32(b []byte) uint32 {
|
|
||||||
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) PutUint32(b []byte, v uint32) {
|
|
||||||
b[0] = byte(v >> 24)
|
|
||||||
b[1] = byte(v >> 16)
|
|
||||||
b[2] = byte(v >> 8)
|
|
||||||
b[3] = byte(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) Uint64(b []byte) uint64 {
|
|
||||||
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
|
||||||
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) PutUint64(b []byte, v uint64) {
|
|
||||||
b[0] = byte(v >> 56)
|
|
||||||
b[1] = byte(v >> 48)
|
|
||||||
b[2] = byte(v >> 40)
|
|
||||||
b[3] = byte(v >> 32)
|
|
||||||
b[4] = byte(v >> 24)
|
|
||||||
b[5] = byte(v >> 16)
|
|
||||||
b[6] = byte(v >> 8)
|
|
||||||
b[7] = byte(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) String() string { return "BigEndian" }
|
|
||||||
|
|
||||||
func (bigEndian) GoString() string { return "binary.BigEndian" }
|
|
||||||
|
|
||||||
// Read reads structured binary data from r into data.
|
|
||||||
// Data must be a pointer to a fixed-size value or a slice
|
|
||||||
// of fixed-size values.
|
|
||||||
// Bytes read from r are decoded using the specified byte order
|
|
||||||
// and written to successive fields of the data.
|
|
||||||
// When reading into structs, the field data for fields with
|
|
||||||
// blank (_) field names is skipped; i.e., blank field names
|
|
||||||
// may be used for padding.
|
|
||||||
// When reading into a struct, all non-blank fields must be exported.
|
|
||||||
func Read(r io.Reader, order ByteOrder, data interface{}) error {
|
|
||||||
// Fast path for basic types and slices.
|
|
||||||
if n := intDataSize(data); n != 0 {
|
|
||||||
var b [8]byte
|
|
||||||
var bs []byte
|
|
||||||
if n > len(b) {
|
|
||||||
bs = make([]byte, n)
|
|
||||||
} else {
|
|
||||||
bs = b[:n]
|
|
||||||
}
|
|
||||||
if _, err := io.ReadFull(r, bs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch data := data.(type) {
|
|
||||||
case *int8:
|
|
||||||
*data = int8(b[0])
|
|
||||||
case *uint8:
|
|
||||||
*data = b[0]
|
|
||||||
case *int16:
|
|
||||||
*data = int16(order.Uint16(bs))
|
|
||||||
case *uint16:
|
|
||||||
*data = order.Uint16(bs)
|
|
||||||
case *int32:
|
|
||||||
*data = int32(order.Uint32(bs))
|
|
||||||
case *uint32:
|
|
||||||
*data = order.Uint32(bs)
|
|
||||||
case *int64:
|
|
||||||
*data = int64(order.Uint64(bs))
|
|
||||||
case *uint64:
|
|
||||||
*data = order.Uint64(bs)
|
|
||||||
case []int8:
|
|
||||||
for i, x := range bs { // Easier to loop over the input for 8-bit values.
|
|
||||||
data[i] = int8(x)
|
|
||||||
}
|
|
||||||
case []uint8:
|
|
||||||
copy(data, bs)
|
|
||||||
case []int16:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = int16(order.Uint16(bs[2*i:]))
|
|
||||||
}
|
|
||||||
case []uint16:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = order.Uint16(bs[2*i:])
|
|
||||||
}
|
|
||||||
case []int32:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = int32(order.Uint32(bs[4*i:]))
|
|
||||||
}
|
|
||||||
case []uint32:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = order.Uint32(bs[4*i:])
|
|
||||||
}
|
|
||||||
case []int64:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = int64(order.Uint64(bs[8*i:]))
|
|
||||||
}
|
|
||||||
case []uint64:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = order.Uint64(bs[8*i:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to reflect-based decoding.
|
|
||||||
v := reflect.ValueOf(data)
|
|
||||||
size := -1
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
v = v.Elem()
|
|
||||||
size = dataSize(v)
|
|
||||||
case reflect.Slice:
|
|
||||||
size = dataSize(v)
|
|
||||||
}
|
|
||||||
if size < 0 {
|
|
||||||
return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String())
|
|
||||||
}
|
|
||||||
d := &decoder{order: order, buf: make([]byte, size)}
|
|
||||||
if _, err := io.ReadFull(r, d.buf); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.value(v)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write writes the binary representation of data into w.
|
|
||||||
// Data must be a fixed-size value or a slice of fixed-size
|
|
||||||
// values, or a pointer to such data.
|
|
||||||
// Bytes written to w are encoded using the specified byte order
|
|
||||||
// and read from successive fields of the data.
|
|
||||||
// When writing structs, zero values are written for fields
|
|
||||||
// with blank (_) field names.
|
|
||||||
func Write(w io.Writer, order ByteOrder, data interface{}) error {
|
|
||||||
// Fast path for basic types and slices.
|
|
||||||
if n := intDataSize(data); n != 0 {
|
|
||||||
var b [8]byte
|
|
||||||
var bs []byte
|
|
||||||
if n > len(b) {
|
|
||||||
bs = make([]byte, n)
|
|
||||||
} else {
|
|
||||||
bs = b[:n]
|
|
||||||
}
|
|
||||||
switch v := data.(type) {
|
|
||||||
case *int8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = byte(*v)
|
|
||||||
case int8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = byte(v)
|
|
||||||
case []int8:
|
|
||||||
for i, x := range v {
|
|
||||||
bs[i] = byte(x)
|
|
||||||
}
|
|
||||||
case *uint8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = *v
|
|
||||||
case uint8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = byte(v)
|
|
||||||
case []uint8:
|
|
||||||
bs = v
|
|
||||||
case *int16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, uint16(*v))
|
|
||||||
case int16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, uint16(v))
|
|
||||||
case []int16:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint16(bs[2*i:], uint16(x))
|
|
||||||
}
|
|
||||||
case *uint16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, *v)
|
|
||||||
case uint16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, v)
|
|
||||||
case []uint16:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint16(bs[2*i:], x)
|
|
||||||
}
|
|
||||||
case *int32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, uint32(*v))
|
|
||||||
case int32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, uint32(v))
|
|
||||||
case []int32:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint32(bs[4*i:], uint32(x))
|
|
||||||
}
|
|
||||||
case *uint32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, *v)
|
|
||||||
case uint32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, v)
|
|
||||||
case []uint32:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint32(bs[4*i:], x)
|
|
||||||
}
|
|
||||||
case *int64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, uint64(*v))
|
|
||||||
case int64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, uint64(v))
|
|
||||||
case []int64:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint64(bs[8*i:], uint64(x))
|
|
||||||
}
|
|
||||||
case *uint64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, *v)
|
|
||||||
case uint64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, v)
|
|
||||||
case []uint64:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint64(bs[8*i:], x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err := w.Write(bs)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to reflect-based encoding.
|
|
||||||
v := reflect.Indirect(reflect.ValueOf(data))
|
|
||||||
size := dataSize(v)
|
|
||||||
if size < 0 {
|
|
||||||
return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String())
|
|
||||||
}
|
|
||||||
buf := make([]byte, size)
|
|
||||||
e := &encoder{order: order, buf: buf}
|
|
||||||
e.value(v)
|
|
||||||
_, err := w.Write(buf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns how many bytes Write would generate to encode the value v, which
|
|
||||||
// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
|
|
||||||
// If v is neither of these, Size returns -1.
|
|
||||||
func Size(v interface{}) int {
|
|
||||||
return dataSize(reflect.Indirect(reflect.ValueOf(v)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// dataSize returns the number of bytes the actual data represented by v occupies in memory.
|
|
||||||
// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
|
|
||||||
// it returns the length of the slice times the element size and does not count the memory
|
|
||||||
// occupied by the header. If the type of v is not acceptable, dataSize returns -1.
|
|
||||||
func dataSize(v reflect.Value) int {
|
|
||||||
if v.Kind() == reflect.Slice {
|
|
||||||
if s := sizeof(v.Type().Elem()); s >= 0 {
|
|
||||||
return s * v.Len()
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
return sizeof(v.Type())
|
|
||||||
}
|
|
||||||
|
|
||||||
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
|
|
||||||
func sizeof(t reflect.Type) int {
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Array:
|
|
||||||
if s := sizeof(t.Elem()); s >= 0 {
|
|
||||||
return s * t.Len()
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
sum := 0
|
|
||||||
for i, n := 0, t.NumField(); i < n; i++ {
|
|
||||||
s := sizeof(t.Field(i).Type)
|
|
||||||
if s < 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
sum += s
|
|
||||||
}
|
|
||||||
return sum
|
|
||||||
|
|
||||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
|
||||||
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
|
||||||
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr:
|
|
||||||
return int(t.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
type coder struct {
|
|
||||||
order ByteOrder
|
|
||||||
buf []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type decoder coder
|
|
||||||
type encoder coder
|
|
||||||
|
|
||||||
func (d *decoder) uint8() uint8 {
|
|
||||||
x := d.buf[0]
|
|
||||||
d.buf = d.buf[1:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint8(x uint8) {
|
|
||||||
e.buf[0] = x
|
|
||||||
e.buf = e.buf[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) uint16() uint16 {
|
|
||||||
x := d.order.Uint16(d.buf[0:2])
|
|
||||||
d.buf = d.buf[2:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint16(x uint16) {
|
|
||||||
e.order.PutUint16(e.buf[0:2], x)
|
|
||||||
e.buf = e.buf[2:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) uint32() uint32 {
|
|
||||||
x := d.order.Uint32(d.buf[0:4])
|
|
||||||
d.buf = d.buf[4:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint32(x uint32) {
|
|
||||||
e.order.PutUint32(e.buf[0:4], x)
|
|
||||||
e.buf = e.buf[4:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) uint64() uint64 {
|
|
||||||
x := d.order.Uint64(d.buf[0:8])
|
|
||||||
d.buf = d.buf[8:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint64(x uint64) {
|
|
||||||
e.order.PutUint64(e.buf[0:8], x)
|
|
||||||
e.buf = e.buf[8:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) int8() int8 { return int8(d.uint8()) }
|
|
||||||
|
|
||||||
func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) int16() int16 { return int16(d.uint16()) }
|
|
||||||
|
|
||||||
func (e *encoder) int16(x int16) { e.uint16(uint16(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) int32() int32 { return int32(d.uint32()) }
|
|
||||||
|
|
||||||
func (e *encoder) int32(x int32) { e.uint32(uint32(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) int64() int64 { return int64(d.uint64()) }
|
|
||||||
|
|
||||||
func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) value(v reflect.Value) {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Array:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
d.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
t := v.Type()
|
|
||||||
l := v.NumField()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
// Note: Calling v.CanSet() below is an optimization.
|
|
||||||
// It would be sufficient to check the field name,
|
|
||||||
// but creating the StructField info for each field is
|
|
||||||
// costly (run "go test -bench=ReadStruct" and compare
|
|
||||||
// results when making changes to this code).
|
|
||||||
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
|
||||||
d.value(v)
|
|
||||||
} else {
|
|
||||||
d.skip(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
d.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Int8:
|
|
||||||
v.SetInt(int64(d.int8()))
|
|
||||||
case reflect.Int16:
|
|
||||||
v.SetInt(int64(d.int16()))
|
|
||||||
case reflect.Int32:
|
|
||||||
v.SetInt(int64(d.int32()))
|
|
||||||
case reflect.Int64:
|
|
||||||
v.SetInt(d.int64())
|
|
||||||
|
|
||||||
case reflect.Uint8:
|
|
||||||
v.SetUint(uint64(d.uint8()))
|
|
||||||
case reflect.Uint16:
|
|
||||||
v.SetUint(uint64(d.uint16()))
|
|
||||||
case reflect.Uint32:
|
|
||||||
v.SetUint(uint64(d.uint32()))
|
|
||||||
case reflect.Uint64:
|
|
||||||
v.SetUint(d.uint64())
|
|
||||||
|
|
||||||
case reflect.Float32:
|
|
||||||
v.SetFloat(float64(math.Float32frombits(d.uint32())))
|
|
||||||
case reflect.Float64:
|
|
||||||
v.SetFloat(math.Float64frombits(d.uint64()))
|
|
||||||
|
|
||||||
case reflect.Complex64:
|
|
||||||
v.SetComplex(complex(
|
|
||||||
float64(math.Float32frombits(d.uint32())),
|
|
||||||
float64(math.Float32frombits(d.uint32())),
|
|
||||||
))
|
|
||||||
case reflect.Complex128:
|
|
||||||
v.SetComplex(complex(
|
|
||||||
math.Float64frombits(d.uint64()),
|
|
||||||
math.Float64frombits(d.uint64()),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) value(v reflect.Value) {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Array:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
e.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
t := v.Type()
|
|
||||||
l := v.NumField()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
// see comment for corresponding code in decoder.value()
|
|
||||||
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
|
||||||
e.value(v)
|
|
||||||
} else {
|
|
||||||
e.skip(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
e.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Int8:
|
|
||||||
e.int8(int8(v.Int()))
|
|
||||||
case reflect.Int16:
|
|
||||||
e.int16(int16(v.Int()))
|
|
||||||
case reflect.Int32:
|
|
||||||
e.int32(int32(v.Int()))
|
|
||||||
case reflect.Int64:
|
|
||||||
e.int64(v.Int())
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Uint8:
|
|
||||||
e.uint8(uint8(v.Uint()))
|
|
||||||
case reflect.Uint16:
|
|
||||||
e.uint16(uint16(v.Uint()))
|
|
||||||
case reflect.Uint32:
|
|
||||||
e.uint32(uint32(v.Uint()))
|
|
||||||
case reflect.Uint64:
|
|
||||||
e.uint64(v.Uint())
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Float32:
|
|
||||||
e.uint32(math.Float32bits(float32(v.Float())))
|
|
||||||
case reflect.Float64:
|
|
||||||
e.uint64(math.Float64bits(v.Float()))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Complex64, reflect.Complex128:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Complex64:
|
|
||||||
x := v.Complex()
|
|
||||||
e.uint32(math.Float32bits(float32(real(x))))
|
|
||||||
e.uint32(math.Float32bits(float32(imag(x))))
|
|
||||||
case reflect.Complex128:
|
|
||||||
x := v.Complex()
|
|
||||||
e.uint64(math.Float64bits(real(x)))
|
|
||||||
e.uint64(math.Float64bits(imag(x)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) skip(v reflect.Value) {
|
|
||||||
d.buf = d.buf[dataSize(v):]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) skip(v reflect.Value) {
|
|
||||||
n := dataSize(v)
|
|
||||||
for i := range e.buf[0:n] {
|
|
||||||
e.buf[i] = 0
|
|
||||||
}
|
|
||||||
e.buf = e.buf[n:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// intDataSize returns the size of the data required to represent the data when encoded.
|
|
||||||
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
|
|
||||||
func intDataSize(data interface{}) int {
|
|
||||||
switch data := data.(type) {
|
|
||||||
case int8, *int8, *uint8:
|
|
||||||
return 1
|
|
||||||
case []int8:
|
|
||||||
return len(data)
|
|
||||||
case []uint8:
|
|
||||||
return len(data)
|
|
||||||
case int16, *int16, *uint16:
|
|
||||||
return 2
|
|
||||||
case []int16:
|
|
||||||
return 2 * len(data)
|
|
||||||
case []uint16:
|
|
||||||
return 2 * len(data)
|
|
||||||
case int32, *int32, *uint32:
|
|
||||||
return 4
|
|
||||||
case []int32:
|
|
||||||
return 4 * len(data)
|
|
||||||
case []uint32:
|
|
||||||
return 4 * len(data)
|
|
||||||
case int64, *int64, *uint64:
|
|
||||||
return 8
|
|
||||||
case []int64:
|
|
||||||
return 8 * len(data)
|
|
||||||
case []uint64:
|
|
||||||
return 8 * len(data)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
|
@ -1,142 +0,0 @@
|
||||||
package process
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
cpu "github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Process struct {
|
|
||||||
Pid int32 `json:"pid"`
|
|
||||||
name string
|
|
||||||
status string
|
|
||||||
numCtxSwitches *NumCtxSwitchesStat
|
|
||||||
uids []int32
|
|
||||||
gids []int32
|
|
||||||
numThreads int32
|
|
||||||
memInfo *MemoryInfoStat
|
|
||||||
|
|
||||||
lastCPUTimes *cpu.CPUTimesStat
|
|
||||||
lastCPUTime time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type OpenFilesStat struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Fd uint64 `json:"fd"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MemoryInfoStat struct {
|
|
||||||
RSS uint64 `json:"rss"` // bytes
|
|
||||||
VMS uint64 `json:"vms"` // bytes
|
|
||||||
Swap uint64 `json:"swap"` // bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
type RlimitStat struct {
|
|
||||||
Resource int32 `json:"resource"`
|
|
||||||
Soft int32 `json:"soft"`
|
|
||||||
Hard int32 `json:"hard"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type IOCountersStat struct {
|
|
||||||
ReadCount uint64 `json:"read_count"`
|
|
||||||
WriteCount uint64 `json:"write_count"`
|
|
||||||
ReadBytes uint64 `json:"read_bytes"`
|
|
||||||
WriteBytes uint64 `json:"write_bytes"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type NumCtxSwitchesStat struct {
|
|
||||||
Voluntary int64 `json:"voluntary"`
|
|
||||||
Involuntary int64 `json:"involuntary"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Process) String() string {
|
|
||||||
s, _ := json.Marshal(p)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o OpenFilesStat) String() string {
|
|
||||||
s, _ := json.Marshal(o)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MemoryInfoStat) String() string {
|
|
||||||
s, _ := json.Marshal(m)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r RlimitStat) String() string {
|
|
||||||
s, _ := json.Marshal(r)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i IOCountersStat) String() string {
|
|
||||||
s, _ := json.Marshal(i)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p NumCtxSwitchesStat) String() string {
|
|
||||||
s, _ := json.Marshal(p)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PidExists(pid int32) (bool, error) {
|
|
||||||
pids, err := Pids()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, i := range pids {
|
|
||||||
if i == pid {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If interval is 0, return difference from last call(non-blocking).
|
|
||||||
// If interval > 0, wait interval sec and return diffrence between start and end.
|
|
||||||
func (p *Process) CPUPercent(interval time.Duration) (float64, error) {
|
|
||||||
numcpu := runtime.NumCPU()
|
|
||||||
calculate := func(t1, t2 *cpu.CPUTimesStat, delta float64) float64 {
|
|
||||||
if delta == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
delta_proc := (t2.User - t1.User) + (t2.System - t1.System)
|
|
||||||
overall_percent := ((delta_proc / delta) * 100) * float64(numcpu)
|
|
||||||
return overall_percent
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuTimes, err := p.CPUTimes()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if interval > 0 {
|
|
||||||
p.lastCPUTimes = cpuTimes
|
|
||||||
p.lastCPUTime = time.Now()
|
|
||||||
time.Sleep(interval)
|
|
||||||
cpuTimes, err = p.CPUTimes()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if p.lastCPUTimes == nil {
|
|
||||||
// invoked first time
|
|
||||||
p.lastCPUTimes, err = p.CPUTimes()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
p.lastCPUTime = time.Now()
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delta := (time.Now().Sub(p.lastCPUTime).Seconds()) * float64(numcpu)
|
|
||||||
ret := calculate(p.lastCPUTimes, cpuTimes, float64(delta))
|
|
||||||
p.lastCPUTimes = cpuTimes
|
|
||||||
p.lastCPUTime = time.Now()
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,359 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
cpu "github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
|
||||||
net "github.com/influxdb/telegraf/plugins/system/ps/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// copied from sys/sysctl.h
|
|
||||||
const (
|
|
||||||
CTLKern = 1 // "high kernel": proc, limits
|
|
||||||
KernProc = 14 // struct: process entries
|
|
||||||
KernProcPID = 1 // by process id
|
|
||||||
KernProcProc = 8 // only return procs
|
|
||||||
KernProcAll = 0 // everything
|
|
||||||
KernProcPathname = 12 // path to executable
|
|
||||||
)
|
|
||||||
|
|
||||||
type _Ctype_struct___0 struct {
|
|
||||||
Pad uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// MemoryInfoExStat is different between OSes
|
|
||||||
type MemoryInfoExStat struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
type MemoryMapsStat struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func Pids() ([]int32, error) {
|
|
||||||
var ret []int32
|
|
||||||
|
|
||||||
pids, err := callPs("pid", 0)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, pid := range pids {
|
|
||||||
v, err := strconv.Atoi(pid[0])
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
ret = append(ret, int32(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Ppid() (int32, error) {
|
|
||||||
r, err := callPs("ppid", p.Pid)
|
|
||||||
v, err := strconv.Atoi(r[0][0])
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return int32(v), err
|
|
||||||
}
|
|
||||||
func (p *Process) Name() (string, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return common.IntToString(k.Proc.P_comm[:]), nil
|
|
||||||
}
|
|
||||||
func (p *Process) Exe() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Cmdline() (string, error) {
|
|
||||||
r, err := callPs("command", p.Pid)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return strings.Join(r[0], " "), err
|
|
||||||
}
|
|
||||||
func (p *Process) CreateTime() (int64, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Cwd() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Parent() (*Process, error) {
|
|
||||||
return p, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Status() (string, error) {
|
|
||||||
r, err := callPs("state", p.Pid)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return r[0][0], err
|
|
||||||
}
|
|
||||||
func (p *Process) Uids() ([]int32, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
uids := make([]int32, 0, 3)
|
|
||||||
|
|
||||||
uids = append(uids, int32(k.Eproc.Pcred.P_ruid), int32(k.Eproc.Ucred.Uid), int32(k.Eproc.Pcred.P_svuid))
|
|
||||||
|
|
||||||
return uids, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Gids() ([]int32, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
gids := make([]int32, 0, 3)
|
|
||||||
gids = append(gids, int32(k.Eproc.Pcred.P_rgid), int32(k.Eproc.Ucred.Ngroups), int32(k.Eproc.Pcred.P_svgid))
|
|
||||||
|
|
||||||
return gids, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Terminal() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
/*
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
ttyNr := uint64(k.Eproc.Tdev)
|
|
||||||
termmap, err := getTerminalMap()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return termmap[ttyNr], nil
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
func (p *Process) Nice() (int32, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return int32(k.Proc.P_nice), nil
|
|
||||||
}
|
|
||||||
func (p *Process) IOnice() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
|
||||||
var rlimit []RlimitStat
|
|
||||||
return rlimit, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumFDs() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumThreads() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
|
|
||||||
/*
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return k.KiNumthreads, nil
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
func (p *Process) Threads() (map[string]string, error) {
|
|
||||||
ret := make(map[string]string, 0)
|
|
||||||
return ret, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
|
||||||
r, err := callPs("rss,vsize,pagein", p.Pid)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rss, err := strconv.Atoi(r[0][0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
vms, err := strconv.Atoi(r[0][1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pagein, err := strconv.Atoi(r[0][2])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &MemoryInfoStat{
|
|
||||||
RSS: uint64(rss),
|
|
||||||
VMS: uint64(vms),
|
|
||||||
Swap: uint64(pagein),
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryPercent() (float32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Children() ([]*Process, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Connections() ([]net.NetConnectionStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) IsRunning() (bool, error) {
|
|
||||||
return true, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
|
||||||
var ret []MemoryMapsStat
|
|
||||||
return &ret, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyParams(k *KinfoProc, p *Process) error {
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func processes() ([]Process, error) {
|
|
||||||
results := make([]Process, 0, 50)
|
|
||||||
|
|
||||||
mib := []int32{CTLKern, KernProc, KernProcAll, 0}
|
|
||||||
buf, length, err := common.CallSyscall(mib)
|
|
||||||
if err != nil {
|
|
||||||
return results, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// get kinfo_proc size
|
|
||||||
k := KinfoProc{}
|
|
||||||
procinfoLen := int(unsafe.Sizeof(k))
|
|
||||||
count := int(length / uint64(procinfoLen))
|
|
||||||
/*
|
|
||||||
fmt.Println(length, procinfoLen, count)
|
|
||||||
b := buf[0*procinfoLen : 0*procinfoLen+procinfoLen]
|
|
||||||
fmt.Println(b)
|
|
||||||
kk, err := parseKinfoProc(b)
|
|
||||||
fmt.Printf("%#v", kk)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// parse buf to procs
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
b := buf[i*procinfoLen : i*procinfoLen+procinfoLen]
|
|
||||||
k, err := parseKinfoProc(b)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p, err := NewProcess(int32(k.Proc.P_pid))
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
copyParams(&k, p)
|
|
||||||
|
|
||||||
results = append(results, *p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
|
||||||
var k KinfoProc
|
|
||||||
br := bytes.NewReader(buf)
|
|
||||||
|
|
||||||
err := Read(br, LittleEndian, &k)
|
|
||||||
if err != nil {
|
|
||||||
return k, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return k, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) getKProc() (*KinfoProc, error) {
|
|
||||||
mib := []int32{CTLKern, KernProc, KernProcPID, p.Pid}
|
|
||||||
procK := KinfoProc{}
|
|
||||||
length := uint64(unsafe.Sizeof(procK))
|
|
||||||
buf := make([]byte, length)
|
|
||||||
_, _, syserr := syscall.Syscall6(
|
|
||||||
syscall.SYS___SYSCTL,
|
|
||||||
uintptr(unsafe.Pointer(&mib[0])),
|
|
||||||
uintptr(len(mib)),
|
|
||||||
uintptr(unsafe.Pointer(&buf[0])),
|
|
||||||
uintptr(unsafe.Pointer(&length)),
|
|
||||||
0,
|
|
||||||
0)
|
|
||||||
if syserr != 0 {
|
|
||||||
return nil, syserr
|
|
||||||
}
|
|
||||||
k, err := parseKinfoProc(buf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &k, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewProcess(pid int32) (*Process, error) {
|
|
||||||
p := &Process{Pid: pid}
|
|
||||||
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// call ps command.
|
|
||||||
// Return value deletes Header line(you must not input wrong arg).
|
|
||||||
// And splited by Space. Caller have responsibility to manage.
|
|
||||||
// If passed arg pid is 0, get information from all process.
|
|
||||||
func callPs(arg string, pid int32) ([][]string, error) {
|
|
||||||
var cmd []string
|
|
||||||
if pid == 0 { // will get from all processes.
|
|
||||||
cmd = []string{"-x", "-o", arg}
|
|
||||||
} else {
|
|
||||||
cmd = []string{"-x", "-o", arg, "-p", strconv.Itoa(int(pid))}
|
|
||||||
}
|
|
||||||
out, err := exec.Command("/bin/ps", cmd...).Output()
|
|
||||||
if err != nil {
|
|
||||||
return [][]string{}, err
|
|
||||||
}
|
|
||||||
lines := strings.Split(string(out), "\n")
|
|
||||||
|
|
||||||
var ret [][]string
|
|
||||||
for _, l := range lines[1:] {
|
|
||||||
var lr []string
|
|
||||||
for _, r := range strings.Split(l, " ") {
|
|
||||||
if r == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lr = append(lr, strings.TrimSpace(r))
|
|
||||||
}
|
|
||||||
if len(lr) != 0 {
|
|
||||||
ret = append(ret, lr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,234 +0,0 @@
|
||||||
// Created by cgo -godefs - DO NOT EDIT
|
|
||||||
// cgo -godefs types_darwin.go
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
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 Timespec struct {
|
|
||||||
Sec int64
|
|
||||||
Nsec int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type Timeval struct {
|
|
||||||
Sec int64
|
|
||||||
Usec int32
|
|
||||||
Pad_cgo_0 [4]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
type Rlimit struct {
|
|
||||||
Cur uint64
|
|
||||||
Max uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
type UGid_t uint32
|
|
||||||
|
|
||||||
type KinfoProc struct {
|
|
||||||
Proc ExternProc
|
|
||||||
Eproc Eproc
|
|
||||||
}
|
|
||||||
|
|
||||||
type Eproc struct {
|
|
||||||
Paddr *uint64
|
|
||||||
Sess *Session
|
|
||||||
Pcred Upcred
|
|
||||||
Ucred Uucred
|
|
||||||
Pad_cgo_0 [4]byte
|
|
||||||
Vm Vmspace
|
|
||||||
Ppid int32
|
|
||||||
Pgid int32
|
|
||||||
Jobc int16
|
|
||||||
Pad_cgo_1 [2]byte
|
|
||||||
Tdev int32
|
|
||||||
Tpgid int32
|
|
||||||
Pad_cgo_2 [4]byte
|
|
||||||
Tsess *Session
|
|
||||||
Wmesg [8]int8
|
|
||||||
Xsize int32
|
|
||||||
Xrssize int16
|
|
||||||
Xccount int16
|
|
||||||
Xswrss int16
|
|
||||||
Pad_cgo_3 [2]byte
|
|
||||||
Flag int32
|
|
||||||
Login [12]int8
|
|
||||||
Spare [4]int32
|
|
||||||
Pad_cgo_4 [4]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Proc struct{}
|
|
||||||
|
|
||||||
type Session struct{}
|
|
||||||
|
|
||||||
type ucred struct {
|
|
||||||
Link _Ctype_struct___0
|
|
||||||
Ref uint64
|
|
||||||
Posix Posix_cred
|
|
||||||
Label *Label
|
|
||||||
Audit Au_session
|
|
||||||
}
|
|
||||||
|
|
||||||
type Uucred struct {
|
|
||||||
Ref int32
|
|
||||||
Uid uint32
|
|
||||||
Ngroups int16
|
|
||||||
Pad_cgo_0 [2]byte
|
|
||||||
Groups [16]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type Upcred struct {
|
|
||||||
Pc_lock [72]int8
|
|
||||||
Pc_ucred *ucred
|
|
||||||
P_ruid uint32
|
|
||||||
P_svuid uint32
|
|
||||||
P_rgid uint32
|
|
||||||
P_svgid uint32
|
|
||||||
P_refcnt int32
|
|
||||||
Pad_cgo_0 [4]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Vmspace struct {
|
|
||||||
Dummy int32
|
|
||||||
Pad_cgo_0 [4]byte
|
|
||||||
Dummy2 *int8
|
|
||||||
Dummy3 [5]int32
|
|
||||||
Pad_cgo_1 [4]byte
|
|
||||||
Dummy4 [3]*int8
|
|
||||||
}
|
|
||||||
|
|
||||||
type Sigacts struct{}
|
|
||||||
|
|
||||||
type ExternProc struct {
|
|
||||||
P_un [16]byte
|
|
||||||
P_vmspace uint64
|
|
||||||
P_sigacts uint64
|
|
||||||
Pad_cgo_0 [3]byte
|
|
||||||
P_flag int32
|
|
||||||
P_stat int8
|
|
||||||
P_pid int32
|
|
||||||
P_oppid int32
|
|
||||||
P_dupfd int32
|
|
||||||
Pad_cgo_1 [4]byte
|
|
||||||
User_stack uint64
|
|
||||||
Exit_thread uint64
|
|
||||||
P_debugger int32
|
|
||||||
Sigwait int32
|
|
||||||
P_estcpu uint32
|
|
||||||
P_cpticks int32
|
|
||||||
P_pctcpu uint32
|
|
||||||
Pad_cgo_2 [4]byte
|
|
||||||
P_wchan uint64
|
|
||||||
P_wmesg uint64
|
|
||||||
P_swtime uint32
|
|
||||||
P_slptime uint32
|
|
||||||
P_realtimer Itimerval
|
|
||||||
P_rtime Timeval
|
|
||||||
P_uticks uint64
|
|
||||||
P_sticks uint64
|
|
||||||
P_iticks uint64
|
|
||||||
P_traceflag int32
|
|
||||||
Pad_cgo_3 [4]byte
|
|
||||||
P_tracep uint64
|
|
||||||
P_siglist int32
|
|
||||||
Pad_cgo_4 [4]byte
|
|
||||||
P_textvp uint64
|
|
||||||
P_holdcnt int32
|
|
||||||
P_sigmask uint32
|
|
||||||
P_sigignore uint32
|
|
||||||
P_sigcatch uint32
|
|
||||||
P_priority uint8
|
|
||||||
P_usrpri uint8
|
|
||||||
P_nice int8
|
|
||||||
P_comm [17]int8
|
|
||||||
Pad_cgo_5 [4]byte
|
|
||||||
P_pgrp uint64
|
|
||||||
P_addr uint64
|
|
||||||
P_xstat uint16
|
|
||||||
P_acflag uint16
|
|
||||||
Pad_cgo_6 [4]byte
|
|
||||||
P_ru uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
type Itimerval struct {
|
|
||||||
Interval Timeval
|
|
||||||
Value Timeval
|
|
||||||
}
|
|
||||||
|
|
||||||
type Vnode struct{}
|
|
||||||
|
|
||||||
type Pgrp struct{}
|
|
||||||
|
|
||||||
type UserStruct struct{}
|
|
||||||
|
|
||||||
type Au_session struct {
|
|
||||||
Aia_p *AuditinfoAddr
|
|
||||||
Mask AuMask
|
|
||||||
}
|
|
||||||
|
|
||||||
type Posix_cred struct {
|
|
||||||
Uid uint32
|
|
||||||
Ruid uint32
|
|
||||||
Svuid uint32
|
|
||||||
Ngroups int16
|
|
||||||
Pad_cgo_0 [2]byte
|
|
||||||
Groups [16]uint32
|
|
||||||
Rgid uint32
|
|
||||||
Svgid uint32
|
|
||||||
Gmuid uint32
|
|
||||||
Flags int32
|
|
||||||
}
|
|
||||||
|
|
||||||
type Label struct{}
|
|
||||||
|
|
||||||
type AuditinfoAddr struct {
|
|
||||||
Auid uint32
|
|
||||||
Mask AuMask
|
|
||||||
Termid AuTidAddr
|
|
||||||
Asid int32
|
|
||||||
Flags uint64
|
|
||||||
}
|
|
||||||
type AuMask struct {
|
|
||||||
Success uint32
|
|
||||||
Failure uint32
|
|
||||||
}
|
|
||||||
type AuTidAddr struct {
|
|
||||||
Port int32
|
|
||||||
Type uint32
|
|
||||||
Addr [4]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type UcredQueue struct {
|
|
||||||
Next *ucred
|
|
||||||
Prev **ucred
|
|
||||||
}
|
|
|
@ -1,263 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
cpu "github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
|
||||||
net "github.com/influxdb/telegraf/plugins/system/ps/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MemoryInfoExStat is different between OSes
|
|
||||||
type MemoryInfoExStat struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
type MemoryMapsStat struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func Pids() ([]int32, error) {
|
|
||||||
var ret []int32
|
|
||||||
procs, err := processes()
|
|
||||||
if err != nil {
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, p := range procs {
|
|
||||||
ret = append(ret, p.Pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Ppid() (int32, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return k.KiPpid, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Name() (string, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(k.KiComm[:]), nil
|
|
||||||
}
|
|
||||||
func (p *Process) Exe() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Cmdline() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) CreateTime() (int64, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Cwd() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Parent() (*Process, error) {
|
|
||||||
return p, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Status() (string, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(k.KiStat[:]), nil
|
|
||||||
}
|
|
||||||
func (p *Process) Uids() ([]int32, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
uids := make([]int32, 0, 3)
|
|
||||||
|
|
||||||
uids = append(uids, int32(k.KiRuid), int32(k.KiUID), int32(k.KiSvuid))
|
|
||||||
|
|
||||||
return uids, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Gids() ([]int32, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
gids := make([]int32, 0, 3)
|
|
||||||
gids = append(gids, int32(k.KiRgid), int32(k.KiNgroups[0]), int32(k.KiSvuid))
|
|
||||||
|
|
||||||
return gids, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Terminal() (string, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
ttyNr := uint64(k.KiTdev)
|
|
||||||
|
|
||||||
termmap, err := getTerminalMap()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return termmap[ttyNr], nil
|
|
||||||
}
|
|
||||||
func (p *Process) Nice() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) IOnice() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
|
||||||
var rlimit []RlimitStat
|
|
||||||
return rlimit, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumFDs() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumThreads() (int32, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return k.KiNumthreads, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Threads() (map[string]string, error) {
|
|
||||||
ret := make(map[string]string, 0)
|
|
||||||
return ret, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
|
||||||
k, err := p.getKProc()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &MemoryInfoStat{
|
|
||||||
RSS: uint64(k.KiRssize),
|
|
||||||
VMS: uint64(k.KiSize),
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryPercent() (float32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Children() ([]*Process, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Connections() ([]net.NetConnectionStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) IsRunning() (bool, error) {
|
|
||||||
return true, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
|
||||||
var ret []MemoryMapsStat
|
|
||||||
return &ret, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyParams(k *KinfoProc, p *Process) error {
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func processes() ([]Process, error) {
|
|
||||||
results := make([]Process, 0, 50)
|
|
||||||
|
|
||||||
mib := []int32{CTLKern, KernProc, KernProcProc, 0}
|
|
||||||
buf, length, err := common.CallSyscall(mib)
|
|
||||||
if err != nil {
|
|
||||||
return results, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// get kinfo_proc size
|
|
||||||
k := KinfoProc{}
|
|
||||||
procinfoLen := int(unsafe.Sizeof(k))
|
|
||||||
count := int(length / uint64(procinfoLen))
|
|
||||||
|
|
||||||
// parse buf to procs
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
b := buf[i*procinfoLen : i*procinfoLen+procinfoLen]
|
|
||||||
k, err := parseKinfoProc(b)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p, err := NewProcess(int32(k.KiPid))
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
copyParams(&k, p)
|
|
||||||
|
|
||||||
results = append(results, *p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
|
||||||
var k KinfoProc
|
|
||||||
br := bytes.NewReader(buf)
|
|
||||||
err := binary.Read(br, binary.LittleEndian, &k)
|
|
||||||
if err != nil {
|
|
||||||
return k, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return k, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) getKProc() (*KinfoProc, error) {
|
|
||||||
mib := []int32{CTLKern, KernProc, KernProcPID, p.Pid}
|
|
||||||
|
|
||||||
buf, length, err := common.CallSyscall(mib)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
procK := KinfoProc{}
|
|
||||||
if length != uint64(unsafe.Sizeof(procK)) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
k, err := parseKinfoProc(buf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &k, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewProcess(pid int32) (*Process, error) {
|
|
||||||
p := &Process{Pid: pid}
|
|
||||||
|
|
||||||
return p, nil
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
// +build 386
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
// copied from sys/sysctl.h
|
|
||||||
const (
|
|
||||||
CTLKern = 1 // "high kernel": proc, limits
|
|
||||||
KernProc = 14 // struct: process entries
|
|
||||||
KernProcPID = 1 // by process id
|
|
||||||
KernProcProc = 8 // only return procs
|
|
||||||
KernProcPathname = 12 // path to executable
|
|
||||||
)
|
|
||||||
|
|
||||||
// copied from sys/user.h
|
|
||||||
type KinfoProc struct {
|
|
||||||
KiStructsize int32
|
|
||||||
KiLayout int32
|
|
||||||
KiArgs int32
|
|
||||||
KiPaddr int32
|
|
||||||
KiAddr int32
|
|
||||||
KiTracep int32
|
|
||||||
KiTextvp int32
|
|
||||||
KiFd int32
|
|
||||||
KiVmspace int32
|
|
||||||
KiWchan int32
|
|
||||||
KiPid int32
|
|
||||||
KiPpid int32
|
|
||||||
KiPgid int32
|
|
||||||
KiTpgid int32
|
|
||||||
KiSid int32
|
|
||||||
KiTsid int32
|
|
||||||
KiJobc [2]byte
|
|
||||||
KiSpareShort1 [2]byte
|
|
||||||
KiTdev int32
|
|
||||||
KiSiglist [16]byte
|
|
||||||
KiSigmask [16]byte
|
|
||||||
KiSigignore [16]byte
|
|
||||||
KiSigcatch [16]byte
|
|
||||||
KiUID int32
|
|
||||||
KiRuid int32
|
|
||||||
KiSvuid int32
|
|
||||||
KiRgid int32
|
|
||||||
KiSvgid int32
|
|
||||||
KiNgroups [2]byte
|
|
||||||
KiSpareShort2 [2]byte
|
|
||||||
KiGroups [64]byte
|
|
||||||
KiSize int32
|
|
||||||
KiRssize int32
|
|
||||||
KiSwrss int32
|
|
||||||
KiTsize int32
|
|
||||||
KiDsize int32
|
|
||||||
KiSsize int32
|
|
||||||
KiXstat [2]byte
|
|
||||||
KiAcflag [2]byte
|
|
||||||
KiPctcpu int32
|
|
||||||
KiEstcpu int32
|
|
||||||
KiSlptime int32
|
|
||||||
KiSwtime int32
|
|
||||||
KiCow int32
|
|
||||||
KiRuntime int64
|
|
||||||
KiStart [8]byte
|
|
||||||
KiChildtime [8]byte
|
|
||||||
KiFlag int32
|
|
||||||
KiKflag int32
|
|
||||||
KiTraceflag int32
|
|
||||||
KiStat [1]byte
|
|
||||||
KiNice [1]byte
|
|
||||||
KiLock [1]byte
|
|
||||||
KiRqindex [1]byte
|
|
||||||
KiOncpu [1]byte
|
|
||||||
KiLastcpu [1]byte
|
|
||||||
KiOcomm [17]byte
|
|
||||||
KiWmesg [9]byte
|
|
||||||
KiLogin [18]byte
|
|
||||||
KiLockname [9]byte
|
|
||||||
KiComm [20]byte
|
|
||||||
KiEmul [17]byte
|
|
||||||
KiSparestrings [68]byte
|
|
||||||
KiSpareints [36]byte
|
|
||||||
KiCrFlags int32
|
|
||||||
KiJid int32
|
|
||||||
KiNumthreads int32
|
|
||||||
KiTid int32
|
|
||||||
KiPri int32
|
|
||||||
KiRusage [72]byte
|
|
||||||
KiRusageCh [72]byte
|
|
||||||
KiPcb int32
|
|
||||||
KiKstack int32
|
|
||||||
KiUdata int32
|
|
||||||
KiTdaddr int32
|
|
||||||
KiSpareptrs [24]byte
|
|
||||||
KiSpareint64s [48]byte
|
|
||||||
KiSflag int32
|
|
||||||
KiTdflags int32
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
// +build amd64
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
// copied from sys/sysctl.h
|
|
||||||
const (
|
|
||||||
CTLKern = 1 // "high kernel": proc, limits
|
|
||||||
KernProc = 14 // struct: process entries
|
|
||||||
KernProcPID = 1 // by process id
|
|
||||||
KernProcProc = 8 // only return procs
|
|
||||||
KernProcPathname = 12 // path to executable
|
|
||||||
)
|
|
||||||
|
|
||||||
// copied from sys/user.h
|
|
||||||
type KinfoProc struct {
|
|
||||||
KiStructsize int32
|
|
||||||
KiLayout int32
|
|
||||||
KiArgs int64
|
|
||||||
KiPaddr int64
|
|
||||||
KiAddr int64
|
|
||||||
KiTracep int64
|
|
||||||
KiTextvp int64
|
|
||||||
KiFd int64
|
|
||||||
KiVmspace int64
|
|
||||||
KiWchan int64
|
|
||||||
KiPid int32
|
|
||||||
KiPpid int32
|
|
||||||
KiPgid int32
|
|
||||||
KiTpgid int32
|
|
||||||
KiSid int32
|
|
||||||
KiTsid int32
|
|
||||||
KiJobc [2]byte
|
|
||||||
KiSpareShort1 [2]byte
|
|
||||||
KiTdev int32
|
|
||||||
KiSiglist [16]byte
|
|
||||||
KiSigmask [16]byte
|
|
||||||
KiSigignore [16]byte
|
|
||||||
KiSigcatch [16]byte
|
|
||||||
KiUID int32
|
|
||||||
KiRuid int32
|
|
||||||
KiSvuid int32
|
|
||||||
KiRgid int32
|
|
||||||
KiSvgid int32
|
|
||||||
KiNgroups [2]byte
|
|
||||||
KiSpareShort2 [2]byte
|
|
||||||
KiGroups [64]byte
|
|
||||||
KiSize int64
|
|
||||||
KiRssize int64
|
|
||||||
KiSwrss int64
|
|
||||||
KiTsize int64
|
|
||||||
KiDsize int64
|
|
||||||
KiSsize int64
|
|
||||||
KiXstat [2]byte
|
|
||||||
KiAcflag [2]byte
|
|
||||||
KiPctcpu int32
|
|
||||||
KiEstcpu int32
|
|
||||||
KiSlptime int32
|
|
||||||
KiSwtime int32
|
|
||||||
KiCow int32
|
|
||||||
KiRuntime int64
|
|
||||||
KiStart [16]byte
|
|
||||||
KiChildtime [16]byte
|
|
||||||
KiFlag int64
|
|
||||||
KiKflag int64
|
|
||||||
KiTraceflag int32
|
|
||||||
KiStat [1]byte
|
|
||||||
KiNice [1]byte
|
|
||||||
KiLock [1]byte
|
|
||||||
KiRqindex [1]byte
|
|
||||||
KiOncpu [1]byte
|
|
||||||
KiLastcpu [1]byte
|
|
||||||
KiOcomm [17]byte
|
|
||||||
KiWmesg [9]byte
|
|
||||||
KiLogin [18]byte
|
|
||||||
KiLockname [9]byte
|
|
||||||
KiComm [20]byte
|
|
||||||
KiEmul [17]byte
|
|
||||||
KiSparestrings [68]byte
|
|
||||||
KiSpareints [36]byte
|
|
||||||
KiCrFlags int32
|
|
||||||
KiJid int32
|
|
||||||
KiNumthreads int32
|
|
||||||
KiTid int32
|
|
||||||
KiPri int32
|
|
||||||
KiRusage [144]byte
|
|
||||||
KiRusageCh [144]byte
|
|
||||||
KiPcb int64
|
|
||||||
KiKstack int64
|
|
||||||
KiUdata int64
|
|
||||||
KiTdaddr int64
|
|
||||||
KiSpareptrs [48]byte
|
|
||||||
KiSpareint64s [96]byte
|
|
||||||
KiSflag int64
|
|
||||||
KiTdflags int64
|
|
||||||
}
|
|
|
@ -1,597 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
cpu "github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
|
||||||
host "github.com/influxdb/telegraf/plugins/system/ps/host"
|
|
||||||
net "github.com/influxdb/telegraf/plugins/system/ps/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
PrioProcess = 0 // linux/resource.h
|
|
||||||
)
|
|
||||||
|
|
||||||
// MemoryInfoExStat is different between OSes
|
|
||||||
type MemoryInfoExStat struct {
|
|
||||||
RSS uint64 `json:"rss"` // bytes
|
|
||||||
VMS uint64 `json:"vms"` // bytes
|
|
||||||
Shared uint64 `json:"shared"` // bytes
|
|
||||||
Text uint64 `json:"text"` // bytes
|
|
||||||
Lib uint64 `json:"lib"` // bytes
|
|
||||||
Data uint64 `json:"data"` // bytes
|
|
||||||
Dirty uint64 `json:"dirty"` // bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MemoryInfoExStat) String() string {
|
|
||||||
s, _ := json.Marshal(m)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
type MemoryMapsStat struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
Rss uint64 `json:"rss"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Pss uint64 `json:"pss"`
|
|
||||||
SharedClean uint64 `json:"shared_clean"`
|
|
||||||
SharedDirty uint64 `json:"shared_dirty"`
|
|
||||||
PrivateClean uint64 `json:"private_clean"`
|
|
||||||
PrivateDirty uint64 `json:"private_dirty"`
|
|
||||||
Referenced uint64 `json:"referenced"`
|
|
||||||
Anonymous uint64 `json:"anonymous"`
|
|
||||||
Swap uint64 `json:"swap"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m MemoryMapsStat) String() string {
|
|
||||||
s, _ := json.Marshal(m)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new Process instance
|
|
||||||
// This only stores Pid
|
|
||||||
func NewProcess(pid int32) (*Process, error) {
|
|
||||||
p := &Process{
|
|
||||||
Pid: int32(pid),
|
|
||||||
}
|
|
||||||
err := p.fillFromStatus()
|
|
||||||
return p, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Ppid() (int32, error) {
|
|
||||||
_, ppid, _, _, _, err := p.fillFromStat()
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
return ppid, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Name() (string, error) {
|
|
||||||
return p.name, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Exe() (string, error) {
|
|
||||||
return p.fillFromExe()
|
|
||||||
}
|
|
||||||
func (p *Process) Cmdline() (string, error) {
|
|
||||||
return p.fillFromCmdline()
|
|
||||||
}
|
|
||||||
func (p *Process) CreateTime() (int64, error) {
|
|
||||||
_, _, _, createTime, _, err := p.fillFromStat()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return createTime, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Cwd() (string, error) {
|
|
||||||
return p.fillFromCwd()
|
|
||||||
}
|
|
||||||
func (p *Process) Parent() (*Process, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Status() (string, error) {
|
|
||||||
return p.status, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Uids() ([]int32, error) {
|
|
||||||
return p.uids, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Gids() ([]int32, error) {
|
|
||||||
return p.gids, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Terminal() (string, error) {
|
|
||||||
terminal, _, _, _, _, err := p.fillFromStat()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return terminal, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Nice() (int32, error) {
|
|
||||||
_, _, _, _, nice, err := p.fillFromStat()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return nice, nil
|
|
||||||
}
|
|
||||||
func (p *Process) IOnice() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
|
||||||
return p.fillFromIO()
|
|
||||||
}
|
|
||||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
|
||||||
return p.numCtxSwitches, nil
|
|
||||||
}
|
|
||||||
func (p *Process) NumFDs() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumThreads() (int32, error) {
|
|
||||||
return p.numThreads, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Threads() (map[string]string, error) {
|
|
||||||
ret := make(map[string]string, 0)
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
|
|
||||||
_, _, cpuTimes, _, _, err := p.fillFromStat()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return cpuTimes, nil
|
|
||||||
}
|
|
||||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
|
||||||
return p.memInfo, nil
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
|
||||||
_, memInfoEx, err := p.fillFromStatm()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return memInfoEx, nil
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryPercent() (float32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Children() ([]*Process, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Connections() ([]net.NetConnectionStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) IsRunning() (bool, error) {
|
|
||||||
return true, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
// MemoryMaps get memory maps from /proc/(pid)/smaps
|
|
||||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
|
||||||
pid := p.Pid
|
|
||||||
var ret []MemoryMapsStat
|
|
||||||
smapsPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "smaps")
|
|
||||||
contents, err := ioutil.ReadFile(smapsPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
lines := strings.Split(string(contents), "\n")
|
|
||||||
|
|
||||||
// function of parsing a block
|
|
||||||
getBlock := func(first_line []string, block []string) (MemoryMapsStat, error) {
|
|
||||||
m := MemoryMapsStat{}
|
|
||||||
m.Path = first_line[len(first_line)-1]
|
|
||||||
|
|
||||||
for _, line := range block {
|
|
||||||
if strings.Contains(line, "VmFlags") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
field := strings.Split(line, ":")
|
|
||||||
if len(field) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
v := strings.Trim(field[1], " kB") // remove last "kB"
|
|
||||||
t, err := strconv.ParseUint(v, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return m, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch field[0] {
|
|
||||||
case "Size":
|
|
||||||
m.Size = t
|
|
||||||
case "Rss":
|
|
||||||
m.Rss = t
|
|
||||||
case "Pss":
|
|
||||||
m.Pss = t
|
|
||||||
case "Shared_Clean":
|
|
||||||
m.SharedClean = t
|
|
||||||
case "Shared_Dirty":
|
|
||||||
m.SharedDirty = t
|
|
||||||
case "Private_Clean":
|
|
||||||
m.PrivateClean = t
|
|
||||||
case "Private_Dirty":
|
|
||||||
m.PrivateDirty = t
|
|
||||||
case "Referenced":
|
|
||||||
m.Referenced = t
|
|
||||||
case "Anonymous":
|
|
||||||
m.Anonymous = t
|
|
||||||
case "Swap":
|
|
||||||
m.Swap = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
blocks := make([]string, 16)
|
|
||||||
for _, line := range lines {
|
|
||||||
field := strings.Split(line, " ")
|
|
||||||
if strings.HasSuffix(field[0], ":") == false {
|
|
||||||
// new block section
|
|
||||||
if len(blocks) > 0 {
|
|
||||||
g, err := getBlock(field, blocks)
|
|
||||||
if err != nil {
|
|
||||||
return &ret, err
|
|
||||||
}
|
|
||||||
ret = append(ret, g)
|
|
||||||
}
|
|
||||||
// starts new block
|
|
||||||
blocks = make([]string, 16)
|
|
||||||
} else {
|
|
||||||
blocks = append(blocks, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Internal functions
|
|
||||||
**/
|
|
||||||
|
|
||||||
// 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")
|
|
||||||
d, err := os.Open(statPath)
|
|
||||||
if err != nil {
|
|
||||||
return 0, nil, err
|
|
||||||
}
|
|
||||||
defer d.Close()
|
|
||||||
fnames, err := d.Readdirnames(-1)
|
|
||||||
numFDs := int32(len(fnames))
|
|
||||||
|
|
||||||
openfiles := make([]*OpenFilesStat, numFDs)
|
|
||||||
for _, fd := range fnames {
|
|
||||||
fpath := filepath.Join(statPath, fd)
|
|
||||||
filepath, err := os.Readlink(fpath)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t, err := strconv.ParseUint(fd, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return numFDs, openfiles, err
|
|
||||||
}
|
|
||||||
o := &OpenFilesStat{
|
|
||||||
Path: filepath,
|
|
||||||
Fd: t,
|
|
||||||
}
|
|
||||||
openfiles = append(openfiles, o)
|
|
||||||
}
|
|
||||||
|
|
||||||
return numFDs, openfiles, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get cwd from /proc/(pid)/cwd
|
|
||||||
func (p *Process) fillFromCwd() (string, error) {
|
|
||||||
pid := p.Pid
|
|
||||||
cwdPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "cwd")
|
|
||||||
cwd, err := os.Readlink(cwdPath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(cwd), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get exe from /proc/(pid)/exe
|
|
||||||
func (p *Process) fillFromExe() (string, error) {
|
|
||||||
pid := p.Pid
|
|
||||||
exePath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "exe")
|
|
||||||
exe, err := os.Readlink(exePath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(exe), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get cmdline from /proc/(pid)/cmdline
|
|
||||||
func (p *Process) fillFromCmdline() (string, error) {
|
|
||||||
pid := p.Pid
|
|
||||||
cmdPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "cmdline")
|
|
||||||
cmdline, err := ioutil.ReadFile(cmdPath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
ret := strings.FieldsFunc(string(cmdline), func(r rune) bool {
|
|
||||||
if r == '\u0000' {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
return strings.Join(ret, " "), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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")
|
|
||||||
ioline, err := ioutil.ReadFile(ioPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
lines := strings.Split(string(ioline), "\n")
|
|
||||||
ret := &IOCountersStat{}
|
|
||||||
|
|
||||||
for _, line := range lines {
|
|
||||||
field := strings.Fields(line)
|
|
||||||
if len(field) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t, err := strconv.ParseUint(field[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
param := field[0]
|
|
||||||
if strings.HasSuffix(param, ":") {
|
|
||||||
param = param[:len(param)-1]
|
|
||||||
}
|
|
||||||
switch param {
|
|
||||||
case "syscr":
|
|
||||||
ret.ReadCount = t
|
|
||||||
case "syscw":
|
|
||||||
ret.WriteCount = t
|
|
||||||
case "read_bytes":
|
|
||||||
ret.ReadBytes = t
|
|
||||||
case "write_bytes":
|
|
||||||
ret.WriteBytes = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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")
|
|
||||||
contents, err := ioutil.ReadFile(memPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
fields := strings.Split(string(contents), " ")
|
|
||||||
|
|
||||||
vms, err := strconv.ParseUint(fields[0], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
rss, err := strconv.ParseUint(fields[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
memInfo := &MemoryInfoStat{
|
|
||||||
RSS: rss * PageSize,
|
|
||||||
VMS: vms * PageSize,
|
|
||||||
}
|
|
||||||
|
|
||||||
shared, err := strconv.ParseUint(fields[2], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
text, err := strconv.ParseUint(fields[3], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
lib, err := strconv.ParseUint(fields[4], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
dirty, err := strconv.ParseUint(fields[5], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
memInfoEx := &MemoryInfoExStat{
|
|
||||||
RSS: rss * PageSize,
|
|
||||||
VMS: vms * PageSize,
|
|
||||||
Shared: shared * PageSize,
|
|
||||||
Text: text * PageSize,
|
|
||||||
Lib: lib * PageSize,
|
|
||||||
Dirty: dirty * PageSize,
|
|
||||||
}
|
|
||||||
|
|
||||||
return memInfo, memInfoEx, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get various status from /proc/(pid)/status
|
|
||||||
func (p *Process) fillFromStatus() error {
|
|
||||||
pid := p.Pid
|
|
||||||
statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "status")
|
|
||||||
contents, err := ioutil.ReadFile(statPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
lines := strings.Split(string(contents), "\n")
|
|
||||||
p.numCtxSwitches = &NumCtxSwitchesStat{}
|
|
||||||
p.memInfo = &MemoryInfoStat{}
|
|
||||||
for _, line := range lines {
|
|
||||||
tabParts := strings.SplitN(line, "\t", 2)
|
|
||||||
if len(tabParts) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
value := tabParts[1]
|
|
||||||
switch strings.TrimRight(tabParts[0], ":") {
|
|
||||||
case "Name":
|
|
||||||
p.name = strings.Trim(value, " \t")
|
|
||||||
case "State":
|
|
||||||
// get between "(" and ")"
|
|
||||||
s := strings.Index(value, "(") + 1
|
|
||||||
e := strings.Index(value, ")")
|
|
||||||
p.status = value[s:e]
|
|
||||||
case "Uid":
|
|
||||||
p.uids = make([]int32, 0, 4)
|
|
||||||
for _, i := range strings.Split(value, "\t") {
|
|
||||||
v, err := strconv.ParseInt(i, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.uids = append(p.uids, int32(v))
|
|
||||||
}
|
|
||||||
case "Gid":
|
|
||||||
p.gids = make([]int32, 0, 4)
|
|
||||||
for _, i := range strings.Split(value, "\t") {
|
|
||||||
v, err := strconv.ParseInt(i, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.gids = append(p.gids, int32(v))
|
|
||||||
}
|
|
||||||
case "Threads":
|
|
||||||
v, err := strconv.ParseInt(value, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.numThreads = int32(v)
|
|
||||||
case "voluntary_ctxt_switches":
|
|
||||||
v, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.numCtxSwitches.Voluntary = v
|
|
||||||
case "nonvoluntary_ctxt_switches":
|
|
||||||
v, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.numCtxSwitches.Involuntary = v
|
|
||||||
case "VmRSS":
|
|
||||||
value := strings.Trim(value, " kB") // remove last "kB"
|
|
||||||
v, err := strconv.ParseUint(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.memInfo.RSS = v * 1024
|
|
||||||
case "VmSize":
|
|
||||||
value := strings.Trim(value, " kB") // remove last "kB"
|
|
||||||
v, err := strconv.ParseUint(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.memInfo.VMS = v * 1024
|
|
||||||
case "VmSwap":
|
|
||||||
value := strings.Trim(value, " kB") // remove last "kB"
|
|
||||||
v, err := strconv.ParseUint(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.memInfo.Swap = v * 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32, error) {
|
|
||||||
pid := p.Pid
|
|
||||||
statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "stat")
|
|
||||||
contents, err := ioutil.ReadFile(statPath)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, nil, 0, 0, err
|
|
||||||
}
|
|
||||||
fields := strings.Fields(string(contents))
|
|
||||||
|
|
||||||
termmap, err := getTerminalMap()
|
|
||||||
terminal := ""
|
|
||||||
if err == nil {
|
|
||||||
t, err := strconv.ParseUint(fields[6], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, nil, 0, 0, err
|
|
||||||
}
|
|
||||||
terminal = termmap[t]
|
|
||||||
}
|
|
||||||
|
|
||||||
ppid, err := strconv.ParseInt(fields[3], 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, nil, 0, 0, err
|
|
||||||
}
|
|
||||||
utime, err := strconv.ParseFloat(fields[13], 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, nil, 0, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
stime, err := strconv.ParseFloat(fields[14], 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, nil, 0, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuTimes := &cpu.CPUTimesStat{
|
|
||||||
CPU: "cpu",
|
|
||||||
User: float64(utime / ClockTicks),
|
|
||||||
System: float64(stime / ClockTicks),
|
|
||||||
}
|
|
||||||
|
|
||||||
bootTime, _ := host.BootTime()
|
|
||||||
t, err := strconv.ParseUint(fields[21], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, nil, 0, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctime := ((t / uint64(ClockTicks)) + uint64(bootTime)) * 1000
|
|
||||||
createTime := int64(ctime)
|
|
||||||
|
|
||||||
// p.Nice = mustParseInt32(fields[18])
|
|
||||||
// use syscall instead of parse Stat file
|
|
||||||
snice, _ := syscall.Getpriority(PrioProcess, int(pid))
|
|
||||||
nice := int32(snice) // FIXME: is this true?
|
|
||||||
|
|
||||||
return terminal, int32(ppid), cpuTimes, createTime, nice, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Pids() ([]int32, error) {
|
|
||||||
var ret []int32
|
|
||||||
|
|
||||||
d, err := os.Open("/proc")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer d.Close()
|
|
||||||
|
|
||||||
fnames, err := d.Readdirnames(-1)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, fname := range fnames {
|
|
||||||
pid, err := strconv.ParseInt(fname, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
// if not numeric name, just skip
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ret = append(ret, int32(pid))
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
// +build linux
|
|
||||||
// +build 386
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
const (
|
|
||||||
ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK)
|
|
||||||
PageSize = 4096 // C.sysconf(C._SC_PAGE_SIZE)
|
|
||||||
)
|
|
|
@ -1,9 +0,0 @@
|
||||||
// +build linux
|
|
||||||
// +build amd64
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
const (
|
|
||||||
ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK)
|
|
||||||
PageSize = 4096 // C.sysconf(C._SC_PAGE_SIZE)
|
|
||||||
)
|
|
|
@ -1,9 +0,0 @@
|
||||||
// +build linux
|
|
||||||
// +build arm
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
const (
|
|
||||||
ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK)
|
|
||||||
PageSize = 4096 // C.sysconf(C._SC_PAGE_SIZE)
|
|
||||||
)
|
|
|
@ -1,102 +0,0 @@
|
||||||
// +build linux freebsd darwin
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"os/user"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// POSIX
|
|
||||||
func getTerminalMap() (map[uint64]string, error) {
|
|
||||||
ret := make(map[uint64]string)
|
|
||||||
var termfiles []string
|
|
||||||
|
|
||||||
d, err := os.Open("/dev")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer d.Close()
|
|
||||||
|
|
||||||
devnames, err := d.Readdirnames(-1)
|
|
||||||
for _, devname := range devnames {
|
|
||||||
if strings.HasPrefix(devname, "/dev/tty") {
|
|
||||||
termfiles = append(termfiles, "/dev/tty/"+devname)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ptsd, err := os.Open("/dev/pts")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer ptsd.Close()
|
|
||||||
|
|
||||||
ptsnames, err := ptsd.Readdirnames(-1)
|
|
||||||
for _, ptsname := range ptsnames {
|
|
||||||
termfiles = append(termfiles, "/dev/pts/"+ptsname)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, name := range termfiles {
|
|
||||||
stat := syscall.Stat_t{}
|
|
||||||
if err = syscall.Stat(name, &stat); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rdev := uint64(stat.Rdev)
|
|
||||||
ret[rdev] = strings.Replace(name, "/dev", "", -1)
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) SendSignal(sig syscall.Signal) error {
|
|
||||||
sigAsStr := "INT"
|
|
||||||
switch sig {
|
|
||||||
case syscall.SIGSTOP:
|
|
||||||
sigAsStr = "STOP"
|
|
||||||
case syscall.SIGCONT:
|
|
||||||
sigAsStr = "CONT"
|
|
||||||
case syscall.SIGTERM:
|
|
||||||
sigAsStr = "TERM"
|
|
||||||
case syscall.SIGKILL:
|
|
||||||
sigAsStr = "KILL"
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.Command("kill", "-s", sigAsStr, strconv.Itoa(int(p.Pid)))
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Suspend() error {
|
|
||||||
return p.SendSignal(syscall.SIGSTOP)
|
|
||||||
}
|
|
||||||
func (p *Process) Resume() error {
|
|
||||||
return p.SendSignal(syscall.SIGCONT)
|
|
||||||
}
|
|
||||||
func (p *Process) Terminate() error {
|
|
||||||
return p.SendSignal(syscall.SIGTERM)
|
|
||||||
}
|
|
||||||
func (p *Process) Kill() error {
|
|
||||||
return p.SendSignal(syscall.SIGKILL)
|
|
||||||
}
|
|
||||||
func (p *Process) Username() (string, error) {
|
|
||||||
uids, err := p.Uids()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if len(uids) > 0 {
|
|
||||||
u, err := user.LookupId(strconv.Itoa(int(uids[0])))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return u.Username, nil
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
// +build linux freebsd
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_SendSignal(t *testing.T) {
|
|
||||||
checkPid := os.Getpid()
|
|
||||||
|
|
||||||
p, _ := NewProcess(int32(checkPid))
|
|
||||||
err := p.SendSignal(syscall.SIGCONT)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("send signal %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,275 +0,0 @@
|
||||||
package process
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testGetProcess() Process {
|
|
||||||
checkPid := os.Getpid() // process.test
|
|
||||||
ret, _ := NewProcess(int32(checkPid))
|
|
||||||
return *ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Pids(t *testing.T) {
|
|
||||||
ret, err := Pids()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
if len(ret) == 0 {
|
|
||||||
t.Errorf("could not get pids %v", ret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Pid_exists(t *testing.T) {
|
|
||||||
checkPid := os.Getpid()
|
|
||||||
|
|
||||||
ret, err := PidExists(int32(checkPid))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ret == false {
|
|
||||||
t.Errorf("could not get process exists: %v", ret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_NewProcess(t *testing.T) {
|
|
||||||
checkPid := os.Getpid()
|
|
||||||
|
|
||||||
ret, err := NewProcess(int32(checkPid))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
empty := &Process{}
|
|
||||||
if runtime.GOOS != "windows" { // Windows pid is 0
|
|
||||||
if empty == ret {
|
|
||||||
t.Errorf("error %v", ret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_memory_maps(t *testing.T) {
|
|
||||||
checkPid := os.Getpid()
|
|
||||||
|
|
||||||
ret, err := NewProcess(int32(checkPid))
|
|
||||||
|
|
||||||
mmaps, err := ret.MemoryMaps(false)
|
|
||||||
if err != nil {
|
|
||||||
if err == common.NotImplementedError {
|
|
||||||
t.SkipNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("memory map get error %v", err)
|
|
||||||
}
|
|
||||||
empty := MemoryMapsStat{}
|
|
||||||
for _, m := range *mmaps {
|
|
||||||
if m == empty {
|
|
||||||
t.Errorf("memory map get error %v", m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func Test_Process_MemoryInfo(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
v, err := p.MemoryInfo()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("geting ppid error %v", err)
|
|
||||||
}
|
|
||||||
empty := MemoryInfoStat{}
|
|
||||||
if v == nil || *v == empty {
|
|
||||||
t.Errorf("could not get memory info %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_CmdLine(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
v, err := p.Cmdline()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("geting ppid error %v", err)
|
|
||||||
}
|
|
||||||
if !strings.Contains(v, "process.test") {
|
|
||||||
t.Errorf("invalid cmd line %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_Ppid(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
v, err := p.Ppid()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("geting ppid error %v", err)
|
|
||||||
}
|
|
||||||
if v == 0 {
|
|
||||||
t.Errorf("return value is 0 %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_Status(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
v, err := p.Status()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("geting ppid error %v", err)
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(v, "S") && v != "running" && v != "sleeping" {
|
|
||||||
t.Errorf("could not get state %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_Terminal(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
_, err := p.Terminal()
|
|
||||||
if err != nil {
|
|
||||||
if err == common.NotImplementedError {
|
|
||||||
t.SkipNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("geting terminal error %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if v == "" {
|
|
||||||
t.Errorf("could not get terminal %v", v)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_IOCounters(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
v, err := p.IOCounters()
|
|
||||||
if err != nil {
|
|
||||||
if err == common.NotImplementedError {
|
|
||||||
t.SkipNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("geting iocounter error %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
empty := &IOCountersStat{}
|
|
||||||
if v == empty {
|
|
||||||
t.Errorf("error %v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_NumCtx(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
_, err := p.NumCtxSwitches()
|
|
||||||
if err != nil {
|
|
||||||
if err == common.NotImplementedError {
|
|
||||||
t.SkipNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("geting numctx error %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_Nice(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
n, err := p.Nice()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("geting nice error %v", err)
|
|
||||||
}
|
|
||||||
if n != 0 && n != 20 && n != 8 {
|
|
||||||
t.Errorf("invalid nice: %d", n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func Test_Process_NumThread(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
n, err := p.NumThreads()
|
|
||||||
if err != nil {
|
|
||||||
if err == common.NotImplementedError {
|
|
||||||
t.SkipNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("geting NumThread error %v", err)
|
|
||||||
}
|
|
||||||
if n < 0 {
|
|
||||||
t.Errorf("invalid NumThread: %d", n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_Name(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
n, err := p.Name()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("geting name error %v", err)
|
|
||||||
}
|
|
||||||
if !strings.Contains(n, "process.test") {
|
|
||||||
t.Errorf("invalid Exe %s", n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func Test_Process_Exe(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
|
|
||||||
n, err := p.Exe()
|
|
||||||
if err != nil {
|
|
||||||
if err == common.NotImplementedError {
|
|
||||||
t.SkipNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("geting Exe error %v", err)
|
|
||||||
}
|
|
||||||
if !strings.Contains(n, "process.test") {
|
|
||||||
t.Errorf("invalid Exe %s", n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_CpuPercent(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
percent, err := p.CPUPercent(0)
|
|
||||||
if err != nil {
|
|
||||||
if err == common.NotImplementedError {
|
|
||||||
t.SkipNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
duration := time.Duration(1000) * time.Microsecond
|
|
||||||
time.Sleep(duration)
|
|
||||||
percent, err = p.CPUPercent(0)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
numcpu := runtime.NumCPU()
|
|
||||||
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
|
|
||||||
if percent < 0.0 {
|
|
||||||
t.Fatalf("CPUPercent value is invalid: %f, %d", percent, numcpu)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Process_CpuPercentLoop(t *testing.T) {
|
|
||||||
p := testGetProcess()
|
|
||||||
numcpu := runtime.NumCPU()
|
|
||||||
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
duration := time.Duration(100) * time.Microsecond
|
|
||||||
percent, err := p.CPUPercent(duration)
|
|
||||||
if err != nil {
|
|
||||||
if err == common.NotImplementedError {
|
|
||||||
t.SkipNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Errorf("error %v", err)
|
|
||||||
}
|
|
||||||
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
|
|
||||||
if percent < 0.0 {
|
|
||||||
t.Fatalf("CPUPercent value is invalid: %f, %d", percent, numcpu)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,305 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/shirou/w32"
|
|
||||||
|
|
||||||
common "github.com/influxdb/telegraf/plugins/system/ps/common"
|
|
||||||
cpu "github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
|
||||||
net "github.com/influxdb/telegraf/plugins/system/ps/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
NoMoreFiles = 0x12
|
|
||||||
MaxPathLength = 260
|
|
||||||
)
|
|
||||||
|
|
||||||
type SystemProcessInformation struct {
|
|
||||||
NextEntryOffset uint64
|
|
||||||
NumberOfThreads uint64
|
|
||||||
Reserved1 [48]byte
|
|
||||||
Reserved2 [3]byte
|
|
||||||
UniqueProcessID uintptr
|
|
||||||
Reserved3 uintptr
|
|
||||||
HandleCount uint64
|
|
||||||
Reserved4 [4]byte
|
|
||||||
Reserved5 [11]byte
|
|
||||||
PeakPagefileUsage uint64
|
|
||||||
PrivatePageCount uint64
|
|
||||||
Reserved6 [6]uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory_info_ex is different between OSes
|
|
||||||
type MemoryInfoExStat struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
type MemoryMapsStat struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func Pids() ([]int32, error) {
|
|
||||||
var ret []int32
|
|
||||||
|
|
||||||
procs, err := processes()
|
|
||||||
if err != nil {
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, proc := range procs {
|
|
||||||
ret = append(ret, proc.Pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Ppid() (int32, error) {
|
|
||||||
ret, _, _, err := p.getFromSnapProcess(p.Pid)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
func (p *Process) Name() (string, error) {
|
|
||||||
query := fmt.Sprintf("ProcessId = %d", p.Pid)
|
|
||||||
lines, err := common.GetWmic("process", "where", query, "get", "Name")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if len(lines) == 0 {
|
|
||||||
return "", fmt.Errorf("could not get Name")
|
|
||||||
}
|
|
||||||
return lines[0][1], nil
|
|
||||||
}
|
|
||||||
func (p *Process) Exe() (string, error) {
|
|
||||||
query := fmt.Sprintf("ProcessId = %d", p.Pid)
|
|
||||||
lines, err := common.GetWmic("process", "where", query, "get", "ExecutablePath")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if len(lines) == 0 {
|
|
||||||
return "", fmt.Errorf("could not get ExecutablePath")
|
|
||||||
}
|
|
||||||
return lines[0][1], nil
|
|
||||||
}
|
|
||||||
func (p *Process) Cmdline() (string, error) {
|
|
||||||
query := fmt.Sprintf("ProcessId = %d", p.Pid)
|
|
||||||
lines, err := common.GetWmic("process", "where", query, "get", "CommandLine")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if len(lines) == 0 {
|
|
||||||
return "", fmt.Errorf("could not get command line")
|
|
||||||
}
|
|
||||||
|
|
||||||
return lines[0][1], nil
|
|
||||||
}
|
|
||||||
func (p *Process) Cwd() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Parent() (*Process, error) {
|
|
||||||
return p, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Status() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Username() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Uids() ([]int32, error) {
|
|
||||||
var uids []int32
|
|
||||||
|
|
||||||
return uids, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Gids() ([]int32, error) {
|
|
||||||
var gids []int32
|
|
||||||
return gids, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Terminal() (string, error) {
|
|
||||||
return "", common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nice returnes priority in Windows
|
|
||||||
func (p *Process) Nice() (int32, error) {
|
|
||||||
query := fmt.Sprintf("ProcessId = %d", p.Pid)
|
|
||||||
lines, err := common.GetWmic("process", "where", query, "get", "Priority")
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if len(lines) == 0 {
|
|
||||||
return 0, fmt.Errorf("could not get command line")
|
|
||||||
}
|
|
||||||
priority, err := strconv.Atoi(lines[0][1])
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return int32(priority), nil
|
|
||||||
}
|
|
||||||
func (p *Process) IOnice() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
|
||||||
var rlimit []RlimitStat
|
|
||||||
|
|
||||||
return rlimit, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumFDs() (int32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) NumThreads() (int32, error) {
|
|
||||||
query := fmt.Sprintf("ProcessId = %d", p.Pid)
|
|
||||||
lines, err := common.GetWmic("process", "where", query, "get", "ThreadCount")
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if len(lines) == 0 {
|
|
||||||
return 0, fmt.Errorf("could not get command line")
|
|
||||||
}
|
|
||||||
count, err := strconv.Atoi(lines[0][1])
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return int32(count), nil
|
|
||||||
}
|
|
||||||
func (p *Process) Threads() (map[string]string, error) {
|
|
||||||
ret := make(map[string]string, 0)
|
|
||||||
return ret, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) MemoryPercent() (float32, error) {
|
|
||||||
return 0, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Children() ([]*Process, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Connections() ([]net.NetConnectionStat, error) {
|
|
||||||
return nil, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) IsRunning() (bool, error) {
|
|
||||||
return true, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
|
||||||
ret := make([]MemoryMapsStat, 0)
|
|
||||||
return &ret, common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewProcess(pid int32) (*Process, error) {
|
|
||||||
p := &Process{Pid: pid}
|
|
||||||
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) SendSignal(sig syscall.Signal) error {
|
|
||||||
return common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) Suspend() error {
|
|
||||||
return common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Resume() error {
|
|
||||||
return common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Terminate() error {
|
|
||||||
return common.NotImplementedError
|
|
||||||
}
|
|
||||||
func (p *Process) Kill() error {
|
|
||||||
return common.NotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Process) getFromSnapProcess(pid int32) (int32, int32, string, error) {
|
|
||||||
snap := w32.CreateToolhelp32Snapshot(w32.TH32CS_SNAPPROCESS, uint32(pid))
|
|
||||||
if snap == 0 {
|
|
||||||
return 0, 0, "", syscall.GetLastError()
|
|
||||||
}
|
|
||||||
defer w32.CloseHandle(snap)
|
|
||||||
var pe32 w32.PROCESSENTRY32
|
|
||||||
pe32.DwSize = uint32(unsafe.Sizeof(pe32))
|
|
||||||
if w32.Process32First(snap, &pe32) == false {
|
|
||||||
return 0, 0, "", syscall.GetLastError()
|
|
||||||
}
|
|
||||||
|
|
||||||
if pe32.Th32ProcessID == uint32(pid) {
|
|
||||||
szexe := syscall.UTF16ToString(pe32.SzExeFile[:])
|
|
||||||
return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for w32.Process32Next(snap, &pe32) {
|
|
||||||
if pe32.Th32ProcessID == uint32(pid) {
|
|
||||||
szexe := syscall.UTF16ToString(pe32.SzExeFile[:])
|
|
||||||
return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, 0, "", errors.New("Couldn't find pid:" + string(pid))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get processes
|
|
||||||
func processes() ([]*Process, error) {
|
|
||||||
lines, err := common.GetWmic("process", "get", "processid")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var results []*Process
|
|
||||||
for _, l := range lines {
|
|
||||||
pid, err := strconv.Atoi(l[1])
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p, err := NewProcess(int32(pid))
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
results = append(results, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getProcInfo(pid int32) (*SystemProcessInformation, error) {
|
|
||||||
initialBufferSize := uint64(0x4000)
|
|
||||||
bufferSize := initialBufferSize
|
|
||||||
buffer := make([]byte, bufferSize)
|
|
||||||
|
|
||||||
var sysProcInfo SystemProcessInformation
|
|
||||||
ret, _, _ := common.ProcNtQuerySystemInformation.Call(
|
|
||||||
uintptr(unsafe.Pointer(&sysProcInfo)),
|
|
||||||
uintptr(unsafe.Pointer(&buffer[0])),
|
|
||||||
uintptr(unsafe.Pointer(&bufferSize)),
|
|
||||||
uintptr(unsafe.Pointer(&bufferSize)))
|
|
||||||
if ret != 0 {
|
|
||||||
return nil, syscall.GetLastError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return &sysProcInfo, nil
|
|
||||||
}
|
|
|
@ -1,160 +0,0 @@
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Hand Writing
|
|
||||||
// - all pointer in ExternProc to uint64
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input to cgo -godefs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
// +godefs map struct_ [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package process
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define __DARWIN_UNIX03 0
|
|
||||||
#define KERNEL
|
|
||||||
#define _DARWIN_USE_64_BIT_INODE
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <mach/mach.h>
|
|
||||||
#include <mach/message.h>
|
|
||||||
#include <sys/event.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/ptrace.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include <sys/signal.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <net/bpf.h>
|
|
||||||
#include <net/if_dl.h>
|
|
||||||
#include <net/if_var.h>
|
|
||||||
#include <net/route.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
#include <sys/proc.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/_types/_timeval.h>
|
|
||||||
#include <sys/appleapiopts.h>
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <bsm/audit.h>
|
|
||||||
#include <sys/queue.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
sizeofPtr = sizeof(void*),
|
|
||||||
};
|
|
||||||
|
|
||||||
union sockaddr_all {
|
|
||||||
struct sockaddr s1; // this one gets used for fields
|
|
||||||
struct sockaddr_in s2; // these pad it out
|
|
||||||
struct sockaddr_in6 s3;
|
|
||||||
struct sockaddr_un s4;
|
|
||||||
struct sockaddr_dl s5;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sockaddr_any {
|
|
||||||
struct sockaddr addr;
|
|
||||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ucred_queue {
|
|
||||||
struct ucred *tqe_next;
|
|
||||||
struct ucred **tqe_prev;
|
|
||||||
TRACEBUF
|
|
||||||
};
|
|
||||||
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
// Time
|
|
||||||
|
|
||||||
type Timespec C.struct_timespec
|
|
||||||
|
|
||||||
type Timeval C.struct_timeval
|
|
||||||
|
|
||||||
// Processes
|
|
||||||
|
|
||||||
type Rusage C.struct_rusage
|
|
||||||
|
|
||||||
type Rlimit C.struct_rlimit
|
|
||||||
|
|
||||||
type UGid_t C.gid_t
|
|
||||||
|
|
||||||
type KinfoProc C.struct_kinfo_proc
|
|
||||||
|
|
||||||
type Eproc C.struct_eproc
|
|
||||||
|
|
||||||
type Proc C.struct_proc
|
|
||||||
|
|
||||||
type Session C.struct_session
|
|
||||||
|
|
||||||
type ucred C.struct_ucred
|
|
||||||
|
|
||||||
type Uucred C.struct__ucred
|
|
||||||
|
|
||||||
type Upcred C.struct__pcred
|
|
||||||
|
|
||||||
type Vmspace C.struct_vmspace
|
|
||||||
|
|
||||||
type Sigacts C.struct_sigacts
|
|
||||||
|
|
||||||
type ExternProc C.struct_extern_proc
|
|
||||||
|
|
||||||
type Itimerval C.struct_itimerval
|
|
||||||
|
|
||||||
type Vnode C.struct_vnode
|
|
||||||
|
|
||||||
type Pgrp C.struct_pgrp
|
|
||||||
|
|
||||||
type UserStruct C.struct_user
|
|
||||||
|
|
||||||
type Au_session C.struct_au_session
|
|
||||||
|
|
||||||
type Posix_cred C.struct_posix_cred
|
|
||||||
|
|
||||||
type Label C.struct_label
|
|
||||||
|
|
||||||
type AuditinfoAddr C.struct_auditinfo_addr
|
|
||||||
type AuMask C.struct_au_mask
|
|
||||||
type AuTidAddr C.struct_au_tid_addr
|
|
||||||
|
|
||||||
// TAILQ(ucred)
|
|
||||||
type UcredQueue C.struct_ucred_queue
|
|
|
@ -1,36 +0,0 @@
|
||||||
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
|
|
|
@ -5,11 +5,11 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/cpu"
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/disk"
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/mem"
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/net"
|
|
||||||
"github.com/influxdb/telegraf/testutil"
|
"github.com/influxdb/telegraf/testutil"
|
||||||
|
"github.com/shirou/gopsutil/cpu"
|
||||||
|
"github.com/shirou/gopsutil/disk"
|
||||||
|
"github.com/shirou/gopsutil/mem"
|
||||||
|
"github.com/shirou/gopsutil/net"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue