Repository: prometheus/procfs
Pull request #640 (2024-05-14 10:52:04)

chore: deprecate `NewTCPx` methods
Deprecate TCP APIs in favor of `github.com/mdlayher/netlink`.

Refer: https://github.com/prometheus/procfs/pull/622#pullrequestreview-2054345257.


Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 018c8e1..684eb15 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -46,6 +46,7 @@ workflows:
         matrix:
           parameters:
             go_version:
+            - "1.20"
             - "1.21"
             - "1.22"
     - test:
@@ -55,5 +56,6 @@ workflows:
         matrix:
           parameters:
             go_version:
+            - "1.20"
             - "1.21"
             - "1.22"
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index b36f71c..5ceb590 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -24,8 +24,8 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout repository
-        uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
-      - name: install Go
+        uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+      - name: Install Go
         uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
         with:
           go-version: 1.22.x
@@ -33,6 +33,7 @@ jobs:
         run: sudo apt-get update && sudo apt-get -y install libsnmp-dev
         if: github.repository == 'prometheus/snmp_exporter'
       - name: Lint
-        uses: golangci/golangci-lint-action@9d1e0624a798bb64f6c3cea93db47765312263dc # v5.1.0
+        uses: golangci/golangci-lint-action@a4f60bb28d35aeee14e6880718e0c85ff1882e64 # v6.0.1
         with:
-          version: v1.56.2
+          args: --verbose
+          version: v1.59.0
diff --git a/.golangci.yml b/.golangci.yml
index c24864a..d7476d5 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,9 +1,18 @@
 ---
 linters:
   enable:
+  - errcheck
   - godot
+  - gofmt
+  - goimports
+  - gosimple
+  - govet
+  - ineffassign
   - misspell
   - revive
+  - staticcheck
+  - testifylint
+  - unused
 
 linter-settings:
   godot:
@@ -11,5 +20,7 @@ linter-settings:
     exclude:
     # Ignore "See: URL"
     - 'See:'
+  goimports:
+      local-prefixes: github.com/prometheus/procfs
   misspell:
     locale: US
diff --git a/Makefile.common b/Makefile.common
index 0e9ace2..1617292 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -61,7 +61,7 @@ PROMU_URL     := https://github.com/prometheus/promu/releases/download/v$(PROMU_
 SKIP_GOLANGCI_LINT :=
 GOLANGCI_LINT :=
 GOLANGCI_LINT_OPTS ?=
-GOLANGCI_LINT_VERSION ?= v1.56.2
+GOLANGCI_LINT_VERSION ?= v1.59.0
 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
 # windows isn't included here because of the path separator being different.
 ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
diff --git a/go.mod b/go.mod
index af4361a..6e9fd6f 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/prometheus/procfs
 
