...

Source file src/github.com/prometheus/procfs/proc_interrupts.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  	"errors"
    20  	"fmt"
    21  	"io"
    22  	"strconv"
    23  	"strings"
    24  
    25  	"github.com/prometheus/procfs/internal/util"
    26  )
    27  
    28  // Interrupt represents a single interrupt line.
    29  type Interrupt struct {
    30  	// Info is the type of interrupt.
    31  	Info string
    32  	// Devices is the name of the device that is located at that IRQ
    33  	Devices string
    34  	// Values is the number of interrupts per CPU.
    35  	Values []string
    36  }
    37  
    38  // Interrupts models the content of /proc/interrupts. Key is the IRQ number.
    39  // - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-interrupts
    40  // - https://raspberrypi.stackexchange.com/questions/105802/explanation-of-proc-interrupts-output
    41  type Interrupts map[string]Interrupt
    42  
    43  // Interrupts creates a new instance from a given Proc instance.
    44  func (p Proc) Interrupts() (Interrupts, error) {
    45  	data, err := util.ReadFileNoStat(p.path("interrupts"))
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	return parseInterrupts(bytes.NewReader(data))
    50  }
    51  
    52  func parseInterrupts(r io.Reader) (Interrupts, error) {
    53  	var (
    54  		interrupts = Interrupts{}
    55  		scanner    = bufio.NewScanner(r)
    56  	)
    57  
    58  	if !scanner.Scan() {
    59  		return nil, errors.New("interrupts empty")
    60  	}
    61  	cpuNum := len(strings.Fields(scanner.Text())) // one header per cpu
    62  
    63  	for scanner.Scan() {
    64  		parts := strings.Fields(scanner.Text())
    65  		if len(parts) == 0 { // skip empty lines
    66  			continue
    67  		}
    68  		if len(parts) < 2 {
    69  			return nil, fmt.Errorf("%w: Not enough fields in interrupts (expected 2+ fields but got %d): %s", ErrFileParse, len(parts), parts)
    70  		}
    71  		intName := parts[0][:len(parts[0])-1] // remove trailing :
    72  
    73  		if len(parts) == 2 {
    74  			interrupts[intName] = Interrupt{
    75  				Info:    "",
    76  				Devices: "",
    77  				Values: []string{
    78  					parts[1],
    79  				},
    80  			}
    81  			continue
    82  		}
    83  
    84  		intr := Interrupt{
    85  			Values: parts[1 : cpuNum+1],
    86  		}
    87  
    88  		if _, err := strconv.Atoi(intName); err == nil { // numeral interrupt
    89  			intr.Info = parts[cpuNum+1]
    90  			intr.Devices = strings.Join(parts[cpuNum+2:], " ")
    91  		} else {
    92  			intr.Info = strings.Join(parts[cpuNum+1:], " ")
    93  		}
    94  		interrupts[intName] = intr
    95  	}
    96  
    97  	return interrupts, scanner.Err()
    98  }
    99  

View as plain text