mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-14 01:07:08 -06:00
Add perf test suite infrastructure, and a perf test for csv-import (#2384)
You can run these yourself using the -perf flag, e.g. > noms serve & > go test -v -perf http://localhost:8000 ./samples/go/csv/csv-import > noms ds http://localhost:8000 Though you'll need to go-get github.com/attic-labs/testdata. Note that all of this only records test results, it doesn't have any concept of failing perf (unless test assertsions themselves fail). It will be the job of some other Noms client (work in progress) to do that. I will be setting this up to run continuously momentarily.
This commit is contained in:
@@ -21,7 +21,7 @@ type connectionState struct {
|
||||
cs http.ConnState
|
||||
}
|
||||
|
||||
type remoteDatabaseServer struct {
|
||||
type RemoteDatabaseServer struct {
|
||||
cs chunks.ChunkStore
|
||||
port int
|
||||
l *net.Listener
|
||||
@@ -31,21 +31,21 @@ type remoteDatabaseServer struct {
|
||||
Ready func()
|
||||
}
|
||||
|
||||
func NewRemoteDatabaseServer(cs chunks.ChunkStore, port int) *remoteDatabaseServer {
|
||||
func NewRemoteDatabaseServer(cs chunks.ChunkStore, port int) *RemoteDatabaseServer {
|
||||
dataVersion := cs.Version()
|
||||
d.PanicIfTrue(constants.NomsVersion != dataVersion, "SDK version %s is incompatible with data of version %s", constants.NomsVersion, dataVersion)
|
||||
return &remoteDatabaseServer{
|
||||
return &RemoteDatabaseServer{
|
||||
cs, port, nil, make(chan *connectionState, 16), false, func() {},
|
||||
}
|
||||
}
|
||||
|
||||
// Port is the actual port used. This may be different than the port passed in to NewRemoteDatabaseServer.
|
||||
func (s *remoteDatabaseServer) Port() int {
|
||||
func (s *RemoteDatabaseServer) Port() int {
|
||||
return s.port
|
||||
}
|
||||
|
||||
// Run blocks while the remoteDatabaseServer is listening. Running on a separate go routine is supported.
|
||||
func (s *remoteDatabaseServer) Run() {
|
||||
// Run blocks while the RemoteDatabaseServer is listening. Running on a separate go routine is supported.
|
||||
func (s *RemoteDatabaseServer) Run() {
|
||||
|
||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", s.port))
|
||||
d.Chk.NoError(err)
|
||||
@@ -95,7 +95,7 @@ func (s *remoteDatabaseServer) Run() {
|
||||
srv.Serve(l)
|
||||
}
|
||||
|
||||
func (s *remoteDatabaseServer) makeHandle(hndlr Handler) httprouter.Handle {
|
||||
func (s *RemoteDatabaseServer) makeHandle(hndlr Handler) httprouter.Handle {
|
||||
return func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
hndlr(w, req, ps, s.cs)
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func (s *remoteDatabaseServer) makeHandle(hndlr Handler) httprouter.Handle {
|
||||
func noopHandle(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
}
|
||||
|
||||
func (s *remoteDatabaseServer) corsHandle(f httprouter.Handle) httprouter.Handle {
|
||||
func (s *RemoteDatabaseServer) corsHandle(f httprouter.Handle) httprouter.Handle {
|
||||
// TODO: Implement full pre-flighting?
|
||||
// See: http://www.html5rocks.com/static/images/cors_server_flowchart.png
|
||||
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
@@ -118,7 +118,7 @@ func (s *remoteDatabaseServer) corsHandle(f httprouter.Handle) httprouter.Handle
|
||||
}
|
||||
}
|
||||
|
||||
func (s *remoteDatabaseServer) connState(c net.Conn, cs http.ConnState) {
|
||||
func (s *RemoteDatabaseServer) connState(c net.Conn, cs http.ConnState) {
|
||||
if s.closing {
|
||||
d.Chk.True(cs == http.StateClosed)
|
||||
return
|
||||
@@ -126,8 +126,8 @@ func (s *remoteDatabaseServer) connState(c net.Conn, cs http.ConnState) {
|
||||
s.csChan <- &connectionState{c, cs}
|
||||
}
|
||||
|
||||
// Will cause the remoteDatabaseServer to stop listening and an existing call to Run() to continue.
|
||||
func (s *remoteDatabaseServer) Stop() {
|
||||
// Will cause the RemoteDatabaseServer to stop listening and an existing call to Run() to continue.
|
||||
func (s *RemoteDatabaseServer) Stop() {
|
||||
s.closing = true
|
||||
(*s.l).Close()
|
||||
(s.cs).Close()
|
||||
|
||||
409
go/perf/suite/suite.go
Normal file
409
go/perf/suite/suite.go
Normal file
@@ -0,0 +1,409 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Package suite implements a performance test suite for Noms, intended for measuring and reporting long running tests.
|
||||
//
|
||||
// Usage is similar to testify's suite:
|
||||
//
|
||||
// 1. Define a test suite struct which inherits from `suite.PerfSuite`.
|
||||
// 2. Define methods on that struct that start with the word "Test", optionally followed by digits, then followed a non-empty capitalized string.
|
||||
// 3. Call `suite.Run` with an instance of that struct.
|
||||
// 4. Run `go test` with the `-perf <path to noms db>` flag. Use `-perf.repeat` to set how many times tests are repeated.
|
||||
//
|
||||
// `PerfSuite` also supports testify/suite style `Setup/TearDown` methods.
|
||||
// - `Setup/TearDownSuite` is called exactly once.
|
||||
// - `Setup/TearDownRep` is called once for each repetition of the test runs, i.e. `-perf.repeat` times.
|
||||
// - `Setup/TearDownTest` is called for every test.
|
||||
//
|
||||
// Test results are written to Noms, along with a soup of the environment they were recorded in.
|
||||
//
|
||||
// Test names are derived from that "non-empty capitalized string": `"Test"` is ommitted because it's redundant, and leading digits are omitted to allow for manual test ordering. For example:
|
||||
//
|
||||
// ```
|
||||
// > cat ./samples/go/csv/csv-import/perf_test.go
|
||||
// type perfSuite {
|
||||
// suite.PerfSuite
|
||||
// }
|
||||
//
|
||||
// func (s *perfSuite) TestFoo() { ... }
|
||||
// func (s *perfSuite) TestZoo() { ... }
|
||||
// func (s *perfSuite) Test01Qux() { ... }
|
||||
// func (s *perfSuite) Test02Bar() { ... }
|
||||
//
|
||||
// func TestPerf(t *testing.T) {
|
||||
// suite.Run("csv-import", t, &perfSuite{})
|
||||
// }
|
||||
//
|
||||
// > go test -v ./samples/go/csv/... -perf http://localhost:8000 -perf.repeat 3
|
||||
// (perf) RUN(1/3) Test01Qux (recorded as "Qux")
|
||||
// (perf) PASS: Test01Qux (5s, paused 15s, total 20s)
|
||||
// (perf) RUN(1/3) Test02Bar (recorded as "Bar")
|
||||
// (perf) PASS: Test02Bar (15s, paused 2s, total 17s)
|
||||
// (perf) RUN(1/3) TestFoo (recorded as "Foo")
|
||||
// (perf) PASS: TestFoo (10s, paused 1s, total 11s)
|
||||
// (perf) RUN(1/3) TestZoo (recorded as "Zoo")
|
||||
// (perf) PASS: TestZoo (1s, paused 42s, total 43s)
|
||||
// ...
|
||||
//
|
||||
// > noms show http://localhost:8000::csv-import
|
||||
// {
|
||||
// environment: ...
|
||||
// tests: [{
|
||||
// "Bar": {elapsed: 15s, paused: 2s, total: 17s},
|
||||
// "Foo": {elapsed: 10s, paused: 1s, total: 11s},
|
||||
// "Qux": {elapsed: 5s, paused: 15s, total: 20s},
|
||||
// "Zoo": {elapsed: 1s, paused: 42s, total: 43s},
|
||||
// }, ...]
|
||||
// ...
|
||||
// }
|
||||
// ```
|
||||
package suite
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/attic-labs/noms/go/chunks"
|
||||
"github.com/attic-labs/noms/go/datas"
|
||||
"github.com/attic-labs/noms/go/dataset"
|
||||
"github.com/attic-labs/noms/go/marshal"
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/testify/assert"
|
||||
testifySuite "github.com/attic-labs/testify/suite"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
)
|
||||
|
||||
var (
|
||||
perfFlag = flag.String("perf", "", "The database to write perf tests to. If this isn't specified, perf tests are skipped. If you want a dry run, use \"mem\" as a database")
|
||||
perfRepeatFlag = flag.Int("perf.repeat", 1, "The number of times to repeat each perf test")
|
||||
perfMemFlag = flag.Bool("perf.mem", false, "Back the test database with a memory store, not leveldb. This will affect test timing, but it's provided in case you're low on disk space")
|
||||
testNamePattern = regexp.MustCompile("^Test[0-9]*([A-Z].*$)")
|
||||
)
|
||||
|
||||
// PerfSuite is the core of the perf testing suite. See package documentation for details.
|
||||
type PerfSuite struct {
|
||||
// T is the `testing.T` instance set when the suite is passed into `Run`.
|
||||
T *testing.T
|
||||
|
||||
// W is the `io.Writer` to write test output, which only outputs if the verbose flag is set.
|
||||
W io.Writer
|
||||
|
||||
// AtticLabs is the path to the attic-labs directory (e.g. /path/to/go/src/github.com/attic-labs).
|
||||
AtticLabs string
|
||||
|
||||
// Database is a Noms database that tests can use for reading and writing. State is persisted across a single Run of a suite.
|
||||
Database datas.Database
|
||||
|
||||
// DatabaseSpec is the Noms spec of `Database` (typically a localhost URL).
|
||||
DatabaseSpec string
|
||||
|
||||
tempFiles []*os.File
|
||||
tempDirs []string
|
||||
paused time.Duration
|
||||
}
|
||||
|
||||
// SetupRepSuite has a SetupRep method, which runs every repetition of the test, i.e. `-perf.repeat` times in total.
|
||||
type SetupRepSuite interface {
|
||||
SetupRep()
|
||||
}
|
||||
|
||||
// TearDownRepSuite has a TearDownRep method, which runs every repetition of the test, i.e. `-perf.repeat` times in total.
|
||||
type TearDownRepSuite interface {
|
||||
TearDownRep()
|
||||
}
|
||||
|
||||
type perfSuiteT interface {
|
||||
Suite() *PerfSuite
|
||||
}
|
||||
|
||||
type timeInfo struct {
|
||||
elapsed, paused, total time.Duration
|
||||
}
|
||||
|
||||
type testRep map[string]timeInfo
|
||||
|
||||
type nopWriter struct{}
|
||||
|
||||
func (r nopWriter) Write(p []byte) (int, error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// Run runs `suiteT` and writes results to dataset `datasetID` in the database given by the `-perf` command line flag.
|
||||
func Run(datasetID string, t *testing.T, suiteT perfSuiteT) {
|
||||
if *perfFlag == "" {
|
||||
return
|
||||
}
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
// Piggy-back off the go test -v flag.
|
||||
verboseFlag := flag.Lookup("test.v")
|
||||
assert.NotNil(verboseFlag)
|
||||
verbose := verboseFlag.Value.(flag.Getter).Get().(bool)
|
||||
|
||||
suite := suiteT.Suite()
|
||||
suite.T = t
|
||||
if verbose {
|
||||
suite.W = os.Stdout
|
||||
} else {
|
||||
suite.W = nopWriter{}
|
||||
}
|
||||
|
||||
gopath := os.Getenv("GOPATH")
|
||||
assert.NotEmpty(gopath)
|
||||
suite.AtticLabs = path.Join(gopath, "src", "github.com", "attic-labs")
|
||||
|
||||
// Clean up temporary directories/files last.
|
||||
defer func() {
|
||||
for _, f := range suite.tempFiles {
|
||||
os.Remove(f.Name())
|
||||
}
|
||||
for _, d := range suite.tempDirs {
|
||||
os.RemoveAll(d)
|
||||
}
|
||||
}()
|
||||
|
||||
// This is the database the perf test results are written to.
|
||||
db, err := spec.GetDatabase(*perfFlag)
|
||||
assert.NoError(err)
|
||||
|
||||
// This is the temporary database for tests to use.
|
||||
//
|
||||
// * Why not use a local database + memory store?
|
||||
// Firstly, because the spec would be "mem", and the spec library doesn't know how to reuse stores.
|
||||
// Secondly, because it's an unrealistic performance measurement.
|
||||
//
|
||||
// * Why use a remote (HTTP) database?
|
||||
// It's more realistic to exercise the HTTP stack, even if it's just talking over localhost.
|
||||
//
|
||||
// * Why provide an option for leveldb vs memory underlying store?
|
||||
// Again, leveldb is more realistic than memory, and in common cases disk space > memory space.
|
||||
// However, on this developer's laptop, there is actually very little disk space, and a lot of memory;
|
||||
// plus making the test run a little bit faster locally is nice.
|
||||
var chunkStore chunks.ChunkStore
|
||||
if *perfMemFlag {
|
||||
chunkStore = chunks.NewMemoryStore()
|
||||
} else {
|
||||
ldbDir := suite.TempDir("suite.suite")
|
||||
chunkStore = chunks.NewLevelDBStoreUseFlags(ldbDir, "")
|
||||
}
|
||||
|
||||
server := datas.NewRemoteDatabaseServer(chunkStore, 0)
|
||||
portChan := make(chan int)
|
||||
server.Ready = func() { portChan <- server.Port() }
|
||||
go server.Run()
|
||||
defer server.Stop()
|
||||
|
||||
port := <-portChan
|
||||
suite.DatabaseSpec = fmt.Sprintf("http://localhost:%d", port)
|
||||
suite.Database = datas.NewRemoteDatabase(suite.DatabaseSpec, "")
|
||||
|
||||
// List of test runs, each a map of test name => timing info.
|
||||
testReps := make([]testRep, *perfRepeatFlag)
|
||||
|
||||
defer func() {
|
||||
reps := make([]types.Value, *perfRepeatFlag)
|
||||
for i, rep := range testReps {
|
||||
timesSlice := types.ValueSlice{}
|
||||
for name, info := range rep {
|
||||
timesSlice = append(timesSlice, types.String(name), types.NewStruct("", types.StructData{
|
||||
"elapsed": types.Number(info.elapsed.Nanoseconds()),
|
||||
"paused": types.Number(info.paused.Nanoseconds()),
|
||||
"total": types.Number(info.total.Nanoseconds()),
|
||||
}))
|
||||
}
|
||||
reps[i] = types.NewMap(timesSlice...)
|
||||
}
|
||||
|
||||
record := types.NewStruct("", map[string]types.Value{
|
||||
"environment": suite.getEnvironment(),
|
||||
"nomsRevision": types.String(suite.getGitHead(path.Join(suite.AtticLabs, "noms"))),
|
||||
"testdataRevision": types.String(suite.getGitHead(path.Join(suite.AtticLabs, "testdata"))),
|
||||
"reps": types.NewList(reps...),
|
||||
})
|
||||
|
||||
ds := dataset.NewDataset(db, datasetID)
|
||||
var err error
|
||||
ds, err = ds.CommitValue(record)
|
||||
assert.NoError(err)
|
||||
assert.NoError(db.Close())
|
||||
}()
|
||||
|
||||
if t, ok := suiteT.(testifySuite.SetupAllSuite); ok {
|
||||
t.SetupSuite()
|
||||
}
|
||||
|
||||
for repIdx := 0; repIdx < *perfRepeatFlag; repIdx++ {
|
||||
testReps[repIdx] = testRep{}
|
||||
|
||||
if t, ok := suiteT.(SetupRepSuite); ok {
|
||||
t.SetupRep()
|
||||
}
|
||||
|
||||
for t, mIdx := reflect.TypeOf(suiteT), 0; mIdx < t.NumMethod(); mIdx++ {
|
||||
m := t.Method(mIdx)
|
||||
|
||||
parts := testNamePattern.FindStringSubmatch(m.Name)
|
||||
if parts == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if t, ok := suiteT.(testifySuite.SetupTestSuite); ok {
|
||||
t.SetupTest()
|
||||
}
|
||||
|
||||
recordName := parts[1]
|
||||
if verbose {
|
||||
fmt.Printf("(perf) RUN(%d/%d) %s (as \"%s\")\n", repIdx+1, *perfRepeatFlag, m.Name, recordName)
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
suite.paused = 0
|
||||
|
||||
err := callSafe(m.Name, m.Func, suiteT)
|
||||
|
||||
total := time.Since(start)
|
||||
elapsed := total - suite.paused
|
||||
|
||||
if verbose && err == nil {
|
||||
fmt.Printf("(perf) PASS: %s (%s, paused for %s, total %s)\n", m.Name, elapsed, suite.paused, total)
|
||||
} else if err != nil {
|
||||
fmt.Printf("(perf) FAIL: %s (%s, paused for %s, total %s)\n", m.Name, elapsed, suite.paused, total)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
testReps[repIdx][recordName] = timeInfo{elapsed, suite.paused, total}
|
||||
|
||||
if t, ok := suiteT.(testifySuite.TearDownTestSuite); ok {
|
||||
t.TearDownTest()
|
||||
}
|
||||
}
|
||||
|
||||
if t, ok := suiteT.(TearDownRepSuite); ok {
|
||||
t.TearDownRep()
|
||||
}
|
||||
}
|
||||
|
||||
if t, ok := suiteT.(testifySuite.TearDownAllSuite); ok {
|
||||
t.TearDownSuite()
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *PerfSuite) Suite() *PerfSuite {
|
||||
return suite
|
||||
}
|
||||
|
||||
// NewAssert returns the `assert.Assertions` instance for this test.
|
||||
func (suite *PerfSuite) NewAssert() *assert.Assertions {
|
||||
return assert.New(suite.T)
|
||||
}
|
||||
|
||||
// TempFile creates a temporary file, which will be automatically cleaned up by the perf test suite.
|
||||
func (suite *PerfSuite) TempFile(prefix string) *os.File {
|
||||
f, err := ioutil.TempFile("", prefix)
|
||||
assert.NoError(suite.T, err)
|
||||
suite.tempFiles = append(suite.tempFiles, f)
|
||||
return f
|
||||
}
|
||||
|
||||
// TempDir creates a temporary directory, which will be automatically cleaned up by the perf test suite.
|
||||
func (suite *PerfSuite) TempDir(prefix string) string {
|
||||
d, err := ioutil.TempDir("", prefix)
|
||||
assert.NoError(suite.T, err)
|
||||
suite.tempDirs = append(suite.tempDirs, d)
|
||||
return d
|
||||
}
|
||||
|
||||
// Pause pauses the test timer while `fn` is executing. Useful for omitting long setup code (e.g. copying files) from the test elapsed time.
|
||||
func (suite *PerfSuite) Pause(fn func()) {
|
||||
start := time.Now()
|
||||
fn()
|
||||
suite.paused += time.Since(start)
|
||||
}
|
||||
|
||||
func callSafe(name string, fun reflect.Value, args ...interface{}) (err interface{}) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = r
|
||||
}
|
||||
}()
|
||||
funArgs := make([]reflect.Value, len(args))
|
||||
for i, arg := range args {
|
||||
funArgs[i] = reflect.ValueOf(arg)
|
||||
}
|
||||
fun.Call(funArgs)
|
||||
return
|
||||
}
|
||||
|
||||
func (suite *PerfSuite) getEnvironment() types.Struct {
|
||||
assert := suite.NewAssert()
|
||||
|
||||
cpuInfos, err := cpu.Info()
|
||||
assert.NoError(err)
|
||||
cpus := make([]types.Value, 0, 2*len(cpuInfos))
|
||||
for i, c := range cpuInfos {
|
||||
cm, err := marshal.Marshal(c)
|
||||
assert.NoError(err)
|
||||
cpus = append(cpus, types.Number(i), cm)
|
||||
}
|
||||
|
||||
vmStat, err := mem.VirtualMemory()
|
||||
assert.NoError(err)
|
||||
mem, err := marshal.Marshal(*vmStat)
|
||||
assert.NoError(err)
|
||||
|
||||
hostInfo, err := host.Info()
|
||||
assert.NoError(err)
|
||||
host, err := marshal.Marshal(*hostInfo)
|
||||
assert.NoError(err)
|
||||
|
||||
partitionStats, err := disk.Partitions(false)
|
||||
assert.NoError(err)
|
||||
partitions := make([]types.Value, 0, 2*len(partitionStats))
|
||||
diskUsages := make([]types.Value, 0, 2*len(partitionStats))
|
||||
for _, p := range partitionStats {
|
||||
pm, err := marshal.Marshal(p)
|
||||
assert.NoError(err)
|
||||
partitions = append(partitions, types.String(p.Device), pm)
|
||||
du, err := disk.Usage(p.Mountpoint)
|
||||
assert.NoError(err)
|
||||
dum, err := marshal.Marshal(*du)
|
||||
assert.NoError(err)
|
||||
diskUsages = append(diskUsages, types.String(p.Mountpoint), dum)
|
||||
}
|
||||
|
||||
return types.NewStruct("", types.StructData{
|
||||
"diskUsages": types.NewMap(diskUsages...),
|
||||
"cpus": types.NewMap(cpus...),
|
||||
"mem": mem,
|
||||
"host": host,
|
||||
"partitions": types.NewMap(partitions...),
|
||||
})
|
||||
}
|
||||
|
||||
func (suite *PerfSuite) getGitHead(dir string) string {
|
||||
stdout := &bytes.Buffer{}
|
||||
cmd := exec.Command("git", "rev-parse", "HEAD")
|
||||
cmd.Stdout = stdout
|
||||
cmd.Dir = dir
|
||||
if err := cmd.Run(); err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(stdout.String())
|
||||
}
|
||||
200
go/perf/suite/suite_test.go
Normal file
200
go/perf/suite/suite_test.go
Normal file
@@ -0,0 +1,200 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package suite
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/attic-labs/noms/go/spec"
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/testify/assert"
|
||||
)
|
||||
|
||||
type testSuite struct {
|
||||
PerfSuite
|
||||
tempFileName, tempDir string
|
||||
setupTest, tearDownTest int
|
||||
setupRep, tearDownRep int
|
||||
setupSuite, tearDownSuite int
|
||||
}
|
||||
|
||||
// This is the only test that does anything interesting. The others are just to test naming.
|
||||
func (s *testSuite) TestInterestingStuff() {
|
||||
assert := s.NewAssert()
|
||||
assert.NotNil(s.T)
|
||||
assert.NotNil(s.W)
|
||||
assert.NotEqual("", s.AtticLabs)
|
||||
assert.NotEqual("", s.DatabaseSpec)
|
||||
|
||||
val := types.Bool(true)
|
||||
r := s.Database.WriteValue(val)
|
||||
assert.True(s.Database.ReadValue(r.TargetHash()).Equals(val))
|
||||
|
||||
s.Pause(func() {
|
||||
s.waitForSmidge()
|
||||
})
|
||||
|
||||
s.tempFileName = s.TempFile("suite.suite_test").Name()
|
||||
s.tempDir = s.TempDir("suite.suite_test")
|
||||
}
|
||||
|
||||
func (s *testSuite) TestFoo() {
|
||||
s.waitForSmidge()
|
||||
}
|
||||
|
||||
func (s *testSuite) TestBar() {
|
||||
s.waitForSmidge()
|
||||
}
|
||||
|
||||
func (s *testSuite) Test01Abc() {
|
||||
s.waitForSmidge()
|
||||
}
|
||||
|
||||
func (s *testSuite) Test02Def() {
|
||||
s.waitForSmidge()
|
||||
}
|
||||
|
||||
func (s *testSuite) testNothing() {
|
||||
s.waitForSmidge()
|
||||
}
|
||||
|
||||
func (s *testSuite) Testimate() {
|
||||
s.waitForSmidge()
|
||||
}
|
||||
|
||||
func (s *testSuite) SetupTest() {
|
||||
s.setupTest++
|
||||
}
|
||||
|
||||
func (s *testSuite) TearDownTest() {
|
||||
s.tearDownTest++
|
||||
}
|
||||
|
||||
func (s *testSuite) SetupRep() {
|
||||
s.setupRep++
|
||||
}
|
||||
|
||||
func (s *testSuite) TearDownRep() {
|
||||
s.tearDownRep++
|
||||
}
|
||||
|
||||
func (s *testSuite) SetupSuite() {
|
||||
s.setupSuite++
|
||||
}
|
||||
|
||||
func (s *testSuite) TearDownSuite() {
|
||||
s.tearDownSuite++
|
||||
}
|
||||
|
||||
func (s *testSuite) waitForSmidge() {
|
||||
// Tests should call this to make sure the measurement shows up as > 0, not that it shows up as a millisecond.
|
||||
<-time.After(time.Millisecond)
|
||||
}
|
||||
|
||||
func TestSuite(t *testing.T) {
|
||||
runTestSuite(t, false)
|
||||
}
|
||||
|
||||
func TestSuiteWithMem(t *testing.T) {
|
||||
runTestSuite(t, true)
|
||||
}
|
||||
|
||||
func runTestSuite(t *testing.T, mem bool) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Write test results to our own temporary LDB database.
|
||||
ldbDir, err := ioutil.TempDir("", "suite.TestSuite")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(ldbDir)
|
||||
|
||||
perfFlagVal := *perfFlag
|
||||
perfRepeatFlagVal := *perfRepeatFlag
|
||||
perfMemFlagVal := *perfMemFlag
|
||||
*perfFlag = ldbDir
|
||||
*perfRepeatFlag = 3
|
||||
*perfMemFlag = mem
|
||||
defer func() {
|
||||
*perfFlag = perfFlagVal
|
||||
*perfRepeatFlag = perfRepeatFlagVal
|
||||
*perfMemFlag = perfMemFlagVal
|
||||
}()
|
||||
|
||||
s := &testSuite{}
|
||||
Run("ds", t, s)
|
||||
|
||||
expectedTests := []string{"Abc", "Bar", "Def", "Foo", "InterestingStuff"}
|
||||
|
||||
// The temp file and dir should have been cleaned up.
|
||||
_, err = os.Stat(s.tempFileName)
|
||||
assert.NotNil(err)
|
||||
_, err = os.Stat(s.tempDir)
|
||||
assert.NotNil(err)
|
||||
|
||||
// The correct number of Setup/TearDown calls should have been run.
|
||||
assert.Equal(1, s.setupSuite)
|
||||
assert.Equal(1, s.tearDownSuite)
|
||||
assert.Equal(*perfRepeatFlag, s.setupRep)
|
||||
assert.Equal(*perfRepeatFlag, s.tearDownRep)
|
||||
assert.Equal(*perfRepeatFlag*len(expectedTests), s.setupTest)
|
||||
assert.Equal(*perfRepeatFlag*len(expectedTests), s.tearDownTest)
|
||||
|
||||
// The results should have been written to the "ds" dataset.
|
||||
ds, err := spec.GetDataset(ldbDir + "::ds")
|
||||
assert.NoError(err)
|
||||
head := ds.HeadValue().(types.Struct)
|
||||
|
||||
// These tests mostly assert that the structure of the results is correct. Specific values are hard.
|
||||
|
||||
getOrFail := func(s types.Struct, f string) types.Value {
|
||||
val, ok := s.MaybeGet(f)
|
||||
assert.True(ok)
|
||||
return val
|
||||
}
|
||||
|
||||
env, ok := getOrFail(head, "environment").(types.Struct)
|
||||
assert.True(ok)
|
||||
|
||||
getOrFail(env, "diskUsages")
|
||||
getOrFail(env, "cpus")
|
||||
getOrFail(env, "mem")
|
||||
getOrFail(env, "host")
|
||||
getOrFail(env, "partitions")
|
||||
|
||||
nomsRevision := getOrFail(head, "nomsRevision")
|
||||
assert.True(ok)
|
||||
assert.True(string(nomsRevision.(types.String)) != "")
|
||||
getOrFail(head, "testdataRevision")
|
||||
|
||||
reps, ok := getOrFail(head, "reps").(types.List)
|
||||
assert.True(ok)
|
||||
assert.Equal(*perfRepeatFlag, int(reps.Len()))
|
||||
|
||||
reps.IterAll(func(rep types.Value, _ uint64) {
|
||||
i := 0
|
||||
|
||||
rep.(types.Map).IterAll(func(k, timesVal types.Value) {
|
||||
assert.True(i < len(expectedTests))
|
||||
assert.Equal(expectedTests[i], string(k.(types.String)))
|
||||
|
||||
times := timesVal.(types.Struct)
|
||||
assert.True(getOrFail(times, "elapsed").(types.Number) > 0)
|
||||
assert.True(getOrFail(times, "total").(types.Number) > 0)
|
||||
|
||||
paused := getOrFail(times, "paused").(types.Number)
|
||||
if k == types.String("InterestingStuff") {
|
||||
assert.True(paused > 0)
|
||||
} else {
|
||||
assert.True(paused == 0)
|
||||
}
|
||||
|
||||
i++
|
||||
})
|
||||
|
||||
assert.Equal(i, len(expectedTests))
|
||||
})
|
||||
}
|
||||
91
samples/go/csv/csv-import/perf_test.go
Normal file
91
samples/go/csv/csv-import/perf_test.go
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/attic-labs/noms/go/dataset"
|
||||
"github.com/attic-labs/noms/go/hash"
|
||||
"github.com/attic-labs/noms/go/perf/suite"
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/testify/assert"
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
// CSV perf suites require the testdata directory to be checked out at $GOPATH/src/github.com/attic-labs/testdata (i.e. ../testdata relative to the noms directory).
|
||||
|
||||
// TODO: Add ny-vehicle-registrations test when CSV importing is faster (testdata/ny-vehicle-registrations/20150218.*).
|
||||
|
||||
type perfSuite struct {
|
||||
suite.PerfSuite
|
||||
csvImportExe string
|
||||
sfcBlobHash hash.Hash
|
||||
}
|
||||
|
||||
func (s *perfSuite) SetupSuite() {
|
||||
// Trick the temp file logic into creating a unique path for the csv-import binary.
|
||||
f := s.TempFile("csv-import.perf_test")
|
||||
f.Close()
|
||||
os.Remove(f.Name())
|
||||
|
||||
s.csvImportExe = f.Name()
|
||||
err := exec.Command("go", "build", "-o", s.csvImportExe, "github.com/attic-labs/noms/samples/go/csv/csv-import").Run()
|
||||
assert.NoError(s.T, err)
|
||||
}
|
||||
|
||||
func (s *perfSuite) Test01ImportSfCrimeBlobFromTestdata() {
|
||||
assert := s.NewAssert()
|
||||
|
||||
var raw []io.Reader
|
||||
|
||||
s.Pause(func() {
|
||||
// The raw data is split into a bunch of files foo.a, foo.b, etc.
|
||||
glob, err := filepath.Glob(path.Join(s.AtticLabs, "testdata", "sf-crime", "2016-07-28.*"))
|
||||
assert.NoError(err)
|
||||
|
||||
raw = make([]io.Reader, len(glob))
|
||||
for i, m := range glob {
|
||||
r, err := os.Open(m)
|
||||
assert.NoError(err)
|
||||
raw[i] = r
|
||||
}
|
||||
})
|
||||
|
||||
defer s.Pause(func() {
|
||||
for _, r := range raw {
|
||||
assert.NoError(r.(io.ReadCloser).Close())
|
||||
}
|
||||
})
|
||||
|
||||
blob := types.NewBlob(io.MultiReader(raw...))
|
||||
fmt.Fprintf(s.W, "csv/raw is %s\n", humanize.Bytes(blob.Len()))
|
||||
|
||||
ds := dataset.NewDataset(s.Database, "csv/raw")
|
||||
_, err := ds.CommitValue(blob)
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
func (s *perfSuite) Test02ImportSfCrimeCSVFromBlob() {
|
||||
assert := s.NewAssert()
|
||||
|
||||
blobSpec := fmt.Sprintf("%s::csv/raw.value", s.DatabaseSpec)
|
||||
destSpec := fmt.Sprintf("%s::csv", s.DatabaseSpec)
|
||||
importCmd := exec.Command(s.csvImportExe, "-p", blobSpec, destSpec)
|
||||
importCmd.Stdout = s.W
|
||||
importCmd.Stderr = os.Stderr
|
||||
|
||||
assert.NoError(importCmd.Run())
|
||||
}
|
||||
|
||||
func TestPerf(t *testing.T) {
|
||||
suite.Run("csv-import", t, &perfSuite{})
|
||||
}
|
||||
2
vendor/github.com/shirou/gopsutil/.version
generated
vendored
Normal file
2
vendor/github.com/shirou/gopsutil/.version
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
http://github.com/shirou/gopsutil
|
||||
e997d2e3dbc8b756de46d61e390ddc54837d63b1
|
||||
61
vendor/github.com/shirou/gopsutil/LICENSE
generated
vendored
Normal file
61
vendor/github.com/shirou/gopsutil/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
gopsutil is distributed under BSD license reproduced below.
|
||||
|
||||
Copyright (c) 2014, WAKAYAMA Shirou
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the gopsutil authors nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
-------
|
||||
internal/common/binary.go in the gopsutil is copied and modifid from golang/encoding/binary.go.
|
||||
|
||||
|
||||
|
||||
Copyright (c) 2009 The Go Authors. 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 Google Inc. 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.
|
||||
18
vendor/github.com/shirou/gopsutil/Makefile
generated
vendored
Normal file
18
vendor/github.com/shirou/gopsutil/Makefile
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
.PHONY: help check
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
SUBPKGS=cpu disk docker host internal load mem net process
|
||||
|
||||
help: ## Show help
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
check: ## Check
|
||||
errcheck -ignore="Close|Run|Write" ./...
|
||||
golint ./... | egrep -v 'underscores|HttpOnly|should have comment|comment on exported|CamelCase|VM|UID'
|
||||
|
||||
build_test: ## test only buildable
|
||||
GOOS=linux go test ./... | grep -v "exec format error"
|
||||
GOOS=freebsd go test ./... | grep -v "exec format error"
|
||||
CGO_ENABLED=0 GOOS=darwin go test ./... | grep -v "exec format error"
|
||||
CGO_ENABLED=1 GOOS=darwin go test ./... | grep -v "exec format error"
|
||||
GOOS=windows go test ./...| grep -v "exec format error"
|
||||
300
vendor/github.com/shirou/gopsutil/README.rst
generated
vendored
Normal file
300
vendor/github.com/shirou/gopsutil/README.rst
generated
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
gopsutil: psutil for golang
|
||||
==============================
|
||||
|
||||
.. image:: https://circleci.com/gh/shirou/gopsutil.svg?&style=shield
|
||||
:target: https://circleci.com/gh/shirou/gopsutil
|
||||
|
||||
.. image:: https://coveralls.io/repos/shirou/gopsutil/badge.svg?branch=master
|
||||
:target: https://coveralls.io/r/shirou/gopsutil?branch=master
|
||||
|
||||
.. image:: https://godoc.org/github.com/shirou/gopsutil?status.svg
|
||||
:target: http://godoc.org/github.com/shirou/gopsutil
|
||||
|
||||
This is a port of psutil (http://pythonhosted.org/psutil/). The challenge is porting all
|
||||
psutil functions on some architectures.
|
||||
|
||||
|
||||
.. highlights:: Breaking Changes!
|
||||
|
||||
Breaking changes is introduced at v2. See `issue 174 <https://github.com/shirou/gopsutil/issues/174>`_ .
|
||||
|
||||
|
||||
Migrating to v2
|
||||
-------------------------
|
||||
|
||||
On gopsutil itself, `v2migration.sh <https://github.com/shirou/gopsutil/blob/v2/v2migration.sh>`_ is used for migration. It can not be commonly used, but it may help you with migration.
|
||||
|
||||
|
||||
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
|
||||
---------
|
||||
|
||||
Note: gopsutil v2 breaks compatibility. If you want to stay with compatibility, please use v1 branch and vendoring.
|
||||
|
||||
.. code:: go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v, _ := mem.VirtualMemory()
|
||||
|
||||
// almost every return value is a struct
|
||||
fmt.Printf("Total: %v, Free:%v, UsedPercent:%f%%\n", v.Total, v.Free, v.UsedPercent)
|
||||
|
||||
// convert to JSON. String() is also implemented
|
||||
fmt.Println(v)
|
||||
}
|
||||
|
||||
The output is below.
|
||||
|
||||
::
|
||||
|
||||
Total: 3179569152, Free:284233728, UsedPercent:84.508194%
|
||||
{"total":3179569152,"available":492572672,"used":2895335424,"usedPercent":84.50819439828305, (snip...)}
|
||||
|
||||
You can set an alternative location to :code:`/proc` by setting the :code:`HOST_PROC` environment variable.
|
||||
|
||||
You can set an alternative location to :code:`/sys` by setting the :code:`HOST_SYS` environment variable.
|
||||
|
||||
You can set an alternative location to :code:`/etc` by setting the :code:`HOST_ETC` environment variable.
|
||||
|
||||
Documentation
|
||||
------------------------
|
||||
|
||||
see http://godoc.org/github.com/shirou/gopsutil
|
||||
|
||||
Requirements
|
||||
-----------------
|
||||
|
||||
- go1.5 or above is required.
|
||||
|
||||
|
||||
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
|
||||
|
||||
- net_protocols (linux only)
|
||||
|
||||
- system wide stats on network protocols (i.e IP, TCP, UDP, etc.)
|
||||
- sourced from /proc/net/snmp
|
||||
|
||||
- iptables nf_conntrack (linux only)
|
||||
|
||||
- system wide stats on netfilter conntrack module
|
||||
- sourced from /proc/sys/net/netfilter/nf_conntrack_count
|
||||
|
||||
Some codes are ported from Ohai. many thanks.
|
||||
|
||||
|
||||
Current Status
|
||||
------------------
|
||||
|
||||
- x: work
|
||||
- b: almost works, but something is broken
|
||||
|
||||
================= ====== ======= ====== =======
|
||||
name Linux FreeBSD MacOSX Windows
|
||||
cpu_times x x x x
|
||||
cpu_count x x x x
|
||||
cpu_percent x x x x
|
||||
cpu_times_percent x x x x
|
||||
virtual_memory x x x x
|
||||
swap_memory x x x
|
||||
disk_partitions x x x x
|
||||
disk_io_counters x x
|
||||
disk_usage x x x x
|
||||
net_io_counters x x b x
|
||||
boot_time x x x x
|
||||
users x x x x
|
||||
pids x x x x
|
||||
pid_exists x x x x
|
||||
net_connections x x
|
||||
net_protocols x
|
||||
net_if_addrs
|
||||
net_if_stats
|
||||
netfilter_conntrack x
|
||||
================= ====== ======= ====== =======
|
||||
|
||||
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 x x
|
||||
nice x x x x
|
||||
num_fds x
|
||||
num_ctx_switches x
|
||||
num_threads x x x x
|
||||
cpu_times x
|
||||
memory_info x x x x
|
||||
memory_info_ex x
|
||||
memory_maps x
|
||||
open_files x
|
||||
send_signal x x x
|
||||
suspend x x x
|
||||
resume x x x
|
||||
terminate x x x
|
||||
kill x x x
|
||||
username x
|
||||
ionice
|
||||
rlimit
|
||||
num_handlres
|
||||
threads
|
||||
cpu_percent x x
|
||||
cpu_affinity
|
||||
memory_percent
|
||||
parent x x
|
||||
children x x x
|
||||
connections x x
|
||||
is_running
|
||||
================ ===== ======= ====== =======
|
||||
|
||||
Original Metrics
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
================== ===== ======= ====== =======
|
||||
item Linux FreeBSD MacOSX Windows
|
||||
**HostInfo**
|
||||
hostname x x x x
|
||||
uptime x x x
|
||||
proces x x
|
||||
os x x x x
|
||||
platform x x x
|
||||
platformfamily x x x
|
||||
virtualization x
|
||||
**CPU**
|
||||
VendorID x x x x
|
||||
Family x x x x
|
||||
Model x x x x
|
||||
Stepping x x x x
|
||||
PhysicalID x
|
||||
CoreID x
|
||||
Cores x x
|
||||
ModelName x x x x
|
||||
**LoadAvg**
|
||||
Load1 x x x
|
||||
Load5 x x x
|
||||
Load15 x x x
|
||||
**GetDockerID**
|
||||
container id x no no no
|
||||
**CgroupsCPU**
|
||||
user x no no no
|
||||
system x no no no
|
||||
**CgroupsMem**
|
||||
various x no no no
|
||||
================== ===== ======= ====== =======
|
||||
|
||||
- future work
|
||||
|
||||
- process_iter
|
||||
- wait_procs
|
||||
- Process class
|
||||
|
||||
- as_dict
|
||||
- wait
|
||||
|
||||
|
||||
License
|
||||
------------
|
||||
|
||||
New BSD License (same as psutil)
|
||||
|
||||
|
||||
Related Works
|
||||
-----------------------
|
||||
|
||||
I have been influenced by the following great works:
|
||||
|
||||
- psutil: http://pythonhosted.org/psutil/
|
||||
- dstat: https://github.com/dagwieers/dstat
|
||||
- gosigar: https://github.com/cloudfoundry/gosigar/
|
||||
- goprocinfo: https://github.com/c9s/goprocinfo
|
||||
- go-ps: https://github.com/mitchellh/go-ps
|
||||
- ohai: https://github.com/opscode/ohai/
|
||||
- bosun: https://github.com/bosun-monitor/bosun/tree/master/cmd/scollector/collectors
|
||||
- mackerel: https://github.com/mackerelio/mackerel-agent/tree/master/metrics
|
||||
|
||||
How to Contribute
|
||||
---------------------------
|
||||
|
||||
1. Fork it
|
||||
2. Create your feature branch (git checkout -b my-new-feature)
|
||||
3. Commit your changes (git commit -am 'Add some feature')
|
||||
4. Push to the branch (git push origin my-new-feature)
|
||||
5. Create new Pull Request
|
||||
|
||||
My English is terrible, so documentation or correcting comments are also
|
||||
welcome.
|
||||
11
vendor/github.com/shirou/gopsutil/circle.yml
generated
vendored
Normal file
11
vendor/github.com/shirou/gopsutil/circle.yml
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
machine:
|
||||
timezone:
|
||||
Asia/Tokyo
|
||||
test:
|
||||
override:
|
||||
- GOOS=linux GOARCH=amd64 go test -v ./...
|
||||
- GOOS=linux GOARCH=386 go get -v ./...
|
||||
- GOOS=linux GOARCH=arm GOARM=7 go get -v ./...
|
||||
- GOOS=freebsd GOARCH=amd64 go get -v ./...
|
||||
- GOOS=windows GOARCH=amd64 go get -v ./...
|
||||
- GOOS=darwin GOARCH=amd64 go get -v ./...
|
||||
26
vendor/github.com/shirou/gopsutil/coverall.sh
generated
vendored
Normal file
26
vendor/github.com/shirou/gopsutil/coverall.sh
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
#/bin/sh
|
||||
|
||||
# see http://www.songmu.jp/riji/entry/2015-01-15-goveralls-multi-package.html
|
||||
|
||||
set -e
|
||||
# cleanup
|
||||
cleanup() {
|
||||
if [ $tmpprof != "" ] && [ -f $tmpprof ]; then
|
||||
rm -f $tmpprof
|
||||
fi
|
||||
exit
|
||||
}
|
||||
trap cleanup INT QUIT TERM EXIT
|
||||
|
||||
# メインの処理
|
||||
prof=${1:-".profile.cov"}
|
||||
echo "mode: count" > $prof
|
||||
gopath1=$(echo $GOPATH | cut -d: -f1)
|
||||
for pkg in $(go list ./...); do
|
||||
tmpprof=$gopath1/src/$pkg/profile.tmp
|
||||
go test -covermode=count -coverprofile=$tmpprof $pkg
|
||||
if [ -f $tmpprof ]; then
|
||||
cat $tmpprof | tail -n +2 >> $prof
|
||||
rm $tmpprof
|
||||
fi
|
||||
done
|
||||
93
vendor/github.com/shirou/gopsutil/cpu/cpu.go
generated
vendored
Normal file
93
vendor/github.com/shirou/gopsutil/cpu/cpu.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
type TimesStat 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:"guestNice"`
|
||||
Stolen float64 `json:"stolen"`
|
||||
}
|
||||
|
||||
type InfoStat struct {
|
||||
CPU int32 `json:"cpu"`
|
||||
VendorID string `json:"vendorId"`
|
||||
Family string `json:"family"`
|
||||
Model string `json:"model"`
|
||||
Stepping int32 `json:"stepping"`
|
||||
PhysicalID string `json:"physicalId"`
|
||||
CoreID string `json:"coreId"`
|
||||
Cores int32 `json:"cores"`
|
||||
ModelName string `json:"modelName"`
|
||||
Mhz float64 `json:"mhz"`
|
||||
CacheSize int32 `json:"cacheSize"`
|
||||
Flags []string `json:"flags"`
|
||||
}
|
||||
|
||||
type lastPercent struct {
|
||||
sync.Mutex
|
||||
lastCPUTimes []TimesStat
|
||||
lastPerCPUTimes []TimesStat
|
||||
}
|
||||
|
||||
var lastCPUPercent lastPercent
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
lastCPUPercent.Lock()
|
||||
lastCPUPercent.lastCPUTimes, _ = Times(false)
|
||||
lastCPUPercent.lastPerCPUTimes, _ = Times(true)
|
||||
lastCPUPercent.Unlock()
|
||||
}
|
||||
|
||||
func Counts(logical bool) (int, error) {
|
||||
return runtime.NumCPU(), nil
|
||||
}
|
||||
|
||||
func (c TimesStat) 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),
|
||||
`"guestNice":` + strconv.FormatFloat(c.GuestNice, 'f', 1, 64),
|
||||
`"stolen":` + strconv.FormatFloat(c.Stolen, 'f', 1, 64),
|
||||
}
|
||||
|
||||
return `{` + strings.Join(v, ",") + `}`
|
||||
}
|
||||
|
||||
// Total returns the total number of seconds in a CPUTimesStat
|
||||
func (c TimesStat) Total() float64 {
|
||||
total := c.User + c.System + c.Nice + c.Iowait + c.Irq + c.Softirq + c.Steal +
|
||||
c.Guest + c.GuestNice + c.Idle + c.Stolen
|
||||
return total
|
||||
}
|
||||
|
||||
func (c InfoStat) String() string {
|
||||
s, _ := json.Marshal(c)
|
||||
return string(s)
|
||||
}
|
||||
106
vendor/github.com/shirou/gopsutil/cpu/cpu_darwin.go
generated
vendored
Normal file
106
vendor/github.com/shirou/gopsutil/cpu/cpu_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
// +build darwin
|
||||
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// sys/resource.h
|
||||
const (
|
||||
CPUser = 0
|
||||
CPNice = 1
|
||||
CPSys = 2
|
||||
CPIntr = 3
|
||||
CPIdle = 4
|
||||
CPUStates = 5
|
||||
)
|
||||
|
||||
// default value. from time.h
|
||||
var ClocksPerSec = float64(128)
|
||||
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
||||
if percpu {
|
||||
return perCPUTimes()
|
||||
}
|
||||
|
||||
return allCPUTimes()
|
||||
}
|
||||
|
||||
// Returns only one CPUInfoStat on FreeBSD
|
||||
func Info() ([]InfoStat, error) {
|
||||
var ret []InfoStat
|
||||
sysctl, err := exec.LookPath("/usr/sbin/sysctl")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
out, err := invoke.Command(sysctl, "machdep.cpu")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
c := InfoStat{}
|
||||
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]
|
||||
}
|
||||
}
|
||||
|
||||
// Use the rated frequency of the CPU. This is a static value and does not
|
||||
// account for low power or Turbo Boost modes.
|
||||
out, err = invoke.Command(sysctl, "hw.cpufrequency")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
values := strings.Fields(string(out))
|
||||
mhz, err := strconv.ParseFloat(values[1], 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
c.Mhz = mhz / 1000000.0
|
||||
|
||||
return append(ret, c), nil
|
||||
}
|
||||
109
vendor/github.com/shirou/gopsutil/cpu/cpu_darwin_cgo.go
generated
vendored
Normal file
109
vendor/github.com/shirou/gopsutil/cpu/cpu_darwin_cgo.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// +build darwin
|
||||
// +build cgo
|
||||
|
||||
package cpu
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/mach_host.h>
|
||||
#include <mach/host_info.h>
|
||||
#if TARGET_OS_MAC
|
||||
#include <libproc.h>
|
||||
#endif
|
||||
#include <mach/processor_info.h>
|
||||
#include <mach/vm_map.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// these CPU times for darwin is borrowed from influxdb/telegraf.
|
||||
|
||||
func perCPUTimes() ([]TimesStat, 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 []TimesStat
|
||||
|
||||
for i := 0; i < int(ncpu); i++ {
|
||||
err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := TimesStat{
|
||||
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() ([]TimesStat, 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 := TimesStat{
|
||||
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 []TimesStat{c}, nil
|
||||
|
||||
}
|
||||
14
vendor/github.com/shirou/gopsutil/cpu/cpu_darwin_nocgo.go
generated
vendored
Normal file
14
vendor/github.com/shirou/gopsutil/cpu/cpu_darwin_nocgo.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// +build darwin
|
||||
// +build !cgo
|
||||
|
||||
package cpu
|
||||
|
||||
import "github.com/shirou/gopsutil/internal/common"
|
||||
|
||||
func perCPUTimes() ([]TimesStat, error) {
|
||||
return []TimesStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func allCPUTimes() ([]TimesStat, error) {
|
||||
return []TimesStat{}, common.ErrNotImplementedError
|
||||
}
|
||||
154
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd.go
generated
vendored
Normal file
154
vendor/github.com/shirou/gopsutil/cpu/cpu_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
// sys/resource.h
|
||||
const (
|
||||
CPUser = 0
|
||||
CPNice = 1
|
||||
CPSys = 2
|
||||
CPIntr = 3
|
||||
CPIdle = 4
|
||||
CPUStates = 5
|
||||
)
|
||||
|
||||
var ClocksPerSec = float64(128)
|
||||
|
||||
func init() {
|
||||
getconf, err := exec.LookPath("/usr/bin/getconf")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
out, err := invoke.Command(getconf, "CLK_TCK")
|
||||
// ignore errors
|
||||
if err == nil {
|
||||
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
|
||||
if err == nil {
|
||||
ClocksPerSec = float64(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
||||
var ret []TimesStat
|
||||
|
||||
var sysctlCall string
|
||||
var ncpu int
|
||||
if percpu {
|
||||
sysctlCall = "kern.cp_times"
|
||||
ncpu, _ = Counts(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 := TimesStat{
|
||||
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 InfoStat on FreeBSD. The information regarding core
|
||||
// count, however is accurate and it is assumed that all InfoStat attributes
|
||||
// are the same across CPUs.
|
||||
func Info() ([]InfoStat, error) {
|
||||
const dmesgBoot = "/var/run/dmesg.boot"
|
||||
lines, _ := common.ReadLines(dmesgBoot)
|
||||
|
||||
c := InfoStat{}
|
||||
var vals []string
|
||||
var err error
|
||||
if vals, err = common.DoSysctrl("hw.clockrate"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c.Mhz, err = strconv.ParseFloat(vals[0], 64); err != nil {
|
||||
return nil, fmt.Errorf("Unable to parse FreeBSD CPU clock rate: %v", err)
|
||||
}
|
||||
c.CPU = int32(c.Mhz)
|
||||
|
||||
if vals, err = common.DoSysctrl("hw.ncpu"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var i64 int64
|
||||
if i64, err = strconv.ParseInt(vals[0], 10, 32); err != nil {
|
||||
return nil, fmt.Errorf("Unable to parse FreeBSD cores: %v", err)
|
||||
}
|
||||
c.Cores = int32(i64)
|
||||
|
||||
if vals, err = common.DoSysctrl("hw.model"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.ModelName = strings.Join(vals, " ")
|
||||
|
||||
for _, line := range lines {
|
||||
if matches := regexp.MustCompile(`Origin\s*=\s*"(.+)"\s+Id\s*=\s*(.+)\s+Family\s*=\s*(.+)\s+Model\s*=\s*(.+)\s+Stepping\s*=\s*(.+)`).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 nil, fmt.Errorf("Unable to parse FreeBSD CPU stepping information from %q: %v", line, err)
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return []InfoStat{c}, nil
|
||||
}
|
||||
244
vendor/github.com/shirou/gopsutil/cpu/cpu_linux.go
generated
vendored
Normal file
244
vendor/github.com/shirou/gopsutil/cpu/cpu_linux.go
generated
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
// +build linux
|
||||
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var cpu_tick = float64(100)
|
||||
|
||||
func init() {
|
||||
getconf, err := exec.LookPath("/usr/bin/getconf")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
out, err := invoke.Command(getconf, "CLK_TCK")
|
||||
// ignore errors
|
||||
if err == nil {
|
||||
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
|
||||
if err == nil {
|
||||
cpu_tick = float64(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
||||
filename := common.HostProc("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++
|
||||
}
|
||||
} else {
|
||||
lines, _ = common.ReadLinesOffsetN(filename, 0, 1)
|
||||
}
|
||||
|
||||
ret := make([]TimesStat, 0, len(lines))
|
||||
|
||||
for _, line := range lines {
|
||||
ct, err := parseStatLine(line)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, *ct)
|
||||
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func sysCPUPath(cpu int32, relPath string) string {
|
||||
return common.HostSys(fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath)
|
||||
}
|
||||
|
||||
func finishCPUInfo(c *InfoStat) error {
|
||||
if c.Mhz == 0 {
|
||||
lines, err := common.ReadLines(sysCPUPath(c.CPU, "cpufreq/cpuinfo_max_freq"))
|
||||
if err == nil {
|
||||
value, err := strconv.ParseFloat(lines[0], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Mhz = value
|
||||
}
|
||||
}
|
||||
if len(c.CoreID) == 0 {
|
||||
lines, err := common.ReadLines(sysCPUPath(c.CPU, "topology/coreId"))
|
||||
if err == nil {
|
||||
c.CoreID = lines[0]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CPUInfo on linux will return 1 item per physical thread.
|
||||
//
|
||||
// CPUs have three levels of counting: sockets, cores, threads.
|
||||
// Cores with HyperThreading count as having 2 threads per core.
|
||||
// Sockets often come with many physical CPU cores.
|
||||
// For example a single socket board with two cores each with HT will
|
||||
// return 4 CPUInfoStat structs on Linux and the "Cores" field set to 1.
|
||||
func Info() ([]InfoStat, error) {
|
||||
filename := common.HostProc("cpuinfo")
|
||||
lines, _ := common.ReadLines(filename)
|
||||
|
||||
var ret []InfoStat
|
||||
|
||||
c := InfoStat{CPU: -1, Cores: 1}
|
||||
for _, line := range lines {
|
||||
fields := strings.Split(line, ":")
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(fields[0])
|
||||
value := strings.TrimSpace(fields[1])
|
||||
|
||||
switch key {
|
||||
case "processor":
|
||||
if c.CPU >= 0 {
|
||||
err := finishCPUInfo(&c)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
ret = append(ret, c)
|
||||
}
|
||||
c = InfoStat{Cores: 1}
|
||||
t, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
c.CPU = int32(t)
|
||||
case "vendorId", "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 "flags", "Features":
|
||||
c.Flags = strings.FieldsFunc(value, func(r rune) bool {
|
||||
return r == ',' || r == ' '
|
||||
})
|
||||
}
|
||||
}
|
||||
if c.CPU >= 0 {
|
||||
err := finishCPUInfo(&c)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
ret = append(ret, c)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func parseStatLine(line string) (*TimesStat, 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
|
||||
}
|
||||
|
||||
ct := &TimesStat{
|
||||
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,
|
||||
}
|
||||
if len(fields) > 8 { // Linux >= 2.6.11
|
||||
steal, err := strconv.ParseFloat(fields[8], 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ct.Steal = float64(steal) / cpu_tick
|
||||
}
|
||||
if len(fields) > 9 { // Linux >= 2.6.24
|
||||
guest, err := strconv.ParseFloat(fields[9], 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ct.Guest = float64(guest) / cpu_tick
|
||||
}
|
||||
if len(fields) > 10 { // Linux >= 3.2.0
|
||||
guestNice, err := strconv.ParseFloat(fields[10], 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ct.GuestNice = float64(guestNice) / cpu_tick
|
||||
}
|
||||
|
||||
return ct, nil
|
||||
}
|
||||
145
vendor/github.com/shirou/gopsutil/cpu/cpu_test.go
generated
vendored
Normal file
145
vendor/github.com/shirou/gopsutil/cpu/cpu_test.go
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCpu_times(t *testing.T) {
|
||||
v, err := Times(false)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Error("could not get CPUs ", err)
|
||||
}
|
||||
empty := TimesStat{}
|
||||
for _, vv := range v {
|
||||
if vv == empty {
|
||||
t.Errorf("could not get CPU User: %v", vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCpu_counts(t *testing.T) {
|
||||
v, err := Counts(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 := TimesStat{
|
||||
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,"guestNice":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 := Info()
|
||||
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 := Percent(time.Millisecond, percpu)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
// Skip CircleCI which CPU num is different
|
||||
if os.Getenv("CIRCLECI") != "true" {
|
||||
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 := Percent(duration, percpu)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
for _, percent := range v {
|
||||
// Check for slightly greater then 100% to account for any rounding issues.
|
||||
if percent < 0.0 || percent > 100.0001*float64(numcpu) {
|
||||
t.Fatalf("CPUPercent value is invalid: %f", percent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testCPUPercentLastUsed(t *testing.T, percpu bool) {
|
||||
|
||||
numcpu := runtime.NumCPU()
|
||||
testCount := 10
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
testCount = 2
|
||||
v, err := Percent(time.Millisecond, percpu)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
// Skip CircleCI which CPU num is different
|
||||
if os.Getenv("CIRCLECI") != "true" {
|
||||
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++ {
|
||||
v, err := Percent(0, percpu)
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
for _, percent := range v {
|
||||
// Check for slightly greater then 100% to account for any rounding issues.
|
||||
if percent < 0.0 || percent > 100.0001*float64(numcpu) {
|
||||
t.Fatalf("CPUPercent value is invalid: %f", percent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCPUPercent(t *testing.T) {
|
||||
testCPUPercent(t, false)
|
||||
}
|
||||
|
||||
func TestCPUPercentPerCpu(t *testing.T) {
|
||||
testCPUPercent(t, true)
|
||||
}
|
||||
|
||||
func TestCPUPercentIntervalZero(t *testing.T) {
|
||||
testCPUPercentLastUsed(t, false)
|
||||
}
|
||||
|
||||
func TestCPUPercentIntervalZeroPerCPU(t *testing.T) {
|
||||
testCPUPercentLastUsed(t, true)
|
||||
}
|
||||
90
vendor/github.com/shirou/gopsutil/cpu/cpu_unix.go
generated
vendored
Normal file
90
vendor/github.com/shirou/gopsutil/cpu/cpu_unix.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
// +build linux freebsd darwin
|
||||
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func getAllBusy(t TimesStat) (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
|
||||
}
|
||||
|
||||
func calculateBusy(t1, t2 TimesStat) 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
|
||||
}
|
||||
|
||||
func calculateAllBusy(t1, t2 []TimesStat) ([]float64, error) {
|
||||
// Make sure the CPU measurements have the same length.
|
||||
if len(t1) != len(t2) {
|
||||
return nil, fmt.Errorf(
|
||||
"received two CPU counts: %d != %d",
|
||||
len(t1), len(t2),
|
||||
)
|
||||
}
|
||||
|
||||
ret := make([]float64, len(t1))
|
||||
for i, t := range t2 {
|
||||
ret[i] = calculateBusy(t1[i], t)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
//Percent calculates the percentage of cpu used either per CPU or combined.
|
||||
//If an interval of 0 is given it will compare the current cpu times against the last call.
|
||||
func Percent(interval time.Duration, percpu bool) ([]float64, error) {
|
||||
if interval <= 0 {
|
||||
return percentUsedFromLastCall(percpu)
|
||||
}
|
||||
|
||||
// Get CPU usage at the start of the interval.
|
||||
cpuTimes1, err := Times(percpu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
time.Sleep(interval)
|
||||
|
||||
// And at the end of the interval.
|
||||
cpuTimes2, err := Times(percpu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return calculateAllBusy(cpuTimes1, cpuTimes2)
|
||||
}
|
||||
|
||||
func percentUsedFromLastCall(percpu bool) ([]float64, error) {
|
||||
cpuTimes, err := Times(percpu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lastCPUPercent.Lock()
|
||||
defer lastCPUPercent.Unlock()
|
||||
var lastTimes []TimesStat
|
||||
if percpu {
|
||||
lastTimes = lastCPUPercent.lastPerCPUTimes
|
||||
lastCPUPercent.lastPerCPUTimes = cpuTimes
|
||||
} else {
|
||||
lastTimes = lastCPUPercent.lastCPUTimes
|
||||
lastCPUPercent.lastCPUTimes = cpuTimes
|
||||
}
|
||||
|
||||
if lastTimes == nil {
|
||||
return nil, fmt.Errorf("Error getting times for cpu percent. LastTimes was nil")
|
||||
}
|
||||
return calculateAllBusy(lastTimes, cpuTimes)
|
||||
|
||||
}
|
||||
105
vendor/github.com/shirou/gopsutil/cpu/cpu_windows.go
generated
vendored
Normal file
105
vendor/github.com/shirou/gopsutil/cpu/cpu_windows.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// +build windows
|
||||
|
||||
package cpu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
type Win32_Processor struct {
|
||||
LoadPercentage *uint16
|
||||
Family uint16
|
||||
Manufacturer string
|
||||
Name string
|
||||
NumberOfLogicalProcessors uint32
|
||||
ProcessorID *string
|
||||
Stepping *string
|
||||
MaxClockSpeed uint32
|
||||
}
|
||||
|
||||
// TODO: Get percpu
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
||||
var ret []TimesStat
|
||||
|
||||
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, TimesStat{
|
||||
Idle: float64(idle),
|
||||
User: float64(user),
|
||||
System: float64(system),
|
||||
})
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func Info() ([]InfoStat, error) {
|
||||
var ret []InfoStat
|
||||
var dst []Win32_Processor
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
err := wmi.Query(q, &dst)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
var procID string
|
||||
for i, l := range dst {
|
||||
procID = ""
|
||||
if l.ProcessorID != nil {
|
||||
procID = *l.ProcessorID
|
||||
}
|
||||
|
||||
cpu := InfoStat{
|
||||
CPU: int32(i),
|
||||
Family: fmt.Sprintf("%d", l.Family),
|
||||
VendorID: l.Manufacturer,
|
||||
ModelName: l.Name,
|
||||
Cores: int32(l.NumberOfLogicalProcessors),
|
||||
PhysicalID: procID,
|
||||
Mhz: float64(l.MaxClockSpeed),
|
||||
Flags: []string{},
|
||||
}
|
||||
ret = append(ret, cpu)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func Percent(interval time.Duration, percpu bool) ([]float64, error) {
|
||||
var ret []float64
|
||||
var dst []Win32_Processor
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
err := wmi.Query(q, &dst)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
for _, l := range dst {
|
||||
// use range but windows can only get one percent.
|
||||
if l.LoadPercentage == nil {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, float64(*l.LoadPercentage))
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
60
vendor/github.com/shirou/gopsutil/disk/disk.go
generated
vendored
Normal file
60
vendor/github.com/shirou/gopsutil/disk/disk.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package disk
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
|
||||
type UsageStat struct {
|
||||
Path string `json:"path"`
|
||||
Fstype string `json:"fstype"`
|
||||
Total uint64 `json:"total"`
|
||||
Free uint64 `json:"free"`
|
||||
Used uint64 `json:"used"`
|
||||
UsedPercent float64 `json:"usedPercent"`
|
||||
InodesTotal uint64 `json:"inodesTotal"`
|
||||
InodesUsed uint64 `json:"inodesUsed"`
|
||||
InodesFree uint64 `json:"inodesFree"`
|
||||
InodesUsedPercent float64 `json:"inodesUsedPercent"`
|
||||
}
|
||||
|
||||
type PartitionStat struct {
|
||||
Device string `json:"device"`
|
||||
Mountpoint string `json:"mountpoint"`
|
||||
Fstype string `json:"fstype"`
|
||||
Opts string `json:"opts"`
|
||||
}
|
||||
|
||||
type IOCountersStat struct {
|
||||
ReadCount uint64 `json:"readCount"`
|
||||
WriteCount uint64 `json:"writeCount"`
|
||||
ReadBytes uint64 `json:"readBytes"`
|
||||
WriteBytes uint64 `json:"writeBytes"`
|
||||
ReadTime uint64 `json:"readTime"`
|
||||
WriteTime uint64 `json:"writeTime"`
|
||||
Name string `json:"name"`
|
||||
IoTime uint64 `json:"ioTime"`
|
||||
SerialNumber string `json:"serialNumber"`
|
||||
}
|
||||
|
||||
func (d UsageStat) String() string {
|
||||
s, _ := json.Marshal(d)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (d PartitionStat) String() string {
|
||||
s, _ := json.Marshal(d)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (d IOCountersStat) String() string {
|
||||
s, _ := json.Marshal(d)
|
||||
return string(s)
|
||||
}
|
||||
111
vendor/github.com/shirou/gopsutil/disk/disk_darwin.go
generated
vendored
Normal file
111
vendor/github.com/shirou/gopsutil/disk/disk_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
// +build darwin
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"path"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
var ret []PartitionStat
|
||||
|
||||
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 := PartitionStat{
|
||||
Device: common.IntToString(stat.Mntfromname[:]),
|
||||
Mountpoint: common.IntToString(stat.Mntonname[:]),
|
||||
Fstype: common.IntToString(stat.Fstypename[:]),
|
||||
Opts: opts,
|
||||
}
|
||||
if all == false {
|
||||
if !path.IsAbs(d.Device) || !common.PathExists(d.Device) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
ret = append(ret, d)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCounters() (map[string]IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func getFsType(stat syscall.Statfs_t) string {
|
||||
return common.IntToString(stat.Fstypename[:])
|
||||
}
|
||||
58
vendor/github.com/shirou/gopsutil/disk/disk_darwin_amd64.go
generated
vendored
Normal file
58
vendor/github.com/shirou/gopsutil/disk/disk_darwin_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// +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
|
||||
}
|
||||
58
vendor/github.com/shirou/gopsutil/disk/disk_darwin_arm64.go
generated
vendored
Normal file
58
vendor/github.com/shirou/gopsutil/disk/disk_darwin_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// +build darwin
|
||||
// +build arm64
|
||||
|
||||
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
|
||||
}
|
||||
176
vendor/github.com/shirou/gopsutil/disk/disk_freebsd.go
generated
vendored
Normal file
176
vendor/github.com/shirou/gopsutil/disk/disk_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
// +build freebsd
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"path"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
var ret []PartitionStat
|
||||
|
||||
// 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 := PartitionStat{
|
||||
Device: common.IntToString(stat.Mntfromname[:]),
|
||||
Mountpoint: common.IntToString(stat.Mntonname[:]),
|
||||
Fstype: common.IntToString(stat.Fstypename[:]),
|
||||
Opts: opts,
|
||||
}
|
||||
if all == false {
|
||||
if !path.IsAbs(d.Device) || !common.PathExists(d.Device) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
ret = append(ret, d)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCounters() (map[string]IOCountersStat, error) {
|
||||
// statinfo->devinfo->devstat
|
||||
// /usr/include/devinfo.h
|
||||
ret := make(map[string]IOCountersStat)
|
||||
|
||||
r, err := syscall.Sysctl("kern.devstat.all")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf := []byte(r)
|
||||
length := len(buf)
|
||||
|
||||
count := int(uint64(length) / uint64(sizeOfDevstat))
|
||||
|
||||
buf = buf[8:] // devstat.all has version in the head.
|
||||
// parse buf to Devstat
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*sizeOfDevstat : i*sizeOfDevstat+sizeOfDevstat]
|
||||
d, err := parseDevstat(b)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
un := strconv.Itoa(int(d.Unit_number))
|
||||
name := common.IntToString(d.Device_name[:]) + un
|
||||
|
||||
ds := IOCountersStat{
|
||||
ReadCount: d.Operations[DEVSTAT_READ],
|
||||
WriteCount: d.Operations[DEVSTAT_WRITE],
|
||||
ReadBytes: d.Bytes[DEVSTAT_READ],
|
||||
WriteBytes: d.Bytes[DEVSTAT_WRITE],
|
||||
ReadTime: uint64(d.Duration[DEVSTAT_READ].Compute() * 1000),
|
||||
WriteTime: uint64(d.Duration[DEVSTAT_WRITE].Compute() * 1000),
|
||||
IoTime: uint64(d.Busy_time.Compute() * 1000),
|
||||
Name: name,
|
||||
}
|
||||
ret[name] = ds
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (b Bintime) Compute() float64 {
|
||||
BINTIME_SCALE := 5.42101086242752217003726400434970855712890625e-20
|
||||
return float64(b.Sec) + float64(b.Frac)*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 := common.Read(br, binary.LittleEndian, &ds)
|
||||
if err != nil {
|
||||
return ds, err
|
||||
}
|
||||
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
func getFsType(stat syscall.Statfs_t) string {
|
||||
return common.IntToString(stat.Fstypename[:])
|
||||
}
|
||||
112
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_386.go
generated
vendored
Normal file
112
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_386.go
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package disk
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x4
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
|
||||
MNT_RDONLY = 0x00000001
|
||||
MNT_SYNCHRONOUS = 0x00000002
|
||||
MNT_NOEXEC = 0x00000004
|
||||
MNT_NOSUID = 0x00000008
|
||||
MNT_UNION = 0x00000020
|
||||
MNT_ASYNC = 0x00000040
|
||||
MNT_SUIDDIR = 0x00100000
|
||||
MNT_SOFTDEP = 0x00200000
|
||||
MNT_NOSYMFOLLOW = 0x00400000
|
||||
MNT_GJOURNAL = 0x02000000
|
||||
MNT_MULTILABEL = 0x04000000
|
||||
MNT_ACLS = 0x08000000
|
||||
MNT_NOATIME = 0x10000000
|
||||
MNT_NOCLUSTERR = 0x40000000
|
||||
MNT_NOCLUSTERW = 0x80000000
|
||||
MNT_NFS4ACLS = 0x00000010
|
||||
|
||||
MNT_WAIT = 1
|
||||
MNT_NOWAIT = 2
|
||||
MNT_LAZY = 3
|
||||
MNT_SUSPEND = 4
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0xf0
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int32
|
||||
_C_long_long int64
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Statfs struct {
|
||||
Version uint32
|
||||
Type uint32
|
||||
Flags uint64
|
||||
Bsize uint64
|
||||
Iosize uint64
|
||||
Blocks uint64
|
||||
Bfree uint64
|
||||
Bavail int64
|
||||
Files uint64
|
||||
Ffree int64
|
||||
Syncwrites uint64
|
||||
Asyncwrites uint64
|
||||
Syncreads uint64
|
||||
Asyncreads uint64
|
||||
Spare [10]uint64
|
||||
Namemax uint32
|
||||
Owner uint32
|
||||
Fsid Fsid
|
||||
Charspare [80]int8
|
||||
Fstypename [16]int8
|
||||
Mntfromname [88]int8
|
||||
Mntonname [88]int8
|
||||
}
|
||||
type Fsid struct {
|
||||
Val [2]int32
|
||||
}
|
||||
|
||||
type Devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
Dev_links _Ctype_struct___0
|
||||
Device_number uint32
|
||||
Device_name [16]int8
|
||||
Unit_number int32
|
||||
Bytes [4]uint64
|
||||
Operations [4]uint64
|
||||
Duration [4]Bintime
|
||||
Busy_time Bintime
|
||||
Creation_time Bintime
|
||||
Block_size uint32
|
||||
Tag_types [3]uint64
|
||||
Flags uint32
|
||||
Device_type uint32
|
||||
Priority uint32
|
||||
Id *byte
|
||||
Sequence1 uint32
|
||||
}
|
||||
type Bintime struct {
|
||||
Sec int32
|
||||
Frac uint64
|
||||
}
|
||||
|
||||
type _Ctype_struct___0 struct {
|
||||
Empty uint32
|
||||
}
|
||||
115
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_amd64.go
generated
vendored
Normal file
115
vendor/github.com/shirou/gopsutil/disk/disk_freebsd_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// 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
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0x120
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
373
vendor/github.com/shirou/gopsutil/disk/disk_linux.go
generated
vendored
Normal file
373
vendor/github.com/shirou/gopsutil/disk/disk_linux.go
generated
vendored
Normal file
@@ -0,0 +1,373 @@
|
||||
// +build linux
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
const (
|
||||
SectorSize = 512
|
||||
)
|
||||
const (
|
||||
// man statfs
|
||||
ADFS_SUPER_MAGIC = 0xadf5
|
||||
AFFS_SUPER_MAGIC = 0xADFF
|
||||
BDEVFS_MAGIC = 0x62646576
|
||||
BEFS_SUPER_MAGIC = 0x42465331
|
||||
BFS_MAGIC = 0x1BADFACE
|
||||
BINFMTFS_MAGIC = 0x42494e4d
|
||||
BTRFS_SUPER_MAGIC = 0x9123683E
|
||||
CGROUP_SUPER_MAGIC = 0x27e0eb
|
||||
CIFS_MAGIC_NUMBER = 0xFF534D42
|
||||
CODA_SUPER_MAGIC = 0x73757245
|
||||
COH_SUPER_MAGIC = 0x012FF7B7
|
||||
CRAMFS_MAGIC = 0x28cd3d45
|
||||
DEBUGFS_MAGIC = 0x64626720
|
||||
DEVFS_SUPER_MAGIC = 0x1373
|
||||
DEVPTS_SUPER_MAGIC = 0x1cd1
|
||||
EFIVARFS_MAGIC = 0xde5e81e4
|
||||
EFS_SUPER_MAGIC = 0x00414A53
|
||||
EXT_SUPER_MAGIC = 0x137D
|
||||
EXT2_OLD_SUPER_MAGIC = 0xEF51
|
||||
EXT2_SUPER_MAGIC = 0xEF53
|
||||
EXT3_SUPER_MAGIC = 0xEF53
|
||||
EXT4_SUPER_MAGIC = 0xEF53
|
||||
FUSE_SUPER_MAGIC = 0x65735546
|
||||
FUTEXFS_SUPER_MAGIC = 0xBAD1DEA
|
||||
HFS_SUPER_MAGIC = 0x4244
|
||||
HOSTFS_SUPER_MAGIC = 0x00c0ffee
|
||||
HPFS_SUPER_MAGIC = 0xF995E849
|
||||
HUGETLBFS_MAGIC = 0x958458f6
|
||||
ISOFS_SUPER_MAGIC = 0x9660
|
||||
JFFS2_SUPER_MAGIC = 0x72b6
|
||||
JFS_SUPER_MAGIC = 0x3153464a
|
||||
MINIX_SUPER_MAGIC = 0x137F /* orig. minix */
|
||||
MINIX_SUPER_MAGIC2 = 0x138F /* 30 char minix */
|
||||
MINIX2_SUPER_MAGIC = 0x2468 /* minix V2 */
|
||||
MINIX2_SUPER_MAGIC2 = 0x2478 /* minix V2, 30 char names */
|
||||
MINIX3_SUPER_MAGIC = 0x4d5a /* minix V3 fs, 60 char names */
|
||||
MQUEUE_MAGIC = 0x19800202
|
||||
MSDOS_SUPER_MAGIC = 0x4d44
|
||||
NCP_SUPER_MAGIC = 0x564c
|
||||
NFS_SUPER_MAGIC = 0x6969
|
||||
NILFS_SUPER_MAGIC = 0x3434
|
||||
NTFS_SB_MAGIC = 0x5346544e
|
||||
OCFS2_SUPER_MAGIC = 0x7461636f
|
||||
OPENPROM_SUPER_MAGIC = 0x9fa1
|
||||
PIPEFS_MAGIC = 0x50495045
|
||||
PROC_SUPER_MAGIC = 0x9fa0
|
||||
PSTOREFS_MAGIC = 0x6165676C
|
||||
QNX4_SUPER_MAGIC = 0x002f
|
||||
QNX6_SUPER_MAGIC = 0x68191122
|
||||
RAMFS_MAGIC = 0x858458f6
|
||||
REISERFS_SUPER_MAGIC = 0x52654973
|
||||
ROMFS_MAGIC = 0x7275
|
||||
SELINUX_MAGIC = 0xf97cff8c
|
||||
SMACK_MAGIC = 0x43415d53
|
||||
SMB_SUPER_MAGIC = 0x517B
|
||||
SOCKFS_MAGIC = 0x534F434B
|
||||
SQUASHFS_MAGIC = 0x73717368
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
SYSV2_SUPER_MAGIC = 0x012FF7B6
|
||||
SYSV4_SUPER_MAGIC = 0x012FF7B5
|
||||
TMPFS_MAGIC = 0x01021994
|
||||
UDF_SUPER_MAGIC = 0x15013346
|
||||
UFS_MAGIC = 0x00011954
|
||||
USBDEVICE_SUPER_MAGIC = 0x9fa2
|
||||
V9FS_MAGIC = 0x01021997
|
||||
VXFS_SUPER_MAGIC = 0xa501FCF5
|
||||
XENFS_SUPER_MAGIC = 0xabba1974
|
||||
XENIX_SUPER_MAGIC = 0x012FF7B4
|
||||
XFS_SUPER_MAGIC = 0x58465342
|
||||
_XIAFS_SUPER_MAGIC = 0x012FD16D
|
||||
|
||||
AFS_SUPER_MAGIC = 0x5346414F
|
||||
AUFS_SUPER_MAGIC = 0x61756673
|
||||
ANON_INODE_FS_SUPER_MAGIC = 0x09041934
|
||||
CEPH_SUPER_MAGIC = 0x00C36400
|
||||
ECRYPTFS_SUPER_MAGIC = 0xF15F
|
||||
FAT_SUPER_MAGIC = 0x4006
|
||||
FHGFS_SUPER_MAGIC = 0x19830326
|
||||
FUSEBLK_SUPER_MAGIC = 0x65735546
|
||||
FUSECTL_SUPER_MAGIC = 0x65735543
|
||||
GFS_SUPER_MAGIC = 0x1161970
|
||||
GPFS_SUPER_MAGIC = 0x47504653
|
||||
MTD_INODE_FS_SUPER_MAGIC = 0x11307854
|
||||
INOTIFYFS_SUPER_MAGIC = 0x2BAD1DEA
|
||||
ISOFS_R_WIN_SUPER_MAGIC = 0x4004
|
||||
ISOFS_WIN_SUPER_MAGIC = 0x4000
|
||||
JFFS_SUPER_MAGIC = 0x07C0
|
||||
KAFS_SUPER_MAGIC = 0x6B414653
|
||||
LUSTRE_SUPER_MAGIC = 0x0BD00BD0
|
||||
NFSD_SUPER_MAGIC = 0x6E667364
|
||||
PANFS_SUPER_MAGIC = 0xAAD7AAEA
|
||||
RPC_PIPEFS_SUPER_MAGIC = 0x67596969
|
||||
SECURITYFS_SUPER_MAGIC = 0x73636673
|
||||
UFS_BYTESWAPPED_SUPER_MAGIC = 0x54190100
|
||||
VMHGFS_SUPER_MAGIC = 0xBACBACBC
|
||||
VZFS_SUPER_MAGIC = 0x565A4653
|
||||
ZFS_SUPER_MAGIC = 0x2FC12FC1
|
||||
)
|
||||
|
||||
// coreutils/src/stat.c
|
||||
var fsTypeMap = map[int64]string{
|
||||
ADFS_SUPER_MAGIC: "adfs", /* 0xADF5 local */
|
||||
AFFS_SUPER_MAGIC: "affs", /* 0xADFF local */
|
||||
AFS_SUPER_MAGIC: "afs", /* 0x5346414F remote */
|
||||
ANON_INODE_FS_SUPER_MAGIC: "anon-inode FS", /* 0x09041934 local */
|
||||
AUFS_SUPER_MAGIC: "aufs", /* 0x61756673 remote */
|
||||
// AUTOFS_SUPER_MAGIC: "autofs", /* 0x0187 local */
|
||||
BEFS_SUPER_MAGIC: "befs", /* 0x42465331 local */
|
||||
BDEVFS_MAGIC: "bdevfs", /* 0x62646576 local */
|
||||
BFS_MAGIC: "bfs", /* 0x1BADFACE local */
|
||||
BINFMTFS_MAGIC: "binfmt_misc", /* 0x42494E4D local */
|
||||
BTRFS_SUPER_MAGIC: "btrfs", /* 0x9123683E local */
|
||||
CEPH_SUPER_MAGIC: "ceph", /* 0x00C36400 remote */
|
||||
CGROUP_SUPER_MAGIC: "cgroupfs", /* 0x0027E0EB local */
|
||||
CIFS_MAGIC_NUMBER: "cifs", /* 0xFF534D42 remote */
|
||||
CODA_SUPER_MAGIC: "coda", /* 0x73757245 remote */
|
||||
COH_SUPER_MAGIC: "coh", /* 0x012FF7B7 local */
|
||||
CRAMFS_MAGIC: "cramfs", /* 0x28CD3D45 local */
|
||||
DEBUGFS_MAGIC: "debugfs", /* 0x64626720 local */
|
||||
DEVFS_SUPER_MAGIC: "devfs", /* 0x1373 local */
|
||||
DEVPTS_SUPER_MAGIC: "devpts", /* 0x1CD1 local */
|
||||
ECRYPTFS_SUPER_MAGIC: "ecryptfs", /* 0xF15F local */
|
||||
EFS_SUPER_MAGIC: "efs", /* 0x00414A53 local */
|
||||
EXT_SUPER_MAGIC: "ext", /* 0x137D local */
|
||||
EXT2_SUPER_MAGIC: "ext2/ext3", /* 0xEF53 local */
|
||||
EXT2_OLD_SUPER_MAGIC: "ext2", /* 0xEF51 local */
|
||||
FAT_SUPER_MAGIC: "fat", /* 0x4006 local */
|
||||
FHGFS_SUPER_MAGIC: "fhgfs", /* 0x19830326 remote */
|
||||
FUSEBLK_SUPER_MAGIC: "fuseblk", /* 0x65735546 remote */
|
||||
FUSECTL_SUPER_MAGIC: "fusectl", /* 0x65735543 remote */
|
||||
FUTEXFS_SUPER_MAGIC: "futexfs", /* 0x0BAD1DEA local */
|
||||
GFS_SUPER_MAGIC: "gfs/gfs2", /* 0x1161970 remote */
|
||||
GPFS_SUPER_MAGIC: "gpfs", /* 0x47504653 remote */
|
||||
HFS_SUPER_MAGIC: "hfs", /* 0x4244 local */
|
||||
HPFS_SUPER_MAGIC: "hpfs", /* 0xF995E849 local */
|
||||
HUGETLBFS_MAGIC: "hugetlbfs", /* 0x958458F6 local */
|
||||
MTD_INODE_FS_SUPER_MAGIC: "inodefs", /* 0x11307854 local */
|
||||
INOTIFYFS_SUPER_MAGIC: "inotifyfs", /* 0x2BAD1DEA local */
|
||||
ISOFS_SUPER_MAGIC: "isofs", /* 0x9660 local */
|
||||
ISOFS_R_WIN_SUPER_MAGIC: "isofs", /* 0x4004 local */
|
||||
ISOFS_WIN_SUPER_MAGIC: "isofs", /* 0x4000 local */
|
||||
JFFS_SUPER_MAGIC: "jffs", /* 0x07C0 local */
|
||||
JFFS2_SUPER_MAGIC: "jffs2", /* 0x72B6 local */
|
||||
JFS_SUPER_MAGIC: "jfs", /* 0x3153464A local */
|
||||
KAFS_SUPER_MAGIC: "k-afs", /* 0x6B414653 remote */
|
||||
LUSTRE_SUPER_MAGIC: "lustre", /* 0x0BD00BD0 remote */
|
||||
MINIX_SUPER_MAGIC: "minix", /* 0x137F local */
|
||||
MINIX_SUPER_MAGIC2: "minix (30 char.)", /* 0x138F local */
|
||||
MINIX2_SUPER_MAGIC: "minix v2", /* 0x2468 local */
|
||||
MINIX2_SUPER_MAGIC2: "minix v2 (30 char.)", /* 0x2478 local */
|
||||
MINIX3_SUPER_MAGIC: "minix3", /* 0x4D5A local */
|
||||
MQUEUE_MAGIC: "mqueue", /* 0x19800202 local */
|
||||
MSDOS_SUPER_MAGIC: "msdos", /* 0x4D44 local */
|
||||
NCP_SUPER_MAGIC: "novell", /* 0x564C remote */
|
||||
NFS_SUPER_MAGIC: "nfs", /* 0x6969 remote */
|
||||
NFSD_SUPER_MAGIC: "nfsd", /* 0x6E667364 remote */
|
||||
NILFS_SUPER_MAGIC: "nilfs", /* 0x3434 local */
|
||||
NTFS_SB_MAGIC: "ntfs", /* 0x5346544E local */
|
||||
OPENPROM_SUPER_MAGIC: "openprom", /* 0x9FA1 local */
|
||||
OCFS2_SUPER_MAGIC: "ocfs2", /* 0x7461636f remote */
|
||||
PANFS_SUPER_MAGIC: "panfs", /* 0xAAD7AAEA remote */
|
||||
PIPEFS_MAGIC: "pipefs", /* 0x50495045 remote */
|
||||
PROC_SUPER_MAGIC: "proc", /* 0x9FA0 local */
|
||||
PSTOREFS_MAGIC: "pstorefs", /* 0x6165676C local */
|
||||
QNX4_SUPER_MAGIC: "qnx4", /* 0x002F local */
|
||||
QNX6_SUPER_MAGIC: "qnx6", /* 0x68191122 local */
|
||||
RAMFS_MAGIC: "ramfs", /* 0x858458F6 local */
|
||||
REISERFS_SUPER_MAGIC: "reiserfs", /* 0x52654973 local */
|
||||
ROMFS_MAGIC: "romfs", /* 0x7275 local */
|
||||
RPC_PIPEFS_SUPER_MAGIC: "rpc_pipefs", /* 0x67596969 local */
|
||||
SECURITYFS_SUPER_MAGIC: "securityfs", /* 0x73636673 local */
|
||||
SELINUX_MAGIC: "selinux", /* 0xF97CFF8C local */
|
||||
SMB_SUPER_MAGIC: "smb", /* 0x517B remote */
|
||||
SOCKFS_MAGIC: "sockfs", /* 0x534F434B local */
|
||||
SQUASHFS_MAGIC: "squashfs", /* 0x73717368 local */
|
||||
SYSFS_MAGIC: "sysfs", /* 0x62656572 local */
|
||||
SYSV2_SUPER_MAGIC: "sysv2", /* 0x012FF7B6 local */
|
||||
SYSV4_SUPER_MAGIC: "sysv4", /* 0x012FF7B5 local */
|
||||
TMPFS_MAGIC: "tmpfs", /* 0x01021994 local */
|
||||
UDF_SUPER_MAGIC: "udf", /* 0x15013346 local */
|
||||
UFS_MAGIC: "ufs", /* 0x00011954 local */
|
||||
UFS_BYTESWAPPED_SUPER_MAGIC: "ufs", /* 0x54190100 local */
|
||||
USBDEVICE_SUPER_MAGIC: "usbdevfs", /* 0x9FA2 local */
|
||||
V9FS_MAGIC: "v9fs", /* 0x01021997 local */
|
||||
VMHGFS_SUPER_MAGIC: "vmhgfs", /* 0xBACBACBC remote */
|
||||
VXFS_SUPER_MAGIC: "vxfs", /* 0xA501FCF5 local */
|
||||
VZFS_SUPER_MAGIC: "vzfs", /* 0x565A4653 local */
|
||||
XENFS_SUPER_MAGIC: "xenfs", /* 0xABBA1974 local */
|
||||
XENIX_SUPER_MAGIC: "xenix", /* 0x012FF7B4 local */
|
||||
XFS_SUPER_MAGIC: "xfs", /* 0x58465342 local */
|
||||
_XIAFS_SUPER_MAGIC: "xia", /* 0x012FD16D local */
|
||||
ZFS_SUPER_MAGIC: "zfs", /* 0x2FC12FC1 local */
|
||||
}
|
||||
|
||||
// Partitions returns disk partitions. If all is false, returns
|
||||
// physical devices only (e.g. hard disks, cd-rom drives, USB keys)
|
||||
// and ignore all others (e.g. memory partitions such as /dev/shm)
|
||||
//
|
||||
// should use setmntent(3) but this implement use /etc/mtab file
|
||||
func Partitions(all bool) ([]PartitionStat, error) {
|
||||
filename := common.HostEtc("mtab")
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fs, err := getFileSystems()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := make([]PartitionStat, 0, len(lines))
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
d := PartitionStat{
|
||||
Device: fields[0],
|
||||
Mountpoint: fields[1],
|
||||
Fstype: fields[2],
|
||||
Opts: fields[3],
|
||||
}
|
||||
if all == false {
|
||||
if d.Device == "none" || !common.StringsHas(fs, d.Fstype) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
ret = append(ret, d)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// getFileSystems returns supported filesystems from /proc/filesystems
|
||||
func getFileSystems() ([]string, error) {
|
||||
filename := common.HostProc("filesystems")
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ret []string
|
||||
for _, line := range lines {
|
||||
if !strings.HasPrefix(line, "nodev") {
|
||||
ret = append(ret, strings.TrimSpace(line))
|
||||
continue
|
||||
}
|
||||
t := strings.Split(line, "\t")
|
||||
if len(t) != 2 || t[1] != "zfs" {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, strings.TrimSpace(t[1]))
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCounters() (map[string]IOCountersStat, error) {
|
||||
filename := common.HostProc("diskstats")
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make(map[string]IOCountersStat, 0)
|
||||
empty := IOCountersStat{}
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 14 {
|
||||
// malformed line in /proc/diskstats, avoid panic by ignoring.
|
||||
continue
|
||||
}
|
||||
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 := IOCountersStat{
|
||||
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
|
||||
}
|
||||
|
||||
// GetDiskSerialNumber returns Serial Number of given device or empty string
|
||||
// on error. Name of device is expected, eg. /dev/sda
|
||||
func GetDiskSerialNumber(name string) string {
|
||||
n := fmt.Sprintf("--name=%s", name)
|
||||
udevadm, err := exec.LookPath("/sbin/udevadm")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
out, err := invoke.Command(udevadm, "info", "--query=property", n)
|
||||
|
||||
// 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 ""
|
||||
}
|
||||
|
||||
func getFsType(stat syscall.Statfs_t) string {
|
||||
t := int64(stat.Type)
|
||||
ret, ok := fsTypeMap[t]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return ret
|
||||
}
|
||||
100
vendor/github.com/shirou/gopsutil/disk/disk_test.go
generated
vendored
Normal file
100
vendor/github.com/shirou/gopsutil/disk/disk_test.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package disk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDisk_usage(t *testing.T) {
|
||||
path := "/"
|
||||
if runtime.GOOS == "windows" {
|
||||
path = "C:"
|
||||
}
|
||||
v, err := Usage(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 := Partitions(false)
|
||||
if err != nil || len(ret) == 0 {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
empty := PartitionStat{}
|
||||
if len(ret) == 0 {
|
||||
t.Errorf("ret is empty")
|
||||
}
|
||||
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 := IOCounters()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if len(ret) == 0 {
|
||||
t.Errorf("ret is empty")
|
||||
}
|
||||
empty := IOCountersStat{}
|
||||
for part, io := range ret {
|
||||
if io == empty {
|
||||
t.Errorf("io_counter error %v, %v", part, io)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiskUsageStat_String(t *testing.T) {
|
||||
v := UsageStat{
|
||||
Path: "/",
|
||||
Total: 1000,
|
||||
Free: 2000,
|
||||
Used: 3000,
|
||||
UsedPercent: 50.1,
|
||||
InodesTotal: 4000,
|
||||
InodesUsed: 5000,
|
||||
InodesFree: 6000,
|
||||
InodesUsedPercent: 49.1,
|
||||
Fstype: "ext4",
|
||||
}
|
||||
e := `{"path":"/","fstype":"ext4","total":1000,"free":2000,"used":3000,"usedPercent":50.1,"inodesTotal":4000,"inodesUsed":5000,"inodesFree":6000,"inodesUsedPercent":49.1}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("DiskUsageStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiskPartitionStat_String(t *testing.T) {
|
||||
v := PartitionStat{
|
||||
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 := IOCountersStat{
|
||||
Name: "sd01",
|
||||
ReadCount: 100,
|
||||
WriteCount: 200,
|
||||
ReadBytes: 300,
|
||||
WriteBytes: 400,
|
||||
SerialNumber: "SERIAL",
|
||||
}
|
||||
e := `{"readCount":100,"writeCount":200,"readBytes":300,"writeBytes":400,"readTime":0,"writeTime":0,"name":"sd01","ioTime":0,"serialNumber":"SERIAL"}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("DiskUsageStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
30
vendor/github.com/shirou/gopsutil/disk/disk_unix.go
generated
vendored
Normal file
30
vendor/github.com/shirou/gopsutil/disk/disk_unix.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// +build freebsd linux darwin
|
||||
|
||||
package disk
|
||||
|
||||
import "syscall"
|
||||
|
||||
func Usage(path string) (*UsageStat, error) {
|
||||
stat := syscall.Statfs_t{}
|
||||
err := syscall.Statfs(path, &stat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bsize := stat.Bsize
|
||||
|
||||
ret := &UsageStat{
|
||||
Path: path,
|
||||
Fstype: getFsType(stat),
|
||||
Total: (uint64(stat.Blocks) * uint64(bsize)),
|
||||
Free: (uint64(stat.Bavail) * 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 = (uint64(stat.Blocks) - uint64(stat.Bfree)) * uint64(bsize)
|
||||
ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
155
vendor/github.com/shirou/gopsutil/disk/disk_windows.go
generated
vendored
Normal file
155
vendor/github.com/shirou/gopsutil/disk/disk_windows.go
generated
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
// +build windows
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/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
|
||||
)
|
||||
|
||||
type Win32_PerfFormattedData struct {
|
||||
Name string
|
||||
AvgDiskBytesPerRead uint64
|
||||
AvgDiskBytesPerWrite uint64
|
||||
AvgDiskReadQueueLength uint64
|
||||
AvgDiskWriteQueueLength uint64
|
||||
AvgDisksecPerRead uint64
|
||||
AvgDisksecPerWrite uint64
|
||||
}
|
||||
|
||||
const WaitMSec = 500
|
||||
|
||||
func Usage(path string) (*UsageStat, error) {
|
||||
ret := &UsageStat{}
|
||||
|
||||
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 = &UsageStat{
|
||||
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 Partitions(all bool) ([]PartitionStat, error) {
|
||||
var ret []PartitionStat
|
||||
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 {
|
||||
if typeret == 5 {
|
||||
continue //device is not ready will happen if there is no disk in the drive
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
opts := "rw"
|
||||
if lpFileSystemFlags&FileReadOnlyVolume != 0 {
|
||||
opts = "ro"
|
||||
}
|
||||
if lpFileSystemFlags&FileFileCompression != 0 {
|
||||
opts += ".compress"
|
||||
}
|
||||
|
||||
d := PartitionStat{
|
||||
Mountpoint: path,
|
||||
Device: path,
|
||||
Fstype: string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)),
|
||||
Opts: opts,
|
||||
}
|
||||
ret = append(ret, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func IOCounters() (map[string]IOCountersStat, error) {
|
||||
ret := make(map[string]IOCountersStat, 0)
|
||||
var dst []Win32_PerfFormattedData
|
||||
|
||||
err := wmi.Query("SELECT * FROM Win32_PerfFormattedData_PerfDisk_LogicalDisk ", &dst)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
for _, d := range dst {
|
||||
if len(d.Name) > 3 { // not get _Total or Harddrive
|
||||
continue
|
||||
}
|
||||
ret[d.Name] = IOCountersStat{
|
||||
Name: d.Name,
|
||||
ReadCount: uint64(d.AvgDiskReadQueueLength),
|
||||
WriteCount: d.AvgDiskWriteQueueLength,
|
||||
ReadBytes: uint64(d.AvgDiskBytesPerRead),
|
||||
WriteBytes: uint64(d.AvgDiskBytesPerWrite),
|
||||
ReadTime: d.AvgDisksecPerRead,
|
||||
WriteTime: d.AvgDisksecPerWrite,
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
88
vendor/github.com/shirou/gopsutil/disk/types_freebsd.go
generated
vendored
Normal file
88
vendor/github.com/shirou/gopsutil/disk/types_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// +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 */
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = C.sizeof_struct_devstat
|
||||
)
|
||||
|
||||
// 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
vendor/github.com/shirou/gopsutil/doc.go
generated
vendored
Normal file
1
vendor/github.com/shirou/gopsutil/doc.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package gopsutil
|
||||
59
vendor/github.com/shirou/gopsutil/docker/docker.go
generated
vendored
Normal file
59
vendor/github.com/shirou/gopsutil/docker/docker.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var ErrDockerNotAvailable = errors.New("docker not available")
|
||||
var ErrCgroupNotAvailable = errors.New("cgroup not available")
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
|
||||
type CgroupMemStat struct {
|
||||
ContainerID string `json:"containerID"`
|
||||
Cache uint64 `json:"cache"`
|
||||
RSS uint64 `json:"rss"`
|
||||
RSSHuge uint64 `json:"rssHuge"`
|
||||
MappedFile uint64 `json:"mappedFile"`
|
||||
Pgpgin uint64 `json:"pgpgin"`
|
||||
Pgpgout uint64 `json:"pgpgout"`
|
||||
Pgfault uint64 `json:"pgfault"`
|
||||
Pgmajfault uint64 `json:"pgmajfault"`
|
||||
InactiveAnon uint64 `json:"inactiveAnon"`
|
||||
ActiveAnon uint64 `json:"activeAnon"`
|
||||
InactiveFile uint64 `json:"inactiveFile"`
|
||||
ActiveFile uint64 `json:"activeFile"`
|
||||
Unevictable uint64 `json:"unevictable"`
|
||||
HierarchicalMemoryLimit uint64 `json:"hierarchicalMemoryLimit"`
|
||||
TotalCache uint64 `json:"totalCache"`
|
||||
TotalRSS uint64 `json:"totalRss"`
|
||||
TotalRSSHuge uint64 `json:"totalRssHuge"`
|
||||
TotalMappedFile uint64 `json:"totalMappedFile"`
|
||||
TotalPgpgIn uint64 `json:"totalPgpgin"`
|
||||
TotalPgpgOut uint64 `json:"totalPgpgout"`
|
||||
TotalPgFault uint64 `json:"totalPgfault"`
|
||||
TotalPgMajFault uint64 `json:"totalPgmajfault"`
|
||||
TotalInactiveAnon uint64 `json:"totalInactiveAnon"`
|
||||
TotalActiveAnon uint64 `json:"totalActiveAnon"`
|
||||
TotalInactiveFile uint64 `json:"totalInactiveFile"`
|
||||
TotalActiveFile uint64 `json:"totalActiveFile"`
|
||||
TotalUnevictable uint64 `json:"totalUnevictable"`
|
||||
MemUsageInBytes uint64 `json:"memUsageInBytes"`
|
||||
MemMaxUsageInBytes uint64 `json:"memMaxUsageInBytes"`
|
||||
MemLimitInBytes uint64 `json:"memoryLimitInBbytes"`
|
||||
MemFailCnt uint64 `json:"memoryFailcnt"`
|
||||
}
|
||||
|
||||
type CgroupDockerStat struct {
|
||||
ContainerID string `json:"containerID"`
|
||||
Name string `json:"name"`
|
||||
Image string `json:"image"`
|
||||
Status string `json:"status"`
|
||||
Running bool `json:"running"`
|
||||
}
|
||||
254
vendor/github.com/shirou/gopsutil/docker/docker_linux.go
generated
vendored
Normal file
254
vendor/github.com/shirou/gopsutil/docker/docker_linux.go
generated
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
// +build linux
|
||||
|
||||
package docker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
cpu "github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
// GetDockerStat returns a list of Docker basic stats.
|
||||
// This requires certain permission.
|
||||
func GetDockerStat() ([]CgroupDockerStat, error) {
|
||||
path, err := exec.LookPath("docker")
|
||||
if err != nil {
|
||||
return nil, ErrDockerNotAvailable
|
||||
}
|
||||
|
||||
out, err := invoke.Command(path, "ps", "-a", "--no-trunc", "--format", "{{.ID}}|{{.Image}}|{{.Names}}|{{.Status}}")
|
||||
if err != nil {
|
||||
return []CgroupDockerStat{}, err
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
ret := make([]CgroupDockerStat, 0, len(lines))
|
||||
|
||||
for _, l := range lines {
|
||||
if l == "" {
|
||||
continue
|
||||
}
|
||||
cols := strings.Split(l, "|")
|
||||
if len(cols) != 4 {
|
||||
continue
|
||||
}
|
||||
names := strings.Split(cols[2], ",")
|
||||
stat := CgroupDockerStat{
|
||||
ContainerID: cols[0],
|
||||
Name: names[0],
|
||||
Image: cols[1],
|
||||
Status: cols[3],
|
||||
Running: strings.Contains(cols[3], "Up"),
|
||||
}
|
||||
ret = append(ret, stat)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (c CgroupDockerStat) String() string {
|
||||
s, _ := json.Marshal(c)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// GetDockerIDList returnes a list of DockerID.
|
||||
// This requires certain permission.
|
||||
func GetDockerIDList() ([]string, error) {
|
||||
path, err := exec.LookPath("docker")
|
||||
if err != nil {
|
||||
return nil, ErrDockerNotAvailable
|
||||
}
|
||||
|
||||
out, err := invoke.Command(path, "ps", "-q", "--no-trunc")
|
||||
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.TimesStat, error) {
|
||||
statfile := getCgroupFilePath(containerID, base, "cpuacct", "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.TimesStat{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.TimesStat, error) {
|
||||
return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
|
||||
}
|
||||
|
||||
func CgroupMem(containerID string, base string) (*CgroupMemStat, error) {
|
||||
statfile := getCgroupFilePath(containerID, base, "memory", "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 "rssHuge":
|
||||
ret.RSSHuge = v
|
||||
case "mappedFile":
|
||||
ret.MappedFile = v
|
||||
case "pgpgin":
|
||||
ret.Pgpgin = v
|
||||
case "pgpgout":
|
||||
ret.Pgpgout = v
|
||||
case "pgfault":
|
||||
ret.Pgfault = v
|
||||
case "pgmajfault":
|
||||
ret.Pgmajfault = v
|
||||
case "inactiveAnon":
|
||||
ret.InactiveAnon = v
|
||||
case "activeAnon":
|
||||
ret.ActiveAnon = v
|
||||
case "inactiveFile":
|
||||
ret.InactiveFile = v
|
||||
case "activeFile":
|
||||
ret.ActiveFile = v
|
||||
case "unevictable":
|
||||
ret.Unevictable = v
|
||||
case "hierarchicalMemoryLimit":
|
||||
ret.HierarchicalMemoryLimit = v
|
||||
case "totalCache":
|
||||
ret.TotalCache = v
|
||||
case "totalRss":
|
||||
ret.TotalRSS = v
|
||||
case "totalRssHuge":
|
||||
ret.TotalRSSHuge = v
|
||||
case "totalMappedFile":
|
||||
ret.TotalMappedFile = v
|
||||
case "totalPgpgin":
|
||||
ret.TotalPgpgIn = v
|
||||
case "totalPgpgout":
|
||||
ret.TotalPgpgOut = v
|
||||
case "totalPgfault":
|
||||
ret.TotalPgFault = v
|
||||
case "totalPgmajfault":
|
||||
ret.TotalPgMajFault = v
|
||||
case "totalInactiveAnon":
|
||||
ret.TotalInactiveAnon = v
|
||||
case "totalActiveAnon":
|
||||
ret.TotalActiveAnon = v
|
||||
case "totalInactiveFile":
|
||||
ret.TotalInactiveFile = v
|
||||
case "totalActiveFile":
|
||||
ret.TotalActiveFile = v
|
||||
case "totalUnevictable":
|
||||
ret.TotalUnevictable = v
|
||||
}
|
||||
}
|
||||
|
||||
r, err := getCgroupMemFile(containerID, base, "memory.usage_in_bytes")
|
||||
if err == nil {
|
||||
ret.MemUsageInBytes = r
|
||||
}
|
||||
r, err = getCgroupMemFile(containerID, base, "memory.max_usage_in_bytes")
|
||||
if err == nil {
|
||||
ret.MemMaxUsageInBytes = r
|
||||
}
|
||||
r, err = getCgroupMemFile(containerID, base, "memoryLimitInBbytes")
|
||||
if err == nil {
|
||||
ret.MemLimitInBytes = r
|
||||
}
|
||||
r, err = getCgroupMemFile(containerID, base, "memoryFailcnt")
|
||||
if err == nil {
|
||||
ret.MemFailCnt = r
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func CgroupMemDocker(containerID string) (*CgroupMemStat, error) {
|
||||
return CgroupMem(containerID, common.HostSys("fs/cgroup/memory/docker"))
|
||||
}
|
||||
|
||||
func (m CgroupMemStat) String() string {
|
||||
s, _ := json.Marshal(m)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// getCgroupFilePath constructs file path to get targetted stats file.
|
||||
func getCgroupFilePath(containerID, base, target, file string) string {
|
||||
if len(base) == 0 {
|
||||
base = common.HostSys(fmt.Sprintf("fs/cgroup/%s/docker", target))
|
||||
}
|
||||
statfile := path.Join(base, containerID, file)
|
||||
|
||||
if _, err := os.Stat(statfile); os.IsNotExist(err) {
|
||||
statfile = path.Join(
|
||||
common.HostSys(fmt.Sprintf("fs/cgroup/%s/system.slice", target)), "docker-"+containerID+".scope", file)
|
||||
}
|
||||
|
||||
return statfile
|
||||
}
|
||||
|
||||
// getCgroupMemFile reads a cgroup file and return the contents as uint64.
|
||||
func getCgroupMemFile(containerID, base, file string) (uint64, error) {
|
||||
statfile := getCgroupFilePath(containerID, base, "memory", file)
|
||||
lines, err := common.ReadLines(statfile)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(lines) != 1 {
|
||||
return 0, fmt.Errorf("wrong format file: %s", statfile)
|
||||
}
|
||||
return strconv.ParseUint(lines[0], 10, 64)
|
||||
}
|
||||
82
vendor/github.com/shirou/gopsutil/docker/docker_linux_test.go
generated
vendored
Normal file
82
vendor/github.com/shirou/gopsutil/docker/docker_linux_test.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// +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 TestGetDockerStat(t *testing.T) {
|
||||
// If there is not docker environment, this test always fail.
|
||||
// not tested here
|
||||
|
||||
/*
|
||||
ret, err := GetDockerStat()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if len(ret) == 0 {
|
||||
t.Errorf("ret is empty")
|
||||
}
|
||||
empty := CgroupDockerStat{}
|
||||
for _, v := range ret {
|
||||
if empty == v {
|
||||
t.Errorf("empty CgroupDockerStat")
|
||||
}
|
||||
if v.ContainerID == "" {
|
||||
t.Errorf("Could not get container id")
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
47
vendor/github.com/shirou/gopsutil/docker/docker_notlinux.go
generated
vendored
Normal file
47
vendor/github.com/shirou/gopsutil/docker/docker_notlinux.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// +build !linux
|
||||
|
||||
package docker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
// GetDockerStat returns a list of Docker basic stats.
|
||||
// This requires certain permission.
|
||||
func GetDockerStat() ([]CgroupDockerStat, error) {
|
||||
return nil, ErrDockerNotAvailable
|
||||
}
|
||||
|
||||
// GetDockerIDList returnes a list of DockerID.
|
||||
// This requires certain permission.
|
||||
func GetDockerIDList() ([]string, error) {
|
||||
return nil, ErrDockerNotAvailable
|
||||
}
|
||||
|
||||
// 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.TimesStat, error) {
|
||||
return nil, ErrCgroupNotAvailable
|
||||
}
|
||||
|
||||
func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) {
|
||||
return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
|
||||
}
|
||||
|
||||
func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
|
||||
return nil, ErrCgroupNotAvailable
|
||||
}
|
||||
|
||||
func CgroupMemDocker(containerid string) (*CgroupMemStat, error) {
|
||||
return CgroupMem(containerid, common.HostSys("fs/cgroup/memory/docker"))
|
||||
}
|
||||
|
||||
func (m CgroupMemStat) String() string {
|
||||
s, _ := json.Marshal(m)
|
||||
return string(s)
|
||||
}
|
||||
46
vendor/github.com/shirou/gopsutil/host/host.go
generated
vendored
Normal file
46
vendor/github.com/shirou/gopsutil/host/host.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
|
||||
// A HostInfoStat describes the host status.
|
||||
// This is not in the psutil but it useful.
|
||||
type InfoStat struct {
|
||||
Hostname string `json:"hostname"`
|
||||
Uptime uint64 `json:"uptime"`
|
||||
BootTime uint64 `json:"bootTime"`
|
||||
Procs uint64 `json:"procs"` // number of processes
|
||||
OS string `json:"os"` // ex: freebsd, linux
|
||||
Platform string `json:"platform"` // ex: ubuntu, linuxmint
|
||||
PlatformFamily string `json:"platformFamily"` // ex: debian, rhel
|
||||
PlatformVersion string `json:"platformVersion"`
|
||||
VirtualizationSystem string `json:"virtualizationSystem"`
|
||||
VirtualizationRole string `json:"virtualizationRole"` // guest or host
|
||||
HostID string `json:"hostid"` // ex: uuid
|
||||
}
|
||||
|
||||
type UserStat struct {
|
||||
User string `json:"user"`
|
||||
Terminal string `json:"terminal"`
|
||||
Host string `json:"host"`
|
||||
Started int `json:"started"`
|
||||
}
|
||||
|
||||
func (h InfoStat) String() string {
|
||||
s, _ := json.Marshal(h)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (u UserStat) String() string {
|
||||
s, _ := json.Marshal(u)
|
||||
return string(s)
|
||||
}
|
||||
164
vendor/github.com/shirou/gopsutil/host/host_darwin.go
generated
vendored
Normal file
164
vendor/github.com/shirou/gopsutil/host/host_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
// +build darwin
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
)
|
||||
|
||||
// from utmpx.h
|
||||
const USER_PROCESS = 7
|
||||
|
||||
func Info() (*InfoStat, error) {
|
||||
ret := &InfoStat{
|
||||
OS: runtime.GOOS,
|
||||
PlatformFamily: "darwin",
|
||||
}
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err == nil {
|
||||
ret.Hostname = hostname
|
||||
}
|
||||
|
||||
platform, family, version, err := PlatformInformation()
|
||||
if err == nil {
|
||||
ret.Platform = platform
|
||||
ret.PlatformFamily = family
|
||||
ret.PlatformVersion = version
|
||||
}
|
||||
|
||||
system, role, err := Virtualization()
|
||||
if err == nil {
|
||||
ret.VirtualizationSystem = system
|
||||
ret.VirtualizationRole = role
|
||||
}
|
||||
|
||||
boot, err := BootTime()
|
||||
if err == nil {
|
||||
ret.BootTime = boot
|
||||
ret.Uptime = uptime(boot)
|
||||
}
|
||||
|
||||
procs, err := process.Pids()
|
||||
if err == nil {
|
||||
ret.Procs = uint64(len(procs))
|
||||
}
|
||||
|
||||
values, err := common.DoSysctrl("kern.uuid")
|
||||
if err == nil && len(values) == 1 && values[0] != "" {
|
||||
ret.HostID = values[0]
|
||||
}
|
||||
|
||||
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 uptime(boot uint64) uint64 {
|
||||
return uint64(time.Now().Unix()) - boot
|
||||
}
|
||||
|
||||
func Uptime() (uint64, error) {
|
||||
boot, err := BootTime()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uptime(boot), nil
|
||||
}
|
||||
|
||||
func Users() ([]UserStat, error) {
|
||||
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 != USER_PROCESS {
|
||||
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 PlatformInformation() (string, string, string, error) {
|
||||
platform := ""
|
||||
family := ""
|
||||
version := ""
|
||||
|
||||
uname, err := exec.LookPath("uname")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
out, err := invoke.Command(uname, "-s")
|
||||
if err == nil {
|
||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
out, err = invoke.Command(uname, "-r")
|
||||
if err == nil {
|
||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
return platform, family, version, nil
|
||||
}
|
||||
|
||||
func Virtualization() (string, string, error) {
|
||||
system := ""
|
||||
role := ""
|
||||
|
||||
return system, role, nil
|
||||
}
|
||||
19
vendor/github.com/shirou/gopsutil/host/host_darwin_amd64.go
generated
vendored
Normal file
19
vendor/github.com/shirou/gopsutil/host/host_darwin_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_darwin.go
|
||||
|
||||
package host
|
||||
|
||||
type Utmpx struct {
|
||||
User [256]int8
|
||||
ID [4]int8
|
||||
Line [32]int8
|
||||
Pid int32
|
||||
Type int16
|
||||
Pad_cgo_0 [6]byte
|
||||
Tv Timeval
|
||||
Host [256]int8
|
||||
Pad [16]uint32
|
||||
}
|
||||
type Timeval struct {
|
||||
Sec int32
|
||||
}
|
||||
206
vendor/github.com/shirou/gopsutil/host/host_freebsd.go
generated
vendored
Normal file
206
vendor/github.com/shirou/gopsutil/host/host_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
// +build freebsd
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
)
|
||||
|
||||
const (
|
||||
UTNameSize = 16 /* see MAXLOGNAME in <sys/param.h> */
|
||||
UTLineSize = 8
|
||||
UTHostSize = 16
|
||||
)
|
||||
|
||||
func Info() (*InfoStat, error) {
|
||||
ret := &InfoStat{
|
||||
OS: runtime.GOOS,
|
||||
PlatformFamily: "freebsd",
|
||||
}
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err == nil {
|
||||
ret.Hostname = hostname
|
||||
}
|
||||
|
||||
platform, family, version, err := PlatformInformation()
|
||||
if err == nil {
|
||||
ret.Platform = platform
|
||||
ret.PlatformFamily = family
|
||||
ret.PlatformVersion = version
|
||||
}
|
||||
|
||||
system, role, err := Virtualization()
|
||||
if err == nil {
|
||||
ret.VirtualizationSystem = system
|
||||
ret.VirtualizationRole = role
|
||||
}
|
||||
|
||||
boot, err := BootTime()
|
||||
if err == nil {
|
||||
ret.BootTime = boot
|
||||
ret.Uptime = uptime(boot)
|
||||
}
|
||||
|
||||
procs, err := process.Pids()
|
||||
if err == nil {
|
||||
ret.Procs = uint64(len(procs))
|
||||
}
|
||||
|
||||
values, err := common.DoSysctrl("kern.hostuuid")
|
||||
if err == nil && len(values) == 1 && values[0] != "" {
|
||||
ret.HostID = values[0]
|
||||
}
|
||||
|
||||
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.ParseUint(v, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return boottime, nil
|
||||
}
|
||||
|
||||
func uptime(boot uint64) uint64 {
|
||||
return uint64(time.Now().Unix()) - boot
|
||||
}
|
||||
|
||||
func Uptime() (uint64, error) {
|
||||
boot, err := BootTime()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uptime(boot), nil
|
||||
}
|
||||
|
||||
func Users() ([]UserStat, error) {
|
||||
utmpfile := "/var/run/utx.active"
|
||||
if !common.PathExists(utmpfile) {
|
||||
utmpfile = "/var/run/utmp" // before 9.0
|
||||
return getUsersFromUtmp(utmpfile)
|
||||
}
|
||||
|
||||
var ret []UserStat
|
||||
file, err := os.Open(utmpfile)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
entrySize := sizeOfUtmpx
|
||||
count := len(buf) / entrySize
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*sizeOfUtmpx : (i+1)*sizeOfUtmpx]
|
||||
var u Utmpx
|
||||
br := bytes.NewReader(b)
|
||||
err := binary.Read(br, binary.LittleEndian, &u)
|
||||
if err != nil || u.Type != 4 {
|
||||
continue
|
||||
}
|
||||
sec := (binary.LittleEndian.Uint32(u.Tv.Sec[:])) / 2 // TODO:
|
||||
user := UserStat{
|
||||
User: common.IntToString(u.User[:]),
|
||||
Terminal: common.IntToString(u.Line[:]),
|
||||
Host: common.IntToString(u.Host[:]),
|
||||
Started: int(sec),
|
||||
}
|
||||
|
||||
ret = append(ret, user)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
||||
}
|
||||
|
||||
func PlatformInformation() (string, string, string, error) {
|
||||
platform := ""
|
||||
family := ""
|
||||
version := ""
|
||||
uname, err := exec.LookPath("uname")
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(uname, "-s")
|
||||
if err == nil {
|
||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
out, err = invoke.Command(uname, "-r")
|
||||
if err == nil {
|
||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
return platform, family, version, nil
|
||||
}
|
||||
|
||||
func Virtualization() (string, string, error) {
|
||||
system := ""
|
||||
role := ""
|
||||
|
||||
return system, role, nil
|
||||
}
|
||||
|
||||
// before 9.0
|
||||
func getUsersFromUtmp(utmpfile string) ([]UserStat, error) {
|
||||
var ret []UserStat
|
||||
file, err := os.Open(utmpfile)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
buf, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
u := Utmp{}
|
||||
entrySize := int(unsafe.Sizeof(u))
|
||||
count := len(buf) / entrySize
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*entrySize : i*entrySize+entrySize]
|
||||
var u Utmp
|
||||
br := bytes.NewReader(b)
|
||||
err := binary.Read(br, binary.LittleEndian, &u)
|
||||
if err != nil || u.Time == 0 {
|
||||
continue
|
||||
}
|
||||
user := UserStat{
|
||||
User: common.IntToString(u.Name[:]),
|
||||
Terminal: common.IntToString(u.Line[:]),
|
||||
Host: common.IntToString(u.Host[:]),
|
||||
Started: int(u.Time),
|
||||
}
|
||||
|
||||
ret = append(ret, user)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
43
vendor/github.com/shirou/gopsutil/host/host_freebsd_386.go
generated
vendored
Normal file
43
vendor/github.com/shirou/gopsutil/host/host_freebsd_386.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package host
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x4
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmpx = 197 // TODO why should 197
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int32
|
||||
_C_long_long int64
|
||||
)
|
||||
|
||||
type Utmp struct {
|
||||
Line [8]int8
|
||||
Name [16]int8
|
||||
Host [16]int8
|
||||
Time int32
|
||||
}
|
||||
|
||||
type Utmpx struct {
|
||||
Type int16
|
||||
Tv Timeval
|
||||
Id [8]int8
|
||||
Pid int32
|
||||
User [32]int8
|
||||
Line [16]int8
|
||||
Host [125]int8
|
||||
// X__ut_spare [64]int8
|
||||
}
|
||||
|
||||
type Timeval struct {
|
||||
Sec [4]byte
|
||||
Usec [3]byte
|
||||
}
|
||||
44
vendor/github.com/shirou/gopsutil/host/host_freebsd_amd64.go
generated
vendored
Normal file
44
vendor/github.com/shirou/gopsutil/host/host_freebsd_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package host
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x8
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x8
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmpx = 197 // TODO: why should 197, not 0x118
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int64
|
||||
_C_long_long int64
|
||||
)
|
||||
|
||||
type Utmp struct {
|
||||
Line [8]int8
|
||||
Name [16]int8
|
||||
Host [16]int8
|
||||
Time int32
|
||||
}
|
||||
|
||||
type Utmpx struct {
|
||||
Type int16
|
||||
Tv Timeval
|
||||
Id [8]int8
|
||||
Pid int32
|
||||
User [32]int8
|
||||
Line [16]int8
|
||||
Host [125]int8
|
||||
// Host [128]int8
|
||||
// X__ut_spare [64]int8
|
||||
}
|
||||
|
||||
type Timeval struct {
|
||||
Sec [4]byte
|
||||
Usec [3]byte
|
||||
}
|
||||
498
vendor/github.com/shirou/gopsutil/host/host_linux.go
generated
vendored
Normal file
498
vendor/github.com/shirou/gopsutil/host/host_linux.go
generated
vendored
Normal file
@@ -0,0 +1,498 @@
|
||||
// +build linux
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
type LSB struct {
|
||||
ID string
|
||||
Release string
|
||||
Codename string
|
||||
Description string
|
||||
}
|
||||
|
||||
// from utmp.h
|
||||
const USER_PROCESS = 7
|
||||
|
||||
func Info() (*InfoStat, error) {
|
||||
ret := &InfoStat{
|
||||
OS: runtime.GOOS,
|
||||
}
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err == nil {
|
||||
ret.Hostname = hostname
|
||||
}
|
||||
|
||||
platform, family, version, err := PlatformInformation()
|
||||
if err == nil {
|
||||
ret.Platform = platform
|
||||
ret.PlatformFamily = family
|
||||
ret.PlatformVersion = version
|
||||
}
|
||||
|
||||
system, role, err := Virtualization()
|
||||
if err == nil {
|
||||
ret.VirtualizationSystem = system
|
||||
ret.VirtualizationRole = role
|
||||
}
|
||||
|
||||
boot, err := BootTime()
|
||||
if err == nil {
|
||||
ret.BootTime = boot
|
||||
ret.Uptime = uptime(boot)
|
||||
}
|
||||
|
||||
if numProcs, err := common.NumProcs(); err == nil {
|
||||
ret.Procs = numProcs
|
||||
}
|
||||
|
||||
sysProductUUID := common.HostSys("class/dmi/id/product_uuid")
|
||||
switch {
|
||||
case common.PathExists(sysProductUUID):
|
||||
lines, err := common.ReadLines(sysProductUUID)
|
||||
if err == nil && len(lines) > 0 && lines[0] != "" {
|
||||
ret.HostID = lines[0]
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
values, err := common.DoSysctrl("kernel.random.boot_id")
|
||||
if err == nil && len(values) == 1 && values[0] != "" {
|
||||
ret.HostID = values[0]
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// BootTime returns the system boot time expressed in seconds since the epoch.
|
||||
func BootTime() (uint64, error) {
|
||||
filename := common.HostProc("stat")
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(line, "btime") {
|
||||
f := strings.Fields(line)
|
||||
if len(f) != 2 {
|
||||
return 0, fmt.Errorf("wrong btime format")
|
||||
}
|
||||
b, err := strconv.ParseInt(f[1], 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(b), nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("could not find btime")
|
||||
}
|
||||
|
||||
func uptime(boot uint64) uint64 {
|
||||
return uint64(time.Now().Unix()) - boot
|
||||
}
|
||||
|
||||
func Uptime() (uint64, error) {
|
||||
boot, err := BootTime()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uptime(boot), nil
|
||||
}
|
||||
|
||||
func Users() ([]UserStat, error) {
|
||||
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
|
||||
}
|
||||
|
||||
count := len(buf) / sizeOfUtmp
|
||||
|
||||
ret := make([]UserStat, 0, count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*sizeOfUtmp : (i+1)*sizeOfUtmp]
|
||||
|
||||
var u utmp
|
||||
br := bytes.NewReader(b)
|
||||
err := binary.Read(br, binary.LittleEndian, &u)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if u.Type != USER_PROCESS {
|
||||
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 getOSRelease() (platform string, version string, err error) {
|
||||
contents, err := common.ReadLines(common.HostEtc("os-release"))
|
||||
if err != nil {
|
||||
return "", "", nil // return empty
|
||||
}
|
||||
for _, line := range contents {
|
||||
field := strings.Split(line, "=")
|
||||
if len(field) < 2 {
|
||||
continue
|
||||
}
|
||||
switch field[0] {
|
||||
case "ID": // use ID for lowercase
|
||||
platform = field[1]
|
||||
case "VERSION":
|
||||
version = field[1]
|
||||
}
|
||||
}
|
||||
return platform, version, nil
|
||||
}
|
||||
|
||||
func getLSB() (*LSB, error) {
|
||||
ret := &LSB{}
|
||||
if common.PathExists(common.HostEtc("lsb-release")) {
|
||||
contents, err := common.ReadLines(common.HostEtc("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") {
|
||||
lsb_release, err := exec.LookPath("/usr/bin/lsb_release")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
out, err := invoke.Command(lsb_release)
|
||||
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 PlatformInformation() (platform string, family string, version string, err error) {
|
||||
|
||||
lsb, err := getLSB()
|
||||
if err != nil {
|
||||
lsb = &LSB{}
|
||||
}
|
||||
|
||||
if common.PathExists(common.HostEtc("oracle-release")) {
|
||||
platform = "oracle"
|
||||
contents, err := common.ReadLines(common.HostEtc("oracle-release"))
|
||||
if err == nil {
|
||||
version = getRedhatishVersion(contents)
|
||||
}
|
||||
|
||||
} else if common.PathExists(common.HostEtc("enterprise-release")) {
|
||||
platform = "oracle"
|
||||
contents, err := common.ReadLines(common.HostEtc("enterprise-release"))
|
||||
if err == nil {
|
||||
version = getRedhatishVersion(contents)
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("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(common.HostEtc("debian_version"))
|
||||
if err == nil {
|
||||
version = contents[0]
|
||||
}
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("redhat-release")) {
|
||||
contents, err := common.ReadLines(common.HostEtc("redhat-release"))
|
||||
if err == nil {
|
||||
version = getRedhatishVersion(contents)
|
||||
platform = getRedhatishPlatform(contents)
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("system-release")) {
|
||||
contents, err := common.ReadLines(common.HostEtc("system-release"))
|
||||
if err == nil {
|
||||
version = getRedhatishVersion(contents)
|
||||
platform = getRedhatishPlatform(contents)
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("gentoo-release")) {
|
||||
platform = "gentoo"
|
||||
contents, err := common.ReadLines(common.HostEtc("gentoo-release"))
|
||||
if err == nil {
|
||||
version = getRedhatishVersion(contents)
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("SuSE-release")) {
|
||||
contents, err := common.ReadLines(common.HostEtc("SuSE-release"))
|
||||
if err == nil {
|
||||
version = getSuseVersion(contents)
|
||||
platform = getSusePlatform(contents)
|
||||
}
|
||||
// TODO: slackware detecion
|
||||
} else if common.PathExists(common.HostEtc("arch-release")) {
|
||||
platform = "arch"
|
||||
version = lsb.Release
|
||||
} else if common.PathExists(common.HostEtc("alpine-release")) {
|
||||
platform = "alpine"
|
||||
contents, err := common.ReadLines(common.HostEtc("alpine-release"))
|
||||
if err == nil && len(contents) > 0 {
|
||||
version = contents[0]
|
||||
}
|
||||
} else if common.PathExists(common.HostEtc("os-release")) {
|
||||
p, v, err := getOSRelease()
|
||||
if err == nil {
|
||||
platform = p
|
||||
version = v
|
||||
}
|
||||
} else if lsb.ID == "RedHat" {
|
||||
platform = "redhat"
|
||||
version = lsb.Release
|
||||
} else if lsb.ID == "Amazon" {
|
||||
platform = "amazon"
|
||||
version = lsb.Release
|
||||
} else if lsb.ID == "ScientificSL" {
|
||||
platform = "scientific"
|
||||
version = lsb.Release
|
||||
} else if lsb.ID == "XenServer" {
|
||||
platform = "xenserver"
|
||||
version = lsb.Release
|
||||
} else if lsb.ID != "" {
|
||||
platform = strings.ToLower(lsb.ID)
|
||||
version = lsb.Release
|
||||
}
|
||||
|
||||
switch platform {
|
||||
case "debian", "ubuntu", "linuxmint", "raspbian":
|
||||
family = "debian"
|
||||
case "fedora":
|
||||
family = "fedora"
|
||||
case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm":
|
||||
family = "rhel"
|
||||
case "suse", "opensuse":
|
||||
family = "suse"
|
||||
case "gentoo":
|
||||
family = "gentoo"
|
||||
case "slackware":
|
||||
family = "slackware"
|
||||
case "arch":
|
||||
family = "arch"
|
||||
case "exherbo":
|
||||
family = "exherbo"
|
||||
case "alpine":
|
||||
family = "alpine"
|
||||
case "coreos":
|
||||
family = "coreos"
|
||||
}
|
||||
|
||||
return platform, family, version, nil
|
||||
|
||||
}
|
||||
|
||||
func getRedhatishVersion(contents []string) string {
|
||||
c := strings.ToLower(strings.Join(contents, ""))
|
||||
|
||||
if strings.Contains(c, "rawhide") {
|
||||
return "rawhide"
|
||||
}
|
||||
if matches := regexp.MustCompile(`release (\d[\d.]*)`).FindStringSubmatch(c); matches != nil {
|
||||
return matches[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getRedhatishPlatform(contents []string) string {
|
||||
c := strings.ToLower(strings.Join(contents, ""))
|
||||
|
||||
if strings.Contains(c, "red hat") {
|
||||
return "redhat"
|
||||
}
|
||||
f := strings.Split(c, " ")
|
||||
|
||||
return f[0]
|
||||
}
|
||||
|
||||
func getSuseVersion(contents []string) string {
|
||||
version := ""
|
||||
for _, line := range contents {
|
||||
if matches := regexp.MustCompile(`VERSION = ([\d.]+)`).FindStringSubmatch(line); matches != nil {
|
||||
version = matches[1]
|
||||
} else if matches := regexp.MustCompile(`PATCHLEVEL = ([\d]+)`).FindStringSubmatch(line); matches != nil {
|
||||
version = version + "." + matches[1]
|
||||
}
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
func getSusePlatform(contents []string) string {
|
||||
c := strings.ToLower(strings.Join(contents, ""))
|
||||
if strings.Contains(c, "opensuse") {
|
||||
return "opensuse"
|
||||
}
|
||||
return "suse"
|
||||
}
|
||||
|
||||
func Virtualization() (string, string, error) {
|
||||
var system string
|
||||
var role string
|
||||
|
||||
filename := common.HostProc("xen")
|
||||
if common.PathExists(filename) {
|
||||
system = "xen"
|
||||
role = "guest" // assume guest
|
||||
|
||||
if common.PathExists(filename + "/capabilities") {
|
||||
contents, err := common.ReadLines(filename + "/capabilities")
|
||||
if err == nil {
|
||||
if common.StringsContains(contents, "control_d") {
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = common.HostProc("modules")
|
||||
if common.PathExists(filename) {
|
||||
contents, err := common.ReadLines(filename)
|
||||
if err == nil {
|
||||
if common.StringsContains(contents, "kvm") {
|
||||
system = "kvm"
|
||||
role = "host"
|
||||
} else if common.StringsContains(contents, "vboxdrv") {
|
||||
system = "vbox"
|
||||
role = "host"
|
||||
} else if common.StringsContains(contents, "vboxguest") {
|
||||
system = "vbox"
|
||||
role = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = common.HostProc("cpuinfo")
|
||||
if common.PathExists(filename) {
|
||||
contents, err := common.ReadLines(filename)
|
||||
if err == nil {
|
||||
if common.StringsContains(contents, "QEMU Virtual CPU") ||
|
||||
common.StringsContains(contents, "Common KVM processor") ||
|
||||
common.StringsContains(contents, "Common 32-bit KVM processor") {
|
||||
system = "kvm"
|
||||
role = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = common.HostProc()
|
||||
if common.PathExists(filename + "/bc/0") {
|
||||
system = "openvz"
|
||||
role = "host"
|
||||
} else if common.PathExists(filename + "/vz") {
|
||||
system = "openvz"
|
||||
role = "guest"
|
||||
}
|
||||
|
||||
// not use dmidecode because it requires root
|
||||
if common.PathExists(filename + "/self/status") {
|
||||
contents, err := common.ReadLines(filename + "/self/status")
|
||||
if err == nil {
|
||||
|
||||
if common.StringsContains(contents, "s_context:") ||
|
||||
common.StringsContains(contents, "VxID:") {
|
||||
system = "linux-vserver"
|
||||
}
|
||||
// TODO: guest or host
|
||||
}
|
||||
}
|
||||
|
||||
if common.PathExists(filename + "/self/cgroup") {
|
||||
contents, err := common.ReadLines(filename + "/self/cgroup")
|
||||
if err == nil {
|
||||
if common.StringsContains(contents, "lxc") {
|
||||
system = "lxc"
|
||||
role = "guest"
|
||||
} else if common.StringsContains(contents, "docker") {
|
||||
system = "docker"
|
||||
role = "guest"
|
||||
} else if common.StringsContains(contents, "machine-rkt") {
|
||||
system = "rkt"
|
||||
role = "guest"
|
||||
} else if common.PathExists("/usr/bin/lxc-version") {
|
||||
system = "lxc"
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if common.PathExists(common.HostEtc("os-release")) {
|
||||
p, _, err := getOSRelease()
|
||||
if err == nil && p == "coreos" {
|
||||
system = "rkt" // Is it true?
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
return system, role, nil
|
||||
}
|
||||
45
vendor/github.com/shirou/gopsutil/host/host_linux_386.go
generated
vendored
Normal file
45
vendor/github.com/shirou/gopsutil/host/host_linux_386.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
// 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
|
||||
sizeOfUtmp = 0x180
|
||||
)
|
||||
|
||||
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 {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
||||
48
vendor/github.com/shirou/gopsutil/host/host_linux_amd64.go
generated
vendored
Normal file
48
vendor/github.com/shirou/gopsutil/host/host_linux_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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
|
||||
sizeOfUtmp = 0x180
|
||||
)
|
||||
|
||||
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 _Ctype_struct___0
|
||||
Addr_v6 [4]int32
|
||||
X__glibc_reserved [20]int8
|
||||
}
|
||||
type exit_status struct {
|
||||
Termination int16
|
||||
Exit int16
|
||||
}
|
||||
type timeval struct {
|
||||
Sec int64
|
||||
Usec int64
|
||||
}
|
||||
|
||||
type _Ctype_struct___0 struct {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
||||
43
vendor/github.com/shirou/gopsutil/host/host_linux_arm.go
generated
vendored
Normal file
43
vendor/github.com/shirou/gopsutil/host/host_linux_arm.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_linux.go | sed "s/uint8/int8/g"
|
||||
|
||||
package host
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x4
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
sizeOfUtmp = 0x180
|
||||
)
|
||||
|
||||
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 timeval
|
||||
Addr_v6 [4]int32
|
||||
X__glibc_reserved [20]int8
|
||||
}
|
||||
type exit_status struct {
|
||||
Termination int16
|
||||
Exit int16
|
||||
}
|
||||
type timeval struct {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
||||
43
vendor/github.com/shirou/gopsutil/host/host_linux_arm64.go
generated
vendored
Normal file
43
vendor/github.com/shirou/gopsutil/host/host_linux_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// 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
|
||||
sizeOfUtmp = 0x180
|
||||
)
|
||||
|
||||
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 timeval
|
||||
Addr_v6 [4]int32
|
||||
X__glibc_reserved [20]int8
|
||||
}
|
||||
type exit_status struct {
|
||||
Termination int16
|
||||
Exit int16
|
||||
}
|
||||
type timeval struct {
|
||||
Sec int64
|
||||
Usec int64
|
||||
}
|
||||
45
vendor/github.com/shirou/gopsutil/host/host_linux_ppc64le.go
generated
vendored
Normal file
45
vendor/github.com/shirou/gopsutil/host/host_linux_ppc64le.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
// +build linux
|
||||
// +build ppc64le
|
||||
// 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
|
||||
sizeOfUtmp = 0x180
|
||||
)
|
||||
|
||||
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 timeval
|
||||
Addr_v6 [4]int32
|
||||
X__glibc_reserved [20]int8
|
||||
}
|
||||
type exit_status struct {
|
||||
Termination int16
|
||||
Exit int16
|
||||
}
|
||||
type timeval struct {
|
||||
Sec int64
|
||||
Usec int64
|
||||
}
|
||||
61
vendor/github.com/shirou/gopsutil/host/host_linux_test.go
generated
vendored
Normal file
61
vendor/github.com/shirou/gopsutil/host/host_linux_test.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// +build linux
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetRedhatishVersion(t *testing.T) {
|
||||
var ret string
|
||||
c := []string{"Rawhide"}
|
||||
ret = getRedhatishVersion(c)
|
||||
if ret != "rawhide" {
|
||||
t.Errorf("Could not get version rawhide: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{"Fedora release 15 (Lovelock)"}
|
||||
ret = getRedhatishVersion(c)
|
||||
if ret != "15" {
|
||||
t.Errorf("Could not get version fedora: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{"Enterprise Linux Server release 5.5 (Carthage)"}
|
||||
ret = getRedhatishVersion(c)
|
||||
if ret != "5.5" {
|
||||
t.Errorf("Could not get version redhat enterprise: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{""}
|
||||
ret = getRedhatishVersion(c)
|
||||
if ret != "" {
|
||||
t.Errorf("Could not get version with no value: %v", ret)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRedhatishPlatform(t *testing.T) {
|
||||
var ret string
|
||||
c := []string{"red hat"}
|
||||
ret = getRedhatishPlatform(c)
|
||||
if ret != "redhat" {
|
||||
t.Errorf("Could not get platform redhat: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{"Fedora release 15 (Lovelock)"}
|
||||
ret = getRedhatishPlatform(c)
|
||||
if ret != "fedora" {
|
||||
t.Errorf("Could not get platform fedora: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{"Enterprise Linux Server release 5.5 (Carthage)"}
|
||||
ret = getRedhatishPlatform(c)
|
||||
if ret != "enterprise" {
|
||||
t.Errorf("Could not get platform redhat enterprise: %v", ret)
|
||||
}
|
||||
|
||||
c = []string{""}
|
||||
ret = getRedhatishPlatform(c)
|
||||
if ret != "" {
|
||||
t.Errorf("Could not get platform with no value: %v", ret)
|
||||
}
|
||||
}
|
||||
88
vendor/github.com/shirou/gopsutil/host/host_test.go
generated
vendored
Normal file
88
vendor/github.com/shirou/gopsutil/host/host_test.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHostInfo(t *testing.T) {
|
||||
v, err := Info()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
empty := &InfoStat{}
|
||||
if v == empty {
|
||||
t.Errorf("Could not get hostinfo %v", v)
|
||||
}
|
||||
if v.Procs == 0 {
|
||||
t.Errorf("Could not determine the number of host processes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUptime(t *testing.T) {
|
||||
v, err := Uptime()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if v == 0 {
|
||||
t.Errorf("Could not get up time %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoot_time(t *testing.T) {
|
||||
v, err := BootTime()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
if v == 0 {
|
||||
t.Errorf("Could not get boot time %v", v)
|
||||
}
|
||||
if v < 946652400 {
|
||||
t.Errorf("Invalid Boottime, older than 2000-01-01")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUsers(t *testing.T) {
|
||||
v, err := Users()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
empty := UserStat{}
|
||||
if len(v) == 0 {
|
||||
t.Errorf("Users is empty")
|
||||
}
|
||||
for _, u := range v {
|
||||
if u == empty {
|
||||
t.Errorf("Could not Users %v", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostInfoStat_String(t *testing.T) {
|
||||
v := InfoStat{
|
||||
Hostname: "test",
|
||||
Uptime: 3000,
|
||||
Procs: 100,
|
||||
OS: "linux",
|
||||
Platform: "ubuntu",
|
||||
BootTime: 1447040000,
|
||||
HostID: "edfd25ff-3c9c-b1a4-e660-bd826495ad35",
|
||||
}
|
||||
e := `{"hostname":"test","uptime":3000,"bootTime":1447040000,"procs":100,"os":"linux","platform":"ubuntu","platformFamily":"","platformVersion":"","virtualizationSystem":"","virtualizationRole":"","hostid":"edfd25ff-3c9c-b1a4-e660-bd826495ad35"}`
|
||||
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)
|
||||
}
|
||||
}
|
||||
133
vendor/github.com/shirou/gopsutil/host/host_windows.go
generated
vendored
Normal file
133
vendor/github.com/shirou/gopsutil/host/host_windows.go
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
// +build windows
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
process "github.com/shirou/gopsutil/process"
|
||||
)
|
||||
|
||||
var (
|
||||
procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime")
|
||||
osInfo *Win32_OperatingSystem
|
||||
)
|
||||
|
||||
type Win32_OperatingSystem struct {
|
||||
Version string
|
||||
Caption string
|
||||
ProductType uint32
|
||||
BuildNumber string
|
||||
LastBootUpTime time.Time
|
||||
}
|
||||
|
||||
func Info() (*InfoStat, error) {
|
||||
ret := &InfoStat{
|
||||
OS: runtime.GOOS,
|
||||
}
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err == nil {
|
||||
ret.Hostname = hostname
|
||||
}
|
||||
|
||||
platform, family, version, err := PlatformInformation()
|
||||
if err == nil {
|
||||
ret.Platform = platform
|
||||
ret.PlatformFamily = family
|
||||
ret.PlatformVersion = version
|
||||
} else {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
boot, err := BootTime()
|
||||
if err == nil {
|
||||
ret.BootTime = boot
|
||||
ret.Uptime, _ = Uptime()
|
||||
}
|
||||
|
||||
procs, err := process.Pids()
|
||||
if err == nil {
|
||||
ret.Procs = uint64(len(procs))
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func GetOSInfo() (Win32_OperatingSystem, error) {
|
||||
var dst []Win32_OperatingSystem
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
err := wmi.Query(q, &dst)
|
||||
if err != nil {
|
||||
return Win32_OperatingSystem{}, err
|
||||
}
|
||||
|
||||
osInfo = &dst[0]
|
||||
|
||||
return dst[0], nil
|
||||
}
|
||||
|
||||
func Uptime() (uint64, error) {
|
||||
if osInfo == nil {
|
||||
_, err := GetOSInfo()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
now := time.Now()
|
||||
t := osInfo.LastBootUpTime.Local()
|
||||
return uint64(now.Sub(t).Seconds()), nil
|
||||
}
|
||||
|
||||
func bootTime(up uint64) uint64 {
|
||||
return uint64(time.Now().Unix()) - up
|
||||
}
|
||||
|
||||
func BootTime() (uint64, error) {
|
||||
up, err := Uptime()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return bootTime(up), nil
|
||||
}
|
||||
|
||||
func PlatformInformation() (platform string, family string, version string, err error) {
|
||||
if osInfo == nil {
|
||||
_, err = GetOSInfo()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Platform
|
||||
platform = strings.Trim(osInfo.Caption, " ")
|
||||
|
||||
// PlatformFamily
|
||||
switch osInfo.ProductType {
|
||||
case 1:
|
||||
family = "Standalone Workstation"
|
||||
case 2:
|
||||
family = "Server (Domain Controller)"
|
||||
case 3:
|
||||
family = "Server"
|
||||
}
|
||||
|
||||
// Platform Version
|
||||
version = fmt.Sprintf("%s Build %s", osInfo.Version, osInfo.BuildNumber)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func Users() ([]UserStat, error) {
|
||||
|
||||
var ret []UserStat
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
17
vendor/github.com/shirou/gopsutil/host/types_darwin.go
generated
vendored
Normal file
17
vendor/github.com/shirou/gopsutil/host/types_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// +build ignore
|
||||
// plus hand editing about timeval
|
||||
|
||||
/*
|
||||
Input to cgo -godefs.
|
||||
*/
|
||||
|
||||
package host
|
||||
|
||||
/*
|
||||
#include <sys/time.h>
|
||||
#include <utmpx.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type Utmpx C.struct_utmpx
|
||||
type Timeval C.struct_timeval
|
||||
44
vendor/github.com/shirou/gopsutil/host/types_freebsd.go
generated
vendored
Normal file
44
vendor/github.com/shirou/gopsutil/host/types_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs.
|
||||
*/
|
||||
|
||||
package host
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <utmpx.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics; for internal use.
|
||||
|
||||
const (
|
||||
sizeofPtr = C.sizeofPtr
|
||||
sizeofShort = C.sizeof_short
|
||||
sizeofInt = C.sizeof_int
|
||||
sizeofLong = C.sizeof_long
|
||||
sizeofLongLong = C.sizeof_longlong
|
||||
sizeOfUtmpx = C.sizeof_struct_utmpx
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
type Utmp C.struct_utmp
|
||||
type Utmpx C.struct_utmpx
|
||||
type Timeval C.struct_timeval
|
||||
42
vendor/github.com/shirou/gopsutil/host/types_linux.go
generated
vendored
Normal file
42
vendor/github.com/shirou/gopsutil/host/types_linux.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs.
|
||||
*/
|
||||
|
||||
package host
|
||||
|
||||
/*
|
||||
#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
|
||||
sizeOfUtmp = C.sizeof_struct_utmp
|
||||
)
|
||||
|
||||
// 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 timeval C.struct_timeval
|
||||
634
vendor/github.com/shirou/gopsutil/internal/common/binary.go
generated
vendored
Normal file
634
vendor/github.com/shirou/gopsutil/internal/common/binary.go
generated
vendored
Normal file
@@ -0,0 +1,634 @@
|
||||
package common
|
||||
|
||||
// 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.
|
||||
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
|
||||
}
|
||||
343
vendor/github.com/shirou/gopsutil/internal/common/common.go
generated
vendored
Normal file
343
vendor/github.com/shirou/gopsutil/internal/common/common.go
generated
vendored
Normal file
@@ -0,0 +1,343 @@
|
||||
package common
|
||||
|
||||
//
|
||||
// gopsutil is a port of psutil(http://pythonhosted.org/psutil/).
|
||||
// This covers these architectures.
|
||||
// - linux (amd64, arm)
|
||||
// - freebsd (amd64)
|
||||
// - windows (amd64)
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Timeout = 3 * time.Second
|
||||
ErrTimeout = errors.New("Command timed out.")
|
||||
)
|
||||
|
||||
type Invoker interface {
|
||||
Command(string, ...string) ([]byte, error)
|
||||
}
|
||||
|
||||
type Invoke struct{}
|
||||
|
||||
func (i Invoke) Command(name string, arg ...string) ([]byte, error) {
|
||||
cmd := exec.Command(name, arg...)
|
||||
return CombinedOutputTimeout(cmd, Timeout)
|
||||
}
|
||||
|
||||
type FakeInvoke struct {
|
||||
CommandExpectedDir string // CommandExpectedDir specifies dir which includes expected outputs.
|
||||
Suffix string // Suffix species expected file name suffix such as "fail"
|
||||
Error error // If Error specfied, return the error.
|
||||
}
|
||||
|
||||
// Command in FakeInvoke returns from expected file if exists.
|
||||
func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) {
|
||||
if i.Error != nil {
|
||||
return []byte{}, i.Error
|
||||
}
|
||||
|
||||
arch := runtime.GOOS
|
||||
|
||||
fname := strings.Join(append([]string{name}, arg...), "")
|
||||
fname = url.QueryEscape(fname)
|
||||
var dir string
|
||||
if i.CommandExpectedDir == "" {
|
||||
dir = "expected"
|
||||
} else {
|
||||
dir = i.CommandExpectedDir
|
||||
}
|
||||
fpath := path.Join(dir, arch, fname)
|
||||
if i.Suffix != "" {
|
||||
fpath += "_" + i.Suffix
|
||||
}
|
||||
if PathExists(fpath) {
|
||||
return ioutil.ReadFile(fpath)
|
||||
}
|
||||
return exec.Command(name, arg...).Output()
|
||||
}
|
||||
|
||||
var ErrNotImplementedError = errors.New("not implemented yet")
|
||||
|
||||
// ReadLines reads contents from a file and splits them by new lines.
|
||||
// A convenience wrapper to ReadLinesOffsetN(filename, 0, -1).
|
||||
func ReadLines(filename string) ([]string, error) {
|
||||
return ReadLinesOffsetN(filename, 0, -1)
|
||||
}
|
||||
|
||||
// ReadLines reads contents from file and splits them by new line.
|
||||
// The offset tells at which line number to start.
|
||||
// The count determines the number of lines to read (starting from offset):
|
||||
// n >= 0: at most n lines
|
||||
// n < 0: whole file
|
||||
func ReadLinesOffsetN(filename string, offset uint, n int) ([]string, error) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return []string{""}, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var ret []string
|
||||
|
||||
r := bufio.NewReader(f)
|
||||
for i := 0; i < n+int(offset) || n < 0; i++ {
|
||||
line, err := r.ReadString('\n')
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if i < int(offset) {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, strings.Trim(line, "\n"))
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func IntToString(orig []int8) string {
|
||||
ret := make([]byte, len(orig))
|
||||
size := -1
|
||||
for i, o := range orig {
|
||||
if o == 0 {
|
||||
size = i
|
||||
break
|
||||
}
|
||||
ret[i] = byte(o)
|
||||
}
|
||||
if size == -1 {
|
||||
size = len(orig)
|
||||
}
|
||||
|
||||
return string(ret[0:size])
|
||||
}
|
||||
|
||||
func UintToString(orig []uint8) 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])
|
||||
}
|
||||
|
||||
// ReadInts reads contents from single line file and returns them as []int32.
|
||||
func ReadInts(filename string) ([]int64, error) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return []int64{}, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var ret []int64
|
||||
|
||||
r := bufio.NewReader(f)
|
||||
|
||||
// The int files that this is concerned with should only be one liners.
|
||||
line, err := r.ReadString('\n')
|
||||
if err != nil {
|
||||
return []int64{}, err
|
||||
}
|
||||
|
||||
i, err := strconv.ParseInt(strings.Trim(line, "\n"), 10, 32)
|
||||
if err != nil {
|
||||
return []int64{}, err
|
||||
}
|
||||
ret = append(ret, i)
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Parse to int32 without error
|
||||
func mustParseInt32(val string) int32 {
|
||||
vv, _ := strconv.ParseInt(val, 10, 32)
|
||||
return int32(vv)
|
||||
}
|
||||
|
||||
// Parse to uint64 without error
|
||||
func mustParseUint64(val string) uint64 {
|
||||
vv, _ := strconv.ParseInt(val, 10, 64)
|
||||
return uint64(vv)
|
||||
}
|
||||
|
||||
// Parse to Float64 without error
|
||||
func mustParseFloat64(val string) float64 {
|
||||
vv, _ := strconv.ParseFloat(val, 64)
|
||||
return vv
|
||||
}
|
||||
|
||||
// StringsHas checks the target string slice contains src or not
|
||||
func StringsHas(target []string, src string) bool {
|
||||
for _, t := range target {
|
||||
if strings.TrimSpace(t) == src {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// StringsContains checks the src in any string of the target string slice
|
||||
func StringsContains(target []string, src string) bool {
|
||||
for _, t := range target {
|
||||
if strings.Contains(t, src) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IntContains checks the src in any int of the target int slice.
|
||||
func IntContains(target []int, src int) bool {
|
||||
for _, t := range target {
|
||||
if src == t {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// get struct attributes.
|
||||
// This method is used only for debugging platform dependent code.
|
||||
func attributes(m interface{}) map[string]reflect.Type {
|
||||
typ := reflect.TypeOf(m)
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
|
||||
attrs := make(map[string]reflect.Type)
|
||||
if typ.Kind() != reflect.Struct {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
p := typ.Field(i)
|
||||
if !p.Anonymous {
|
||||
attrs[p.Name] = p.Type
|
||||
}
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
func PathExists(filename string) bool {
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//GetEnv retrieves the environment variable key. If it does not exist it returns the default.
|
||||
func GetEnv(key string, dfault string, combineWith ...string) string {
|
||||
value := os.Getenv(key)
|
||||
if value == "" {
|
||||
value = dfault
|
||||
}
|
||||
|
||||
switch len(combineWith) {
|
||||
case 0:
|
||||
return value
|
||||
case 1:
|
||||
return filepath.Join(value, combineWith[0])
|
||||
default:
|
||||
all := make([]string, len(combineWith)+1)
|
||||
all[0] = value
|
||||
copy(all[1:], combineWith)
|
||||
return filepath.Join(all...)
|
||||
}
|
||||
panic("invalid switch case")
|
||||
}
|
||||
|
||||
func HostProc(combineWith ...string) string {
|
||||
return GetEnv("HOST_PROC", "/proc", combineWith...)
|
||||
}
|
||||
|
||||
func HostSys(combineWith ...string) string {
|
||||
return GetEnv("HOST_SYS", "/sys", combineWith...)
|
||||
}
|
||||
|
||||
func HostEtc(combineWith ...string) string {
|
||||
return GetEnv("HOST_ETC", "/etc", combineWith...)
|
||||
}
|
||||
|
||||
// CombinedOutputTimeout runs the given command with the given timeout and
|
||||
// returns the combined output of stdout and stderr.
|
||||
// If the command times out, it attempts to kill the process.
|
||||
// copied from https://github.com/influxdata/telegraf
|
||||
func CombinedOutputTimeout(c *exec.Cmd, timeout time.Duration) ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
c.Stdout = &b
|
||||
c.Stderr = &b
|
||||
if err := c.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err := WaitTimeout(c, timeout)
|
||||
return b.Bytes(), err
|
||||
}
|
||||
|
||||
// WaitTimeout waits for the given command to finish with a timeout.
|
||||
// It assumes the command has already been started.
|
||||
// If the command times out, it attempts to kill the process.
|
||||
// copied from https://github.com/influxdata/telegraf
|
||||
func WaitTimeout(c *exec.Cmd, timeout time.Duration) error {
|
||||
timer := time.NewTimer(timeout)
|
||||
done := make(chan error)
|
||||
go func() { done <- c.Wait() }()
|
||||
select {
|
||||
case err := <-done:
|
||||
timer.Stop()
|
||||
return err
|
||||
case <-timer.C:
|
||||
if err := c.Process.Kill(); err != nil {
|
||||
log.Printf("FATAL error killing process: %s", err)
|
||||
return err
|
||||
}
|
||||
// wait for the command to return after killing it
|
||||
<-done
|
||||
return ErrTimeout
|
||||
}
|
||||
}
|
||||
70
vendor/github.com/shirou/gopsutil/internal/common/common_darwin.go
generated
vendored
Normal file
70
vendor/github.com/shirou/gopsutil/internal/common/common_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// +build darwin
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
err := os.Setenv("LC_ALL", "C")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
sysctl, err := exec.LookPath("/usr/sbin/sysctl")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
out, err := exec.Command(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
|
||||
}
|
||||
70
vendor/github.com/shirou/gopsutil/internal/common/common_freebsd.go
generated
vendored
Normal file
70
vendor/github.com/shirou/gopsutil/internal/common/common_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// +build freebsd
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
err := os.Setenv("LC_ALL", "C")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
sysctl, err := exec.LookPath("/sbin/sysctl")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
out, err := exec.Command(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) {
|
||||
mibptr := unsafe.Pointer(&mib[0])
|
||||
miblen := uint64(len(mib))
|
||||
|
||||
// get required buffer size
|
||||
length := uint64(0)
|
||||
_, _, err := syscall.Syscall6(
|
||||
syscall.SYS___SYSCTL,
|
||||
uintptr(mibptr),
|
||||
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(mibptr),
|
||||
uintptr(miblen),
|
||||
uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(unsafe.Pointer(&length)),
|
||||
0,
|
||||
0)
|
||||
if err != 0 {
|
||||
return buf, length, err
|
||||
}
|
||||
|
||||
return buf, length, nil
|
||||
}
|
||||
43
vendor/github.com/shirou/gopsutil/internal/common/common_linux.go
generated
vendored
Normal file
43
vendor/github.com/shirou/gopsutil/internal/common/common_linux.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// +build linux
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
err := os.Setenv("LC_ALL", "C")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
sysctl, err := exec.LookPath("/sbin/sysctl")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
out, err := exec.Command(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 NumProcs() (uint64, error) {
|
||||
f, err := os.Open(HostProc())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
list, err := f.Readdir(-1)
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(len(list)), err
|
||||
}
|
||||
97
vendor/github.com/shirou/gopsutil/internal/common/common_test.go
generated
vendored
Normal file
97
vendor/github.com/shirou/gopsutil/internal/common/common_test.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadlines(t *testing.T) {
|
||||
ret, err := ReadLines("common_test.go")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !strings.Contains(ret[0], "package common") {
|
||||
t.Error("could not read correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadLinesOffsetN(t *testing.T) {
|
||||
ret, err := ReadLinesOffsetN("common_test.go", 2, 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
fmt.Println(ret[0])
|
||||
if !strings.Contains(ret[0], `import (`) {
|
||||
t.Error("could not read correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntToString(t *testing.T) {
|
||||
src := []int8{65, 66, 67}
|
||||
dst := IntToString(src)
|
||||
if dst != "ABC" {
|
||||
t.Error("could not convert")
|
||||
}
|
||||
}
|
||||
func TestByteToString(t *testing.T) {
|
||||
src := []byte{65, 66, 67}
|
||||
dst := ByteToString(src)
|
||||
if dst != "ABC" {
|
||||
t.Error("could not convert")
|
||||
}
|
||||
|
||||
src = []byte{0, 65, 66, 67}
|
||||
dst = ByteToString(src)
|
||||
if dst != "ABC" {
|
||||
t.Error("could not convert")
|
||||
}
|
||||
}
|
||||
|
||||
func TestmustParseInt32(t *testing.T) {
|
||||
ret := mustParseInt32("11111")
|
||||
if ret != int32(11111) {
|
||||
t.Error("could not parse")
|
||||
}
|
||||
}
|
||||
func TestmustParseUint64(t *testing.T) {
|
||||
ret := mustParseUint64("11111")
|
||||
if ret != uint64(11111) {
|
||||
t.Error("could not parse")
|
||||
}
|
||||
}
|
||||
func TestmustParseFloat64(t *testing.T) {
|
||||
ret := mustParseFloat64("11111.11")
|
||||
if ret != float64(11111.11) {
|
||||
t.Error("could not parse")
|
||||
}
|
||||
ret = mustParseFloat64("11111")
|
||||
if ret != float64(11111) {
|
||||
t.Error("could not parse")
|
||||
}
|
||||
}
|
||||
func TestStringsContains(t *testing.T) {
|
||||
target, err := ReadLines("common_test.go")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !StringsContains(target, "func TestStringsContains(t *testing.T) {") {
|
||||
t.Error("cloud not test correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathExists(t *testing.T) {
|
||||
if !PathExists("common_test.go") {
|
||||
t.Error("exists but return not exists")
|
||||
}
|
||||
if PathExists("should_not_exists.go") {
|
||||
t.Error("not exists but return exists")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostEtc(t *testing.T) {
|
||||
p := HostEtc("mtab")
|
||||
if p != "/etc/mtab" {
|
||||
t.Errorf("invalid HostEtc, %s", p)
|
||||
}
|
||||
}
|
||||
66
vendor/github.com/shirou/gopsutil/internal/common/common_unix.go
generated
vendored
Normal file
66
vendor/github.com/shirou/gopsutil/internal/common/common_unix.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// +build linux freebsd darwin
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) {
|
||||
var cmd []string
|
||||
if pid == 0 { // will get from all processes.
|
||||
cmd = []string{"-a", "-n", "-P"}
|
||||
} else {
|
||||
cmd = []string{"-a", "-n", "-P", "-p", strconv.Itoa(int(pid))}
|
||||
}
|
||||
cmd = append(cmd, args...)
|
||||
lsof, err := exec.LookPath("lsof")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
out, err := invoke.Command(lsof, cmd...)
|
||||
if err != nil {
|
||||
// if no pid found, lsof returnes code 1.
|
||||
if err.Error() == "exit status 1" && len(out) == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
|
||||
var ret []string
|
||||
for _, l := range lines[1:] {
|
||||
if len(l) == 0 {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, l)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func CallPgrep(invoke Invoker, pid int32) ([]int32, error) {
|
||||
var cmd []string
|
||||
cmd = []string{"-P", strconv.Itoa(int(pid))}
|
||||
pgrep, err := exec.LookPath("pgrep")
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
}
|
||||
out, err := invoke.Command(pgrep, cmd...)
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
ret := make([]int32, 0, len(lines))
|
||||
for _, l := range lines {
|
||||
if len(l) == 0 {
|
||||
continue
|
||||
}
|
||||
i, err := strconv.Atoi(l)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, int32(i))
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
110
vendor/github.com/shirou/gopsutil/internal/common/common_windows.go
generated
vendored
Normal file
110
vendor/github.com/shirou/gopsutil/internal/common/common_windows.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
// +build windows
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// for double values
|
||||
type PDH_FMT_COUNTERVALUE_DOUBLE struct {
|
||||
CStatus uint32
|
||||
DoubleValue float64
|
||||
}
|
||||
|
||||
// for 64 bit integer values
|
||||
type PDH_FMT_COUNTERVALUE_LARGE struct {
|
||||
CStatus uint32
|
||||
LargeValue int64
|
||||
}
|
||||
|
||||
// for long values
|
||||
type PDH_FMT_COUNTERVALUE_LONG struct {
|
||||
CStatus uint32
|
||||
LongValue int32
|
||||
padding [4]byte
|
||||
}
|
||||
|
||||
// windows system const
|
||||
const (
|
||||
ERROR_SUCCESS = 0
|
||||
ERROR_FILE_NOT_FOUND = 2
|
||||
DRIVE_REMOVABLE = 2
|
||||
DRIVE_FIXED = 3
|
||||
HKEY_LOCAL_MACHINE = 0x80000002
|
||||
RRF_RT_REG_SZ = 0x00000002
|
||||
RRF_RT_REG_DWORD = 0x00000010
|
||||
PDH_FMT_LONG = 0x00000100
|
||||
PDH_FMT_DOUBLE = 0x00000200
|
||||
PDH_FMT_LARGE = 0x00000400
|
||||
PDH_INVALID_DATA = 0xc0000bc6
|
||||
PDH_INVALID_HANDLE = 0xC0000bbc
|
||||
PDH_NO_DATA = 0x800007d5
|
||||
)
|
||||
|
||||
var (
|
||||
Modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
ModNt = syscall.NewLazyDLL("ntdll.dll")
|
||||
ModPdh = syscall.NewLazyDLL("pdh.dll")
|
||||
|
||||
ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes")
|
||||
ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation")
|
||||
PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery")
|
||||
PdhAddCounter = ModPdh.NewProc("PdhAddCounterW")
|
||||
PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
|
||||
PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
|
||||
PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
|
||||
)
|
||||
|
||||
type FILETIME struct {
|
||||
DwLowDateTime uint32
|
||||
DwHighDateTime uint32
|
||||
}
|
||||
|
||||
// borrowed from net/interface_windows.go
|
||||
func BytePtrToString(p *uint8) string {
|
||||
a := (*[10000]uint8)(unsafe.Pointer(p))
|
||||
i := 0
|
||||
for a[i] != 0 {
|
||||
i++
|
||||
}
|
||||
return string(a[:i])
|
||||
}
|
||||
|
||||
// CounterInfo
|
||||
// copied from https://github.com/mackerelio/mackerel-agent/
|
||||
type CounterInfo struct {
|
||||
PostName string
|
||||
CounterName string
|
||||
Counter syscall.Handle
|
||||
}
|
||||
|
||||
// CreateQuery XXX
|
||||
// copied from https://github.com/mackerelio/mackerel-agent/
|
||||
func CreateQuery() (syscall.Handle, error) {
|
||||
var query syscall.Handle
|
||||
r, _, err := PdhOpenQuery.Call(0, 0, uintptr(unsafe.Pointer(&query)))
|
||||
if r != 0 {
|
||||
return 0, err
|
||||
}
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// CreateCounter XXX
|
||||
func CreateCounter(query syscall.Handle, pname, cname string) (*CounterInfo, error) {
|
||||
var counter syscall.Handle
|
||||
r, _, err := PdhAddCounter.Call(
|
||||
uintptr(query),
|
||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(cname))),
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&counter)))
|
||||
if r != 0 {
|
||||
return nil, err
|
||||
}
|
||||
return &CounterInfo{
|
||||
PostName: pname,
|
||||
CounterName: cname,
|
||||
Counter: counter,
|
||||
}, nil
|
||||
}
|
||||
35
vendor/github.com/shirou/gopsutil/load/load.go
generated
vendored
Normal file
35
vendor/github.com/shirou/gopsutil/load/load.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
package load
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
|
||||
type AvgStat struct {
|
||||
Load1 float64 `json:"load1"`
|
||||
Load5 float64 `json:"load5"`
|
||||
Load15 float64 `json:"load15"`
|
||||
}
|
||||
|
||||
func (l AvgStat) String() string {
|
||||
s, _ := json.Marshal(l)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
type MiscStat struct {
|
||||
ProcsRunning int `json:"procsRunning"`
|
||||
ProcsBlocked int `json:"procsBlocked"`
|
||||
Ctxt int `json:"ctxt"`
|
||||
}
|
||||
|
||||
func (m MiscStat) String() string {
|
||||
s, _ := json.Marshal(m)
|
||||
return string(s)
|
||||
}
|
||||
67
vendor/github.com/shirou/gopsutil/load/load_darwin.go
generated
vendored
Normal file
67
vendor/github.com/shirou/gopsutil/load/load_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// +build darwin
|
||||
|
||||
package load
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func Avg() (*AvgStat, 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 := &AvgStat{
|
||||
Load1: float64(load1),
|
||||
Load5: float64(load5),
|
||||
Load15: float64(load15),
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Misc returnes miscellaneous host-wide statistics.
|
||||
// darwin use ps command to get process running/blocked count.
|
||||
// Almost same as FreeBSD implementation, but state is different.
|
||||
// U means 'Uninterruptible Sleep'.
|
||||
func Misc() (*MiscStat, error) {
|
||||
bin, err := exec.LookPath("ps")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := invoke.Command(bin, "axo", "state")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
|
||||
ret := MiscStat{}
|
||||
for _, l := range lines {
|
||||
if strings.Contains(l, "R") {
|
||||
ret.ProcsRunning++
|
||||
} else if strings.Contains(l, "U") {
|
||||
// uninterruptible sleep == blocked
|
||||
ret.ProcsBlocked++
|
||||
}
|
||||
}
|
||||
|
||||
return &ret, nil
|
||||
}
|
||||
65
vendor/github.com/shirou/gopsutil/load/load_freebsd.go
generated
vendored
Normal file
65
vendor/github.com/shirou/gopsutil/load/load_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// +build freebsd
|
||||
|
||||
package load
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func Avg() (*AvgStat, 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 := &AvgStat{
|
||||
Load1: float64(load1),
|
||||
Load5: float64(load5),
|
||||
Load15: float64(load15),
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Misc returnes miscellaneous host-wide statistics.
|
||||
// darwin use ps command to get process running/blocked count.
|
||||
// Almost same as Darwin implementation, but state is different.
|
||||
func Misc() (*MiscStat, error) {
|
||||
bin, err := exec.LookPath("ps")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := invoke.Command(bin, "axo", "state")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
|
||||
ret := MiscStat{}
|
||||
for _, l := range lines {
|
||||
if strings.Contains(l, "R") {
|
||||
ret.ProcsRunning++
|
||||
} else if strings.Contains(l, "D") {
|
||||
ret.ProcsBlocked++
|
||||
}
|
||||
}
|
||||
|
||||
return &ret, nil
|
||||
}
|
||||
78
vendor/github.com/shirou/gopsutil/load/load_linux.go
generated
vendored
Normal file
78
vendor/github.com/shirou/gopsutil/load/load_linux.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// +build linux
|
||||
|
||||
package load
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func Avg() (*AvgStat, error) {
|
||||
filename := common.HostProc("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 := &AvgStat{
|
||||
Load1: load1,
|
||||
Load5: load5,
|
||||
Load15: load15,
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Misc returnes miscellaneous host-wide statistics.
|
||||
// Note: the name should be changed near future.
|
||||
func Misc() (*MiscStat, error) {
|
||||
filename := common.HostProc("stat")
|
||||
out, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &MiscStat{}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) != 2 {
|
||||
continue
|
||||
}
|
||||
v, err := strconv.ParseInt(fields[1], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
switch fields[0] {
|
||||
case "procs_running":
|
||||
ret.ProcsRunning = int(v)
|
||||
case "procs_blocked":
|
||||
ret.ProcsBlocked = int(v)
|
||||
case "ctxt":
|
||||
ret.Ctxt = int(v)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
54
vendor/github.com/shirou/gopsutil/load/load_test.go
generated
vendored
Normal file
54
vendor/github.com/shirou/gopsutil/load/load_test.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
package load
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
v, err := Avg()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
|
||||
empty := &AvgStat{}
|
||||
if v == empty {
|
||||
t.Errorf("error load: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadAvgStat_String(t *testing.T) {
|
||||
v := AvgStat{
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMisc(t *testing.T) {
|
||||
v, err := Misc()
|
||||
if err != nil {
|
||||
t.Errorf("error %v", err)
|
||||
}
|
||||
|
||||
empty := &MiscStat{}
|
||||
if v == empty {
|
||||
t.Errorf("error load: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMiscStatString(t *testing.T) {
|
||||
v := MiscStat{
|
||||
ProcsRunning: 1,
|
||||
ProcsBlocked: 2,
|
||||
Ctxt: 3,
|
||||
}
|
||||
e := `{"procsRunning":1,"procsBlocked":2,"ctxt":3}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("TestMiscString string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
19
vendor/github.com/shirou/gopsutil/load/load_windows.go
generated
vendored
Normal file
19
vendor/github.com/shirou/gopsutil/load/load_windows.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// +build windows
|
||||
|
||||
package load
|
||||
|
||||
import (
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func Avg() (*AvgStat, error) {
|
||||
ret := AvgStat{}
|
||||
|
||||
return &ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func Misc() (*MiscStat, error) {
|
||||
ret := MiscStat{}
|
||||
|
||||
return &ret, common.ErrNotImplementedError
|
||||
}
|
||||
76
vendor/github.com/shirou/gopsutil/mem/mem.go
generated
vendored
Normal file
76
vendor/github.com/shirou/gopsutil/mem/mem.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package mem
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
|
||||
// Memory usage statistics. Total, Available and Used contain numbers of bytes
|
||||
// for human consumption.
|
||||
//
|
||||
// The other fields in this struct contain kernel specific values.
|
||||
type VirtualMemoryStat struct {
|
||||
// Total amount of RAM on this system
|
||||
Total uint64 `json:"total"`
|
||||
|
||||
// RAM available for programs to allocate
|
||||
//
|
||||
// This value is computed from the kernel specific values.
|
||||
Available uint64 `json:"available"`
|
||||
|
||||
// RAM used by programs
|
||||
//
|
||||
// This value is computed from the kernel specific values.
|
||||
Used uint64 `json:"used"`
|
||||
|
||||
// Percentage of RAM used by programs
|
||||
//
|
||||
// This value is computed from the kernel specific values.
|
||||
UsedPercent float64 `json:"usedPercent"`
|
||||
|
||||
// This is the kernel's notion of free memory; RAM chips whose bits nobody
|
||||
// cares about the value of right now. For a human consumable number,
|
||||
// Available is what you really want.
|
||||
Free uint64 `json:"free"`
|
||||
|
||||
// OS X / BSD specific numbers:
|
||||
// http://www.macyourself.com/2010/02/17/what-is-free-wired-active-and-inactive-system-memory-ram/
|
||||
Active uint64 `json:"active"`
|
||||
Inactive uint64 `json:"inactive"`
|
||||
Wired uint64 `json:"wired"`
|
||||
|
||||
// Linux specific numbers
|
||||
// https://www.centos.org/docs/5/html/5.1/Deployment_Guide/s2-proc-meminfo.html
|
||||
// https://www.kernel.org/doc/Documentation/filesystems/proc.txt
|
||||
Buffers uint64 `json:"buffers"`
|
||||
Cached uint64 `json:"cached"`
|
||||
Writeback uint64 `json:"writeback"`
|
||||
Dirty uint64 `json:"dirty"`
|
||||
WritebackTmp uint64 `json:"writebacktmp"`
|
||||
}
|
||||
|
||||
type SwapMemoryStat struct {
|
||||
Total uint64 `json:"total"`
|
||||
Used uint64 `json:"used"`
|
||||
Free uint64 `json:"free"`
|
||||
UsedPercent float64 `json:"usedPercent"`
|
||||
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)
|
||||
}
|
||||
69
vendor/github.com/shirou/gopsutil/mem/mem_darwin.go
generated
vendored
Normal file
69
vendor/github.com/shirou/gopsutil/mem/mem_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// +build darwin
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func getHwMemsize() (uint64, error) {
|
||||
totalString, err := syscall.Sysctl("hw.memsize")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// syscall.sysctl() helpfully assumes the result is a null-terminated string and
|
||||
// removes the last byte of the result if it's 0 :/
|
||||
totalString += "\x00"
|
||||
|
||||
total := uint64(binary.LittleEndian.Uint64([]byte(totalString)))
|
||||
|
||||
return total, 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
|
||||
}
|
||||
53
vendor/github.com/shirou/gopsutil/mem/mem_darwin_cgo.go
generated
vendored
Normal file
53
vendor/github.com/shirou/gopsutil/mem/mem_darwin_cgo.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// +build darwin
|
||||
// +build cgo
|
||||
|
||||
package mem
|
||||
|
||||
/*
|
||||
#include <mach/mach_host.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// VirtualMemory returns VirtualmemoryStat.
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
count := C.mach_msg_type_number_t(C.HOST_VM_INFO_COUNT)
|
||||
var vmstat C.vm_statistics_data_t
|
||||
|
||||
status := C.host_statistics(C.host_t(C.mach_host_self()),
|
||||
C.HOST_VM_INFO,
|
||||
C.host_info_t(unsafe.Pointer(&vmstat)),
|
||||
&count)
|
||||
|
||||
if status != C.KERN_SUCCESS {
|
||||
return nil, fmt.Errorf("host_statistics error=%d", status)
|
||||
}
|
||||
|
||||
pageSize := uint64(syscall.Getpagesize())
|
||||
total, err := getHwMemsize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
totalCount := C.natural_t(total / pageSize)
|
||||
|
||||
availableCount := vmstat.inactive_count + vmstat.free_count
|
||||
usedPercent := 100 * float64(totalCount-availableCount) / float64(totalCount)
|
||||
|
||||
usedCount := totalCount - availableCount
|
||||
|
||||
return &VirtualMemoryStat{
|
||||
Total: total,
|
||||
Available: pageSize * uint64(availableCount),
|
||||
Used: pageSize * uint64(usedCount),
|
||||
UsedPercent: usedPercent,
|
||||
Free: pageSize * uint64(vmstat.free_count),
|
||||
Active: pageSize * uint64(vmstat.active_count),
|
||||
Inactive: pageSize * uint64(vmstat.inactive_count),
|
||||
Wired: pageSize * uint64(vmstat.wire_count),
|
||||
}, nil
|
||||
}
|
||||
88
vendor/github.com/shirou/gopsutil/mem/mem_darwin_nocgo.go
generated
vendored
Normal file
88
vendor/github.com/shirou/gopsutil/mem/mem_darwin_nocgo.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// +build darwin
|
||||
// +build !cgo
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Runs vm_stat and returns Free and inactive pages
|
||||
func getVMStat(vms *VirtualMemoryStat) error {
|
||||
vm_stat, err := exec.LookPath("vm_stat")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out, err := invoke.Command(vm_stat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return parseVMStat(string(out), vms)
|
||||
}
|
||||
|
||||
func parseVMStat(out string, vms *VirtualMemoryStat) error {
|
||||
var err error
|
||||
|
||||
lines := strings.Split(out, "\n")
|
||||
pagesize := uint64(syscall.Getpagesize())
|
||||
for _, line := range lines {
|
||||
fields := strings.Split(line, ":")
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(fields[0])
|
||||
value := strings.Trim(fields[1], " .")
|
||||
switch key {
|
||||
case "Pages free":
|
||||
free, e := strconv.ParseUint(value, 10, 64)
|
||||
if e != nil {
|
||||
err = e
|
||||
}
|
||||
vms.Free = free * pagesize
|
||||
case "Pages inactive":
|
||||
inactive, e := strconv.ParseUint(value, 10, 64)
|
||||
if e != nil {
|
||||
err = e
|
||||
}
|
||||
vms.Inactive = inactive * pagesize
|
||||
case "Pages active":
|
||||
active, e := strconv.ParseUint(value, 10, 64)
|
||||
if e != nil {
|
||||
err = e
|
||||
}
|
||||
vms.Active = active * pagesize
|
||||
case "Pages wired down":
|
||||
wired, e := strconv.ParseUint(value, 10, 64)
|
||||
if e != nil {
|
||||
err = e
|
||||
}
|
||||
vms.Wired = wired * pagesize
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// VirtualMemory returns VirtualmemoryStat.
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
ret := &VirtualMemoryStat{}
|
||||
|
||||
total, err := getHwMemsize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = getVMStat(ret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret.Available = ret.Free + ret.Inactive
|
||||
ret.Total = total
|
||||
|
||||
ret.Used = ret.Total - ret.Available
|
||||
ret.UsedPercent = 100 * float64(ret.Used) / float64(ret.Total)
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
46
vendor/github.com/shirou/gopsutil/mem/mem_darwin_test.go
generated
vendored
Normal file
46
vendor/github.com/shirou/gopsutil/mem/mem_darwin_test.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// +build darwin
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestVirtualMemoryDarwin(t *testing.T) {
|
||||
v, err := VirtualMemory()
|
||||
assert.Nil(t, err)
|
||||
|
||||
outBytes, err := invoke.Command("/usr/sbin/sysctl", "hw.memsize")
|
||||
assert.Nil(t, err)
|
||||
outString := string(outBytes)
|
||||
outString = strings.TrimSpace(outString)
|
||||
outParts := strings.Split(outString, " ")
|
||||
actualTotal, err := strconv.ParseInt(outParts[1], 10, 64)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, uint64(actualTotal), v.Total)
|
||||
|
||||
assert.True(t, v.Available > 0)
|
||||
assert.Equal(t, v.Available, v.Free+v.Inactive, "%v", v)
|
||||
|
||||
assert.True(t, v.Used > 0)
|
||||
assert.True(t, v.Used < v.Total)
|
||||
|
||||
assert.True(t, v.UsedPercent > 0)
|
||||
assert.True(t, v.UsedPercent < 100)
|
||||
|
||||
assert.True(t, v.Free > 0)
|
||||
assert.True(t, v.Free < v.Available)
|
||||
|
||||
assert.True(t, v.Active > 0)
|
||||
assert.True(t, v.Active < v.Total)
|
||||
|
||||
assert.True(t, v.Inactive > 0)
|
||||
assert.True(t, v.Inactive < v.Total)
|
||||
|
||||
assert.True(t, v.Wired > 0)
|
||||
assert.True(t, v.Wired < v.Total)
|
||||
}
|
||||
134
vendor/github.com/shirou/gopsutil/mem/mem_freebsd.go
generated
vendored
Normal file
134
vendor/github.com/shirou/gopsutil/mem/mem_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
// +build freebsd
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/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,
|
||||
}
|
||||
|
||||
ret.Available = ret.Inactive + ret.Cached + ret.Free
|
||||
ret.Used = ret.Total - ret.Available
|
||||
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) {
|
||||
swapinfo, err := exec.LookPath("swapinfo")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := invoke.Command(swapinfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
return &SwapMemoryStat{
|
||||
Total: total_v,
|
||||
Used: used_v,
|
||||
Free: free_v,
|
||||
UsedPercent: up_v,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("no swap devices found")
|
||||
}
|
||||
106
vendor/github.com/shirou/gopsutil/mem/mem_linux.go
generated
vendored
Normal file
106
vendor/github.com/shirou/gopsutil/mem/mem_linux.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
// +build linux
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
filename := common.HostProc("meminfo")
|
||||
lines, _ := common.ReadLines(filename)
|
||||
// flag if MemAvailable is in /proc/meminfo (kernel 3.14+)
|
||||
memavail := false
|
||||
|
||||
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 "MemAvailable":
|
||||
memavail = true
|
||||
ret.Available = 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
|
||||
case "Writeback":
|
||||
ret.Writeback = t * 1024
|
||||
case "WritebackTmp":
|
||||
ret.WritebackTmp = t * 1024
|
||||
case "Dirty":
|
||||
ret.Dirty = t * 1024
|
||||
}
|
||||
}
|
||||
if !memavail {
|
||||
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
||||
}
|
||||
ret.Used = ret.Total - ret.Available
|
||||
ret.UsedPercent = float64(ret.Total-ret.Available) / 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.Total-ret.Free) / float64(ret.Total) * 100.0
|
||||
} else {
|
||||
ret.UsedPercent = 0
|
||||
}
|
||||
filename := common.HostProc("vmstat")
|
||||
lines, _ := common.ReadLines(filename)
|
||||
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
|
||||
}
|
||||
72
vendor/github.com/shirou/gopsutil/mem/mem_test.go
generated
vendored
Normal file
72
vendor/github.com/shirou/gopsutil/mem/mem_test.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package mem
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
assert.True(t, v.Total > 0)
|
||||
assert.True(t, v.Available > 0)
|
||||
assert.True(t, v.Used > 0)
|
||||
|
||||
assert.Equal(t, v.Total, v.Available+v.Used,
|
||||
"Total should be computable from available + used: %v", v)
|
||||
|
||||
assert.True(t, v.Free > 0)
|
||||
assert.True(t, v.Available > v.Free,
|
||||
"Free should be a subset of Available: %v", v)
|
||||
|
||||
assert.InDelta(t, v.UsedPercent,
|
||||
100*float64(v.Used)/float64(v.Total), 0.1,
|
||||
"UsedPercent should be how many percent of Total is Used: %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,"usedPercent":30.1,"free":40,"active":0,"inactive":0,"wired":0,"buffers":0,"cached":0,"writeback":0,"dirty":0,"writebacktmp":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,"usedPercent":30.1,"sin":0,"sout":0}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("SwapMemoryStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
50
vendor/github.com/shirou/gopsutil/mem/mem_windows.go
generated
vendored
Normal file
50
vendor/github.com/shirou/gopsutil/mem/mem_windows.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// +build windows
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/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
|
||||
}
|
||||
37
vendor/github.com/shirou/gopsutil/mktypes.sh
generated
vendored
Normal file
37
vendor/github.com/shirou/gopsutil/mktypes.sh
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
DIRS="cpu disk docker host load mem net process"
|
||||
|
||||
GOOS=`uname | tr '[:upper:]' '[:lower:]'`
|
||||
ARCH=`uname -m`
|
||||
|
||||
case $ARCH in
|
||||
amd64)
|
||||
GOARCH="amd64"
|
||||
;;
|
||||
x86_64)
|
||||
GOARCH="amd64"
|
||||
;;
|
||||
i386)
|
||||
GOARCH="386"
|
||||
;;
|
||||
i686)
|
||||
GOARCH="386"
|
||||
;;
|
||||
arm)
|
||||
GOARCH="arm"
|
||||
;;
|
||||
*)
|
||||
echo "unknown arch: $ARCH"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
for DIR in $DIRS
|
||||
do
|
||||
if [ -e ${DIR}/types_${GOOS}.go ]; then
|
||||
echo "// +build $GOOS" > ${DIR}/${DIR}_${GOOS}_${GOARCH}.go
|
||||
echo "// +build $GOARCH" >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go
|
||||
go tool cgo -godefs ${DIR}/types_${GOOS}.go >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
246
vendor/github.com/shirou/gopsutil/net/net.go
generated
vendored
Normal file
246
vendor/github.com/shirou/gopsutil/net/net.go
generated
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
|
||||
type IOCountersStat struct {
|
||||
Name string `json:"name"` // interface name
|
||||
BytesSent uint64 `json:"bytesSent"` // number of bytes sent
|
||||
BytesRecv uint64 `json:"bytesRecv"` // number of bytes received
|
||||
PacketsSent uint64 `json:"packetsSent"` // number of packets sent
|
||||
PacketsRecv uint64 `json:"packetsRecv"` // 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)
|
||||
Fifoin uint64 `json:"fifoin"` // total number of FIFO buffers errors while receiving
|
||||
Fifoout uint64 `json:"fifoout"` // total number of FIFO buffers errors while sending
|
||||
|
||||
}
|
||||
|
||||
// Addr is implemented compatibility to psutil
|
||||
type Addr struct {
|
||||
IP string `json:"ip"`
|
||||
Port uint32 `json:"port"`
|
||||
}
|
||||
|
||||
type ConnectionStat 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"`
|
||||
}
|
||||
|
||||
// System wide stats about different network protocols
|
||||
type ProtoCountersStat struct {
|
||||
Protocol string `json:"protocol"`
|
||||
Stats map[string]int64 `json:"stats"`
|
||||
}
|
||||
|
||||
// NetInterfaceAddr is designed for represent interface addresses
|
||||
type InterfaceAddr struct {
|
||||
Addr string `json:"addr"`
|
||||
}
|
||||
|
||||
type InterfaceStat 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 []InterfaceAddr `json:"addrs"`
|
||||
}
|
||||
|
||||
type FilterStat struct {
|
||||
ConnTrackCount int64 `json:"conntrackCount"`
|
||||
ConnTrackMax int64 `json:"conntrackMax"`
|
||||
}
|
||||
|
||||
var constMap = map[string]int{
|
||||
"TCP": syscall.SOCK_STREAM,
|
||||
"UDP": syscall.SOCK_DGRAM,
|
||||
"IPv4": syscall.AF_INET,
|
||||
"IPv6": syscall.AF_INET6,
|
||||
}
|
||||
|
||||
func (n IOCountersStat) String() string {
|
||||
s, _ := json.Marshal(n)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (n ConnectionStat) String() string {
|
||||
s, _ := json.Marshal(n)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (n ProtoCountersStat) String() string {
|
||||
s, _ := json.Marshal(n)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (a Addr) String() string {
|
||||
s, _ := json.Marshal(a)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (n InterfaceStat) String() string {
|
||||
s, _ := json.Marshal(n)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (n InterfaceAddr) String() string {
|
||||
s, _ := json.Marshal(n)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func Interfaces() ([]InterfaceStat, error) {
|
||||
is, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make([]InterfaceStat, 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 := InterfaceStat{
|
||||
Name: ifi.Name,
|
||||
MTU: ifi.MTU,
|
||||
HardwareAddr: ifi.HardwareAddr.String(),
|
||||
Flags: flags,
|
||||
}
|
||||
addrs, err := ifi.Addrs()
|
||||
if err == nil {
|
||||
r.Addrs = make([]InterfaceAddr, 0, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
r.Addrs = append(r.Addrs, InterfaceAddr{
|
||||
Addr: addr.String(),
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
ret = append(ret, r)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func getIOCountersAll(n []IOCountersStat) ([]IOCountersStat, error) {
|
||||
r := IOCountersStat{
|
||||
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 []IOCountersStat{r}, nil
|
||||
}
|
||||
|
||||
func parseNetLine(line string) (ConnectionStat, error) {
|
||||
f := strings.Fields(line)
|
||||
if len(f) < 9 {
|
||||
return ConnectionStat{}, fmt.Errorf("wrong line,%s", line)
|
||||
}
|
||||
|
||||
pid, err := strconv.Atoi(f[1])
|
||||
if err != nil {
|
||||
return ConnectionStat{}, err
|
||||
}
|
||||
fd, err := strconv.Atoi(strings.Trim(f[3], "u"))
|
||||
if err != nil {
|
||||
return ConnectionStat{}, fmt.Errorf("unknown fd, %s", f[3])
|
||||
}
|
||||
netFamily, ok := constMap[f[4]]
|
||||
if !ok {
|
||||
return ConnectionStat{}, fmt.Errorf("unknown family, %s", f[4])
|
||||
}
|
||||
netType, ok := constMap[f[7]]
|
||||
if !ok {
|
||||
return ConnectionStat{}, fmt.Errorf("unknown type, %s", f[7])
|
||||
}
|
||||
|
||||
laddr, raddr, err := parseNetAddr(f[8])
|
||||
if err != nil {
|
||||
return ConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s", f[8])
|
||||
}
|
||||
|
||||
n := ConnectionStat{
|
||||
Fd: uint32(fd),
|
||||
Family: uint32(netFamily),
|
||||
Type: uint32(netType),
|
||||
Laddr: laddr,
|
||||
Raddr: raddr,
|
||||
Pid: int32(pid),
|
||||
}
|
||||
if len(f) == 10 {
|
||||
n.Status = strings.Trim(f[9], "()")
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func parseNetAddr(line string) (laddr Addr, raddr Addr, err error) {
|
||||
parse := func(l string) (Addr, error) {
|
||||
host, port, err := net.SplitHostPort(l)
|
||||
if err != nil {
|
||||
return Addr{}, fmt.Errorf("wrong addr, %s", l)
|
||||
}
|
||||
lport, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
return Addr{}, err
|
||||
}
|
||||
return Addr{IP: host, Port: uint32(lport)}, nil
|
||||
}
|
||||
|
||||
addrs := strings.Split(line, "->")
|
||||
if len(addrs) == 0 {
|
||||
return laddr, raddr, fmt.Errorf("wrong netaddr, %s", line)
|
||||
}
|
||||
laddr, err = parse(addrs[0])
|
||||
if len(addrs) == 2 { // remote addr exists
|
||||
raddr, err = parse(addrs[1])
|
||||
if err != nil {
|
||||
return laddr, raddr, err
|
||||
}
|
||||
}
|
||||
|
||||
return laddr, raddr, err
|
||||
}
|
||||
114
vendor/github.com/shirou/gopsutil/net/net_darwin.go
generated
vendored
Normal file
114
vendor/github.com/shirou/gopsutil/net/net_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
// +build darwin
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
// example of netstat -idbn output on yosemite
|
||||
// Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Drop
|
||||
// lo0 16384 <Link#1> 869107 0 169411755 869107 0 169411755 0 0
|
||||
// lo0 16384 ::1/128 ::1 869107 - 169411755 869107 - 169411755 - -
|
||||
// lo0 16384 127 127.0.0.1 869107 - 169411755 869107 - 169411755 - -
|
||||
func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
||||
netstat, err := exec.LookPath("/usr/sbin/netstat")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := invoke.Command(netstat, "-ibdnW")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(out), "\n")
|
||||
ret := make([]IOCountersStat, 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.StringsHas(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, 7)
|
||||
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
|
||||
}
|
||||
if len(values) == 12 {
|
||||
vv = append(vv, values[base+10])
|
||||
}
|
||||
|
||||
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 := IOCountersStat{
|
||||
Name: values[0],
|
||||
PacketsRecv: parsed[0],
|
||||
Errin: parsed[1],
|
||||
BytesRecv: parsed[2],
|
||||
PacketsSent: parsed[3],
|
||||
Errout: parsed[4],
|
||||
BytesSent: parsed[5],
|
||||
}
|
||||
if len(parsed) == 7 {
|
||||
n.Dropout = parsed[6]
|
||||
}
|
||||
ret = append(ret, n)
|
||||
}
|
||||
|
||||
if pernic == false {
|
||||
return getIOCountersAll(ret)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCounters(pernic)
|
||||
}
|
||||
|
||||
func FilterCounters() ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for darwin")
|
||||
}
|
||||
|
||||
// NetProtoCounters returns network statistics for the entire system
|
||||
// If protocols is empty then all protocols are returned, otherwise
|
||||
// just the protocols in the list are returned.
|
||||
// Not Implemented for Darwin
|
||||
func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
||||
return nil, errors.New("NetProtoCounters not implemented for darwin")
|
||||
}
|
||||
108
vendor/github.com/shirou/gopsutil/net/net_freebsd.go
generated
vendored
Normal file
108
vendor/github.com/shirou/gopsutil/net/net_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
// +build freebsd
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
||||
netstat, err := exec.LookPath("/usr/bin/netstat")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := invoke.Command(netstat, "-ibdnW")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(out), "\n")
|
||||
ret := make([]IOCountersStat, 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.StringsHas(exists, values[0]) {
|
||||
// skip if already get
|
||||
continue
|
||||
}
|
||||
exists = append(exists, values[0])
|
||||
|
||||
if len(values) < 12 {
|
||||
continue
|
||||
}
|
||||
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 := IOCountersStat{
|
||||
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 getIOCountersAll(ret)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCounters(pernic)
|
||||
}
|
||||
|
||||
func FilterCounters() ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for freebsd")
|
||||
}
|
||||
|
||||
// NetProtoCounters returns network statistics for the entire system
|
||||
// If protocols is empty then all protocols are returned, otherwise
|
||||
// just the protocols in the list are returned.
|
||||
// Not Implemented for FreeBSD
|
||||
func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
||||
return nil, errors.New("NetProtoCounters not implemented for freebsd")
|
||||
}
|
||||
630
vendor/github.com/shirou/gopsutil/net/net_linux.go
generated
vendored
Normal file
630
vendor/github.com/shirou/gopsutil/net/net_linux.go
generated
vendored
Normal file
@@ -0,0 +1,630 @@
|
||||
// +build linux
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/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 IOCounters(pernic bool) ([]IOCountersStat, error) {
|
||||
filename := common.HostProc("net/dev")
|
||||
return IOCountersByFile(pernic, filename)
|
||||
}
|
||||
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
statlen := len(lines) - 1
|
||||
|
||||
ret := make([]IOCountersStat, 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
|
||||
}
|
||||
fifoIn, err := strconv.ParseUint(fields[4], 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
|
||||
}
|
||||
fifoOut, err := strconv.ParseUint(fields[14], 10, 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
nic := IOCountersStat{
|
||||
Name: interfaceName,
|
||||
BytesRecv: bytesRecv,
|
||||
PacketsRecv: packetsRecv,
|
||||
Errin: errIn,
|
||||
Dropin: dropIn,
|
||||
Fifoin: fifoIn,
|
||||
BytesSent: bytesSent,
|
||||
PacketsSent: packetsSent,
|
||||
Errout: errOut,
|
||||
Dropout: dropOut,
|
||||
Fifoout: fifoOut,
|
||||
}
|
||||
ret = append(ret, nic)
|
||||
}
|
||||
|
||||
if pernic == false {
|
||||
return getIOCountersAll(ret)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
var netProtocols = []string{
|
||||
"ip",
|
||||
"icmp",
|
||||
"icmpmsg",
|
||||
"tcp",
|
||||
"udp",
|
||||
"udplite",
|
||||
}
|
||||
|
||||
// NetProtoCounters returns network statistics for the entire system
|
||||
// If protocols is empty then all protocols are returned, otherwise
|
||||
// just the protocols in the list are returned.
|
||||
// Available protocols:
|
||||
// ip,icmp,icmpmsg,tcp,udp,udplite
|
||||
func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
||||
if len(protocols) == 0 {
|
||||
protocols = netProtocols
|
||||
}
|
||||
|
||||
stats := make([]ProtoCountersStat, 0, len(protocols))
|
||||
protos := make(map[string]bool, len(protocols))
|
||||
for _, p := range protocols {
|
||||
protos[p] = true
|
||||
}
|
||||
|
||||
filename := common.HostProc("net/snmp")
|
||||
lines, err := common.ReadLines(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
linecount := len(lines)
|
||||
for i := 0; i < linecount; i++ {
|
||||
line := lines[i]
|
||||
r := strings.IndexRune(line, ':')
|
||||
if r == -1 {
|
||||
return nil, errors.New(filename + " is not fomatted correctly, expected ':'.")
|
||||
}
|
||||
proto := strings.ToLower(line[:r])
|
||||
if !protos[proto] {
|
||||
// skip protocol and data line
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
// Read header line
|
||||
statNames := strings.Split(line[r+2:], " ")
|
||||
|
||||
// Read data line
|
||||
i++
|
||||
statValues := strings.Split(lines[i][r+2:], " ")
|
||||
if len(statNames) != len(statValues) {
|
||||
return nil, errors.New(filename + " is not fomatted correctly, expected same number of columns.")
|
||||
}
|
||||
stat := ProtoCountersStat{
|
||||
Protocol: proto,
|
||||
Stats: make(map[string]int64, len(statNames)),
|
||||
}
|
||||
for j := range statNames {
|
||||
value, err := strconv.ParseInt(statValues[j], 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stat.Stats[statNames[j]] = value
|
||||
}
|
||||
stats = append(stats, stat)
|
||||
}
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// NetFilterCounters returns iptables conntrack statistics
|
||||
// the currently in use conntrack count and the max.
|
||||
// If the file does not exist or is invalid it will return nil.
|
||||
func FilterCounters() ([]FilterStat, error) {
|
||||
countfile := common.HostProc("sys/net/netfilter/nf_conntrackCount")
|
||||
maxfile := common.HostProc("sys/net/netfilter/nf_conntrackMax")
|
||||
|
||||
count, err := common.ReadInts(countfile)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats := make([]FilterStat, 0, 1)
|
||||
|
||||
max, err := common.ReadInts(maxfile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payload := FilterStat{
|
||||
ConnTrackCount: count[0],
|
||||
ConnTrackMax: max[0],
|
||||
}
|
||||
|
||||
stats = append(stats, payload)
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
|
||||
var TCPStatuses = map[string]string{
|
||||
"01": "ESTABLISHED",
|
||||
"02": "SYN_SENT",
|
||||
"03": "SYN_RECV",
|
||||
"04": "FIN_WAIT1",
|
||||
"05": "FIN_WAIT2",
|
||||
"06": "TIME_WAIT",
|
||||
"07": "CLOSE",
|
||||
"08": "CLOSE_WAIT",
|
||||
"09": "LAST_ACK",
|
||||
"0A": "LISTEN",
|
||||
"0B": "CLOSING",
|
||||
}
|
||||
|
||||
type netConnectionKindType struct {
|
||||
family uint32
|
||||
sockType uint32
|
||||
filename string
|
||||
}
|
||||
|
||||
var kindTCP4 = netConnectionKindType{
|
||||
family: syscall.AF_INET,
|
||||
sockType: syscall.SOCK_STREAM,
|
||||
filename: "tcp",
|
||||
}
|
||||
var kindTCP6 = netConnectionKindType{
|
||||
family: syscall.AF_INET6,
|
||||
sockType: syscall.SOCK_STREAM,
|
||||
filename: "tcp6",
|
||||
}
|
||||
var kindUDP4 = netConnectionKindType{
|
||||
family: syscall.AF_INET,
|
||||
sockType: syscall.SOCK_DGRAM,
|
||||
filename: "udp",
|
||||
}
|
||||
var kindUDP6 = netConnectionKindType{
|
||||
family: syscall.AF_INET6,
|
||||
sockType: syscall.SOCK_DGRAM,
|
||||
filename: "udp6",
|
||||
}
|
||||
var kindUNIX = netConnectionKindType{
|
||||
family: syscall.AF_UNIX,
|
||||
filename: "unix",
|
||||
}
|
||||
|
||||
var netConnectionKindMap = map[string][]netConnectionKindType{
|
||||
"all": []netConnectionKindType{kindTCP4, kindTCP6, kindUDP4, kindUDP6, kindUNIX},
|
||||
"tcp": []netConnectionKindType{kindTCP4, kindTCP6},
|
||||
"tcp4": []netConnectionKindType{kindTCP4},
|
||||
"tcp6": []netConnectionKindType{kindTCP6},
|
||||
"udp": []netConnectionKindType{kindUDP4, kindUDP6},
|
||||
"udp4": []netConnectionKindType{kindUDP4},
|
||||
"udp6": []netConnectionKindType{kindUDP6},
|
||||
"unix": []netConnectionKindType{kindUNIX},
|
||||
"inet": []netConnectionKindType{kindTCP4, kindTCP6, kindUDP4, kindUDP6},
|
||||
"inet4": []netConnectionKindType{kindTCP4, kindUDP4},
|
||||
"inet6": []netConnectionKindType{kindTCP6, kindUDP6},
|
||||
}
|
||||
|
||||
type inodeMap struct {
|
||||
pid int32
|
||||
fd uint32
|
||||
}
|
||||
|
||||
type connTmp struct {
|
||||
fd uint32
|
||||
family uint32
|
||||
sockType uint32
|
||||
laddr Addr
|
||||
raddr Addr
|
||||
status string
|
||||
pid int32
|
||||
boundPid int32
|
||||
path string
|
||||
}
|
||||
|
||||
// Return a list of network connections opened.
|
||||
func Connections(kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsPid(kind, 0)
|
||||
}
|
||||
|
||||
// Return a list of network connections opened by a process.
|
||||
func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) {
|
||||
tmap, ok := netConnectionKindMap[kind]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid kind, %s", kind)
|
||||
}
|
||||
root := common.HostProc()
|
||||
var err error
|
||||
var inodes map[string][]inodeMap
|
||||
if pid == 0 {
|
||||
inodes, err = getProcInodesAll(root)
|
||||
} else {
|
||||
inodes, err = getProcInodes(root, pid)
|
||||
if len(inodes) == 0 {
|
||||
// no connection for the pid
|
||||
return []ConnectionStat{}, nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cound not get pid(s), %d", pid)
|
||||
}
|
||||
|
||||
dupCheckMap := make(map[string]bool)
|
||||
var ret []ConnectionStat
|
||||
|
||||
for _, t := range tmap {
|
||||
var path string
|
||||
var ls []connTmp
|
||||
path = fmt.Sprintf("%s/net/%s", root, t.filename)
|
||||
switch t.family {
|
||||
case syscall.AF_INET:
|
||||
fallthrough
|
||||
case syscall.AF_INET6:
|
||||
ls, err = processInet(path, t, inodes, pid)
|
||||
case syscall.AF_UNIX:
|
||||
ls, err = processUnix(path, t, inodes, pid)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range ls {
|
||||
conn := ConnectionStat{
|
||||
Fd: c.fd,
|
||||
Family: c.family,
|
||||
Type: c.sockType,
|
||||
Laddr: c.laddr,
|
||||
Raddr: c.raddr,
|
||||
Status: c.status,
|
||||
Pid: c.pid,
|
||||
}
|
||||
if c.pid == 0 {
|
||||
conn.Pid = c.boundPid
|
||||
} else {
|
||||
conn.Pid = c.pid
|
||||
}
|
||||
// check duplicate using JSON format
|
||||
json := conn.String()
|
||||
_, exists := dupCheckMap[json]
|
||||
if !exists {
|
||||
ret = append(ret, conn)
|
||||
dupCheckMap[json] = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// getProcInodes returnes fd of the pid.
|
||||
func getProcInodes(root string, pid int32) (map[string][]inodeMap, error) {
|
||||
ret := make(map[string][]inodeMap)
|
||||
|
||||
dir := fmt.Sprintf("%s/%d/fd", root, pid)
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return ret, nil
|
||||
}
|
||||
for _, fd := range files {
|
||||
inodePath := fmt.Sprintf("%s/%d/fd/%s", root, pid, fd.Name())
|
||||
|
||||
inode, err := os.Readlink(inodePath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if !strings.HasPrefix(inode, "socket:[") {
|
||||
continue
|
||||
}
|
||||
// the process is using a socket
|
||||
l := len(inode)
|
||||
inode = inode[8 : l-1]
|
||||
_, ok := ret[inode]
|
||||
if !ok {
|
||||
ret[inode] = make([]inodeMap, 0)
|
||||
}
|
||||
fd, err := strconv.Atoi(fd.Name())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
i := inodeMap{
|
||||
pid: pid,
|
||||
fd: uint32(fd),
|
||||
}
|
||||
ret[inode] = append(ret[inode], i)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Pids retunres all pids.
|
||||
// Note: this is a copy of process_linux.Pids()
|
||||
// FIXME: Import process occures import cycle.
|
||||
// move to common made other platform breaking. Need consider.
|
||||
func Pids() ([]int32, error) {
|
||||
var ret []int32
|
||||
|
||||
d, err := os.Open(common.HostProc())
|
||||
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
|
||||
}
|
||||
|
||||
func getProcInodesAll(root string) (map[string][]inodeMap, error) {
|
||||
pids, err := Pids()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make(map[string][]inodeMap)
|
||||
|
||||
for _, pid := range pids {
|
||||
t, err := getProcInodes(root, pid)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
if len(t) == 0 {
|
||||
continue
|
||||
}
|
||||
// TODO: update ret.
|
||||
ret = updateMap(ret, t)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// decodeAddress decode addresse represents addr in proc/net/*
|
||||
// ex:
|
||||
// "0500000A:0016" -> "10.0.0.5", 22
|
||||
// "0085002452100113070057A13F025401:0035" -> "2400:8500:1301:1052:a157:7:154:23f", 53
|
||||
func decodeAddress(family uint32, src string) (Addr, error) {
|
||||
t := strings.Split(src, ":")
|
||||
if len(t) != 2 {
|
||||
return Addr{}, fmt.Errorf("does not contain port, %s", src)
|
||||
}
|
||||
addr := t[0]
|
||||
port, err := strconv.ParseInt("0x"+t[1], 0, 64)
|
||||
if err != nil {
|
||||
return Addr{}, fmt.Errorf("invalid port, %s", src)
|
||||
}
|
||||
decoded, err := hex.DecodeString(addr)
|
||||
if err != nil {
|
||||
return Addr{}, fmt.Errorf("decode error, %s", err)
|
||||
}
|
||||
var ip net.IP
|
||||
// Assumes this is little_endian
|
||||
if family == syscall.AF_INET {
|
||||
ip = net.IP(Reverse(decoded))
|
||||
} else { // IPv6
|
||||
ip, err = parseIPv6HexString(decoded)
|
||||
if err != nil {
|
||||
return Addr{}, err
|
||||
}
|
||||
}
|
||||
return Addr{
|
||||
IP: ip.String(),
|
||||
Port: uint32(port),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Reverse reverses array of bytes.
|
||||
func Reverse(s []byte) []byte {
|
||||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// parseIPv6HexString parse array of bytes to IPv6 string
|
||||
func parseIPv6HexString(src []byte) (net.IP, error) {
|
||||
if len(src) != 16 {
|
||||
return nil, fmt.Errorf("invalid IPv6 string")
|
||||
}
|
||||
|
||||
buf := make([]byte, 0, 16)
|
||||
for i := 0; i < len(src); i += 4 {
|
||||
r := Reverse(src[i : i+4])
|
||||
buf = append(buf, r...)
|
||||
}
|
||||
return net.IP(buf), nil
|
||||
}
|
||||
|
||||
func processInet(file string, kind netConnectionKindType, inodes map[string][]inodeMap, filterPid int32) ([]connTmp, error) {
|
||||
|
||||
if strings.HasSuffix(file, "6") && !common.PathExists(file) {
|
||||
// IPv6 not supported, return empty.
|
||||
return []connTmp{}, nil
|
||||
}
|
||||
lines, err := common.ReadLines(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ret []connTmp
|
||||
// skip first line
|
||||
for _, line := range lines[1:] {
|
||||
l := strings.Fields(line)
|
||||
if len(l) < 10 {
|
||||
continue
|
||||
}
|
||||
laddr := l[1]
|
||||
raddr := l[2]
|
||||
status := l[3]
|
||||
inode := l[9]
|
||||
pid := int32(0)
|
||||
fd := uint32(0)
|
||||
i, exists := inodes[inode]
|
||||
if exists {
|
||||
pid = i[0].pid
|
||||
fd = i[0].fd
|
||||
}
|
||||
if filterPid > 0 && filterPid != pid {
|
||||
continue
|
||||
}
|
||||
if kind.sockType == syscall.SOCK_STREAM {
|
||||
status = TCPStatuses[status]
|
||||
} else {
|
||||
status = "NONE"
|
||||
}
|
||||
la, err := decodeAddress(kind.family, laddr)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ra, err := decodeAddress(kind.family, raddr)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ret = append(ret, connTmp{
|
||||
fd: fd,
|
||||
family: kind.family,
|
||||
sockType: kind.sockType,
|
||||
laddr: la,
|
||||
raddr: ra,
|
||||
status: status,
|
||||
pid: pid,
|
||||
})
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func processUnix(file string, kind netConnectionKindType, inodes map[string][]inodeMap, filterPid int32) ([]connTmp, error) {
|
||||
lines, err := common.ReadLines(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ret []connTmp
|
||||
// skip first line
|
||||
for _, line := range lines[1:] {
|
||||
tokens := strings.Fields(line)
|
||||
if len(tokens) < 6 {
|
||||
continue
|
||||
}
|
||||
st, err := strconv.Atoi(tokens[4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inode := tokens[6]
|
||||
|
||||
var pairs []inodeMap
|
||||
pairs, exists := inodes[inode]
|
||||
if !exists {
|
||||
pairs = []inodeMap{
|
||||
inodeMap{},
|
||||
}
|
||||
}
|
||||
for _, pair := range pairs {
|
||||
if filterPid > 0 && filterPid != pair.pid {
|
||||
continue
|
||||
}
|
||||
var path string
|
||||
if len(tokens) == 8 {
|
||||
path = tokens[len(tokens)-1]
|
||||
}
|
||||
ret = append(ret, connTmp{
|
||||
fd: pair.fd,
|
||||
family: kind.family,
|
||||
sockType: uint32(st),
|
||||
laddr: Addr{
|
||||
IP: path,
|
||||
},
|
||||
pid: pair.pid,
|
||||
status: "NONE",
|
||||
path: path,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func updateMap(src map[string][]inodeMap, add map[string][]inodeMap) map[string][]inodeMap {
|
||||
for key, value := range add {
|
||||
a, exists := src[key]
|
||||
if !exists {
|
||||
src[key] = value
|
||||
continue
|
||||
}
|
||||
src[key] = append(a, value...)
|
||||
}
|
||||
return src
|
||||
}
|
||||
75
vendor/github.com/shirou/gopsutil/net/net_linux_test.go
generated
vendored
Normal file
75
vendor/github.com/shirou/gopsutil/net/net_linux_test.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetProcInodesAll(t *testing.T) {
|
||||
if os.Getenv("CIRCLECI") == "true" {
|
||||
t.Skip("Skip CI")
|
||||
}
|
||||
|
||||
root := common.HostProc("")
|
||||
v, err := getProcInodesAll(root)
|
||||
assert.Nil(t, err)
|
||||
assert.NotEmpty(t, v)
|
||||
}
|
||||
|
||||
type AddrTest struct {
|
||||
IP string
|
||||
Port int
|
||||
Error bool
|
||||
}
|
||||
|
||||
func TestDecodeAddress(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
addr := map[string]AddrTest{
|
||||
"0500000A:0016": AddrTest{
|
||||
IP: "10.0.0.5",
|
||||
Port: 22,
|
||||
},
|
||||
"0100007F:D1C2": AddrTest{
|
||||
IP: "127.0.0.1",
|
||||
Port: 53698,
|
||||
},
|
||||
"11111:0035": AddrTest{
|
||||
Error: true,
|
||||
},
|
||||
"0100007F:BLAH": AddrTest{
|
||||
Error: true,
|
||||
},
|
||||
"0085002452100113070057A13F025401:0035": AddrTest{
|
||||
IP: "2400:8500:1301:1052:a157:7:154:23f",
|
||||
Port: 53,
|
||||
},
|
||||
"00855210011307F025401:0035": AddrTest{
|
||||
Error: true,
|
||||
},
|
||||
}
|
||||
|
||||
for src, dst := range addr {
|
||||
family := syscall.AF_INET
|
||||
if len(src) > 13 {
|
||||
family = syscall.AF_INET6
|
||||
}
|
||||
addr, err := decodeAddress(uint32(family), src)
|
||||
if dst.Error {
|
||||
assert.NotNil(err, src)
|
||||
} else {
|
||||
assert.Nil(err, src)
|
||||
assert.Equal(dst.IP, addr.IP, src)
|
||||
assert.Equal(dst.Port, int(addr.Port), src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReverse(t *testing.T) {
|
||||
src := []byte{0x01, 0x02, 0x03}
|
||||
assert.Equal(t, []byte{0x03, 0x02, 0x01}, Reverse(src))
|
||||
}
|
||||
228
vendor/github.com/shirou/gopsutil/net/net_test.go
generated
vendored
Normal file
228
vendor/github.com/shirou/gopsutil/net/net_test.go
generated
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
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 := IOCountersStat{
|
||||
Name: "test",
|
||||
BytesSent: 100,
|
||||
}
|
||||
e := `{"name":"test","bytesSent":100,"bytesRecv":0,"packetsSent":0,"packetsRecv":0,"errin":0,"errout":0,"dropin":0,"dropout":0,"fifoin":0,"fifoout":0}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("NetIOCountersStat string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetProtoCountersStatString(t *testing.T) {
|
||||
v := ProtoCountersStat{
|
||||
Protocol: "tcp",
|
||||
Stats: map[string]int64{
|
||||
"MaxConn": -1,
|
||||
"ActiveOpens": 4000,
|
||||
"PassiveOpens": 3000,
|
||||
},
|
||||
}
|
||||
e := `{"protocol":"tcp","stats":{"ActiveOpens":4000,"MaxConn":-1,"PassiveOpens":3000}}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("NetProtoCountersStat string is invalid: %v", v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNetConnectionStatString(t *testing.T) {
|
||||
v := ConnectionStat{
|
||||
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 := IOCounters(false)
|
||||
per, err := IOCounters(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 := IOCounters(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 TestGetNetIOCountersAll(t *testing.T) {
|
||||
n := []IOCountersStat{
|
||||
IOCountersStat{
|
||||
Name: "a",
|
||||
BytesRecv: 10,
|
||||
PacketsRecv: 10,
|
||||
},
|
||||
IOCountersStat{
|
||||
Name: "b",
|
||||
BytesRecv: 10,
|
||||
PacketsRecv: 10,
|
||||
Errin: 10,
|
||||
},
|
||||
}
|
||||
ret, err := getIOCountersAll(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 := Interfaces()
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetProtoCountersStatsAll(t *testing.T) {
|
||||
v, err := ProtoCounters(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get NetProtoCounters: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Fatalf("Could not get NetProtoCounters: %v", err)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.Protocol == "" {
|
||||
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
|
||||
}
|
||||
if len(vv.Stats) == 0 {
|
||||
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetProtoCountersStats(t *testing.T) {
|
||||
v, err := ProtoCounters([]string{"tcp", "ip"})
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get NetProtoCounters: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Fatalf("Could not get NetProtoCounters: %v", err)
|
||||
}
|
||||
if len(v) != 2 {
|
||||
t.Fatalf("Go incorrect number of NetProtoCounters: %v", err)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.Protocol != "tcp" && vv.Protocol != "ip" {
|
||||
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
|
||||
}
|
||||
if len(vv.Stats) == 0 {
|
||||
t.Errorf("Invalid NetProtoCountersStat: %v", vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetConnections(t *testing.T) {
|
||||
if ci := os.Getenv("CI"); ci != "" { // skip if test on drone.io
|
||||
return
|
||||
}
|
||||
|
||||
v, err := Connections("inet")
|
||||
if err != nil {
|
||||
t.Errorf("could not get NetConnections: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Errorf("could not get NetConnections: %v", v)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.Family == 0 {
|
||||
t.Errorf("invalid NetConnections: %v", vv)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNetFilterCounters(t *testing.T) {
|
||||
if ci := os.Getenv("CI"); ci != "" { // skip if test on drone.io
|
||||
return
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
// some test environment has not the path.
|
||||
if !common.PathExists("/proc/sys/net/netfilter/nf_conntrackCount") {
|
||||
t.SkipNow()
|
||||
}
|
||||
}
|
||||
|
||||
v, err := FilterCounters()
|
||||
if err != nil {
|
||||
t.Errorf("could not get NetConnections: %v", err)
|
||||
}
|
||||
if len(v) == 0 {
|
||||
t.Errorf("could not get NetConnections: %v", v)
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.ConnTrackMax == 0 {
|
||||
t.Errorf("nf_conntrackMax needs to be greater than zero: %v", vv)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
68
vendor/github.com/shirou/gopsutil/net/net_unix.go
generated
vendored
Normal file
68
vendor/github.com/shirou/gopsutil/net/net_unix.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// +build freebsd darwin
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
// Return a list of network connections opened.
|
||||
func Connections(kind string) ([]ConnectionStat, error) {
|
||||
return ConnectionsPid(kind, 0)
|
||||
}
|
||||
|
||||
// Return a list of network connections opened by a process.
|
||||
func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) {
|
||||
var ret []ConnectionStat
|
||||
|
||||
args := []string{"-i"}
|
||||
switch strings.ToLower(kind) {
|
||||
default:
|
||||
fallthrough
|
||||
case "":
|
||||
fallthrough
|
||||
case "all":
|
||||
fallthrough
|
||||
case "inet":
|
||||
args = append(args, "tcp", "-i", "udp")
|
||||
case "inet4":
|
||||
args = append(args, "4")
|
||||
case "inet6":
|
||||
args = append(args, "6")
|
||||
case "tcp":
|
||||
args = append(args, "tcp")
|
||||
case "tcp4":
|
||||
args = append(args, "4tcp")
|
||||
case "tcp6":
|
||||
args = append(args, "6tcp")
|
||||
case "udp":
|
||||
args = append(args, "udp")
|
||||
case "udp4":
|
||||
args = append(args, "6udp")
|
||||
case "udp6":
|
||||
args = append(args, "6udp")
|
||||
case "unix":
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
r, err := common.CallLsof(invoke, pid, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, rr := range r {
|
||||
if strings.HasPrefix(rr, "COMMAND") {
|
||||
continue
|
||||
}
|
||||
n, err := parseNetLine(rr)
|
||||
if err != nil {
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
ret = append(ret, n)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
116
vendor/github.com/shirou/gopsutil/net/net_windows.go
generated
vendored
Normal file
116
vendor/github.com/shirou/gopsutil/net/net_windows.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
// +build windows
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/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 IOCounters(pernic bool) ([]IOCountersStat, error) {
|
||||
ifs, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ai, err := getAdapterList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ret []IOCountersStat
|
||||
|
||||
for _, ifi := range ifs {
|
||||
name := ifi.Name
|
||||
for ; ai != nil; ai = ai.Next {
|
||||
name = common.BytePtrToString(&ai.Description[0])
|
||||
c := IOCountersStat{
|
||||
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 getIOCountersAll(ret)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// NetIOCountersByFile is an method which is added just a compatibility for linux.
|
||||
func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
|
||||
return IOCounters(pernic)
|
||||
}
|
||||
|
||||
// Return a list of network connections opened by a process
|
||||
func Connections(kind string) ([]ConnectionStat, error) {
|
||||
var ret []ConnectionStat
|
||||
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
func FilterCounters() ([]FilterStat, error) {
|
||||
return nil, errors.New("NetFilterCounters not implemented for windows")
|
||||
}
|
||||
|
||||
// NetProtoCounters returns network statistics for the entire system
|
||||
// If protocols is empty then all protocols are returned, otherwise
|
||||
// just the protocols in the list are returned.
|
||||
// Not Implemented for Windows
|
||||
func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
||||
return nil, errors.New("NetProtoCounters not implemented for windows")
|
||||
}
|
||||
10
vendor/github.com/shirou/gopsutil/process/expected/darwin/%2Fbin%2Fps-ax-opid_fail
generated
vendored
Normal file
10
vendor/github.com/shirou/gopsutil/process/expected/darwin/%2Fbin%2Fps-ax-opid_fail
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
PID
|
||||
245
|
||||
247
|
||||
248
|
||||
249
|
||||
254
|
||||
262
|
||||
264
|
||||
265
|
||||
267
|
||||
167
vendor/github.com/shirou/gopsutil/process/process.go
generated
vendored
Normal file
167
vendor/github.com/shirou/gopsutil/process/process.go
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
package process
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
)
|
||||
|
||||
var invoke common.Invoker
|
||||
|
||||
func init() {
|
||||
invoke = common.Invoke{}
|
||||
}
|
||||
|
||||
type Process struct {
|
||||
Pid int32 `json:"pid"`
|
||||
name string
|
||||
status string
|
||||
parent int32
|
||||
numCtxSwitches *NumCtxSwitchesStat
|
||||
uids []int32
|
||||
gids []int32
|
||||
numThreads int32
|
||||
memInfo *MemoryInfoStat
|
||||
|
||||
lastCPUTimes *cpu.TimesStat
|
||||
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:"readCount"`
|
||||
WriteCount uint64 `json:"writeCount"`
|
||||
ReadBytes uint64 `json:"readBytes"`
|
||||
WriteBytes uint64 `json:"writeBytes"`
|
||||
}
|
||||
|
||||
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) Percent(interval time.Duration) (float64, error) {
|
||||
cpuTimes, err := p.Times()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
now := time.Now()
|
||||
|
||||
if interval > 0 {
|
||||
p.lastCPUTimes = cpuTimes
|
||||
p.lastCPUTime = now
|
||||
time.Sleep(interval)
|
||||
cpuTimes, err = p.Times()
|
||||
now = time.Now()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
if p.lastCPUTimes == nil {
|
||||
// invoked first time
|
||||
p.lastCPUTimes = cpuTimes
|
||||
p.lastCPUTime = now
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
numcpu := runtime.NumCPU()
|
||||
delta := (now.Sub(p.lastCPUTime).Seconds()) * float64(numcpu)
|
||||
ret := calculatePercent(p.lastCPUTimes, cpuTimes, delta, numcpu)
|
||||
p.lastCPUTimes = cpuTimes
|
||||
p.lastCPUTime = now
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64 {
|
||||
if delta == 0 {
|
||||
return 0
|
||||
}
|
||||
delta_proc := t2.Total() - t1.Total()
|
||||
overall_percent := ((delta_proc / delta) * 100) * float64(numcpu)
|
||||
return overall_percent
|
||||
}
|
||||
|
||||
// MemoryPercent returns how many percent of the total RAM this process uses
|
||||
func (p *Process) MemoryPercent() (float32, error) {
|
||||
machineMemory, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
total := machineMemory.Total
|
||||
|
||||
processMemory, err := p.MemoryInfo()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
used := processMemory.RSS
|
||||
|
||||
return (100 * float32(used) / float32(total)), nil
|
||||
}
|
||||
451
vendor/github.com/shirou/gopsutil/process/process_darwin.go
generated
vendored
Normal file
451
vendor/github.com/shirou/gopsutil/process/process_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,451 @@
|
||||
// +build darwin
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/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
|
||||
)
|
||||
|
||||
const (
|
||||
ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK)
|
||||
)
|
||||
|
||||
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, false)
|
||||
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, false)
|
||||
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.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Cmdline returns the command line arguments of the process as a string with
|
||||
// each argument separated by 0x20 ascii character.
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
r, err := callPs("command", p.Pid, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.Join(r[0], " "), err
|
||||
}
|
||||
|
||||
// CmdlineSlice returns the command line arguments of the process as a slice with each
|
||||
// element being an argument. Because of current deficiencies in the way that the command
|
||||
// line arguments are found, single arguments that have spaces in the will actually be
|
||||
// reported as two separate items. In order to do something better CGO would be needed
|
||||
// to use the native darwin functions.
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
r, err := callPs("command", p.Pid, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r[0], err
|
||||
}
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
rr, err := common.CallLsof(invoke, p.Pid, "-FR")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, r := range rr {
|
||||
if strings.HasPrefix(r, "p") { // skip if process
|
||||
continue
|
||||
}
|
||||
l := string(r)
|
||||
v, err := strconv.Atoi(strings.Replace(l, "R", "", 1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewProcess(int32(v))
|
||||
}
|
||||
return nil, fmt.Errorf("could not find parent line")
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
r, err := callPs("state", p.Pid, false)
|
||||
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
|
||||
}
|
||||
|
||||
// See: http://unix.superglobalmegacorp.com/Net2/newsrc/sys/ucred.h.html
|
||||
userEffectiveUID := int32(k.Eproc.Ucred.UID)
|
||||
|
||||
return []int32{userEffectiveUID}, 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.ErrNotImplementedError
|
||||
/*
|
||||
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.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
r, err := callPs("utime,stime", p.Pid, true)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int32(len(r)), nil
|
||||
}
|
||||
func (p *Process) Threads() (map[string]string, error) {
|
||||
ret := make(map[string]string, 0)
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func convertCPUTimes(s string) (ret float64, err error) {
|
||||
var t int
|
||||
var _tmp string
|
||||
if strings.Contains(s, ":") {
|
||||
_t := strings.Split(s, ":")
|
||||
hour, err := strconv.Atoi(_t[0])
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
t += hour * 60 * 100
|
||||
_tmp = _t[1]
|
||||
} else {
|
||||
_tmp = s
|
||||
}
|
||||
|
||||
_t := strings.Split(_tmp, ".")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
h, err := strconv.Atoi(_t[0])
|
||||
t += h * 100
|
||||
h, err = strconv.Atoi(_t[1])
|
||||
t += h
|
||||
return float64(t) / ClockTicks, nil
|
||||
}
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
r, err := callPs("utime,stime", p.Pid, false)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
utime, err := convertCPUTimes(r[0][0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stime, err := convertCPUTimes(r[0][1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &cpu.TimesStat{
|
||||
CPU: "cpu",
|
||||
User: utime,
|
||||
System: stime,
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
r, err := callPs("rss,vsize,pagein", p.Pid, false)
|
||||
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) * 1024,
|
||||
VMS: uint64(vms) * 1024,
|
||||
Swap: uint64(pagein),
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
pids, err := common.CallPgrep(invoke, p.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make([]*Process, 0, len(pids))
|
||||
for _, pid := range pids {
|
||||
np, err := NewProcess(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret = append(ret, np)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return net.ConnectionsPid("all", p.Pid)
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return true, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
var ret []MemoryMapsStat
|
||||
return &ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
results = append(results, *p)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
||||
var k KinfoProc
|
||||
br := bytes.NewReader(buf)
|
||||
|
||||
err := common.Read(br, binary.LittleEndian, &k)
|
||||
if err != nil {
|
||||
return k, err
|
||||
}
|
||||
|
||||
return k, nil
|
||||
}
|
||||
|
||||
// Returns a proc as defined here:
|
||||
// http://unix.superglobalmegacorp.com/Net2/newsrc/sys/kinfo_proc.h.html
|
||||
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, threadOption bool) ([][]string, error) {
|
||||
bin, err := exec.LookPath("ps")
|
||||
if err != nil {
|
||||
return [][]string{}, err
|
||||
}
|
||||
|
||||
var cmd []string
|
||||
if pid == 0 { // will get from all processes.
|
||||
cmd = []string{"-ax", "-o", arg}
|
||||
} else if threadOption {
|
||||
cmd = []string{"-x", "-o", arg, "-M", "-p", strconv.Itoa(int(pid))}
|
||||
} else {
|
||||
cmd = []string{"-x", "-o", arg, "-p", strconv.Itoa(int(pid))}
|
||||
}
|
||||
out, err := invoke.Command(bin, cmd...)
|
||||
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
|
||||
}
|
||||
234
vendor/github.com/shirou/gopsutil/process/process_darwin_amd64.go
generated
vendored
Normal file
234
vendor/github.com/shirou/gopsutil/process/process_darwin_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
// 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
|
||||
}
|
||||
336
vendor/github.com/shirou/gopsutil/process/process_freebsd.go
generated
vendored
Normal file
336
vendor/github.com/shirou/gopsutil/process/process_freebsd.go
generated
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
// +build freebsd
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
cpu "github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
net "github.com/shirou/gopsutil/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.Ppid, nil
|
||||
}
|
||||
func (p *Process) Name() (string, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return common.IntToString(k.Comm[:]), nil
|
||||
}
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ret := strings.FieldsFunc(string(buf), func(r rune) bool {
|
||||
if r == '\u0000' {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return strings.Join(ret, " "), nil
|
||||
}
|
||||
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(buf) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if buf[len(buf)-1] == 0 {
|
||||
buf = buf[:len(buf)-1]
|
||||
}
|
||||
parts := bytes.Split(buf, []byte{0})
|
||||
var strParts []string
|
||||
for _, p := range parts {
|
||||
strParts = append(strParts, string(p))
|
||||
}
|
||||
|
||||
return strParts, nil
|
||||
}
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
return p, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var s string
|
||||
switch k.Stat {
|
||||
case SIDL:
|
||||
s = "I"
|
||||
case SRUN:
|
||||
s = "R"
|
||||
case SSLEEP:
|
||||
s = "S"
|
||||
case SSTOP:
|
||||
s = "T"
|
||||
case SZOMB:
|
||||
s = "Z"
|
||||
case SWAIT:
|
||||
s = "W"
|
||||
case SLOCK:
|
||||
s = "L"
|
||||
}
|
||||
|
||||
return s, 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.Ruid), int32(k.Uid), int32(k.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.Rgid), int32(k.Ngroups), int32(k.Svgid))
|
||||
|
||||
return gids, nil
|
||||
}
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ttyNr := uint64(k.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.Nice), nil
|
||||
}
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
return rlimit, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &IOCountersStat{
|
||||
ReadCount: uint64(k.Rusage.Inblock),
|
||||
WriteCount: uint64(k.Rusage.Oublock),
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return k.Numthreads, nil
|
||||
}
|
||||
func (p *Process) Threads() (map[string]string, error) {
|
||||
ret := make(map[string]string, 0)
|
||||
return ret, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cpu.TimesStat{
|
||||
CPU: "cpu",
|
||||
User: float64(k.Rusage.Utime.Sec) + float64(k.Rusage.Utime.Usec)/1000000,
|
||||
System: float64(k.Rusage.Stime.Sec) + float64(k.Rusage.Stime.Usec)/1000000,
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v, err := syscall.Sysctl("vm.stats.vm.v_page_size")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pageSize := common.LittleEndian.Uint16([]byte(v))
|
||||
|
||||
return &MemoryInfoStat{
|
||||
RSS: uint64(k.Rssize) * uint64(pageSize),
|
||||
VMS: uint64(k.Size),
|
||||
}, nil
|
||||
}
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
pids, err := common.CallPgrep(invoke, p.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make([]*Process, 0, len(pids))
|
||||
for _, pid := range pids {
|
||||
np, err := NewProcess(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret = append(ret, np)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return true, common.ErrNotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
var ret []MemoryMapsStat
|
||||
return &ret, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
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
|
||||
count := int(length / uint64(sizeOfKinfoProc))
|
||||
|
||||
// parse buf to procs
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*sizeOfKinfoProc : (i+1)*sizeOfKinfoProc]
|
||||
k, err := parseKinfoProc(b)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p, err := NewProcess(int32(k.Pid))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
results = append(results, *p)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
||||
var k KinfoProc
|
||||
br := bytes.NewReader(buf)
|
||||
err := common.Read(br, binary.LittleEndian, &k)
|
||||
return k, err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
if length != sizeOfKinfoProc {
|
||||
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
|
||||
}
|
||||
192
vendor/github.com/shirou/gopsutil/process/process_freebsd_386.go
generated
vendored
Normal file
192
vendor/github.com/shirou/gopsutil/process/process_freebsd_386.go
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package process
|
||||
|
||||
const (
|
||||
CTLKern = 1
|
||||
KernProc = 14
|
||||
KernProcPID = 1
|
||||
KernProcProc = 8
|
||||
KernProcPathname = 12
|
||||
KernProcArgs = 7
|
||||
)
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x4
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfKinfoVmentry = 0x488
|
||||
sizeOfKinfoProc = 0x300
|
||||
)
|
||||
|
||||
const (
|
||||
SIDL = 1
|
||||
SRUN = 2
|
||||
SSLEEP = 3
|
||||
SSTOP = 4
|
||||
SZOMB = 5
|
||||
SWAIT = 6
|
||||
SLOCK = 7
|
||||
)
|
||||
|
||||
type (
|
||||
_C_short int16
|
||||
_C_int int32
|
||||
_C_long int32
|
||||
_C_long_long int64
|
||||
)
|
||||
|
||||
type Timespec struct {
|
||||
Sec int32
|
||||
Nsec int32
|
||||
}
|
||||
|
||||
type Timeval struct {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
||||
|
||||
type Rusage struct {
|
||||
Utime Timeval
|
||||
Stime Timeval
|
||||
Maxrss int32
|
||||
Ixrss int32
|
||||
Idrss int32
|
||||
Isrss int32
|
||||
Minflt int32
|
||||
Majflt int32
|
||||
Nswap int32
|
||||
Inblock int32
|
||||
Oublock int32
|
||||
Msgsnd int32
|
||||
Msgrcv int32
|
||||
Nsignals int32
|
||||
Nvcsw int32
|
||||
Nivcsw int32
|
||||
}
|
||||
|
||||
type Rlimit struct {
|
||||
Cur int64
|
||||
Max int64
|
||||
}
|
||||
|
||||
type KinfoProc struct {
|
||||
Structsize int32
|
||||
Layout int32
|
||||
Args int32 /* pargs */
|
||||
Paddr int32 /* proc */
|
||||
Addr int32 /* user */
|
||||
Tracep int32 /* vnode */
|
||||
Textvp int32 /* vnode */
|
||||
Fd int32 /* filedesc */
|
||||
Vmspace int32 /* vmspace */
|
||||
Wchan int32
|
||||
Pid int32
|
||||
Ppid int32
|
||||
Pgid int32
|
||||
Tpgid int32
|
||||
Sid int32
|
||||
Tsid int32
|
||||
Jobc int16
|
||||
Spare_short1 int16
|
||||
Tdev uint32
|
||||
Siglist [16]byte /* sigset */
|
||||
Sigmask [16]byte /* sigset */
|
||||
Sigignore [16]byte /* sigset */
|
||||
Sigcatch [16]byte /* sigset */
|
||||
Uid uint32
|
||||
Ruid uint32
|
||||
Svuid uint32
|
||||
Rgid uint32
|
||||
Svgid uint32
|
||||
Ngroups int16
|
||||
Spare_short2 int16
|
||||
Groups [16]uint32
|
||||
Size uint32
|
||||
Rssize int32
|
||||
Swrss int32
|
||||
Tsize int32
|
||||
Dsize int32
|
||||
Ssize int32
|
||||
Xstat uint16
|
||||
Acflag uint16
|
||||
Pctcpu uint32
|
||||
Estcpu uint32
|
||||
Slptime uint32
|
||||
Swtime uint32
|
||||
Cow uint32
|
||||
Runtime uint64
|
||||
Start Timeval
|
||||
Childtime Timeval
|
||||
Flag int32
|
||||
Kiflag int32
|
||||
Traceflag int32
|
||||
Stat int8
|
||||
Nice int8
|
||||
Lock int8
|
||||
Rqindex int8
|
||||
Oncpu uint8
|
||||
Lastcpu uint8
|
||||
Tdname [17]int8
|
||||
Wmesg [9]int8
|
||||
Login [18]int8
|
||||
Lockname [9]int8
|
||||
Comm [20]int8
|
||||
Emul [17]int8
|
||||
Loginclass [18]int8
|
||||
Sparestrings [50]int8
|
||||
Spareints [7]int32
|
||||
Flag2 int32
|
||||
Fibnum int32
|
||||
Cr_flags uint32
|
||||
Jid int32
|
||||
Numthreads int32
|
||||
Tid int32
|
||||
Pri Priority
|
||||
Rusage Rusage
|
||||
Rusage_ch Rusage
|
||||
Pcb int32 /* pcb */
|
||||
Kstack int32
|
||||
Udata int32
|
||||
Tdaddr int32 /* thread */
|
||||
Spareptrs [6]int32
|
||||
Sparelongs [12]int32
|
||||
Sflag int32
|
||||
Tdflags int32
|
||||
}
|
||||
|
||||
type Priority struct {
|
||||
Class uint8
|
||||
Level uint8
|
||||
Native uint8
|
||||
User uint8
|
||||
}
|
||||
|
||||
type KinfoVmentry struct {
|
||||
Structsize int32
|
||||
Type int32
|
||||
Start uint64
|
||||
End uint64
|
||||
Offset uint64
|
||||
Vn_fileid uint64
|
||||
Vn_fsid uint32
|
||||
Flags int32
|
||||
Resident int32
|
||||
Private_resident int32
|
||||
Protection int32
|
||||
Ref_count int32
|
||||
Shadow_count int32
|
||||
Vn_type int32
|
||||
Vn_size uint64
|
||||
Vn_rdev uint32
|
||||
Vn_mode uint16
|
||||
Status uint16
|
||||
X_kve_ispare [12]int32
|
||||
Path [1024]int8
|
||||
}
|
||||
192
vendor/github.com/shirou/gopsutil/process/process_freebsd_amd64.go
generated
vendored
Normal file
192
vendor/github.com/shirou/gopsutil/process/process_freebsd_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package process
|
||||
|
||||
const (
|
||||
CTLKern = 1
|
||||
KernProc = 14
|
||||
KernProcPID = 1
|
||||
KernProcProc = 8
|
||||
KernProcPathname = 12
|
||||
KernProcArgs = 7
|
||||
)
|
||||
|
||||
const (
|
||||
sizeofPtr = 0x8
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x8
|
||||
sizeofLongLong = 0x8
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfKinfoVmentry = 0x488
|
||||
sizeOfKinfoProc = 0x440
|
||||
)
|
||||
|
||||
const (
|
||||
SIDL = 1
|
||||
SRUN = 2
|
||||
SSLEEP = 3
|
||||
SSTOP = 4
|
||||
SZOMB = 5
|
||||
SWAIT = 6
|
||||
SLOCK = 7
|
||||
)
|
||||
|
||||
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 int64
|
||||
}
|
||||
|
||||
type Rusage struct {
|
||||
Utime Timeval
|
||||
Stime Timeval
|
||||
Maxrss int64
|
||||
Ixrss int64
|
||||
Idrss int64
|
||||
Isrss int64
|
||||
Minflt int64
|
||||
Majflt int64
|
||||
Nswap int64
|
||||
Inblock int64
|
||||
Oublock int64
|
||||
Msgsnd int64
|
||||
Msgrcv int64
|
||||
Nsignals int64
|
||||
Nvcsw int64
|
||||
Nivcsw int64
|
||||
}
|
||||
|
||||
type Rlimit struct {
|
||||
Cur int64
|
||||
Max int64
|
||||
}
|
||||
|
||||
type KinfoProc struct {
|
||||
Structsize int32
|
||||
Layout int32
|
||||
Args int64 /* pargs */
|
||||
Paddr int64 /* proc */
|
||||
Addr int64 /* user */
|
||||
Tracep int64 /* vnode */
|
||||
Textvp int64 /* vnode */
|
||||
Fd int64 /* filedesc */
|
||||
Vmspace int64 /* vmspace */
|
||||
Wchan int64
|
||||
Pid int32
|
||||
Ppid int32
|
||||
Pgid int32
|
||||
Tpgid int32
|
||||
Sid int32
|
||||
Tsid int32
|
||||
Jobc int16
|
||||
Spare_short1 int16
|
||||
Tdev uint32
|
||||
Siglist [16]byte /* sigset */
|
||||
Sigmask [16]byte /* sigset */
|
||||
Sigignore [16]byte /* sigset */
|
||||
Sigcatch [16]byte /* sigset */
|
||||
Uid uint32
|
||||
Ruid uint32
|
||||
Svuid uint32
|
||||
Rgid uint32
|
||||
Svgid uint32
|
||||
Ngroups int16
|
||||
Spare_short2 int16
|
||||
Groups [16]uint32
|
||||
Size uint64
|
||||
Rssize int64
|
||||
Swrss int64
|
||||
Tsize int64
|
||||
Dsize int64
|
||||
Ssize int64
|
||||
Xstat uint16
|
||||
Acflag uint16
|
||||
Pctcpu uint32
|
||||
Estcpu uint32
|
||||
Slptime uint32
|
||||
Swtime uint32
|
||||
Cow uint32
|
||||
Runtime uint64
|
||||
Start Timeval
|
||||
Childtime Timeval
|
||||
Flag int64
|
||||
Kiflag int64
|
||||
Traceflag int32
|
||||
Stat int8
|
||||
Nice int8
|
||||
Lock int8
|
||||
Rqindex int8
|
||||
Oncpu uint8
|
||||
Lastcpu uint8
|
||||
Tdname [17]int8
|
||||
Wmesg [9]int8
|
||||
Login [18]int8
|
||||
Lockname [9]int8
|
||||
Comm [20]int8
|
||||
Emul [17]int8
|
||||
Loginclass [18]int8
|
||||
Sparestrings [50]int8
|
||||
Spareints [7]int32
|
||||
Flag2 int32
|
||||
Fibnum int32
|
||||
Cr_flags uint32
|
||||
Jid int32
|
||||
Numthreads int32
|
||||
Tid int32
|
||||
Pri Priority
|
||||
Rusage Rusage
|
||||
Rusage_ch Rusage
|
||||
Pcb int64 /* pcb */
|
||||
Kstack int64
|
||||
Udata int64
|
||||
Tdaddr int64 /* thread */
|
||||
Spareptrs [6]int64
|
||||
Sparelongs [12]int64
|
||||
Sflag int64
|
||||
Tdflags int64
|
||||
}
|
||||
|
||||
type Priority struct {
|
||||
Class uint8
|
||||
Level uint8
|
||||
Native uint8
|
||||
User uint8
|
||||
}
|
||||
|
||||
type KinfoVmentry struct {
|
||||
Structsize int32
|
||||
Type int32
|
||||
Start uint64
|
||||
End uint64
|
||||
Offset uint64
|
||||
Vn_fileid uint64
|
||||
Vn_fsid uint32
|
||||
Flags int32
|
||||
Resident int32
|
||||
Private_resident int32
|
||||
Protection int32
|
||||
Ref_count int32
|
||||
Shadow_count int32
|
||||
Vn_type int32
|
||||
Vn_size uint64
|
||||
Vn_rdev uint32
|
||||
Vn_mode uint16
|
||||
Status uint16
|
||||
X_kve_ispare [12]int32
|
||||
Path [1024]int8
|
||||
}
|
||||
767
vendor/github.com/shirou/gopsutil/process/process_linux.go
generated
vendored
Normal file
767
vendor/github.com/shirou/gopsutil/process/process_linux.go
generated
vendored
Normal file
@@ -0,0 +1,767 @@
|
||||
// +build linux
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/net"
|
||||
)
|
||||
|
||||
var ErrorNoChildren = errors.New("process does not have children")
|
||||
|
||||
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:"sharedClean"`
|
||||
SharedDirty uint64 `json:"sharedDirty"`
|
||||
PrivateClean uint64 `json:"privateClean"`
|
||||
PrivateDirty uint64 `json:"privateDirty"`
|
||||
Referenced uint64 `json:"referenced"`
|
||||
Anonymous uint64 `json:"anonymous"`
|
||||
Swap uint64 `json:"swap"`
|
||||
}
|
||||
|
||||
// String returns JSON value of the process.
|
||||
func (m MemoryMapsStat) String() string {
|
||||
s, _ := json.Marshal(m)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// NewProcess creates a new Process instance, it only stores the pid and
|
||||
// checks that the process exists. Other method on Process can be used
|
||||
// to get more information about the process. An error will be returned
|
||||
// if the process does not exist.
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{
|
||||
Pid: int32(pid),
|
||||
}
|
||||
file, err := os.Open(common.HostProc(strconv.Itoa(int(p.Pid))))
|
||||
defer file.Close()
|
||||
return p, err
|
||||
}
|
||||
|
||||
// Ppid returns Parent Process ID of the process.
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
_, ppid, _, _, _, err := p.fillFromStat()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return ppid, nil
|
||||
}
|
||||
|
||||
// Name returns name of the process.
|
||||
func (p *Process) Name() (string, error) {
|
||||
if p.name == "" {
|
||||
if err := p.fillFromStatus(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return p.name, nil
|
||||
}
|
||||
|
||||
// Exe returns executable path of the process.
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return p.fillFromExe()
|
||||
}
|
||||
|
||||
// Cmdline returns the command line arguments of the process as a string with
|
||||
// each argument separated by 0x20 ascii character.
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
return p.fillFromCmdline()
|
||||
}
|
||||
|
||||
// CmdlineSlice returns the command line arguments of the process as a slice with each
|
||||
// element being an argument.
|
||||
func (p *Process) CmdlineSlice() ([]string, error) {
|
||||
return p.fillSliceFromCmdline()
|
||||
}
|
||||
|
||||
// CreateTime returns created time of the process in seconds since the epoch, in UTC.
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
_, _, _, createTime, _, err := p.fillFromStat()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return createTime, nil
|
||||
}
|
||||
|
||||
// Cwd returns current working directory of the process.
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return p.fillFromCwd()
|
||||
}
|
||||
|
||||
// Parent returns parent Process of the process.
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.parent == 0 {
|
||||
return nil, fmt.Errorf("wrong number of parents")
|
||||
}
|
||||
return NewProcess(p.parent)
|
||||
}
|
||||
|
||||
// Status returns the process status.
|
||||
// Return value could be one of these.
|
||||
// R: Running S: Sleep T: Stop I: Idle
|
||||
// Z: Zombie W: Wait L: Lock
|
||||
// The charactor is same within all supported platforms.
|
||||
func (p *Process) Status() (string, error) {
|
||||
err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return p.status, nil
|
||||
}
|
||||
|
||||
// Uids returns user ids of the process as a slice of the int
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
}
|
||||
return p.uids, nil
|
||||
}
|
||||
|
||||
// Gids returns group ids of the process as a slice of the int
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
}
|
||||
return p.gids, nil
|
||||
}
|
||||
|
||||
// Terminal returns a terminal which is associated with the process.
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
terminal, _, _, _, _, err := p.fillFromStat()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return terminal, nil
|
||||
}
|
||||
|
||||
// Nice returns a nice value (priority).
|
||||
// Notice: gopsutil can not set nice value.
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
_, _, _, _, nice, err := p.fillFromStat()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return nice, nil
|
||||
}
|
||||
|
||||
// IOnice returns process I/O nice value (priority).
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return 0, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// Rlimit returns Resource Limits.
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// IOCounters returns IO Counters.
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return p.fillFromIO()
|
||||
}
|
||||
|
||||
// NumCtxSwitches returns the number of the context switches of the process.
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.numCtxSwitches, nil
|
||||
}
|
||||
|
||||
// NumFDs returns the number of File Descriptors used by the process.
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
numFds, _, err := p.fillFromfd()
|
||||
return numFds, err
|
||||
}
|
||||
|
||||
// NumThreads returns the number of threads used by the process.
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return p.numThreads, nil
|
||||
}
|
||||
|
||||
// Threads returns a map of threads
|
||||
//
|
||||
// Notice: Not implemented yet. always returns empty map.
|
||||
func (p *Process) Threads() (map[string]string, error) {
|
||||
ret := make(map[string]string, 0)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Times returns CPU times of the process.
|
||||
func (p *Process) Times() (*cpu.TimesStat, error) {
|
||||
_, _, cpuTimes, _, _, err := p.fillFromStat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cpuTimes, nil
|
||||
}
|
||||
|
||||
// CPUAffinity returns CPU affinity of the process.
|
||||
//
|
||||
// Notice: Not implemented yet.
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// MemoryInfo returns platform in-dependend memory information, such as RSS, VMS and Swap
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
meminfo, _, err := p.fillFromStatm()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return meminfo, nil
|
||||
}
|
||||
|
||||
// MemoryInfoEx returns platform dependend memory information.
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
_, memInfoEx, err := p.fillFromStatm()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return memInfoEx, nil
|
||||
}
|
||||
|
||||
// Children returns a slice of Process of the process.
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
pids, err := common.CallPgrep(invoke, p.Pid)
|
||||
if err != nil {
|
||||
if pids == nil || len(pids) == 0 {
|
||||
return nil, ErrorNoChildren
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
ret := make([]*Process, 0, len(pids))
|
||||
for _, pid := range pids {
|
||||
np, err := NewProcess(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret = append(ret, np)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// OpenFiles returns a slice of OpenFilesStat opend by the process.
|
||||
// OpenFilesStat includes a file path and file descriptor.
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
_, ofs, err := p.fillFromfd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make([]OpenFilesStat, len(ofs))
|
||||
for i, o := range ofs {
|
||||
ret[i] = *o
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Connections returns a slice of net.ConnectionStat used by the process.
|
||||
// This returns all kind of the connection. This measn TCP, UDP or UNIX.
|
||||
func (p *Process) Connections() ([]net.ConnectionStat, error) {
|
||||
return net.ConnectionsPid("all", p.Pid)
|
||||
}
|
||||
|
||||
// NetIOCounters returns NetIOCounters of the process.
|
||||
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
|
||||
filename := common.HostProc(strconv.Itoa(int(p.Pid)), "net/dev")
|
||||
return net.IOCountersByFile(pernic, filename)
|
||||
}
|
||||
|
||||
// IsRunning returns whether the process is running or not.
|
||||
// Not implemented yet.
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return true, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
// MemoryMaps get memory maps from /proc/(pid)/smaps
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
pid := p.Pid
|
||||
var ret []MemoryMapsStat
|
||||
smapsPath := common.HostProc(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 := common.HostProc(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))
|
||||
|
||||
var openfiles []*OpenFilesStat
|
||||
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 := common.HostProc(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 := common.HostProc(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 := common.HostProc(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
|
||||
}
|
||||
|
||||
func (p *Process) fillSliceFromCmdline() ([]string, error) {
|
||||
pid := p.Pid
|
||||
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
|
||||
cmdline, err := ioutil.ReadFile(cmdPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cmdline) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if cmdline[len(cmdline)-1] == 0 {
|
||||
cmdline = cmdline[:len(cmdline)-1]
|
||||
}
|
||||
parts := bytes.Split(cmdline, []byte{0})
|
||||
var strParts []string
|
||||
for _, p := range parts {
|
||||
strParts = append(strParts, string(p))
|
||||
}
|
||||
|
||||
return strParts, nil
|
||||
}
|
||||
|
||||
// Get IO status from /proc/(pid)/io
|
||||
func (p *Process) fillFromIO() (*IOCountersStat, error) {
|
||||
pid := p.Pid
|
||||
ioPath := common.HostProc(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 := common.HostProc(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 := common.HostProc(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":
|
||||
p.status = value[0:1]
|
||||
case "PPid", "Ppid":
|
||||
pval, err := strconv.ParseInt(value, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.parent = int32(pval)
|
||||
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.TimesStat, int64, int32, error) {
|
||||
pid := p.Pid
|
||||
statPath := common.HostProc(strconv.Itoa(int(pid)), "stat")
|
||||
contents, err := ioutil.ReadFile(statPath)
|
||||
if err != nil {
|
||||
return "", 0, nil, 0, 0, err
|
||||
}
|
||||
fields := strings.Fields(string(contents))
|
||||
|
||||
i := 1
|
||||
for !strings.HasSuffix(fields[i], ")") {
|
||||
i++
|
||||
}
|
||||
|
||||
termmap, err := getTerminalMap()
|
||||
terminal := ""
|
||||
if err == nil {
|
||||
t, err := strconv.ParseUint(fields[i+5], 10, 64)
|
||||
if err != nil {
|
||||
return "", 0, nil, 0, 0, err
|
||||
}
|
||||
terminal = termmap[t]
|
||||
}
|
||||
|
||||
ppid, err := strconv.ParseInt(fields[i+2], 10, 32)
|
||||
if err != nil {
|
||||
return "", 0, nil, 0, 0, err
|
||||
}
|
||||
utime, err := strconv.ParseFloat(fields[i+12], 64)
|
||||
if err != nil {
|
||||
return "", 0, nil, 0, 0, err
|
||||
}
|
||||
|
||||
stime, err := strconv.ParseFloat(fields[i+13], 64)
|
||||
if err != nil {
|
||||
return "", 0, nil, 0, 0, err
|
||||
}
|
||||
|
||||
cpuTimes := &cpu.TimesStat{
|
||||
CPU: "cpu",
|
||||
User: float64(utime / ClockTicks),
|
||||
System: float64(stime / ClockTicks),
|
||||
}
|
||||
|
||||
bootTime, _ := host.BootTime()
|
||||
t, err := strconv.ParseUint(fields[i+20], 10, 64)
|
||||
if err != nil {
|
||||
return "", 0, nil, 0, 0, err
|
||||
}
|
||||
ctime := (t / uint64(ClockTicks)) + uint64(bootTime)
|
||||
createTime := int64(ctime * 1000)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Pids returns a slice of process ID list which are running now.
|
||||
func Pids() ([]int32, error) {
|
||||
var ret []int32
|
||||
|
||||
d, err := os.Open(common.HostProc())
|
||||
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
|
||||
}
|
||||
9
vendor/github.com/shirou/gopsutil/process/process_linux_386.go
generated
vendored
Normal file
9
vendor/github.com/shirou/gopsutil/process/process_linux_386.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build linux
|
||||
// +build 386
|
||||
|
||||
package process
|
||||
|
||||
const (
|
||||
ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK)
|
||||
PageSize = 4096 // C.sysconf(C._SC_PAGE_SIZE)
|
||||
)
|
||||
9
vendor/github.com/shirou/gopsutil/process/process_linux_amd64.go
generated
vendored
Normal file
9
vendor/github.com/shirou/gopsutil/process/process_linux_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build linux
|
||||
// +build amd64
|
||||
|
||||
package process
|
||||
|
||||
const (
|
||||
ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK)
|
||||
PageSize = 4096 // C.sysconf(C._SC_PAGE_SIZE)
|
||||
)
|
||||
9
vendor/github.com/shirou/gopsutil/process/process_linux_arm.go
generated
vendored
Normal file
9
vendor/github.com/shirou/gopsutil/process/process_linux_arm.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build linux
|
||||
// +build arm
|
||||
|
||||
package process
|
||||
|
||||
const (
|
||||
ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK)
|
||||
PageSize = 4096 // C.sysconf(C._SC_PAGE_SIZE)
|
||||
)
|
||||
9
vendor/github.com/shirou/gopsutil/process/process_linux_arm64.go
generated
vendored
Normal file
9
vendor/github.com/shirou/gopsutil/process/process_linux_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build linux
|
||||
// +build arm64
|
||||
|
||||
package process
|
||||
|
||||
const (
|
||||
ClockTicks = 100 // C.sysconf(C._SC_CLK_TCK)
|
||||
PageSize = 4096 // C.sysconf(C._SC_PAGE_SIZE)
|
||||
)
|
||||
122
vendor/github.com/shirou/gopsutil/process/process_posix.go
generated
vendored
Normal file
122
vendor/github.com/shirou/gopsutil/process/process_posix.go
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
// +build linux freebsd darwin
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// SendSignal sends a syscall.Signal to the process.
|
||||
// Currently, SIGSTOP, SIGCONT, SIGTERM and SIGKILL are supported.
|
||||
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"
|
||||
}
|
||||
|
||||
kill, err := exec.LookPath("kill")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := exec.Command(kill, "-s", sigAsStr, strconv.Itoa(int(p.Pid)))
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
err = common.WaitTimeout(cmd, common.Timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Suspend sends SIGSTOP to the process.
|
||||
func (p *Process) Suspend() error {
|
||||
return p.SendSignal(syscall.SIGSTOP)
|
||||
}
|
||||
|
||||
// Resume sends SIGCONT to the process.
|
||||
func (p *Process) Resume() error {
|
||||
return p.SendSignal(syscall.SIGCONT)
|
||||
}
|
||||
|
||||
// Terminate sends SIGTERM to the process.
|
||||
func (p *Process) Terminate() error {
|
||||
return p.SendSignal(syscall.SIGTERM)
|
||||
}
|
||||
|
||||
// Kill sends SIGKILL to the process.
|
||||
func (p *Process) Kill() error {
|
||||
return p.SendSignal(syscall.SIGKILL)
|
||||
}
|
||||
|
||||
// Username returns a username of the process.
|
||||
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
|
||||
}
|
||||
19
vendor/github.com/shirou/gopsutil/process/process_posix_test.go
generated
vendored
Normal file
19
vendor/github.com/shirou/gopsutil/process/process_posix_test.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// +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)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user