github.com/core-coin/go-core/v2@v2.1.9/metrics/disk_linux.go (about)

     1  // Copyright 2015 The go-core Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-core library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Contains the Linux implementation of process disk IO counter retrieval.
    18  
    19  package metrics
    20  
    21  import (
    22  	"bufio"
    23  	"fmt"
    24  	"io"
    25  	"os"
    26  	"strconv"
    27  	"strings"
    28  
    29  	"golang.org/x/sys/unix"
    30  )
    31  
    32  // ReadDiskStats retrieves the disk IO stats belonging to the current process.
    33  func ReadDiskStats(stats *DiskStats) error {
    34  	// Open the process disk IO counter file
    35  	inf, err := os.Open(fmt.Sprintf("/proc/%d/io", os.Getpid()))
    36  	if err != nil {
    37  		return err
    38  	}
    39  	defer inf.Close()
    40  	in := bufio.NewReader(inf)
    41  
    42  	// Iterate over the IO counter, and extract what we need
    43  	for {
    44  		// Read the next line and split to key and value
    45  		line, err := in.ReadString('\n')
    46  		if err != nil {
    47  			if err == io.EOF {
    48  				return nil
    49  			}
    50  			return err
    51  		}
    52  		parts := strings.Split(line, ":")
    53  		if len(parts) != 2 {
    54  			continue
    55  		}
    56  		key := strings.TrimSpace(parts[0])
    57  		value, err := strconv.ParseInt(strings.TrimSpace(parts[1]), 10, 64)
    58  		if err != nil {
    59  			return err
    60  		}
    61  
    62  		// Update the counter based on the key
    63  		switch key {
    64  		case "syscr":
    65  			stats.ReadCount = value
    66  		case "syscw":
    67  			stats.WriteCount = value
    68  		case "rchar":
    69  			stats.ReadBytes = value
    70  		case "wchar":
    71  			stats.WriteBytes = value
    72  		}
    73  
    74  		var stat unix.Statfs_t
    75  		wd, err := os.Getwd()
    76  		if err != nil {
    77  			return err
    78  		}
    79  		err = unix.Statfs(wd, &stat)
    80  		if err != nil {
    81  			return err
    82  		}
    83  		stats.FreeSpaceGB = int64(stat.Bavail * uint64(stat.Bsize) / (1 << 30)) // bytes to GB
    84  	}
    85  }