Skip to content

Commit afabf5c

Browse files
committed
Squashing commits
Signed-off-by: Muhammad Shahzeb <[email protected]>
1 parent f360499 commit afabf5c

File tree

9 files changed

+175
-15
lines changed

9 files changed

+175
-15
lines changed

.github/workflows/golangci-lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- name: Checkout repository
2727
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
2828
- name: Install Go
29-
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
29+
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
3030
with:
3131
go-version: 1.22.x
3232
- name: Install snmp_exporter/generator dependencies

blockdevice/stats.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ type BlockQueueStats struct {
178178
WriteZeroesMaxBytes uint64
179179
}
180180

181+
type IODeviceStats struct {
182+
IODoneCount uint64
183+
IOErrCount uint64
184+
}
185+
181186
// DeviceMapperInfo models the devicemapper files that are located in the sysfs tree for each block device
182187
// and described in the kernel documentation:
183188
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm
@@ -209,6 +214,7 @@ const (
209214
sysBlockQueue = "queue"
210215
sysBlockDM = "dm"
211216
sysUnderlyingDev = "slaves"
217+
sysDevicePath = "device"
212218
)
213219

214220
// FS represents the pseudo-filesystems proc and sys, which provides an
@@ -474,3 +480,25 @@ func (fs FS) SysBlockDeviceUnderlyingDevices(device string) (UnderlyingDeviceInf
474480
return UnderlyingDeviceInfo{DeviceNames: underlying}, nil
475481

476482
}
483+
484+
// SysBlockDeviceIO returns stats for the block device io counters
485+
// IO done count: /sys/block/<disk>/device/iodone_cnt
486+
// IO error count: /sys/block/<disk>/device/ioerr_cnt.
487+
func (fs FS) SysBlockDeviceIOStat(device string) (IODeviceStats, error) {
488+
var (
489+
ioDeviceStats IODeviceStats
490+
err error
491+
)
492+
for file, p := range map[string]*uint64{
493+
"iodone_cnt": &ioDeviceStats.IODoneCount,
494+
"ioerr_cnt": &ioDeviceStats.IOErrCount,
495+
} {
496+
var val uint64
497+
val, err = util.ReadHexFromFile(fs.sys.Path(sysBlockPath, device, sysDevicePath, file))
498+
if err != nil {
499+
return IODeviceStats{}, err
500+
}
501+
*p = val
502+
}
503+
return ioDeviceStats, nil
504+
}

