mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-24 13:48:56 +08:00
delete v2 directory, move v3 to top #1078
This commit is contained in:
parent
3b417071a5
commit
0969c9436b
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@ -1,10 +1,6 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: gomod
|
||||
directory: /v3
|
||||
schedule:
|
||||
interval: daily
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
|
11
.github/labeler.yml
vendored
11
.github/labeler.yml
vendored
@ -1,32 +1,21 @@
|
||||
v3:
|
||||
- v3/**/*.go
|
||||
package:cpu:
|
||||
- cpu/*
|
||||
- v3/cpu/*
|
||||
package:disk:
|
||||
- disk/*
|
||||
- v3/disk/*
|
||||
package:docker:
|
||||
- docker/*
|
||||
- v3/docker/*
|
||||
package:host:
|
||||
- host/*
|
||||
- v3/host/*
|
||||
package:load:
|
||||
- load/*
|
||||
- v3/load/*
|
||||
package:mem:
|
||||
- mem/*
|
||||
- v3/mem/*
|
||||
package:net:
|
||||
- net/*
|
||||
- v3/net/*
|
||||
package:process:
|
||||
- process/*
|
||||
- v3/process/*
|
||||
package:winservices:
|
||||
- winservices/*
|
||||
- v3/winservices/*
|
||||
os:linux:
|
||||
- ./**/*_linux.go
|
||||
- ./**/*_linux_mips64.go
|
||||
|
34
.github/workflows/build_test.yml
vendored
34
.github/workflows/build_test.yml
vendored
@ -1,38 +1,6 @@
|
||||
on: [push, pull_request]
|
||||
name: Build Test
|
||||
jobs:
|
||||
build_test_v2:
|
||||
env:
|
||||
GOPATH: ${{ github.workspace }}
|
||||
GO111MODULE: off
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x, 1.17.x]
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: ${{ github.workspace }}/src/github.com/shirou/gopsutil
|
||||
- name: Get dependencies
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
if ! command -v dep &>/dev/null; then
|
||||
mkdir -p $GOPATH/bin
|
||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
echo "PATH=$GOPATH/bin:$PATH" >> $GITHUB_PATH
|
||||
fi
|
||||
cd $GOPATH/src/github.com/shirou/gopsutil
|
||||
dep ensure
|
||||
# exclude v3 from being run with ./...
|
||||
rm -rf $GOPATH/src/github.com/shirou/gopsutil/v3
|
||||
- name: Build Test v2
|
||||
run: |
|
||||
cd $GOPATH/src/github.com/shirou/gopsutil && make build_test
|
||||
build_test_v3:
|
||||
strategy:
|
||||
matrix:
|
||||
@ -47,4 +15,4 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
- name: Build Test v3
|
||||
run: |
|
||||
cd v3 && make build_test
|
||||
make build_test
|
74
.github/workflows/test.yml
vendored
74
.github/workflows/test.yml
vendored
@ -16,76 +16,4 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
- name: Test
|
||||
run: |
|
||||
cd ./v3/
|
||||
go test ./...
|
||||
|
||||
test_v3_gopath:
|
||||
env:
|
||||
GOPATH: ${{ github.workspace }}
|
||||
GO111MODULE: off
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x, 1.17.x]
|
||||
os: [ubuntu-20.04, ubuntu-18.04, windows-2019, windows-2016, macOS-10.15, macos-11]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: ${{ github.workspace }}/src/github.com/shirou/gopsutil
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go get -t github.com/shirou/gopsutil/v3/...
|
||||
- name: Test
|
||||
run: |
|
||||
go test github.com/shirou/gopsutil/v3/...
|
||||
|
||||
test_v2_gopath:
|
||||
env:
|
||||
GOPATH: ${{ github.workspace }}
|
||||
GO111MODULE: off
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x, 1.17.x]
|
||||
os: [ubuntu-20.04, ubuntu-18.04, windows-2019, windows-2016, macOS-10.15, macos-11]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: ${{ github.workspace }}/src/github.com/shirou/gopsutil
|
||||
- name: Get dependencies
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
go get -d -u github.com/golang/dep
|
||||
cd $Env:GOPATH/src/github.com/golang/dep
|
||||
git checkout v0.5.4
|
||||
go install -ldflags="-X main.version=v0.5.4" ./cmd/dep
|
||||
echo "$Env:GOPATH/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
cd $Env:GOPATH/src/github.com/shirou/gopsutil
|
||||
dep ensure
|
||||
# exclude v3 from being run with ./...
|
||||
try { rm -ErrorAction:Stop -Recurse -Force $Env:GOPATH/src/github.com/shirou/gopsutil/v3 } catch [System.Management.Automation.ItemNotFoundException] {}
|
||||
- name: Get dependencies
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
if ! command -v dep &>/dev/null; then
|
||||
mkdir -p $GOPATH/bin
|
||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
echo "PATH=$GOPATH/bin:$PATH" >> $GITHUB_PATH
|
||||
fi
|
||||
cd $GOPATH/src/github.com/shirou/gopsutil
|
||||
dep ensure
|
||||
# exclude v3 from being run with ./...
|
||||
rm -rf $GOPATH/src/github.com/shirou/gopsutil/v3
|
||||
- name: Test
|
||||
run: |
|
||||
go test github.com/shirou/gopsutil/...
|
||||
go test ./...
|
7
Makefile
7
Makefile
@ -2,7 +2,6 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
SUBPKGS=cpu disk docker host internal load mem net process
|
||||
TAG=$(shell date +'v3.%y.%-m' --date='last Month')
|
||||
|
||||
help: ## Show help
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
@ -29,6 +28,7 @@ build_test: ## test only buildable
|
||||
GOOS=netbsd go test ./... | $(BUILD_FAIL_PATTERN)
|
||||
# cross build to OpenBSD not worked since process has "C"
|
||||
# GOOS=openbsd go test ./... | $(BUILD_FAIL_PATTERN)
|
||||
GOOS=plan9 go test ./... | $(BUILD_FAIL_PATTERN)
|
||||
|
||||
ifeq ($(shell uname -s), Darwin)
|
||||
CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)
|
||||
@ -68,6 +68,9 @@ vet:
|
||||
GOOS=windows GOARCH=amd64 go vet ./...
|
||||
GOOS=windows GOARCH=386 go vet ./...
|
||||
|
||||
GOOS=plan9 GOARCH=amd64 go vet ./...
|
||||
GOOS=plan9 GOARCH=386 go vet ./...
|
||||
|
||||
macos_test:
|
||||
CGO_ENABLED=0 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)
|
||||
CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)
|
||||
@ -75,6 +78,8 @@ macos_test:
|
||||
init_tools:
|
||||
go get github.com/golang/dep/cmd/dep
|
||||
|
||||
TAG=$(shell date +'v3.%y.%-m' --date='last Month')
|
||||
|
||||
release:
|
||||
git tag $(TAG)
|
||||
git push origin $(TAG)
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
// TimesStat contains the amounts of time the CPU has spent performing different
|
||||
|
@ -14,11 +14,11 @@ import (
|
||||
// sys/resource.h
|
||||
const (
|
||||
CPUser = 0
|
||||
CPNice = 1
|
||||
CPSys = 2
|
||||
CPIntr = 3
|
||||
CPIdle = 4
|
||||
CPUStates = 5
|
||||
cpNice = 1
|
||||
cpSys = 2
|
||||
cpIntr = 3
|
||||
cpIdle = 4
|
||||
cpUStates = 5
|
||||
)
|
||||
|
||||
// default value. from time.h
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
package cpu
|
||||
|
||||
import "github.com/shirou/gopsutil/internal/common"
|
||||
import "github.com/shirou/gopsutil/v3/internal/common"
|
||||
|
||||
func perCPUTimes() ([]TimesStat, error) {
|
||||
return []TimesStat{}, common.ErrNotImplementedError
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/tklauser/go-sysconf"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows,!dragonfly
|
||||
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows,!dragonfly,!plan9
|
||||
|
||||
package cpu
|
||||
|
||||
@ -6,7 +6,7 @@ import (
|
||||
"context"
|
||||
"runtime"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func Times(percpu bool) ([]TimesStat, error) {
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/tklauser/go-sysconf"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func TestParseDmesgBoot(t *testing.T) {
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/tklauser/go-sysconf"
|
||||
)
|
||||
|
||||
@ -321,7 +321,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
if err == nil {
|
||||
for _, line := range lines {
|
||||
line = strings.ToLower(line)
|
||||
if strings.HasPrefix(line, "processor") {
|
||||
if strings.HasPrefix(line, "processor") {
|
||||
_, err = strconv.Atoi(strings.TrimSpace(line[strings.IndexByte(line, ':')+1:]))
|
||||
if err == nil {
|
||||
ret++
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/tklauser/go-sysconf"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
@ -20,20 +20,20 @@ import (
|
||||
// sys/sched.h
|
||||
var (
|
||||
CPUser = 0
|
||||
CPNice = 1
|
||||
CPSys = 2
|
||||
CPIntr = 3
|
||||
CPIdle = 4
|
||||
CPUStates = 5
|
||||
cpNice = 1
|
||||
cpSys = 2
|
||||
cpIntr = 3
|
||||
cpIdle = 4
|
||||
cpUStates = 5
|
||||
)
|
||||
|
||||
// sys/sysctl.h
|
||||
const (
|
||||
CTLKern = 1 // "high kernel": proc, limits
|
||||
CTLHw = 6 // CTL_HW
|
||||
SMT = 24 // HW_SMT
|
||||
KernCptime = 40 // KERN_CPTIME
|
||||
KernCptime2 = 71 // KERN_CPTIME2
|
||||
ctlKern = 1 // "high kernel": proc, limits
|
||||
ctlHw = 6 // CTL_HW
|
||||
sMT = 24 // HW_sMT
|
||||
kernCptime = 40 // KERN_CPTIME
|
||||
kernCptime2 = 71 // KERN_CPTIME2
|
||||
)
|
||||
|
||||
var ClocksPerSec = float64(128)
|
||||
@ -56,15 +56,15 @@ func init() {
|
||||
return
|
||||
}
|
||||
if version >= 6.4 {
|
||||
CPIntr = 4
|
||||
CPIdle = 5
|
||||
CPUStates = 6
|
||||
cpIntr = 4
|
||||
cpIdle = 5
|
||||
cpUStates = 6
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func smt() (bool, error) {
|
||||
mib := []int32{CTLHw, SMT}
|
||||
mib := []int32{ctlHw, sMT}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -108,12 +108,12 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
|
||||
j *= 2
|
||||
}
|
||||
|
||||
var cpuTimes = make([]int32, CPUStates)
|
||||
var cpuTimes = make([]int32, cpUStates)
|
||||
var mib []int32
|
||||
if percpu {
|
||||
mib = []int32{CTLKern, KernCptime2, int32(j)}
|
||||
mib = []int32{ctlKern, kernCptime2, int32(j)}
|
||||
} else {
|
||||
mib = []int32{CTLKern, KernCptime}
|
||||
mib = []int32{ctlKern, kernCptime}
|
||||
}
|
||||
buf, _, err := common.CallSyscall(mib)
|
||||
if err != nil {
|
||||
@ -127,10 +127,10 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
|
||||
}
|
||||
c := TimesStat{
|
||||
User: float64(cpuTimes[CPUser]) / ClocksPerSec,
|
||||
Nice: float64(cpuTimes[CPNice]) / ClocksPerSec,
|
||||
System: float64(cpuTimes[CPSys]) / ClocksPerSec,
|
||||
Idle: float64(cpuTimes[CPIdle]) / ClocksPerSec,
|
||||
Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec,
|
||||
Nice: float64(cpuTimes[cpNice]) / ClocksPerSec,
|
||||
System: float64(cpuTimes[cpSys]) / ClocksPerSec,
|
||||
Idle: float64(cpuTimes[cpIdle]) / ClocksPerSec,
|
||||
Irq: float64(cpuTimes[cpIntr]) / ClocksPerSec,
|
||||
}
|
||||
if percpu {
|
||||
c.CPU = fmt.Sprintf("cpu%d", j)
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package cpu
|
||||
@ -5,11 +6,10 @@ package cpu
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
@ -18,15 +18,7 @@ var (
|
||||
procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo")
|
||||
)
|
||||
|
||||
type Win32_Processor struct {
|
||||
Win32_ProcessorWithoutLoadPct
|
||||
LoadPercentage *uint16
|
||||
}
|
||||
|
||||
// LoadPercentage takes a linearly more time as the number of sockets increases.
|
||||
// For vSphere by default corespersocket = 1, meaning for a 40 vCPU VM Get Processor Info
|
||||
// could take more than half a minute.
|
||||
type Win32_ProcessorWithoutLoadPct struct {
|
||||
type win32_Processor struct {
|
||||
Family uint16
|
||||
Manufacturer string
|
||||
Name string
|
||||
@ -51,12 +43,6 @@ type win32_SystemProcessorPerformanceInformation struct {
|
||||
InterruptCount uint32
|
||||
}
|
||||
|
||||
// Win32_PerfFormattedData_PerfOS_System struct to have count of processes and processor queue length
|
||||
type Win32_PerfFormattedData_PerfOS_System struct {
|
||||
Processes uint32
|
||||
ProcessorQueueLength uint32
|
||||
}
|
||||
|
||||
const (
|
||||
ClocksPerSec = 10000000.0
|
||||
|
||||
@ -112,9 +98,8 @@ func Info() ([]InfoStat, error) {
|
||||
|
||||
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
var ret []InfoStat
|
||||
var dst []Win32_ProcessorWithoutLoadPct
|
||||
var dst []win32_Processor
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
q = strings.ReplaceAll(q, "Win32_ProcessorWithoutLoadPct", "Win32_Processor")
|
||||
if err := common.WMIQueryWithContext(ctx, q, &dst); err != nil {
|
||||
return ret, err
|
||||
}
|
||||
@ -142,22 +127,6 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// ProcInfo returns processes count and processor queue length in the system.
|
||||
// There is a single queue for processor even on multiprocessors systems.
|
||||
func ProcInfo() ([]Win32_PerfFormattedData_PerfOS_System, error) {
|
||||
return ProcInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func ProcInfoWithContext(ctx context.Context) ([]Win32_PerfFormattedData_PerfOS_System, error) {
|
||||
var ret []Win32_PerfFormattedData_PerfOS_System
|
||||
q := wmi.CreateQuery(&ret, "")
|
||||
err := common.WMIQueryWithContext(ctx, q, &ret)
|
||||
if err != nil {
|
||||
return []Win32_PerfFormattedData_PerfOS_System{}, err
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// perCPUTimes returns times stat per cpu, per core and overall for all CPUs
|
||||
func perCPUTimes() ([]TimesStat, error) {
|
||||
var ret []TimesStat
|
||||
@ -251,9 +220,8 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
|
||||
}
|
||||
// physical cores https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_psutil_windows.c#L499
|
||||
// for the time being, try with unreliable and slow WMI call…
|
||||
var dst []Win32_ProcessorWithoutLoadPct
|
||||
var dst []win32_Processor
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
q = strings.ReplaceAll(q, "Win32_ProcessorWithoutLoadPct", "Win32_Processor")
|
||||
if err := common.WMIQueryWithContext(ctx, q, &dst); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
24
disk/disk.go
24
disk/disk.go
@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
@ -23,10 +23,10 @@ type UsageStat struct {
|
||||
}
|
||||
|
||||
type PartitionStat struct {
|
||||
Device string `json:"device"`
|
||||
Mountpoint string `json:"mountpoint"`
|
||||
Fstype string `json:"fstype"`
|
||||
Opts string `json:"opts"`
|
||||
Device string `json:"device"`
|
||||
Mountpoint string `json:"mountpoint"`
|
||||
Fstype string `json:"fstype"`
|
||||
Opts []string `json:"opts"`
|
||||
}
|
||||
|
||||
type IOCountersStat struct {
|
||||
@ -80,3 +80,17 @@ func Partitions(all bool) ([]PartitionStat, error) {
|
||||
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
||||
return IOCountersWithContext(context.Background(), names...)
|
||||
}
|
||||
|
||||
// SerialNumber returns Serial Number of given device or empty string
|
||||
// on error. Name of device is expected, eg. /dev/sda
|
||||
func SerialNumber(name string) (string, error) {
|
||||
return SerialNumberWithContext(context.Background(), name)
|
||||
}
|
||||
|
||||
// Label returns label of given device or empty string on error.
|
||||
// Name of device is expected, eg. /dev/sda
|
||||
// Supports label based on devicemapper name
|
||||
// See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
|
||||
func Label(name string) (string, error) {
|
||||
return LabelWithContext(context.Background(), name)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ package disk
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -23,42 +23,42 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
return ret, err
|
||||
}
|
||||
for _, stat := range fs {
|
||||
opts := "rw"
|
||||
opts := []string{"rw"}
|
||||
if stat.Flags&unix.MNT_RDONLY != 0 {
|
||||
opts = "ro"
|
||||
opts = []string{"ro"}
|
||||
}
|
||||
if stat.Flags&unix.MNT_SYNCHRONOUS != 0 {
|
||||
opts += ",sync"
|
||||
opts = append(opts, "sync")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOEXEC != 0 {
|
||||
opts += ",noexec"
|
||||
opts = append(opts, "noexec")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOSUID != 0 {
|
||||
opts += ",nosuid"
|
||||
opts = append(opts, "nosuid")
|
||||
}
|
||||
if stat.Flags&unix.MNT_UNION != 0 {
|
||||
opts += ",union"
|
||||
opts = append(opts, "union")
|
||||
}
|
||||
if stat.Flags&unix.MNT_ASYNC != 0 {
|
||||
opts += ",async"
|
||||
opts = append(opts, "async")
|
||||
}
|
||||
if stat.Flags&unix.MNT_DONTBROWSE != 0 {
|
||||
opts += ",nobrowse"
|
||||
opts = append(opts, "nobrowse")
|
||||
}
|
||||
if stat.Flags&unix.MNT_AUTOMOUNTED != 0 {
|
||||
opts += ",automounted"
|
||||
opts = append(opts, "automounted")
|
||||
}
|
||||
if stat.Flags&unix.MNT_JOURNALED != 0 {
|
||||
opts += ",journaled"
|
||||
opts = append(opts, "journaled")
|
||||
}
|
||||
if stat.Flags&unix.MNT_MULTILABEL != 0 {
|
||||
opts += ",multilabel"
|
||||
opts = append(opts, "multilabel")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOATIME != 0 {
|
||||
opts += ",noatime"
|
||||
opts = append(opts, "noatime")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NODEV != 0 {
|
||||
opts += ",nodev"
|
||||
opts = append(opts, "nodev")
|
||||
}
|
||||
d := PartitionStat{
|
||||
Device: common.ByteToString(stat.Mntfromname[:]),
|
||||
@ -76,3 +76,11 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
func getFsType(stat unix.Statfs_t) string {
|
||||
return common.ByteToString(stat.Fstypename[:])
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
@ -14,12 +14,12 @@ import "C"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
var buf [C.NDRIVE]C.DriveStats
|
||||
n, err := C.readdrivestat(&buf[0], C.int(len(buf)))
|
||||
n, err := C.v3readdrivestat(&buf[0], C.int(len(buf)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ package disk
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
|
@ -5,7 +5,7 @@ package disk
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
||||
@ -19,3 +19,11 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
return nil, common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
// PartitionsWithContext returns disk partition.
|
||||
@ -30,54 +30,54 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
}
|
||||
|
||||
for _, stat := range fs {
|
||||
opts := "rw"
|
||||
opts := []string{"rw"}
|
||||
if stat.Flags&unix.MNT_RDONLY != 0 {
|
||||
opts = "ro"
|
||||
opts = []string{"ro"}
|
||||
}
|
||||
if stat.Flags&unix.MNT_SYNCHRONOUS != 0 {
|
||||
opts += ",sync"
|
||||
opts = append(opts, "sync")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOEXEC != 0 {
|
||||
opts += ",noexec"
|
||||
opts = append(opts, "noexec")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOSUID != 0 {
|
||||
opts += ",nosuid"
|
||||
opts = append(opts, "nosuid")
|
||||
}
|
||||
if stat.Flags&unix.MNT_UNION != 0 {
|
||||
opts += ",union"
|
||||
opts = append(opts, "union")
|
||||
}
|
||||
if stat.Flags&unix.MNT_ASYNC != 0 {
|
||||
opts += ",async"
|
||||
opts = append(opts, "async")
|
||||
}
|
||||
if stat.Flags&unix.MNT_SUIDDIR != 0 {
|
||||
opts += ",suiddir"
|
||||
opts = append(opts, "suiddir")
|
||||
}
|
||||
if stat.Flags&unix.MNT_SOFTDEP != 0 {
|
||||
opts += ",softdep"
|
||||
opts = append(opts, "softdep")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOSYMFOLLOW != 0 {
|
||||
opts += ",nosymfollow"
|
||||
opts = append(opts, "nosymfollow")
|
||||
}
|
||||
if stat.Flags&unix.MNT_GJOURNAL != 0 {
|
||||
opts += ",gjournal"
|
||||
opts = append(opts, "gjournal")
|
||||
}
|
||||
if stat.Flags&unix.MNT_MULTILABEL != 0 {
|
||||
opts += ",multilabel"
|
||||
opts = append(opts, "multilabel")
|
||||
}
|
||||
if stat.Flags&unix.MNT_ACLS != 0 {
|
||||
opts += ",acls"
|
||||
opts = append(opts, "acls")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOATIME != 0 {
|
||||
opts += ",noatime"
|
||||
opts = append(opts, "noatime")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOCLUSTERR != 0 {
|
||||
opts += ",noclusterr"
|
||||
opts = append(opts, "noclusterr")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NOCLUSTERW != 0 {
|
||||
opts += ",noclusterw"
|
||||
opts = append(opts, "noclusterw")
|
||||
}
|
||||
if stat.Flags&unix.MNT_NFS4ACLS != 0 {
|
||||
opts += ",nfsv4acls"
|
||||
opts = append(opts, "nfsv4acls")
|
||||
}
|
||||
|
||||
d := PartitionStat{
|
||||
@ -105,13 +105,13 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
||||
buf := []byte(r)
|
||||
length := len(buf)
|
||||
|
||||
count := int(uint64(length) / uint64(sizeOfDevstat))
|
||||
count := int(uint64(length) / uint64(sizeOfdevstat))
|
||||
|
||||
buf = buf[8:] // devstat.all has version in the head.
|
||||
// parse buf to Devstat
|
||||
// parse buf to devstat
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*sizeOfDevstat : i*sizeOfDevstat+sizeOfDevstat]
|
||||
d, err := parseDevstat(b)
|
||||
b := buf[i*sizeOfdevstat : i*sizeOfdevstat+sizeOfdevstat]
|
||||
d, err := parsedevstat(b)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@ -123,12 +123,12 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
||||
}
|
||||
|
||||
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),
|
||||
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,
|
||||
}
|
||||
@ -138,15 +138,15 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (b Bintime) Compute() float64 {
|
||||
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)
|
||||
|
||||
func parseDevstat(buf []byte) (Devstat, error) {
|
||||
var ds Devstat
|
||||
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)
|
||||
@ -160,3 +160,11 @@ func parseDevstat(buf []byte) (Devstat, error) {
|
||||
func getFsType(stat unix.Statfs_t) string {
|
||||
return common.ByteToString(stat.Fstypename[:])
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
@ -11,14 +11,14 @@ const (
|
||||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0xf0
|
||||
sizeOfdevstat = 0xf0
|
||||
)
|
||||
|
||||
type (
|
||||
@ -29,21 +29,21 @@ type (
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
type devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
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
|
||||
Duration [4]bintime
|
||||
Busy_time bintime
|
||||
Creation_time bintime
|
||||
Block_size uint32
|
||||
Tag_types [3]uint64
|
||||
Flags uint32
|
||||
@ -52,7 +52,7 @@ type Devstat struct {
|
||||
Id *byte
|
||||
Sequence1 uint32
|
||||
}
|
||||
type Bintime struct {
|
||||
type bintime struct {
|
||||
Sec int32
|
||||
Frac uint64
|
||||
}
|
||||
|
@ -11,14 +11,14 @@ const (
|
||||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0x120
|
||||
sizeOfdevstat = 0x120
|
||||
)
|
||||
|
||||
type (
|
||||
@ -29,21 +29,21 @@ type (
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
type devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
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
|
||||
Duration [4]bintime
|
||||
Busy_time bintime
|
||||
Creation_time bintime
|
||||
Block_size uint32
|
||||
Pad_cgo_0 [4]byte
|
||||
Tag_types [3]uint64
|
||||
@ -55,7 +55,7 @@ type Devstat struct {
|
||||
Sequence1 uint32
|
||||
Pad_cgo_2 [4]byte
|
||||
}
|
||||
type Bintime struct {
|
||||
type bintime struct {
|
||||
Sec int64
|
||||
Frac uint64
|
||||
}
|
||||
|
@ -11,14 +11,14 @@ const (
|
||||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0xf0
|
||||
sizeOfdevstat = 0xf0
|
||||
)
|
||||
|
||||
type (
|
||||
@ -29,21 +29,21 @@ type (
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
type devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
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
|
||||
Duration [4]bintime
|
||||
Busy_time bintime
|
||||
Creation_time bintime
|
||||
Block_size uint32
|
||||
Tag_types [3]uint64
|
||||
Flags uint32
|
||||
@ -52,7 +52,7 @@ type Devstat struct {
|
||||
Id *byte
|
||||
Sequence1 uint32
|
||||
}
|
||||
type Bintime struct {
|
||||
type bintime struct {
|
||||
Sec int32
|
||||
Frac uint64
|
||||
}
|
||||
|
@ -13,14 +13,14 @@ const (
|
||||
sizeofLongLong = 0x8
|
||||
sizeofLongDouble = 0x8
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = 0x120
|
||||
sizeOfdevstat = 0x120
|
||||
)
|
||||
|
||||
type (
|
||||
@ -31,21 +31,21 @@ type (
|
||||
_C_long_double int64
|
||||
)
|
||||
|
||||
type Devstat struct {
|
||||
type devstat struct {
|
||||
Sequence0 uint32
|
||||
Allocated int32
|
||||
Start_count uint32
|
||||
End_count uint32
|
||||
Busy_from Bintime
|
||||
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
|
||||
Duration [4]bintime
|
||||
Busy_time bintime
|
||||
Creation_time bintime
|
||||
Block_size uint32
|
||||
Tag_types [3]uint64
|
||||
Flags uint32
|
||||
@ -55,7 +55,7 @@ type Devstat struct {
|
||||
Sequence1 uint32
|
||||
Pad_cgo_0 [4]byte
|
||||
}
|
||||
type Bintime struct {
|
||||
type bintime struct {
|
||||
Sec int64
|
||||
Frac uint64
|
||||
}
|
||||
|
@ -13,12 +13,12 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
SectorSize = 512
|
||||
sectorSize = 512
|
||||
)
|
||||
const (
|
||||
// man statfs
|
||||
@ -252,7 +252,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
Device: fields[0],
|
||||
Mountpoint: unescapeFstab(fields[1]),
|
||||
Fstype: fields[2],
|
||||
Opts: fields[3],
|
||||
Opts: strings.Fields(fields[3]),
|
||||
}
|
||||
|
||||
if !all {
|
||||
@ -274,14 +274,10 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
fields := strings.Fields(parts[0])
|
||||
blockDeviceID := fields[2]
|
||||
mountPoint := fields[4]
|
||||
mountOpts := fields[5]
|
||||
mountOpts := strings.Split(fields[5], ",")
|
||||
|
||||
if rootDir := fields[3]; rootDir != "" && rootDir != "/" {
|
||||
if len(mountOpts) == 0 {
|
||||
mountOpts = "bind"
|
||||
} else {
|
||||
mountOpts = "bind," + mountOpts
|
||||
}
|
||||
mountOpts = append(mountOpts, "bind")
|
||||
}
|
||||
|
||||
fields = strings.Fields(parts[1])
|
||||
@ -418,8 +414,8 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
||||
return ret, err
|
||||
}
|
||||
d := IOCountersStat{
|
||||
ReadBytes: rbytes * SectorSize,
|
||||
WriteBytes: wbytes * SectorSize,
|
||||
ReadBytes: rbytes * sectorSize,
|
||||
WriteBytes: wbytes * sectorSize,
|
||||
ReadCount: reads,
|
||||
WriteCount: writes,
|
||||
MergedReadCount: mergedReads,
|
||||
@ -435,25 +431,19 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
||||
}
|
||||
d.Name = name
|
||||
|
||||
d.SerialNumber = GetDiskSerialNumber(name)
|
||||
d.Label = GetLabel(name)
|
||||
d.SerialNumber, _ = SerialNumberWithContext(ctx, name)
|
||||
d.Label, _ = LabelWithContext(ctx, 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 {
|
||||
return GetDiskSerialNumberWithContext(context.Background(), name)
|
||||
}
|
||||
|
||||
func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
var stat unix.Stat_t
|
||||
err := unix.Stat(name, &stat)
|
||||
if err != nil {
|
||||
return ""
|
||||
return "", err
|
||||
}
|
||||
major := unix.Major(uint64(stat.Rdev))
|
||||
minor := unix.Minor(uint64(stat.Rdev))
|
||||
@ -465,7 +455,7 @@ func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
||||
for scanner.Scan() {
|
||||
values := strings.Split(scanner.Text(), "=")
|
||||
if len(values) == 2 && values[0] == "E:ID_SERIAL" {
|
||||
return values[1]
|
||||
return values[1], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -476,28 +466,24 @@ func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
||||
model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
|
||||
serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
|
||||
if len(model) > 0 && len(serial) > 0 {
|
||||
return fmt.Sprintf("%s_%s", string(model), string(serial))
|
||||
return fmt.Sprintf("%s_%s", string(model), string(serial)), nil
|
||||
}
|
||||
return ""
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// GetLabel returns label of given device or empty string on error.
|
||||
// Name of device is expected, eg. /dev/sda
|
||||
// Supports label based on devicemapper name
|
||||
// See https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
|
||||
func GetLabel(name string) string {
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
// Try label based on devicemapper name
|
||||
dmname_filename := common.HostSys(fmt.Sprintf("block/%s/dm/name", name))
|
||||
|
||||
if !common.PathExists(dmname_filename) {
|
||||
return ""
|
||||
return "", nil
|
||||
}
|
||||
|
||||
dmname, err := ioutil.ReadFile(dmname_filename)
|
||||
if err != nil {
|
||||
return ""
|
||||
return "", err
|
||||
} else {
|
||||
return strings.TrimSpace(string(dmname))
|
||||
return strings.TrimSpace(string(dmname)), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -26,33 +26,33 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
}
|
||||
|
||||
for _, stat := range fs {
|
||||
opts := "rw"
|
||||
opts := []string{"rw"}
|
||||
if stat.F_flags&unix.MNT_RDONLY != 0 {
|
||||
opts = "ro"
|
||||
opts = []string{"rw"}
|
||||
}
|
||||
if stat.F_flags&unix.MNT_SYNCHRONOUS != 0 {
|
||||
opts += ",sync"
|
||||
opts = append(opts, "sync")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_NOEXEC != 0 {
|
||||
opts += ",noexec"
|
||||
opts = append(opts, "noexec")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_NOSUID != 0 {
|
||||
opts += ",nosuid"
|
||||
opts = append(opts, "nosuid")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_NODEV != 0 {
|
||||
opts += ",nodev"
|
||||
opts = append(opts, "nodev")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_ASYNC != 0 {
|
||||
opts += ",async"
|
||||
opts = append(opts, "async")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_SOFTDEP != 0 {
|
||||
opts += ",softdep"
|
||||
opts = append(opts, "softdep")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_NOATIME != 0 {
|
||||
opts += ",noatime"
|
||||
opts = append(opts, "noatime")
|
||||
}
|
||||
if stat.F_flags&unix.MNT_WXALLOWED != 0 {
|
||||
opts += ",wxallowed"
|
||||
opts = append(opts, "wxallowed")
|
||||
}
|
||||
|
||||
d := PartitionStat{
|
||||
@ -148,3 +148,11 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
func getFsType(stat unix.Statfs_t) string {
|
||||
return common.IntToString(stat.F_fstypename[:])
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
@ -6,10 +6,10 @@
|
||||
package disk
|
||||
|
||||
const (
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
@ -34,4 +34,4 @@ type Timeval struct {
|
||||
}
|
||||
|
||||
type Diskstat struct{}
|
||||
type Bintime struct{}
|
||||
type bintime struct{}
|
||||
|
@ -4,10 +4,10 @@
|
||||
package disk
|
||||
|
||||
const (
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
@ -33,4 +33,4 @@ type Timeval struct {
|
||||
}
|
||||
|
||||
type Diskstat struct{}
|
||||
type Bintime struct{}
|
||||
type bintime struct{}
|
||||
|
@ -6,10 +6,10 @@
|
||||
package disk
|
||||
|
||||
const (
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
@ -34,4 +34,4 @@ type Timeval struct {
|
||||
}
|
||||
|
||||
type Diskstat struct{}
|
||||
type Bintime struct{}
|
||||
type bintime struct{}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -69,7 +69,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
Device: fields[0],
|
||||
Mountpoint: fields[1],
|
||||
Fstype: fields[2],
|
||||
Opts: fields[3],
|
||||
Opts: strings.Split(fields[3], ","),
|
||||
})
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
@ -113,3 +113,10 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
||||
|
||||
return usageStat, nil
|
||||
}
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func skipIfNotImplementedErr(t *testing.T, err error) {
|
||||
@ -38,12 +38,11 @@ func TestDisk_partitions(t *testing.T) {
|
||||
}
|
||||
t.Log(ret)
|
||||
|
||||
empty := PartitionStat{}
|
||||
if len(ret) == 0 {
|
||||
t.Errorf("ret is empty")
|
||||
}
|
||||
for _, disk := range ret {
|
||||
if disk == empty {
|
||||
if disk.Device == "" {
|
||||
t.Errorf("Could not get device info %v", disk)
|
||||
}
|
||||
}
|
||||
@ -108,9 +107,9 @@ func TestDiskPartitionStat_String(t *testing.T) {
|
||||
Device: "sd01",
|
||||
Mountpoint: "/",
|
||||
Fstype: "ext4",
|
||||
Opts: "ro",
|
||||
Opts: []string{"ro"},
|
||||
}
|
||||
e := `{"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)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
@ -21,8 +21,8 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
FileFileCompression = int64(16) // 0x00000010
|
||||
FileReadOnlyVolume = int64(524288) // 0x00080000
|
||||
fileFileCompression = int64(16) // 0x00000010
|
||||
fileReadOnlyVolume = int64(524288) // 0x00080000
|
||||
)
|
||||
|
||||
// diskPerformance is an equivalent representation of DISK_PERFORMANCE in the Windows API.
|
||||
@ -110,12 +110,12 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
opts := "rw"
|
||||
if lpFileSystemFlags&FileReadOnlyVolume != 0 {
|
||||
opts = "ro"
|
||||
opts := []string{"rw"}
|
||||
if lpFileSystemFlags&fileReadOnlyVolume != 0 {
|
||||
opts = []string{"ro"}
|
||||
}
|
||||
if lpFileSystemFlags&FileFileCompression != 0 {
|
||||
opts += ".compress"
|
||||
if lpFileSystemFlags&fileFileCompression != 0 {
|
||||
opts = append(opts, "compress")
|
||||
}
|
||||
|
||||
d := PartitionStat{
|
||||
@ -181,3 +181,11 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
|
||||
}
|
||||
return drivemap, nil
|
||||
}
|
||||
|
||||
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
||||
func LabelWithContext(ctx context.Context, name string) (string, error) {
|
||||
return "", common.ErrNotImplementedError
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ static int getdrivestat(io_registry_entry_t d, DriveStats *stat);
|
||||
static int fillstat(io_registry_entry_t d, DriveStats *stat);
|
||||
|
||||
int
|
||||
readdrivestat(DriveStats a[], int n)
|
||||
v3readdrivestat(DriveStats a[], int n)
|
||||
{
|
||||
mach_port_t port;
|
||||
CFMutableDictionaryRef match;
|
||||
|
@ -29,5 +29,4 @@ struct CPUStats {
|
||||
natural_t idle;
|
||||
};
|
||||
|
||||
extern int readdrivestat(DriveStats a[], int n);
|
||||
extern int readcpustat(CPUStats *cpu);
|
||||
extern int v3readdrivestat(DriveStats a[], int n);
|
||||
|
@ -38,14 +38,14 @@ const (
|
||||
sizeofLongLong = C.sizeof_longlong
|
||||
sizeofLongDouble = C.sizeof_longlong
|
||||
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
sizeOfDevstat = C.sizeof_struct_devstat
|
||||
sizeOfdevstat = C.sizeof_struct_devstat
|
||||
)
|
||||
|
||||
// Basic types
|
||||
@ -58,5 +58,5 @@ type (
|
||||
_C_long_double C.longlong
|
||||
)
|
||||
|
||||
type Devstat C.struct_devstat
|
||||
type Bintime C.struct_bintime
|
||||
type devstat C.struct_devstat
|
||||
type bintime C.struct_bintime
|
||||
|
@ -15,10 +15,10 @@ package disk
|
||||
import "C"
|
||||
|
||||
const (
|
||||
DEVSTAT_NO_DATA = 0x00
|
||||
DEVSTAT_READ = 0x01
|
||||
DEVSTAT_WRITE = 0x02
|
||||
DEVSTAT_FREE = 0x03
|
||||
devstat_NO_DATA = 0x00
|
||||
devstat_READ = 0x01
|
||||
devstat_WRITE = 0x02
|
||||
devstat_FREE = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
@ -29,4 +29,4 @@ type Diskstats C.struct_diskstats
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Diskstat C.struct_diskstat
|
||||
type Bintime C.struct_bintime
|
||||
type bintime C.struct_bintime
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var ErrDockerNotAvailable = errors.New("docker not available")
|
||||
@ -51,7 +51,7 @@ type CgroupMemStat struct {
|
||||
TotalUnevictable uint64 `json:"totalUnevictable"`
|
||||
MemUsageInBytes uint64 `json:"memUsageInBytes"`
|
||||
MemMaxUsageInBytes uint64 `json:"memMaxUsageInBytes"`
|
||||
MemLimitInBytes uint64 `json:"memoryLimitInBbytes"`
|
||||
MemLimitInBytes uint64 `json:"memoryLimitInBytes"`
|
||||
MemFailCnt uint64 `json:"memoryFailcnt"`
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
cpu "github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
cpu "github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
// GetDockerStat returns a list of Docker basic stats.
|
||||
@ -89,7 +89,7 @@ func GetDockerIDListWithContext(ctx context.Context) ([]string, error) {
|
||||
// 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) {
|
||||
func CgroupCPU(containerID string, base string) (*CgroupCPUStat, error) {
|
||||
return CgroupCPUWithContext(context.Background(), containerID, base)
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ func CgroupCPUUsage(containerID string, base string) (float64, error) {
|
||||
return CgroupCPUUsageWithContext(context.Background(), containerID, base)
|
||||
}
|
||||
|
||||
func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*cpu.TimesStat, error) {
|
||||
func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*CgroupCPUStat, error) {
|
||||
statfile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.stat")
|
||||
lines, err := common.ReadLines(statfile)
|
||||
if err != nil {
|
||||
@ -111,7 +111,9 @@ func CgroupCPUWithContext(ctx context.Context, containerID string, base string)
|
||||
if len(containerID) == 0 {
|
||||
containerID = "all"
|
||||
}
|
||||
ret := &cpu.TimesStat{CPU: containerID}
|
||||
|
||||
ret := &CgroupCPUStat{}
|
||||
ret.CPU = containerID
|
||||
for _, line := range lines {
|
||||
fields := strings.Split(line, " ")
|
||||
if fields[0] == "user" {
|
||||
@ -127,6 +129,11 @@ func CgroupCPUWithContext(ctx context.Context, containerID string, base string)
|
||||
}
|
||||
}
|
||||
}
|
||||
usage, err := CgroupCPUUsageWithContext(ctx, containerID, base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret.Usage = usage
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@ -145,7 +152,7 @@ func CgroupCPUUsageWithContext(ctx context.Context, containerID, base string) (f
|
||||
return ns / nanoseconds, nil
|
||||
}
|
||||
|
||||
func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) {
|
||||
func CgroupCPUDocker(containerid string) (*CgroupCPUStat, error) {
|
||||
return CgroupCPUDockerWithContext(context.Background(), containerid)
|
||||
}
|
||||
|
||||
@ -153,7 +160,7 @@ func CgroupCPUUsageDocker(containerid string) (float64, error) {
|
||||
return CgroupCPUDockerUsageWithContext(context.Background(), containerid)
|
||||
}
|
||||
|
||||
func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*cpu.TimesStat, error) {
|
||||
func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) {
|
||||
return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
|
||||
}
|
||||
|
||||
@ -249,11 +256,11 @@ func CgroupMemWithContext(ctx context.Context, containerID string, base string)
|
||||
if err == nil {
|
||||
ret.MemMaxUsageInBytes = r
|
||||
}
|
||||
r, err = getCgroupMemFile(containerID, base, "memoryLimitInBbytes")
|
||||
r, err = getCgroupMemFile(containerID, base, "memory.limit_in_bytes")
|
||||
if err == nil {
|
||||
ret.MemLimitInBytes = r
|
||||
}
|
||||
r, err = getCgroupMemFile(containerID, base, "memoryFailcnt")
|
||||
r, err = getCgroupMemFile(containerID, base, "memory.failcnt")
|
||||
if err == nil {
|
||||
ret.MemFailCnt = r
|
||||
}
|
||||
|
@ -5,8 +5,7 @@ package docker
|
||||
import (
|
||||
"context"
|
||||
|
||||
cpu "github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
// GetDockerStat returns a list of Docker basic stats.
|
||||
@ -33,19 +32,19 @@ func GetDockerIDListWithContext(ctx context.Context) ([]string, error) {
|
||||
// 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) {
|
||||
func CgroupCPU(containerid string, base string) (*CgroupCPUStat, error) {
|
||||
return CgroupCPUWithContext(context.Background(), containerid, base)
|
||||
}
|
||||
|
||||
func CgroupCPUWithContext(ctx context.Context, containerid string, base string) (*cpu.TimesStat, error) {
|
||||
func CgroupCPUWithContext(ctx context.Context, containerid string, base string) (*CgroupCPUStat, error) {
|
||||
return nil, ErrCgroupNotAvailable
|
||||
}
|
||||
|
||||
func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) {
|
||||
func CgroupCPUDocker(containerid string) (*CgroupCPUStat, error) {
|
||||
return CgroupCPUDockerWithContext(context.Background(), containerid)
|
||||
}
|
||||
|
||||
func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*cpu.TimesStat, error) {
|
||||
func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) {
|
||||
return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
@ -27,7 +27,7 @@ type InfoStat struct {
|
||||
KernelArch string `json:"kernelArch"` // native cpu architecture queried at runtime, as returned by `uname -m` or empty string in case of error
|
||||
VirtualizationSystem string `json:"virtualizationSystem"`
|
||||
VirtualizationRole string `json:"virtualizationRole"` // guest or host
|
||||
HostID string `json:"hostid"` // ex: uuid
|
||||
HostID string `json:"hostId"` // ex: uuid
|
||||
}
|
||||
|
||||
type UserStat struct {
|
||||
@ -39,7 +39,9 @@ type UserStat struct {
|
||||
|
||||
type TemperatureStat struct {
|
||||
SensorKey string `json:"sensorKey"`
|
||||
Temperature float64 `json:"sensorTemperature"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
High float64 `json:"sensorHigh"`
|
||||
Critical float64 `json:"sensorCritical"`
|
||||
}
|
||||
|
||||
func (h InfoStat) String() string {
|
||||
|
@ -13,13 +13,13 @@ import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// from utmpx.h
|
||||
const USER_PROCESS = 7
|
||||
const user_PROCESS = 7
|
||||
|
||||
func HostIDWithContext(ctx context.Context) (string, error) {
|
||||
ioreg, err := exec.LookPath("ioreg")
|
||||
@ -81,7 +81,7 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if u.Type != USER_PROCESS {
|
||||
if u.Type != user_PROCESS {
|
||||
continue
|
||||
}
|
||||
user := UserStat{
|
||||
|
@ -6,7 +6,7 @@ package host
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||
|
@ -5,7 +5,7 @@ package host
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func HostIDWithContext(ctx context.Context) (string, error) {
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
@ -15,11 +15,11 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type LSB struct {
|
||||
type lsbStruct struct {
|
||||
ID string
|
||||
Release string
|
||||
Codename string
|
||||
@ -27,7 +27,11 @@ type LSB struct {
|
||||
}
|
||||
|
||||
// from utmp.h
|
||||
const USER_PROCESS = 7
|
||||
const (
|
||||
user_PROCESS = 7
|
||||
|
||||
hostTemperatureScale = 1000.0
|
||||
)
|
||||
|
||||
func HostIDWithContext(ctx context.Context) (string, error) {
|
||||
sysProductUUID := common.HostSys("class/dmi/id/product_uuid")
|
||||
@ -104,7 +108,7 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if u.Type != USER_PROCESS {
|
||||
if u.Type != user_PROCESS {
|
||||
continue
|
||||
}
|
||||
user := UserStat{
|
||||
@ -120,8 +124,8 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
|
||||
|
||||
}
|
||||
|
||||
func getLSB() (*LSB, error) {
|
||||
ret := &LSB{}
|
||||
func getlsbStruct() (*lsbStruct, error) {
|
||||
ret := &lsbStruct{}
|
||||
if common.PathExists(common.HostEtc("lsb-release")) {
|
||||
contents, err := common.ReadLines(common.HostEtc("lsb-release"))
|
||||
if err != nil {
|
||||
@ -175,9 +179,9 @@ func getLSB() (*LSB, error) {
|
||||
}
|
||||
|
||||
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
|
||||
lsb, err := getLSB()
|
||||
lsb, err := getlsbStruct()
|
||||
if err != nil {
|
||||
lsb = &LSB{}
|
||||
lsb = &lsbStruct{}
|
||||
}
|
||||
|
||||
if common.PathExists(common.HostEtc("oracle-release")) {
|
||||
@ -366,19 +370,27 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
||||
}
|
||||
|
||||
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||
var temperatures []TemperatureStat
|
||||
files, err := filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_*"))
|
||||
if err != nil {
|
||||
var err error
|
||||
|
||||
var files []string
|
||||
|
||||
temperatures := make([]TemperatureStat, 0)
|
||||
|
||||
// Only the temp*_input file provides current temperature
|
||||
// value in millidegree Celsius as reported by the temperature to the device:
|
||||
// https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
|
||||
if files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_input")); err != nil {
|
||||
return temperatures, err
|
||||
}
|
||||
|
||||
if len(files) == 0 {
|
||||
// CentOS has an intermediate /device directory:
|
||||
// https://github.com/giampaolo/psutil/issues/971
|
||||
files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/device/temp*_*"))
|
||||
if err != nil {
|
||||
if files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/device/temp*_input")); err != nil {
|
||||
return temperatures, err
|
||||
}
|
||||
}
|
||||
|
||||
var warns Warnings
|
||||
|
||||
if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files
|
||||
@ -413,6 +425,8 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
|
||||
return temperatures, warns.Reference()
|
||||
}
|
||||
|
||||
temperatures = make([]TemperatureStat, 0, len(files))
|
||||
|
||||
// example directory
|
||||
// device/ temp1_crit_alarm temp2_crit_alarm temp3_crit_alarm temp4_crit_alarm temp5_crit_alarm temp6_crit_alarm temp7_crit_alarm
|
||||
// name temp1_input temp2_input temp3_input temp4_input temp5_input temp6_input temp7_input
|
||||
@ -420,44 +434,81 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
|
||||
// subsystem/ temp1_max temp2_max temp3_max temp4_max temp5_max temp6_max temp7_max
|
||||
// temp1_crit temp2_crit temp3_crit temp4_crit temp5_crit temp6_crit temp7_crit uevent
|
||||
for _, file := range files {
|
||||
filename := strings.Split(filepath.Base(file), "_")
|
||||
if filename[1] == "label" {
|
||||
// Do not try to read the temperature of the label file
|
||||
continue
|
||||
}
|
||||
var raw []byte
|
||||
|
||||
var temperature float64
|
||||
|
||||
// Get the base directory location
|
||||
directory := filepath.Dir(file)
|
||||
|
||||
// Get the base filename prefix like temp1
|
||||
basename := strings.Split(filepath.Base(file), "_")[0]
|
||||
|
||||
// Get the base path like <dir>/temp1
|
||||
basepath := filepath.Join(directory, basename)
|
||||
|
||||
// Get the label of the temperature you are reading
|
||||
var label string
|
||||
c, _ := ioutil.ReadFile(filepath.Join(filepath.Dir(file), filename[0]+"_label"))
|
||||
if c != nil {
|
||||
//format the label from "Core 0" to "core0_"
|
||||
label = fmt.Sprintf("%s_", strings.Join(strings.Split(strings.TrimSpace(strings.ToLower(string(c))), " "), ""))
|
||||
label := ""
|
||||
|
||||
if raw, _ = ioutil.ReadFile(basepath + "_label"); len(raw) != 0 {
|
||||
// Format the label from "Core 0" to "core_0"
|
||||
label = strings.Join(strings.Split(strings.TrimSpace(strings.ToLower(string(raw))), " "), "_")
|
||||
}
|
||||
|
||||
// Get the name of the temperature you are reading
|
||||
name, err := ioutil.ReadFile(filepath.Join(filepath.Dir(file), "name"))
|
||||
if err != nil {
|
||||
if raw, err = ioutil.ReadFile(filepath.Join(directory, "name")); err != nil {
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
|
||||
name := strings.TrimSpace(string(raw))
|
||||
|
||||
if label != "" {
|
||||
name = name + "_" + label
|
||||
}
|
||||
|
||||
// Get the temperature reading
|
||||
current, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
temperature, err := strconv.ParseFloat(strings.TrimSpace(string(current)), 64)
|
||||
if err != nil {
|
||||
if raw, err = ioutil.ReadFile(file); err != nil {
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
|
||||
tempName := strings.TrimSpace(strings.ToLower(string(strings.Join(filename[1:], ""))))
|
||||
if temperature, err = strconv.ParseFloat(strings.TrimSpace(string(raw)), 64); err != nil {
|
||||
warns.Add(err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Add discovered temperature sensor to the list
|
||||
temperatures = append(temperatures, TemperatureStat{
|
||||
SensorKey: fmt.Sprintf("%s_%s%s", strings.TrimSpace(string(name)), label, tempName),
|
||||
Temperature: temperature / 1000.0,
|
||||
SensorKey: name,
|
||||
Temperature: temperature / hostTemperatureScale,
|
||||
High: optionalValueReadFromFile(basepath+"_max") / hostTemperatureScale,
|
||||
Critical: optionalValueReadFromFile(basepath+"_crit") / hostTemperatureScale,
|
||||
})
|
||||
}
|
||||
|
||||
return temperatures, warns.Reference()
|
||||
}
|
||||
|
||||
func optionalValueReadFromFile(filename string) float64 {
|
||||
var raw []byte
|
||||
|
||||
var err error
|
||||
|
||||
var value float64
|
||||
|
||||
// Check if file exists
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if raw, err = ioutil.ReadFile(filename); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
if value, err = strconv.ParseFloat(strings.TrimSpace(string(raw)), 64); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func HostIDWithContext(ctx context.Context) (string, error) {
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func skipIfNotImplementedErr(t *testing.T, err error) {
|
||||
@ -101,7 +101,7 @@ func TestHostInfoStat_String(t *testing.T) {
|
||||
HostID: "edfd25ff-3c9c-b1a4-e660-bd826495ad35",
|
||||
KernelArch: "x86_64",
|
||||
}
|
||||
e := `{"hostname":"test","uptime":3000,"bootTime":1447040000,"procs":100,"os":"linux","platform":"ubuntu","platformFamily":"","platformVersion":"","kernelVersion":"","kernelArch":"x86_64","virtualizationSystem":"","virtualizationRole":"","hostid":"edfd25ff-3c9c-b1a4-e660-bd826495ad35"}`
|
||||
e := `{"hostname":"test","uptime":3000,"bootTime":1447040000,"procs":100,"os":"linux","platform":"ubuntu","platformFamily":"","platformVersion":"","kernelVersion":"","kernelArch":"x86_64","virtualizationSystem":"","virtualizationRole":"","hostId":"edfd25ff-3c9c-b1a4-e660-bd826495ad35"}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("HostInfoStat string is invalid:\ngot %v\nwant %v", v, e)
|
||||
}
|
||||
@ -137,10 +137,12 @@ func TestTemperatureStat_String(t *testing.T) {
|
||||
v := TemperatureStat{
|
||||
SensorKey: "CPU",
|
||||
Temperature: 1.1,
|
||||
High: 30.1,
|
||||
Critical: 0.1,
|
||||
}
|
||||
s := `{"sensorKey":"CPU","sensorTemperature":1.1}`
|
||||
s := `{"sensorKey":"CPU","temperature":1.1,"sensorHigh":30.1,"sensorCritical":0.1}`
|
||||
if s != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("TemperatureStat string is invalid")
|
||||
t.Errorf("TemperatureStat string is invalid, %v", fmt.Sprintf("%v", v))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package host
|
||||
@ -13,8 +14,8 @@ import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
@ -253,7 +253,7 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error {
|
||||
b[0] = *v
|
||||
case uint8:
|
||||
bs = b[:1]
|
||||
b[0] = v
|
||||
b[0] = byte(v)
|
||||
case []uint8:
|
||||
bs = v
|
||||
case *int16:
|
||||
|
@ -94,7 +94,7 @@ func (i FakeInvoke) CommandWithContext(ctx context.Context, name string, arg ...
|
||||
|
||||
var ErrNotImplementedError = errors.New("not implemented yet")
|
||||
|
||||
// ReadFile reads contents from a file.
|
||||
// ReadFile reads contents from a file
|
||||
func ReadFile(filename string) (string, error) {
|
||||
content, err := ioutil.ReadFile(filename)
|
||||
|
||||
@ -111,7 +111,7 @@ func ReadLines(filename string) ([]string, error) {
|
||||
return ReadLinesOffsetN(filename, 0, -1)
|
||||
}
|
||||
|
||||
// ReadLinesOffsetN reads contents from file and splits them by new line.
|
||||
// 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
|
||||
@ -165,7 +165,7 @@ func UintToString(orig []uint8) string {
|
||||
size = i
|
||||
break
|
||||
}
|
||||
ret[i] = o
|
||||
ret[i] = byte(o)
|
||||
}
|
||||
if size == -1 {
|
||||
size = len(orig)
|
||||
@ -224,31 +224,31 @@ func ReadInts(filename string) ([]int64, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// HexToUint32 parses Hex to uint32 without error.
|
||||
// Parse Hex to uint32 without error
|
||||
func HexToUint32(hex string) uint32 {
|
||||
vv, _ := strconv.ParseUint(hex, 16, 32)
|
||||
return uint32(vv)
|
||||
}
|
||||
|
||||
// mustParseInt32 parses to int32 without error.
|
||||
// Parse to int32 without error
|
||||
func mustParseInt32(val string) int32 {
|
||||
vv, _ := strconv.ParseInt(val, 10, 32)
|
||||
return int32(vv)
|
||||
}
|
||||
|
||||
// mustParseUint64 parses to uint64 without error.
|
||||
// Parse to uint64 without error
|
||||
func mustParseUint64(val string) uint64 {
|
||||
vv, _ := strconv.ParseInt(val, 10, 64)
|
||||
return uint64(vv)
|
||||
}
|
||||
|
||||
// mustParseFloat64 parses to Float64 without error.
|
||||
// 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.
|
||||
// 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 {
|
||||
@ -258,7 +258,7 @@ func StringsHas(target []string, src string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// StringsContains checks the src in any string of the target string slice.
|
||||
// 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) {
|
||||
@ -308,7 +308,7 @@ func PathExists(filename string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// GetEnv retrieves the environment variable key. If it does not exist it returns the default.
|
||||
//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 == "" {
|
||||
|
@ -26,8 +26,8 @@ func DoSysctrl(mib string) ([]string, error) {
|
||||
return []string{}, err
|
||||
}
|
||||
v := strings.Replace(string(out), "{ ", "", 1)
|
||||
v = strings.Replace(v, " }", "", 1)
|
||||
values := strings.Fields(v)
|
||||
v = strings.Replace(string(v), " }", "", 1)
|
||||
values := strings.Fields(string(v))
|
||||
|
||||
return values, nil
|
||||
}
|
||||
@ -55,6 +55,7 @@ func NumProcs() (uint64, error) {
|
||||
}
|
||||
|
||||
func BootTimeWithContext(ctx context.Context) (uint64, error) {
|
||||
|
||||
system, role, err := Virtualization()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -75,18 +76,6 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if statFile == "uptime" {
|
||||
if len(lines) != 1 {
|
||||
return 0, fmt.Errorf("wrong uptime format")
|
||||
}
|
||||
f := strings.Fields(lines[0])
|
||||
b, err := strconv.ParseFloat(f[0], 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t := uint64(time.Now().Unix()) - uint64(b)
|
||||
return t, nil
|
||||
}
|
||||
if statFile == "stat" {
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(line, "btime") {
|
||||
@ -102,6 +91,17 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
} else if statFile == "uptime" {
|
||||
if len(lines) != 1 {
|
||||
return 0, fmt.Errorf("wrong uptime format")
|
||||
}
|
||||
f := strings.Fields(lines[0])
|
||||
b, err := strconv.ParseFloat(f[0], 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t := uint64(time.Now().Unix()) - uint64(b)
|
||||
return t, nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("could not find btime")
|
||||
@ -111,7 +111,7 @@ func Virtualization() (string, string, error) {
|
||||
return VirtualizationWithContext(context.Background())
|
||||
}
|
||||
|
||||
// required variables for concurrency safe virtualization caching.
|
||||
// required variables for concurrency safe virtualization caching
|
||||
var (
|
||||
cachedVirtMap map[string]string
|
||||
cachedVirtMutex sync.RWMutex
|
||||
@ -137,8 +137,10 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
||||
|
||||
if PathExists(filepath.Join(filename, "capabilities")) {
|
||||
contents, err := ReadLines(filepath.Join(filename, "capabilities"))
|
||||
if err == nil && StringsContains(contents, "control_d") {
|
||||
role = "host"
|
||||
if err == nil {
|
||||
if StringsContains(contents, "control_d") {
|
||||
role = "host"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,17 +149,16 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
||||
if PathExists(filename) {
|
||||
contents, err := ReadLines(filename)
|
||||
if err == nil {
|
||||
switch {
|
||||
case StringsContains(contents, "kvm"):
|
||||
if StringsContains(contents, "kvm") {
|
||||
system = "kvm"
|
||||
role = "host"
|
||||
case StringsContains(contents, "vboxdrv"):
|
||||
} else if StringsContains(contents, "vboxdrv") {
|
||||
system = "vbox"
|
||||
role = "host"
|
||||
case StringsContains(contents, "vboxguest"):
|
||||
} else if StringsContains(contents, "vboxguest") {
|
||||
system = "vbox"
|
||||
role = "guest"
|
||||
case StringsContains(contents, "vmware"):
|
||||
} else if StringsContains(contents, "vmware") {
|
||||
system = "vmware"
|
||||
role = "guest"
|
||||
}
|
||||
@ -200,6 +201,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
||||
if PathExists(filepath.Join(filename, "self", "status")) {
|
||||
contents, err := ReadLines(filepath.Join(filename, "self", "status"))
|
||||
if err == nil {
|
||||
|
||||
if StringsContains(contents, "s_context:") ||
|
||||
StringsContains(contents, "VxID:") {
|
||||
system = "linux-vserver"
|
||||
@ -222,17 +224,16 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
|
||||
if PathExists(filepath.Join(filename, "self", "cgroup")) {
|
||||
contents, err := ReadLines(filepath.Join(filename, "self", "cgroup"))
|
||||
if err == nil {
|
||||
switch {
|
||||
case StringsContains(contents, "lxc"):
|
||||
if StringsContains(contents, "lxc") {
|
||||
system = "lxc"
|
||||
role = "guest"
|
||||
case StringsContains(contents, "docker"):
|
||||
} else if StringsContains(contents, "docker") {
|
||||
system = "docker"
|
||||
role = "guest"
|
||||
case StringsContains(contents, "machine-rkt"):
|
||||
} else if StringsContains(contents, "machine-rkt") {
|
||||
system = "rkt"
|
||||
role = "guest"
|
||||
case PathExists("/usr/bin/lxc-version"):
|
||||
} else if PathExists("/usr/bin/lxc-version") {
|
||||
system = "lxc"
|
||||
role = "host"
|
||||
}
|
||||
@ -280,7 +281,7 @@ func GetOSRelease() (platform string, version string, err error) {
|
||||
return platform, version, nil
|
||||
}
|
||||
|
||||
// trimQuotes removes quotes in the source string.
|
||||
// Remove quotes of the source string
|
||||
func trimQuotes(s string) string {
|
||||
if len(s) >= 2 {
|
||||
if s[0] == '"' && s[len(s)-1] == '"' {
|
||||
|
@ -32,7 +32,8 @@ func TestReadLinesOffsetN(t *testing.T) {
|
||||
|
||||
func TestIntToString(t *testing.T) {
|
||||
src := []int8{65, 66, 67}
|
||||
if dst := IntToString(src); dst != "ABC" {
|
||||
dst := IntToString(src)
|
||||
if dst != "ABC" {
|
||||
t.Error("could not convert")
|
||||
}
|
||||
}
|
||||
@ -57,7 +58,8 @@ func TestHexToUint32(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMustParseInt32(t *testing.T) {
|
||||
if ret := mustParseInt32("11111"); ret != int32(11111) {
|
||||
ret := mustParseInt32("11111")
|
||||
if ret != int32(11111) {
|
||||
t.Error("could not parse")
|
||||
}
|
||||
}
|
||||
@ -100,7 +102,8 @@ func TestHostEtc(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("windows doesn't have etc")
|
||||
}
|
||||
if p := HostEtc("mtab"); p != "/etc/mtab" {
|
||||
p := HostEtc("mtab")
|
||||
if p != "/etc/mtab" {
|
||||
t.Errorf("invalid HostEtc, %s", p)
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,8 @@ func CallLsofWithContext(ctx context.Context, invoke Invoker, pid int32, args ..
|
||||
}
|
||||
|
||||
func CallPgrepWithContext(ctx context.Context, invoke Invoker, pid int32) ([]int32, error) {
|
||||
cmd := []string{"-P", strconv.Itoa(int(pid))}
|
||||
var cmd []string
|
||||
cmd = []string{"-P", strconv.Itoa(int(pid))}
|
||||
pgrep, err := exec.LookPath("pgrep")
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
|
@ -2,11 +2,10 @@ package common_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func TestSleep(test *testing.T) {
|
||||
@ -14,7 +13,7 @@ func TestSleep(test *testing.T) {
|
||||
var t = func(name string, ctx context.Context, expected error) {
|
||||
test.Run(name, func(test *testing.T) {
|
||||
var err = common.Sleep(ctx, dt)
|
||||
if !errors.Is(err, expected) {
|
||||
if err != expected {
|
||||
test.Errorf("expected %v, got %v", expected, err)
|
||||
}
|
||||
})
|
||||
|
@ -3,7 +3,7 @@ package load
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
|
@ -1,3 +1,4 @@
|
||||
//go:build freebsd || openbsd
|
||||
// +build freebsd openbsd
|
||||
|
||||
package load
|
||||
|
@ -5,7 +5,7 @@ package load
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func Avg() (*AvgStat, error) {
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func Avg() (*AvgStat, error) {
|
||||
@ -26,15 +26,16 @@ func AvgWithContext(ctx context.Context) (*AvgStat, error) {
|
||||
|
||||
func sysinfoAvgWithContext(ctx context.Context) (*AvgStat, error) {
|
||||
var info syscall.Sysinfo_t
|
||||
if err := syscall.Sysinfo(&info); err != nil {
|
||||
err := syscall.Sysinfo(&info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
const siLoadShift = 16
|
||||
const si_load_shift = 16
|
||||
return &AvgStat{
|
||||
Load1: float64(info.Loads[0]) / float64(1<<siLoadShift),
|
||||
Load5: float64(info.Loads[1]) / float64(1<<siLoadShift),
|
||||
Load15: float64(info.Loads[2]) / float64(1<<siLoadShift),
|
||||
Load1: float64(info.Loads[0]) / float64(1<<si_load_shift),
|
||||
Load5: float64(info.Loads[1]) / float64(1<<si_load_shift),
|
||||
Load15: float64(info.Loads[2]) / float64(1<<si_load_shift),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -102,6 +103,7 @@ func MiscWithContext(ctx context.Context) (*MiscStat, error) {
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
procsTotal, err := getProcsTotal()
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func Avg() (*AvgStat, error) {
|
||||
|
@ -1,15 +1,14 @@
|
||||
package load
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func skipIfNotImplementedErr(t testing.TB, err error) {
|
||||
if errors.Is(err, common.ErrNotImplementedError) {
|
||||
if err == common.ErrNotImplementedError {
|
||||
t.Skip("not implemented")
|
||||
}
|
||||
}
|
||||
@ -71,6 +70,7 @@ func TestMiscStatString(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkLoad(b *testing.B) {
|
||||
|
||||
loadAvg := func(t testing.TB) {
|
||||
v, err := Avg()
|
||||
skipIfNotImplementedErr(t, err)
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var (
|
||||
|
50
mem/mem.go
50
mem/mem.go
@ -3,7 +3,7 @@ package mem
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
@ -52,30 +52,30 @@ type VirtualMemoryStat struct {
|
||||
// https://www.kernel.org/doc/Documentation/vm/overcommit-accounting
|
||||
Buffers uint64 `json:"buffers"`
|
||||
Cached uint64 `json:"cached"`
|
||||
Writeback uint64 `json:"writeback"`
|
||||
WriteBack uint64 `json:"writeBack"`
|
||||
Dirty uint64 `json:"dirty"`
|
||||
WritebackTmp uint64 `json:"writebacktmp"`
|
||||
WriteBackTmp uint64 `json:"writeBackTmp"`
|
||||
Shared uint64 `json:"shared"`
|
||||
Slab uint64 `json:"slab"`
|
||||
SReclaimable uint64 `json:"sreclaimable"`
|
||||
SUnreclaim uint64 `json:"sunreclaim"`
|
||||
PageTables uint64 `json:"pagetables"`
|
||||
SwapCached uint64 `json:"swapcached"`
|
||||
CommitLimit uint64 `json:"commitlimit"`
|
||||
CommittedAS uint64 `json:"committedas"`
|
||||
HighTotal uint64 `json:"hightotal"`
|
||||
HighFree uint64 `json:"highfree"`
|
||||
LowTotal uint64 `json:"lowtotal"`
|
||||
LowFree uint64 `json:"lowfree"`
|
||||
SwapTotal uint64 `json:"swaptotal"`
|
||||
SwapFree uint64 `json:"swapfree"`
|
||||
Sreclaimable uint64 `json:"sreclaimable"`
|
||||
Sunreclaim uint64 `json:"sunreclaim"`
|
||||
PageTables uint64 `json:"pageTables"`
|
||||
SwapCached uint64 `json:"swapCached"`
|
||||
CommitLimit uint64 `json:"commitLimit"`
|
||||
CommittedAS uint64 `json:"committedAS"`
|
||||
HighTotal uint64 `json:"highTotal"`
|
||||
HighFree uint64 `json:"highFree"`
|
||||
LowTotal uint64 `json:"lowTotal"`
|
||||
LowFree uint64 `json:"lowFree"`
|
||||
SwapTotal uint64 `json:"swapTotal"`
|
||||
SwapFree uint64 `json:"swapFree"`
|
||||
Mapped uint64 `json:"mapped"`
|
||||
VMallocTotal uint64 `json:"vmalloctotal"`
|
||||
VMallocUsed uint64 `json:"vmallocused"`
|
||||
VMallocChunk uint64 `json:"vmallocchunk"`
|
||||
HugePagesTotal uint64 `json:"hugepagestotal"`
|
||||
HugePagesFree uint64 `json:"hugepagesfree"`
|
||||
HugePageSize uint64 `json:"hugepagesize"`
|
||||
VmallocTotal uint64 `json:"vmallocTotal"`
|
||||
VmallocUsed uint64 `json:"vmallocUsed"`
|
||||
VmallocChunk uint64 `json:"vmallocChunk"`
|
||||
HugePagesTotal uint64 `json:"hugePagesTotal"`
|
||||
HugePagesFree uint64 `json:"hugePagesFree"`
|
||||
HugePageSize uint64 `json:"hugePageSize"`
|
||||
}
|
||||
|
||||
type SwapMemoryStat struct {
|
||||
@ -85,13 +85,13 @@ type SwapMemoryStat struct {
|
||||
UsedPercent float64 `json:"usedPercent"`
|
||||
Sin uint64 `json:"sin"`
|
||||
Sout uint64 `json:"sout"`
|
||||
PgIn uint64 `json:"pgin"`
|
||||
PgOut uint64 `json:"pgout"`
|
||||
PgFault uint64 `json:"pgfault"`
|
||||
PgIn uint64 `json:"pgIn"`
|
||||
PgOut uint64 `json:"pgOut"`
|
||||
PgFault uint64 `json:"pgFault"`
|
||||
|
||||
// Linux specific numbers
|
||||
// https://www.kernel.org/doc/Documentation/cgroup-v2.txt
|
||||
PgMajFault uint64 `json:"pgmajfault"`
|
||||
PgMajFault uint64 `json:"pgMajFault"`
|
||||
}
|
||||
|
||||
func (m VirtualMemoryStat) String() string {
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows
|
||||
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows,!plan9
|
||||
|
||||
package mem
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -62,7 +62,7 @@ func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *Virtu
|
||||
memavail := false
|
||||
activeFile := false // "Active(file)" not available: 2.6.28 / Dec 2008
|
||||
inactiveFile := false // "Inactive(file)" not available: 2.6.28 / Dec 2008
|
||||
sReclaimable := false // "SReclaimable:" not available: 2.6.19 / Nov 2006
|
||||
sReclaimable := false // "Sreclaimable:" not available: 2.6.19 / Nov 2006
|
||||
|
||||
ret := &VirtualMemoryStat{}
|
||||
retEx := &VirtualMemoryExStat{}
|
||||
@ -152,18 +152,18 @@ func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *Virtu
|
||||
return ret, retEx, err
|
||||
}
|
||||
retEx.Unevictable = t * 1024
|
||||
case "Writeback":
|
||||
case "WriteBack":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.Writeback = t * 1024
|
||||
case "WritebackTmp":
|
||||
ret.WriteBack = t * 1024
|
||||
case "WriteBackTmp":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.WritebackTmp = t * 1024
|
||||
ret.WriteBackTmp = t * 1024
|
||||
case "Dirty":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
@ -188,13 +188,13 @@ func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *Virtu
|
||||
return ret, retEx, err
|
||||
}
|
||||
sReclaimable = true
|
||||
ret.SReclaimable = t * 1024
|
||||
ret.Sreclaimable = t * 1024
|
||||
case "SUnreclaim":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.SUnreclaim = t * 1024
|
||||
ret.Sunreclaim = t * 1024
|
||||
case "PageTables":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
@ -266,19 +266,19 @@ func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *Virtu
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.VMallocTotal = t * 1024
|
||||
ret.VmallocTotal = t * 1024
|
||||
case "VmallocUsed":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.VMallocUsed = t * 1024
|
||||
ret.VmallocUsed = t * 1024
|
||||
case "VmallocChunk":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return ret, retEx, err
|
||||
}
|
||||
ret.VMallocChunk = t * 1024
|
||||
ret.VmallocChunk = t * 1024
|
||||
case "HugePages_Total":
|
||||
t, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
@ -300,7 +300,7 @@ func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *Virtu
|
||||
}
|
||||
}
|
||||
|
||||
ret.Cached += ret.SReclaimable
|
||||
ret.Cached += ret.Sreclaimable
|
||||
|
||||
if !memavail {
|
||||
if activeFile && inactiveFile && sReclaimable {
|
||||
@ -357,25 +357,25 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
|
||||
continue
|
||||
}
|
||||
ret.Sout = value * 4 * 1024
|
||||
case "pgpgin":
|
||||
case "pgpgIn":
|
||||
value, err := strconv.ParseUint(fields[1], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret.PgIn = value * 4 * 1024
|
||||
case "pgpgout":
|
||||
case "pgpgOut":
|
||||
value, err := strconv.ParseUint(fields[1], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret.PgOut = value * 4 * 1024
|
||||
case "pgfault":
|
||||
case "pgFault":
|
||||
value, err := strconv.ParseUint(fields[1], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret.PgFault = value * 4 * 1024
|
||||
case "pgmajfault":
|
||||
case "pgMajFault":
|
||||
value, err := strconv.ParseUint(fields[1], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
@ -421,7 +421,7 @@ func calcuateAvailVmem(ret *VirtualMemoryStat, retEx *VirtualMemoryExStat) uint6
|
||||
pageCache := retEx.ActiveFile + retEx.InactiveFile
|
||||
pageCache -= uint64(math.Min(float64(pageCache/2), float64(watermarkLow)))
|
||||
availMemory += pageCache
|
||||
availMemory += ret.SReclaimable - uint64(math.Min(float64(ret.SReclaimable/2.0), float64(watermarkLow)))
|
||||
availMemory += ret.Sreclaimable - uint64(math.Min(float64(ret.Sreclaimable/2.0), float64(watermarkLow)))
|
||||
|
||||
if availMemory < 0 {
|
||||
availMemory = 0
|
||||
|
@ -37,13 +37,13 @@ var virtualMemoryTests = []struct {
|
||||
Laundry: 0,
|
||||
Buffers: 212496384,
|
||||
Cached: 4069036032,
|
||||
Writeback: 0,
|
||||
WriteBack: 0,
|
||||
Dirty: 176128,
|
||||
WritebackTmp: 0,
|
||||
WriteBackTmp: 0,
|
||||
Shared: 1222402048,
|
||||
Slab: 253771776,
|
||||
SReclaimable: 186470400,
|
||||
SUnreclaim: 67301376,
|
||||
Sreclaimable: 186470400,
|
||||
Sunreclaim: 67301376,
|
||||
PageTables: 65241088,
|
||||
SwapCached: 0,
|
||||
CommitLimit: 16509730816,
|
||||
@ -55,9 +55,9 @@ var virtualMemoryTests = []struct {
|
||||
SwapTotal: 8258580480,
|
||||
SwapFree: 8258580480,
|
||||
Mapped: 1172627456,
|
||||
VMallocTotal: 35184372087808,
|
||||
VMallocUsed: 0,
|
||||
VMallocChunk: 0,
|
||||
VmallocTotal: 35184372087808,
|
||||
VmallocUsed: 0,
|
||||
VmallocChunk: 0,
|
||||
HugePagesTotal: 0,
|
||||
HugePagesFree: 0,
|
||||
HugePageSize: 2097152},
|
||||
@ -74,13 +74,13 @@ var virtualMemoryTests = []struct {
|
||||
Laundry: 0,
|
||||
Buffers: 4915200,
|
||||
Cached: 96829440,
|
||||
Writeback: 0,
|
||||
WriteBack: 0,
|
||||
Dirty: 0,
|
||||
WritebackTmp: 0,
|
||||
WriteBackTmp: 0,
|
||||
Shared: 0,
|
||||
Slab: 9293824,
|
||||
SReclaimable: 2764800,
|
||||
SUnreclaim: 6529024,
|
||||
Sreclaimable: 2764800,
|
||||
Sunreclaim: 6529024,
|
||||
PageTables: 405504,
|
||||
SwapCached: 0,
|
||||
CommitLimit: 130289664,
|
||||
@ -92,9 +92,9 @@ var virtualMemoryTests = []struct {
|
||||
SwapTotal: 0,
|
||||
SwapFree: 0,
|
||||
Mapped: 38793216,
|
||||
VMallocTotal: 1996488704,
|
||||
VMallocUsed: 0,
|
||||
VMallocChunk: 0,
|
||||
VmallocTotal: 1996488704,
|
||||
VmallocUsed: 0,
|
||||
VmallocChunk: 0,
|
||||
HugePagesTotal: 0,
|
||||
HugePagesFree: 0,
|
||||
HugePageSize: 0},
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
// VirtualMemory for Solaris is a minimal implementation which only returns
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -86,7 +86,7 @@ func TestVirtualMemoryStat_String(t *testing.T) {
|
||||
UsedPercent: 30.1,
|
||||
Free: 40,
|
||||
}
|
||||
e := `{"total":10,"available":20,"used":30,"usedPercent":30.1,"free":40,"active":0,"inactive":0,"wired":0,"laundry":0,"buffers":0,"cached":0,"writeback":0,"dirty":0,"writebacktmp":0,"shared":0,"slab":0,"sreclaimable":0,"sunreclaim":0,"pagetables":0,"swapcached":0,"commitlimit":0,"committedas":0,"hightotal":0,"highfree":0,"lowtotal":0,"lowfree":0,"swaptotal":0,"swapfree":0,"mapped":0,"vmalloctotal":0,"vmallocused":0,"vmallocchunk":0,"hugepagestotal":0,"hugepagesfree":0,"hugepagesize":0}`
|
||||
e := `{"total":10,"available":20,"used":30,"usedPercent":30.1,"free":40,"active":0,"inactive":0,"wired":0,"laundry":0,"buffers":0,"cached":0,"writeBack":0,"dirty":0,"writeBackTmp":0,"shared":0,"slab":0,"sreclaimable":0,"sunreclaim":0,"pageTables":0,"swapCached":0,"commitLimit":0,"committedAS":0,"highTotal":0,"highFree":0,"lowTotal":0,"lowFree":0,"swapTotal":0,"swapFree":0,"mapped":0,"vmallocTotal":0,"vmallocUsed":0,"vmallocChunk":0,"hugePagesTotal":0,"hugePagesFree":0,"hugePageSize":0}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("VirtualMemoryStat string is invalid: %v", v)
|
||||
}
|
||||
@ -105,7 +105,7 @@ func TestSwapMemoryStat_String(t *testing.T) {
|
||||
PgFault: 5,
|
||||
PgMajFault: 6,
|
||||
}
|
||||
e := `{"total":10,"used":30,"free":40,"usedPercent":30.1,"sin":1,"sout":2,"pgin":3,"pgout":4,"pgfault":5,"pgmajfault":6}`
|
||||
e := `{"total":10,"used":30,"free":40,"usedPercent":30.1,"sin":1,"sout":2,"pgIn":3,"pgOut":4,"pgFault":5,"pgMajFault":6}`
|
||||
if e != fmt.Sprintf("%v", v) {
|
||||
t.Errorf("SwapMemoryStat string is invalid: %v", v)
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
71
net/net.go
71
net/net.go
@ -5,7 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var invoke common.Invoker = common.Invoke{}
|
||||
@ -53,39 +53,45 @@ type InterfaceAddr struct {
|
||||
Addr string `json:"addr"`
|
||||
}
|
||||
|
||||
// InterfaceAddrList is a list of InterfaceAddr
|
||||
type InterfaceAddrList []InterfaceAddr
|
||||
|
||||
type InterfaceStat struct {
|
||||
Index int `json:"index"`
|
||||
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"`
|
||||
Index int `json:"index"`
|
||||
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 InterfaceAddrList `json:"addrs"`
|
||||
}
|
||||
|
||||
// InterfaceStatList is a list of InterfaceStat
|
||||
type InterfaceStatList []InterfaceStat
|
||||
|
||||
type FilterStat struct {
|
||||
ConnTrackCount int64 `json:"conntrackCount"`
|
||||
ConnTrackMax int64 `json:"conntrackMax"`
|
||||
ConnTrackCount int64 `json:"connTrackCount"`
|
||||
ConnTrackMax int64 `json:"connTrackMax"`
|
||||
}
|
||||
|
||||
// ConntrackStat has conntrack summary info
|
||||
type ConntrackStat struct {
|
||||
Entries uint32 `json:"entries"` // Number of entries in the conntrack table
|
||||
Searched uint32 `json:"searched"` // Number of conntrack table lookups performed
|
||||
Found uint32 `json:"found"` // Number of searched entries which were successful
|
||||
New uint32 `json:"new"` // Number of entries added which were not expected before
|
||||
Invalid uint32 `json:"invalid"` // Number of packets seen which can not be tracked
|
||||
Ignore uint32 `json:"ignore"` // Packets seen which are already connected to an entry
|
||||
Delete uint32 `json:"delete"` // Number of entries which were removed
|
||||
DeleteList uint32 `json:"delete_list"` // Number of entries which were put to dying list
|
||||
Insert uint32 `json:"insert"` // Number of entries inserted into the list
|
||||
InsertFailed uint32 `json:"insert_failed"` // # insertion attempted but failed (same entry exists)
|
||||
Drop uint32 `json:"drop"` // Number of packets dropped due to conntrack failure.
|
||||
EarlyDrop uint32 `json:"early_drop"` // Dropped entries to make room for new ones, if maxsize reached
|
||||
IcmpError uint32 `json:"icmp_error"` // Subset of invalid. Packets that can't be tracked d/t error
|
||||
ExpectNew uint32 `json:"expect_new"` // Entries added after an expectation was already present
|
||||
ExpectCreate uint32 `json:"expect_create"` // Expectations added
|
||||
ExpectDelete uint32 `json:"expect_delete"` // Expectations deleted
|
||||
SearchRestart uint32 `json:"search_restart"` // Conntrack table lookups restarted due to hashtable resizes
|
||||
Entries uint32 `json:"entries"` // Number of entries in the conntrack table
|
||||
Searched uint32 `json:"searched"` // Number of conntrack table lookups performed
|
||||
Found uint32 `json:"found"` // Number of searched entries which were successful
|
||||
New uint32 `json:"new"` // Number of entries added which were not expected before
|
||||
Invalid uint32 `json:"invalid"` // Number of packets seen which can not be tracked
|
||||
Ignore uint32 `json:"ignore"` // Packets seen which are already connected to an entry
|
||||
Delete uint32 `json:"delete"` // Number of entries which were removed
|
||||
DeleteList uint32 `json:"deleteList"` // Number of entries which were put to dying list
|
||||
Insert uint32 `json:"insert"` // Number of entries inserted into the list
|
||||
InsertFailed uint32 `json:"insertFailed"` // # insertion attempted but failed (same entry exists)
|
||||
Drop uint32 `json:"drop"` // Number of packets dropped due to conntrack failure.
|
||||
EarlyDrop uint32 `json:"earlyDrop"` // Dropped entries to make room for new ones, if maxsize reached
|
||||
IcmpError uint32 `json:"icmpError"` // Subset of invalid. Packets that can't be tracked d/t error
|
||||
ExpectNew uint32 `json:"expectNew"` // Entries added after an expectation was already present
|
||||
ExpectCreate uint32 `json:"expectCreate"` // Expectations added
|
||||
ExpectDelete uint32 `json:"expectDelete"` // Expectations deleted
|
||||
SearchRestart uint32 `json:"searchRestart"` // Conntrack table lookups restarted due to hashtable resizes
|
||||
}
|
||||
|
||||
func NewConntrackStat(e uint32, s uint32, f uint32, n uint32, inv uint32, ign uint32, del uint32, dlst uint32, ins uint32, insfail uint32, drop uint32, edrop uint32, ie uint32, en uint32, ec uint32, ed uint32, sr uint32) *ConntrackStat {
|
||||
@ -182,6 +188,11 @@ func (n InterfaceStat) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (l InterfaceStatList) String() string {
|
||||
s, _ := json.Marshal(l)
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (n InterfaceAddr) String() string {
|
||||
s, _ := json.Marshal(n)
|
||||
return string(s)
|
||||
@ -192,16 +203,16 @@ func (n ConntrackStat) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func Interfaces() ([]InterfaceStat, error) {
|
||||
func Interfaces() (InterfaceStatList, error) {
|
||||
return InterfacesWithContext(context.Background())
|
||||
}
|
||||
|
||||
func InterfacesWithContext(ctx context.Context) ([]InterfaceStat, error) {
|
||||
func InterfacesWithContext(ctx context.Context) (InterfaceStatList, error) {
|
||||
is, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make([]InterfaceStat, 0, len(is))
|
||||
ret := make(InterfaceStatList, 0, len(is))
|
||||
for _, ifi := range is {
|
||||
|
||||
var flags []string
|
||||
@ -230,7 +241,7 @@ func InterfacesWithContext(ctx context.Context) ([]InterfaceStat, error) {
|
||||
}
|
||||
addrs, err := ifi.Addrs()
|
||||
if err == nil {
|
||||
r.Addrs = make([]InterfaceAddr, 0, len(addrs))
|
||||
r.Addrs = make(InterfaceAddrList, 0, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
r.Addrs = append(r.Addrs, InterfaceAddr{
|
||||
Addr: addr.String(),
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func parseNetstatI(output string) ([]IOCountersStat, error) {
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
@ -5,7 +5,7 @@ package net
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
||||
|
@ -16,27 +16,27 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
const ( // Conntrack Column numbers
|
||||
CT_ENTRIES = iota
|
||||
CT_SEARCHED
|
||||
CT_FOUND
|
||||
CT_NEW
|
||||
CT_INVALID
|
||||
CT_IGNORE
|
||||
CT_DELETE
|
||||
CT_DELETE_LIST
|
||||
CT_INSERT
|
||||
CT_INSERT_FAILED
|
||||
CT_DROP
|
||||
CT_EARLY_DROP
|
||||
CT_ICMP_ERROR
|
||||
CT_EXPECT_NEW
|
||||
CT_EXPECT_CREATE
|
||||
CT_EXPECT_DELETE
|
||||
CT_SEARCH_RESTART
|
||||
ctENTRIES = iota
|
||||
ctSEARCHED
|
||||
ctFOUND
|
||||
ctNEW
|
||||
ctINVALID
|
||||
ctIGNORE
|
||||
ctDELETE
|
||||
ctDELETE_LIST
|
||||
ctINSERT
|
||||
ctINSERT_FAILED
|
||||
ctDROP
|
||||
ctEARLY_DROP
|
||||
ctICMP_ERROR
|
||||
CT_EXPEctNEW
|
||||
ctEXPECT_CREATE
|
||||
CT_EXPEctDELETE
|
||||
ctSEARCH_RESTART
|
||||
)
|
||||
|
||||
// NetIOCounters returnes network I/O statistics for every network
|
||||
@ -278,23 +278,23 @@ func conntrackStatsFromFile(filename string, percpu bool) ([]ConntrackStat, erro
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) == 17 && fields[0] != "entries" {
|
||||
statlist.Append(NewConntrackStat(
|
||||
common.HexToUint32(fields[CT_ENTRIES]),
|
||||
common.HexToUint32(fields[CT_SEARCHED]),
|
||||
common.HexToUint32(fields[CT_FOUND]),
|
||||
common.HexToUint32(fields[CT_NEW]),
|
||||
common.HexToUint32(fields[CT_INVALID]),
|
||||
common.HexToUint32(fields[CT_IGNORE]),
|
||||
common.HexToUint32(fields[CT_DELETE]),
|
||||
common.HexToUint32(fields[CT_DELETE_LIST]),
|
||||
common.HexToUint32(fields[CT_INSERT]),
|
||||
common.HexToUint32(fields[CT_INSERT_FAILED]),
|
||||
common.HexToUint32(fields[CT_DROP]),
|
||||
common.HexToUint32(fields[CT_EARLY_DROP]),
|
||||
common.HexToUint32(fields[CT_ICMP_ERROR]),
|
||||
common.HexToUint32(fields[CT_EXPECT_NEW]),
|
||||
common.HexToUint32(fields[CT_EXPECT_CREATE]),
|
||||
common.HexToUint32(fields[CT_EXPECT_DELETE]),
|
||||
common.HexToUint32(fields[CT_SEARCH_RESTART]),
|
||||
common.HexToUint32(fields[ctENTRIES]),
|
||||
common.HexToUint32(fields[ctSEARCHED]),
|
||||
common.HexToUint32(fields[ctFOUND]),
|
||||
common.HexToUint32(fields[ctNEW]),
|
||||
common.HexToUint32(fields[ctINVALID]),
|
||||
common.HexToUint32(fields[ctIGNORE]),
|
||||
common.HexToUint32(fields[ctDELETE]),
|
||||
common.HexToUint32(fields[ctDELETE_LIST]),
|
||||
common.HexToUint32(fields[ctINSERT]),
|
||||
common.HexToUint32(fields[ctINSERT_FAILED]),
|
||||
common.HexToUint32(fields[ctDROP]),
|
||||
common.HexToUint32(fields[ctEARLY_DROP]),
|
||||
common.HexToUint32(fields[ctICMP_ERROR]),
|
||||
common.HexToUint32(fields[CT_EXPEctNEW]),
|
||||
common.HexToUint32(fields[ctEXPECT_CREATE]),
|
||||
common.HexToUint32(fields[CT_EXPEctDELETE]),
|
||||
common.HexToUint32(fields[ctSEARCH_RESTART]),
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -306,7 +306,7 @@ func conntrackStatsFromFile(filename string, percpu bool) ([]ConntrackStat, erro
|
||||
}
|
||||
|
||||
// http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
|
||||
var TCPStatuses = map[string]string{
|
||||
var tcpStatuses = map[string]string{
|
||||
"01": "ESTABLISHED",
|
||||
"02": "SYN_SENT",
|
||||
"03": "SYN_RECV",
|
||||
@ -545,12 +545,12 @@ func getProcInodes(root string, pid int32, max int) (map[string][]inodeMap, erro
|
||||
return ret, err
|
||||
}
|
||||
defer f.Close()
|
||||
files, err := f.Readdir(max)
|
||||
dirEntries, err := f.ReadDir(max)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
for _, fd := range files {
|
||||
inodePath := fmt.Sprintf("%s/%d/fd/%s", root, pid, fd.Name())
|
||||
for _, dirEntry := range dirEntries {
|
||||
inodePath := fmt.Sprintf("%s/%d/fd/%s", root, pid, dirEntry.Name())
|
||||
|
||||
inode, err := os.Readlink(inodePath)
|
||||
if err != nil {
|
||||
@ -566,7 +566,7 @@ func getProcInodes(root string, pid int32, max int) (map[string][]inodeMap, erro
|
||||
if !ok {
|
||||
ret[inode] = make([]inodeMap, 0)
|
||||
}
|
||||
fd, err := strconv.Atoi(fd.Name())
|
||||
fd, err := strconv.Atoi(dirEntry.Name())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@ -786,7 +786,7 @@ func processInet(file string, kind netConnectionKindType, inodes map[string][]in
|
||||
continue
|
||||
}
|
||||
if kind.sockType == syscall.SOCK_STREAM {
|
||||
status = TCPStatuses[status]
|
||||
status = tcpStatuses[status]
|
||||
} else {
|
||||
status = "NONE"
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -187,7 +187,7 @@ func TestConntrackStatFileParsing(t *testing.T) {
|
||||
assert.Nil(t, err, "Temporary file creation failed: ", err)
|
||||
|
||||
data := []byte(`
|
||||
entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete search_restart
|
||||
entries searched found new invalid ignore delete deleteList insert insertFailed drop earlyDrop icmpError expectNew expectCreate expectDelete searchRestart
|
||||
0000007b 00000000 00000000 00000000 000b115a 00000084 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000004a
|
||||
0000007b 00000000 00000000 00000000 0007eee5 00000068 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000035
|
||||
0000007b 00000000 00000000 00000000 0090346b 00000057 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000025
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
var portMatch = regexp.MustCompile(`(.*)\.(\d+)$`)
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
"github.com/shirou/gopsutil/v3/internal/common"
|
||||
)
|
||||
|
||||
func skipIfNotImplementedErr(t *testing.T, err error) {
|
||||
@ -20,7 +20,7 @@ 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}" {
|
||||
if s != `{"ip":"192.168.0.1","port":8000}` {
|
||||
t.Errorf("Addr string is invalid: %v", v)
|
||||
}
|
||||
}
|
||||
@ -232,7 +232,7 @@ func TestNetFilterCounters(t *testing.T) {
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
// some test environment has not the path.
|
||||
if !common.PathExists("/proc/sys/net/netfilter/nf_conntrackCount") {
|
||||
if !common.PathExists("/proc/sys/net/netfilter/nf_connTrackCount") {
|
||||
t.SkipNow()
|
||||
}
|
||||
}
|
||||
@ -247,8 +247,30 @@ func TestNetFilterCounters(t *testing.T) {
|
||||
}
|
||||
for _, vv := range v {
|
||||
if vv.ConnTrackMax == 0 {
|
||||
t.Errorf("nf_conntrackMax needs to be greater than zero: %v", vv)
|
||||
t.Errorf("nf_connTrackMax needs to be greater than zero: %v", vv)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestInterfaceStatString(t *testing.T) {
|
||||
v := InterfaceStat{
|
||||
Index: 0,
|
||||
MTU: 1500,
|
||||
Name: "eth0",
|
||||
HardwareAddr: "01:23:45:67:89:ab",
|
||||
Flags: []string{"up", "down"},
|
||||
Addrs: InterfaceAddrList{{Addr: "1.2.3.4"}, {Addr: "5.6.7.8"}},
|
||||
}
|
||||
|
||||
s := fmt.Sprintf("%v", v)
|
||||
if s != `{"index":0,"mtu":1500,"name":"eth0","hardwareAddr":"01:23:45:67:89:ab","flags":["up","down"],"addrs":[{"addr":"1.2.3.4"},{"addr":"5.6.7.8"}]}` {
|
||||
t.Errorf("InterfaceStat string is invalid: %v", s)
|
||||
}
|
||||
|
||||
list := InterfaceStatList{v, v}
|
||||
s = fmt.Sprintf("%v", list)
|
||||
if s != `[{"index":0,"mtu":1500,"name":"eth0","hardwareAddr":"01:23:45:67:89:ab","flags":["up","down"],"addrs":[{"addr":"1.2.3.4"},{"addr":"5.6.7.8"}]},{"index":0,"mtu":1500,"name":"eth0","hardwareAddr":"01:23:45:67:89:ab","flags":["up","down"],"addrs":[{"addr":"1.2.3.4"},{"addr":"5.6.7.8"}]}]` {
|
||||
t.Errorf("InterfaceStatList string is invalid: %v", s)
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user