...

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

Documentation: github.com/prometheus/procfs

     1  // Copyright 2017 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  	"fmt"
    19  	"io"
    20  	"os"
    21  	"strconv"
    22  	"strings"
    23  )
    24  
    25  // A BuddyInfo is the details parsed from /proc/buddyinfo.
    26  // The data is comprised of an array of free fragments of each size.
    27  // The sizes are 2^n*PAGE_SIZE, where n is the array index.
    28  type BuddyInfo struct {
    29  	Node  string
    30  	Zone  string
    31  	Sizes []float64
    32  }
    33  
    34  // BuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem.
    35  func (fs FS) BuddyInfo() ([]BuddyInfo, error) {
    36  	file, err := os.Open(fs.proc.Path("buddyinfo"))
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	defer file.Close()
    41  
    42  	return parseBuddyInfo(file)
    43  }
    44  
    45  func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
    46  	var (
    47  		buddyInfo   = []BuddyInfo{}
    48  		scanner     = bufio.NewScanner(r)
    49  		bucketCount = -1
    50  	)
    51  
    52  	for scanner.Scan() {
    53  		var err error
    54  		line := scanner.Text()
    55  		parts := strings.Fields(line)
    56  
    57  		if len(parts) < 4 {
    58  			return nil, fmt.Errorf("%w: Invalid number of fields, found: %v", ErrFileParse, parts)
    59  		}
    60  
    61  		node := strings.TrimRight(parts[1], ",")
    62  		zone := strings.TrimRight(parts[3], ",")
    63  		arraySize := len(parts[4:])
    64  
    65  		if bucketCount == -1 {
    66  			bucketCount = arraySize
    67  		} else {
    68  			if bucketCount != arraySize {
    69  				return nil, fmt.Errorf("%w: mismatch in number of buddyinfo buckets, previous count %d, new count %d", ErrFileParse, bucketCount, arraySize)
    70  			}
    71  		}
    72  
    73  		sizes := make([]float64, arraySize)
    74  		for i := 0; i < arraySize; i++ {
    75  			sizes[i], err = strconv.ParseFloat(parts[i+4], 64)
    76  			if err != nil {
    77  				return nil, fmt.Errorf("%s: Invalid valid in buddyinfo: %f: %w", ErrFileParse, sizes[i], err)
    78  			}
    79  		}
    80  
    81  		buddyInfo = append(buddyInfo, BuddyInfo{node, zone, sizes})
    82  	}
    83  
    84  	return buddyInfo, scanner.Err()
    85  }
    86  

View as plain text