ext4/ext4.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2019 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
// Package btrfs provides access to statistics exposed by ext4 filesystems.
15+
package ext4
16+
17+
import (
18+
"path/filepath"
19+
"strings"
20+
21+
"github.com/prometheus/procfs/internal/fs"
22+
"github.com/prometheus/procfs/internal/util"
23+
)
24+
25+
const (
26+
sysFSPath = "fs"
27+
sysFSExt4Path = "ext4"
28+
)
29+
30+
// Stats contains statistics for a single Btrfs filesystem.
31+
// See Linux fs/btrfs/sysfs.c for more information.
32+
type Stats struct {
33+
Name string
34+
35+
Errors uint64
36+
Warnings uint64
37+
Messages uint64
38+
}
39+
40+
// FS represents the pseudo-filesystems proc and sys, which provides an
41+
// interface to kernel data structures.
42+
type FS struct {
43+
proc *fs.FS
44+
sys *fs.FS
45+
}
46+
47+
// NewDefaultFS returns a new blockdevice fs using the default mountPoints for proc and sys.
48+
// It will error if either of these mount points can't be read.
49+
func NewDefaultFS() (FS, error) {
50+
return NewFS(fs.DefaultProcMountPoint, fs.DefaultSysMountPoint)
51+
}
52+
53+
// NewFS returns a new XFS handle using the given proc and sys mountPoints. It will error
54+
// if either of the mounts point can't be read.
55+
func NewFS(procMountPoint string, sysMountPoint string) (FS, error) {
56+
if strings.TrimSpace(procMountPoint) == "" {
57+
procMountPoint = fs.DefaultProcMountPoint
58+
}
59+
procfs, err := fs.NewFS(procMountPoint)
60+
if err != nil {
61+
return FS{}, err
62+
}
63+
if strings.TrimSpace(sysMountPoint) == "" {
64+
sysMountPoint = fs.DefaultSysMountPoint
65+
}
66+
sysfs, err := fs.NewFS(sysMountPoint)
67+
if err != nil {
68+
return FS{}, err
69+
}
70+
return FS{&procfs, &sysfs}, nil
71+
}
72+
73+
// ProcStat returns stats for the filesystem.
74+
func (fs FS) ProcStat() ([]*Stats, error) {
75+
matches, err := filepath.Glob(fs.sys.Path("fs/ext4/*"))
76+
if err != nil {
77+
return nil, err
78+
}
79+
80+
stats := make([]*Stats, 0, len(matches))
81+
for _, m := range matches {
82+
s := &Stats{}
83+
84+
// "*" used in glob above indicates the name of the filesystem.
85+
name := filepath.Base(m)
86+
s.Name = name
87+
for file, p := range map[string]*uint64{
88+
"errors_count": &s.Errors,
89+
"warning_count": &s.Warnings,
90+
"msg_count": &s.Messages,
91+
} {
92+
var val uint64
93+
val, err = util.ReadUintFromFile(fs.sys.Path(sysFSPath, sysFSExt4Path, name, file))
94+
if err == nil {
95+
*p = val
96+
}
97+
}
98+
99+
stats = append(stats, s)
100+
}
101+
102+
return stats, nil
103+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ go 1.20
55
require (
66
github.com/google/go-cmp v0.6.0
77
golang.org/x/sync v0.7.0
8-
golang.org/x/sys v0.20.0
8+
golang.org/x/sys v0.21.0
99
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
22
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
33
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
44
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
5-
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
6-
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5+
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
6+
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

internal/util/parse.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,12 @@ func ParseBool(b string) *bool {
110110
}
111111
return &truth
112112
}
113+
114+
// ReadHexFromFile reads a file and attempts to parse a uint64 from a hexadecimal format 0xXX.
115+
func ReadHexFromFile(path string) (uint64, error) {
116+
data, err := os.ReadFile(path)
117+
if err != nil {
118+
return 0, err
119+
}
120+
return strconv.ParseUint(strings.TrimSpace(string(data[2:])), 16, 64)
121+
}

proc_status.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,11 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt
146146
}
147147
}
148148
case "NSpid":
149-
s.NSpids = calcNSPidsList(vString)
149+
nspids, err := calcNSPidsList(vString)
150+
if err != nil {
151+
return err
152+
}
153+
s.NSpids = nspids
150154
case "VmPeak":
151155
s.VmPeak = vUintBytes
152156
case "VmSize":
@@ -222,17 +226,17 @@ func calcCpusAllowedList(cpuString string) []uint64 {
222226
return g
223227
}
224228

225-
func calcNSPidsList(nspidsString string) []uint64 {
226-
s := strings.Split(nspidsString, " ")
229+
func calcNSPidsList(nspidsString string) ([]uint64, error) {
230+
s := strings.Split(nspidsString, "\t")
227231
var nspids []uint64
228232

229233
for _, nspid := range s {
230-
nspid, _ := strconv.ParseUint(nspid, 10, 64)
231-
if nspid == 0 {
232-
continue
234+
nspid, err := strconv.ParseUint(nspid, 10, 64)
235+
if err != nil {
236+
return nil, err
233237
}
234238
nspids = append(nspids, nspid)
235239
}
236240

237-
return nspids
241+
return nspids, nil
238242
}

proc_status_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,19 @@ func TestCpusAllowedList(t *testing.T) {
139139
t.Errorf("want CpusAllowedList %v, have %v", want, have)
140140
}
141141
}
142+
143+
func TestNsPids(t *testing.T) {
144+
p, err := getProcFixtures(t).Proc(26235)
145+
if err != nil {
146+
t.Fatal(err)
147+
}
148+
149+
s, err := p.NewStatus()
150+
if err != nil {
151+
t.Fatal(err)
152+
}
153+
154+
if want, have := []uint64{26235, 1}, s.NSpids; !reflect.DeepEqual(want, have) {
155+
t.Errorf("want NsPids %v, have %v", want, have)
156+
}
157+
}

testdata/fixtures.ttar

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -818,10 +818,10 @@ Uid: 0 0 0 0
818818
Gid: 0 0 0 0
819819
FDSize: 64
820820
Groups:
821-
NStgid: 26235 1
822-
NSpid: 26235 1
823-
NSpgid: 26235 1
824-
NSsid: 26235 1
821+
NStgid: 26235 1
822+
NSpid: 26235 1
823+
NSpgid: 26235 1
824+
NSsid: 26235 1
825825
VmPeak: 758200 kB
826826
VmSize: 758200 kB
827827
VmLck: 0 kB

0 commit comments

Comments
 (0)