...

Source file src/github.com/prometheus/procfs/softirqs.go

Documentation: github.com/prometheus/procfs

     1  // Copyright 2022 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 procfs
    15  
    16  import (
    17  	"bufio"
    18  	"bytes"
    19  	"fmt"
    20  	"io"
    21  	"strconv"
    22  	"strings"
    23  
    24  	"github.com/prometheus/procfs/internal/util"
    25  )
    26  
    27  // Softirqs represents the softirq statistics.
    28  type Softirqs struct {
    29  	Hi      []uint64
    30  	Timer   []uint64
    31  	NetTx   []uint64
    32  	NetRx   []uint64
    33  	Block   []uint64
    34  	IRQPoll []uint64
    35  	Tasklet []uint64
    36  	Sched   []uint64
    37  	HRTimer []uint64
    38  	RCU     []uint64
    39  }
    40  
    41  func (fs FS) Softirqs() (Softirqs, error) {
    42  	fileName := fs.proc.Path("softirqs")
    43  	data, err := util.ReadFileNoStat(fileName)
    44  	if err != nil {
    45  		return Softirqs{}, err
    46  	}
    47  
    48  	reader := bytes.NewReader(data)
    49  
    50  	return parseSoftirqs(reader)
    51  }
    52  
    53  func parseSoftirqs(r io.Reader) (Softirqs, error) {
    54  	var (
    55  		softirqs = Softirqs{}
    56  		scanner  = bufio.NewScanner(r)
    57  	)
    58  
    59  	if !scanner.Scan() {
    60  		return Softirqs{}, fmt.Errorf("%w: softirqs empty", ErrFileRead)
    61  	}
    62  
    63  	for scanner.Scan() {
    64  		parts := strings.Fields(scanner.Text())
    65  		var err error
    66  
    67  		// require at least one cpu
    68  		if len(parts) < 2 {
    69  			continue
    70  		}
    71  		switch {
    72  		case parts[0] == "HI:":
    73  			perCPU := parts[1:]
    74  			softirqs.Hi = make([]uint64, len(perCPU))
    75  			for i, count := range perCPU {
    76  				if softirqs.Hi[i], err = strconv.ParseUint(count, 10, 64); err != nil {
    77  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err)
    78  				}
    79  			}
    80  		case parts[0] == "TIMER:":
    81  			perCPU := parts[1:]
    82  			softirqs.Timer = make([]uint64, len(perCPU))
    83  			for i, count := range perCPU {
    84  				if softirqs.Timer[i], err = strconv.ParseUint(count, 10, 64); err != nil {
    85  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err)
    86  				}
    87  			}
    88  		case parts[0] == "NET_TX:":
    89  			perCPU := parts[1:]
    90  			softirqs.NetTx = make([]uint64, len(perCPU))
    91  			for i, count := range perCPU {
    92  				if softirqs.NetTx[i], err = strconv.ParseUint(count, 10, 64); err != nil {
    93  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err)
    94  				}
    95  			}
    96  		case parts[0] == "NET_RX:":
    97  			perCPU := parts[1:]
    98  			softirqs.NetRx = make([]uint64, len(perCPU))
    99  			for i, count := range perCPU {
   100  				if softirqs.NetRx[i], err = strconv.ParseUint(count, 10, 64); err != nil {
   101  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err)
   102  				}
   103  			}
   104  		case parts[0] == "BLOCK:":
   105  			perCPU := parts[1:]
   106  			softirqs.Block = make([]uint64, len(perCPU))
   107  			for i, count := range perCPU {
   108  				if softirqs.Block[i], err = strconv.ParseUint(count, 10, 64); err != nil {
   109  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err)
   110  				}
   111  			}
   112  		case parts[0] == "IRQ_POLL:":
   113  			perCPU := parts[1:]
   114  			softirqs.IRQPoll = make([]uint64, len(perCPU))
   115  			for i, count := range perCPU {
   116  				if softirqs.IRQPoll[i], err = strconv.ParseUint(count, 10, 64); err != nil {
   117  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err)
   118  				}
   119  			}
   120  		case parts[0] == "TASKLET:":
   121  			perCPU := parts[1:]
   122  			softirqs.Tasklet = make([]uint64, len(perCPU))
   123  			for i, count := range perCPU {
   124  				if softirqs.Tasklet[i], err = strconv.ParseUint(count, 10, 64); err != nil {
   125  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err)
   126  				}
   127  			}
   128  		case parts[0] == "SCHED:":
   129  			perCPU := parts[1:]
   130  			softirqs.Sched = make([]uint64, len(perCPU))
   131  			for i, count := range perCPU {
   132  				if softirqs.Sched[i], err = strconv.ParseUint(count, 10, 64); err != nil {
   133  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err)
   134  				}
   135  			}
   136  		case parts[0] == "HRTIMER:":
   137  			perCPU := parts[1:]
   138  			softirqs.HRTimer = make([]uint64, len(perCPU))
   139  			for i, count := range perCPU {
   140  				if softirqs.HRTimer[i], err = strconv.ParseUint(count, 10, 64); err != nil {
   141  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err)
   142  				}
   143  			}
   144  		case parts[0] == "RCU:":
   145  			perCPU := parts[1:]
   146  			softirqs.RCU = make([]uint64, len(perCPU))
   147  			for i, count := range perCPU {
   148  				if softirqs.RCU[i], err = strconv.ParseUint(count, 10, 64); err != nil {
   149  					return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (RCU%d): %w", ErrFileParse, count, i, err)
   150  				}
   151  			}
   152  		}
   153  	}
   154  
   155  	if err := scanner.Err(); err != nil {
   156  		return Softirqs{}, fmt.Errorf("%s: couldn't parse softirqs: %w", ErrFileParse, err)
   157  	}
   158  
   159  	return softirqs, scanner.Err()
   160  }
   161  

View as plain text