-go 1.21
+go 1.20
 
 require (
 	github.com/google/go-cmp v0.6.0
diff --git a/net_tcp.go b/net_tcp.go
index 5277629..0396d72 100644
--- a/net_tcp.go
+++ b/net_tcp.go
@@ -25,24 +25,28 @@ type (
 
 // NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams
 // read from /proc/net/tcp.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
 func (fs FS) NetTCP() (NetTCP, error) {
 	return newNetTCP(fs.proc.Path("net/tcp"))
 }
 
 // NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams
 // read from /proc/net/tcp6.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
 func (fs FS) NetTCP6() (NetTCP, error) {
 	return newNetTCP(fs.proc.Path("net/tcp6"))
 }
 
 // NetTCPSummary returns already computed statistics like the total queue lengths
 // for TCP datagrams read from /proc/net/tcp.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead.
 func (fs FS) NetTCPSummary() (*NetTCPSummary, error) {
 	return newNetTCPSummary(fs.proc.Path("net/tcp"))
 }
 
 // NetTCP6Summary returns already computed statistics like the total queue lengths
 // for TCP datagrams read from /proc/net/tcp6.
+// Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead.
 func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) {
 	return newNetTCPSummary(fs.proc.Path("net/tcp6"))
 }
diff --git a/sysfs/class_power_supply.go b/sysfs/class_power_supply.go
index c50c32b..cb1a251 100644
--- a/sysfs/class_power_supply.go
+++ b/sysfs/class_power_supply.go
@@ -143,7 +143,7 @@ func parsePowerSupply(path string) (*PowerSupply, error) {
 		name := filepath.Join(path, f.Name())
 		value, err := util.SysReadFile(name)
 		if err != nil {
-			if os.IsNotExist(err) || err.Error() == "operation not supported" || errors.Is(err, os.ErrInvalid) {
+			if os.IsNotExist(err) || err.Error() == "operation not supported" || err.Error() == "no such device" || errors.Is(err, os.ErrInvalid) {
 				continue
 			}
 			return nil, fmt.Errorf("failed to read file %q: %w", name, err)
diff --git a/sysfs/class_thermal.go b/sysfs/class_thermal.go
index ab9048f..10f4a9a 100644
--- a/sysfs/class_thermal.go
+++ b/sysfs/class_thermal.go
@@ -23,8 +23,9 @@ import (
 	"strings"
 	"syscall"
 
-	"github.com/prometheus/procfs/internal/util"
 	fsp "io/fs"
+
+	"github.com/prometheus/procfs/internal/util"
 )
 
 // ClassThermalZoneStats contains info from files in /sys/class/thermal/thermal_zone<zone>
diff --git a/sysfs/system_cpu.go b/sysfs/system_cpu.go
index 5b1bec8..a68c6d9 100644
--- a/sysfs/system_cpu.go
+++ b/sysfs/system_cpu.go
@@ -132,6 +132,16 @@ func (c CPU) ThermalThrottle() (*CPUThermalThrottle, error) {
 	return t, nil
 }
 
+// Online returns the online status of a CPU from `/sys/devices/system/cpu/cpuN/online`.
+func (c CPU) Online() (bool, error) {
+	cpuPath := filepath.Join(string(c), "online")
+	str, err := util.SysReadFile(cpuPath)
+	if err != nil {
+		return false, err
+	}
+	return str == "1", nil
+}
+
 func parseCPUThermalThrottle(cpuPath string) (*CPUThermalThrottle, error) {
 	t := CPUThermalThrottle{}
 	var err error


Test patch:
diff --git a/mdstat_test.go b/mdstat_test.go
index adeb2bb..7a577ed 100644
--- a/mdstat_test.go
+++ b/mdstat_test.go
@@ -13,8 +13,11 @@
 
 package procfs
 
-import "testing"
-import "github.com/google/go-cmp/cmp"
+import (
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
 
 func TestFS_MDStat(t *testing.T) {
 	fs := getProcFixtures(t)
diff --git a/net_conntrackstat_test.go b/net_conntrackstat_test.go
index b19222a..67aa18d 100644
--- a/net_conntrackstat_test.go
+++ b/net_conntrackstat_test.go
@@ -34,7 +34,7 @@ func TestParseConntrackStat(t *testing.T) {
 	}
 
 	want := []ConntrackStatEntry{
-		ConntrackStatEntry{
+		{
 			Entries:       33,
 			Found:         0,
 			Invalid:       3,
@@ -45,7 +45,7 @@ func TestParseConntrackStat(t *testing.T) {
 			EarlyDrop:     0,
 			SearchRestart: 0,
 		},
-		ConntrackStatEntry{
+		{
 			Entries:       33,
 			Found:         0,
 			Invalid:       2,
@@ -56,7 +56,7 @@ func TestParseConntrackStat(t *testing.T) {
 			EarlyDrop:     0,
 			SearchRestart: 2,
 		},
-		ConntrackStatEntry{
+		{
 			Entries:       33,
 			Found:         0,
 			Invalid:       1,
@@ -67,7 +67,7 @@ func TestParseConntrackStat(t *testing.T) {
 			EarlyDrop:     0,
 			SearchRestart: 1,
 		},
-		ConntrackStatEntry{
+		{
 			Entries:       33,
 			Found:         0,
 			Invalid:       47,
@@ -96,7 +96,7 @@ func TestParseOldConntrackStat(t *testing.T) {
 	}
 
 	want := []ConntrackStatEntry{
-		ConntrackStatEntry{
+		{
 			Entries:       43,
 			Searched:      202143,
 			Found:         48658538,
diff --git a/net_udp_test.go b/net_udp_test.go
index 6576161..0db53bf 100644
--- a/net_udp_test.go
+++ b/net_udp_test.go
@@ -30,7 +30,7 @@ func Test_newNetUDP(t *testing.T) {
 			name: "udp file found, no error should come up",
 			file: "testdata/fixtures/proc/net/udp",
 			want: []*netIPSocketLine{
-				&netIPSocketLine{
+				{
 					Sl:        0,
 					LocalAddr: net.IP{10, 0, 0, 5},
 					LocalPort: 22,
@@ -43,7 +43,7 @@ func Test_newNetUDP(t *testing.T) {
 					Inode:     2740,
 					Drops:     intToU64(100),
 				},
-				&netIPSocketLine{
+				{
 					Sl:        1,
 					LocalAddr: net.IP{0, 0, 0, 0},
 					LocalPort: 22,
@@ -56,7 +56,7 @@ func Test_newNetUDP(t *testing.T) {
 					Inode:     2740,
 					Drops:     intToU64(100),
 				},
-				&netIPSocketLine{
+				{
 					Sl:        2,
 					LocalAddr: net.IP{0, 0, 0, 0},
 					LocalPort: 22,
@@ -76,7 +76,7 @@ func Test_newNetUDP(t *testing.T) {
 			name: "udp6 file found, no error should come up",
 			file: "testdata/fixtures/proc/net/udp6",
 			want: []*netIPSocketLine{
-				&netIPSocketLine{
+				{
 					Sl:        1315,
 					LocalAddr: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 					LocalPort: 5355,
@@ -89,7 +89,7 @@ func Test_newNetUDP(t *testing.T) {
 					Inode:     21040,
 					Drops:     intToU64(0),
 				},
-				&netIPSocketLine{
+				{
 					Sl:        6073,
 					LocalAddr: net.IP{254, 128, 0, 0, 0, 0, 0, 0, 86, 225, 173, 255, 254, 124, 102, 9},
 					LocalPort: 51073,
diff --git a/proc_test.go b/proc_test.go
index 239e35b..ecf889a 100644
--- a/proc_test.go
+++ b/proc_test.go
@@ -257,9 +257,9 @@ func TestFileDescriptorsInfo(t *testing.T) {
 	sort.Sort(fdinfos)
 	var want = ProcFDInfos{
 		ProcFDInfo{FD: "0", Pos: "0", Flags: "02004000", MntID: "13", InotifyInfos: []InotifyInfo{
-			InotifyInfo{WD: "3", Ino: "1", Sdev: "34", Mask: "fce"},
-			InotifyInfo{WD: "2", Ino: "1300016", Sdev: "fd00002", Mask: "fce"},
-			InotifyInfo{WD: "1", Ino: "2e0001", Sdev: "fd00000", Mask: "fce"},
+			{WD: "3", Ino: "1", Sdev: "34", Mask: "fce"},
+			{WD: "2", Ino: "1300016", Sdev: "fd00002", Mask: "fce"},
+			{WD: "1", Ino: "2e0001", Sdev: "fd00000", Mask: "fce"},
 		}},
 		ProcFDInfo{FD: "1", Pos: "0", Flags: "02004002", MntID: "13", InotifyInfos: nil},
 		ProcFDInfo{FD: "10", Pos: "0", Flags: "02004002", MntID: "9", InotifyInfos: nil},
diff --git a/sysfs/system_cpu_test.go b/sysfs/system_cpu_test.go
index 577c118..a39c570 100644
--- a/sysfs/system_cpu_test.go
+++ b/sysfs/system_cpu_test.go
@@ -18,6 +18,7 @@ package sysfs
 
 import (
 	"errors"
+	"os"
 	"reflect"
 	"testing"
 )
@@ -63,6 +64,34 @@ func TestCPUTopology(t *testing.T) {
 	}
 }
 
+func TestCPUOnline(t *testing.T) {
+	fs, err := NewFS(sysTestFixtures)
+	if err != nil {
+		t.Fatal(err)
+	}
+	cpus, err := fs.CPUs()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if want, have := 3, len(cpus); want != have {
+		t.Errorf("incorrect number of CPUs, have %v, want %v", want, have)
+	}
+	cpu0Online, err := cpus[0].Online()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if want, have := true, cpu0Online; want != have {
+		t.Errorf("incorrect online status, have %v, want %v", want, have)
+	}
+	cpu1Online, err := cpus[1].Online()
+	if err != nil && !errors.Is(err, os.ErrNotExist) {
+		t.Fatal(err)
+	}
+	if want, have := false, cpu1Online; want != have {
+		t.Errorf("incorrect online status, have %v, want %v", want, have)
+	}
+}
+
 func TestCPUThermalThrottle(t *testing.T) {
 	fs, err := NewFS(sysTestFixtures)
 	if err != nil {
diff --git a/testdata/fixtures.ttar b/testdata/fixtures.ttar
index a998b27..61e879e 100644
--- a/testdata/fixtures.ttar
+++ b/testdata/fixtures.ttar
@@ -13441,6 +13441,11 @@ Mode: 775
 Path: fixtures/sys/devices/system/cpu/cpu0/cpufreq
 SymlinkTo: ../cpufreq/policy0
 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/devices/system/cpu/cpu0/online
+Lines: 1
+1EOF
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Directory: fixtures/sys/devices/system/cpu/cpu0/thermal_throttle
 Mode: 755
 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -