Introduce disk io stats metrics (#15512)

This commit is contained in:
Anis Elleuch
2022-08-16 15:13:49 +01:00
committed by GitHub
parent 9c025b8cce
commit 5682685c80
20 changed files with 404 additions and 47 deletions

View File

@@ -30,4 +30,36 @@ type Info struct {
Files uint64
Ffree uint64
FSType string
Major uint32
Minor uint32
}
// DevID is the drive major and minor ids
type DevID struct {
Major uint32
Minor uint32
}
// AllDrivesIOStats is map between drive devices and IO stats
type AllDrivesIOStats map[DevID]IOStats
// IOStats contains stats of a single drive
type IOStats struct {
ReadIOs uint64
ReadMerges uint64
ReadSectors uint64
ReadTicks uint64
WriteIOs uint64
WriteMerges uint64
WriteSectors uint64
WriteTicks uint64
CurrentIOs uint64
TotalTicks uint64
ReqTicks uint64
DiscardIOs uint64
DiscardMerges uint64
DiscardSectors uint64
DiscardTicks uint64
FlushIOs uint64
FlushTicks uint64
}

View File

@@ -21,6 +21,7 @@
package disk
import (
"errors"
"fmt"
"syscall"
)
@@ -46,3 +47,8 @@ func GetInfo(path string) (info Info, err error) {
info.Used = info.Total - info.Free
return info, nil
}
// GetAllDrivesIOStats returns IO stats of all drives found in the machine
func GetAllDrivesIOStats() (info AllDrivesIOStats, err error) {
return nil, errors.New("operation unsupported")
}

View File

@@ -21,6 +21,7 @@
package disk
import (
"errors"
"fmt"
"syscall"
)
@@ -46,3 +47,8 @@ func GetInfo(path string) (info Info, err error) {
info.Used = info.Total - info.Free
return info, nil
}
// GetAllDrivesIOStats returns IO stats of all drives found in the machine
func GetAllDrivesIOStats() (info AllDrivesIOStats, err error) {
return nil, errors.New("operation unsupported")
}

View File

@@ -21,8 +21,14 @@
package disk
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
"syscall"
"golang.org/x/sys/unix"
)
// GetInfo returns total and free bytes available in a directory, e.g. `/`.
@@ -49,5 +55,138 @@ func GetInfo(path string) (info Info, err error) {
return info, fmt.Errorf("detected free space (%d) > total drive space (%d), fs corruption at (%s). please run 'fsck'", info.Free, info.Total, path)
}
info.Used = info.Total - info.Free
st := syscall.Stat_t{}
err = syscall.Stat(path, &st)
if err != nil {
return Info{}, err
}
//nolint:unconvert
devID := uint64(st.Dev) // Needed to support multiple GOARCHs
info.Major = unix.Major(devID)
info.Minor = unix.Minor(devID)
return info, nil
}
const (
statsPath = "/proc/diskstats"
)
// GetAllDrivesIOStats returns IO stats of all drives found in the machine
func GetAllDrivesIOStats() (info AllDrivesIOStats, err error) {
proc, err := os.Open(statsPath)
if err != nil {
return nil, err
}
defer proc.Close()
ret := make(AllDrivesIOStats)
sc := bufio.NewScanner(proc)
for sc.Scan() {
line := sc.Text()
fields := strings.Fields(line)
if len(fields) < 11 {
continue
}
var err error
var ds IOStats
ds.ReadIOs, err = strconv.ParseUint((fields[3]), 10, 64)
if err != nil {
return ret, err
}
ds.ReadMerges, err = strconv.ParseUint((fields[4]), 10, 64)
if err != nil {
return ret, err
}
ds.ReadSectors, err = strconv.ParseUint((fields[5]), 10, 64)
if err != nil {
return ret, err
}
ds.ReadTicks, err = strconv.ParseUint((fields[6]), 10, 64)
if err != nil {
return ret, err
}
ds.WriteIOs, err = strconv.ParseUint((fields[7]), 10, 64)
if err != nil {
return ret, err
}
ds.WriteMerges, err = strconv.ParseUint((fields[8]), 10, 64)
if err != nil {
return ret, err
}
ds.WriteSectors, err = strconv.ParseUint((fields[9]), 10, 64)
if err != nil {
return ret, err
}
ds.WriteTicks, err = strconv.ParseUint((fields[10]), 10, 64)
if err != nil {
return ret, err
}
if len(fields) > 11 {
ds.CurrentIOs, err = strconv.ParseUint((fields[11]), 10, 64)
if err != nil {
return ret, err
}
ds.TotalTicks, err = strconv.ParseUint((fields[12]), 10, 64)
if err != nil {
return ret, err
}
ds.ReqTicks, err = strconv.ParseUint((fields[13]), 10, 64)
if err != nil {
return ret, err
}
}
if len(fields) > 14 {
ds.DiscardIOs, err = strconv.ParseUint((fields[14]), 10, 64)
if err != nil {
return ret, err
}
ds.DiscardMerges, err = strconv.ParseUint((fields[15]), 10, 64)
if err != nil {
return ret, err
}
ds.DiscardSectors, err = strconv.ParseUint((fields[16]), 10, 64)
if err != nil {
return ret, err
}
ds.DiscardTicks, err = strconv.ParseUint((fields[17]), 10, 64)
if err != nil {
return ret, err
}
}
if len(fields) > 18 {
ds.FlushIOs, err = strconv.ParseUint((fields[18]), 10, 64)
if err != nil {
return ret, err
}
ds.FlushTicks, err = strconv.ParseUint((fields[19]), 10, 64)
if err != nil {
return ret, err
}
}
major, err := strconv.ParseUint((fields[0]), 10, 32)
if err != nil {
return ret, err
}
minor, err := strconv.ParseUint((fields[1]), 10, 32)
if err != nil {
return ret, err
}
ret[DevID{uint32(major), uint32(minor)}] = ds
}
if err := sc.Err(); err != nil {
return nil, err
}
return ret, nil
}

View File

@@ -21,6 +21,7 @@
package disk
import (
"errors"
"fmt"
"strconv"
"syscall"
@@ -81,3 +82,8 @@ func GetInfo(path string) (info Info, err error) {
info.Used = info.Total - info.Free
return info, nil
}
// GetAllDrivesIOStats returns IO stats of all drives found in the machine
func GetAllDrivesIOStats() (info AllDrivesIOStats, err error) {
return nil, errors.New("operation unsupported")
}

View File

@@ -21,6 +21,7 @@
package disk
import (
"errors"
"fmt"
"strconv"
"syscall"
@@ -81,3 +82,8 @@ func GetInfo(path string) (info Info, err error) {
info.Used = info.Total - info.Free
return info, nil
}
// GetAllDrivesIOStats returns IO stats of all drives found in the machine
func GetAllDrivesIOStats() (info AllDrivesIOStats, err error) {
return nil, errors.New("operation unsupported")
}

View File

@@ -21,6 +21,7 @@
package disk
import (
"errors"
"fmt"
"golang.org/x/sys/unix"
@@ -46,3 +47,8 @@ func GetInfo(path string) (info Info, err error) {
info.Used = info.Total - info.Free
return info, nil
}
// GetAllDrivesIOStats returns IO stats of all drives found in the machine
func GetAllDrivesIOStats() (info AllDrivesIOStats, err error) {
return nil, errors.New("operation unsupported")
}

View File

@@ -21,6 +21,7 @@
package disk
import (
"errors"
"fmt"
"syscall"
)
@@ -46,3 +47,8 @@ func GetInfo(path string) (info Info, err error) {
info.Used = info.Total - info.Free
return info, nil
}
// GetAllDrivesIOStats returns IO stats of all drives found in the machine
func GetAllDrivesIOStats() (info AllDrivesIOStats, err error) {
return nil, errors.New("operation unsupported")
}

View File

@@ -21,6 +21,7 @@
package disk
import (
"errors"
"fmt"
"golang.org/x/sys/unix"
@@ -46,3 +47,8 @@ func GetInfo(path string) (info Info, err error) {
info.Used = info.Total - info.Free
return info, nil
}
// GetAllDrivesIOStats returns IO stats of all drives found in the machine
func GetAllDrivesIOStats() (info AllDrivesIOStats, err error) {
return nil, errors.New("operation unsupported")
}

View File

@@ -21,6 +21,7 @@
package disk
import (
"errors"
"fmt"
"os"
"syscall"
@@ -106,3 +107,8 @@ func GetInfo(path string) (info Info, err error) {
return info, nil
}
// GetAllDrivesIOStats returns IO stats of all drives found in the machine
func GetAllDrivesIOStats() (info AllDrivesIOStats, err error) {
return nil, errors.New("operation unsupported")
}