blob: d3a8268078c7b02f9bcafbec759e5a288d1fc2e2 [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001// 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
14package procfs
15
16import (
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.
28type BuddyInfo struct {
29 Node string
30 Zone string
31 Sizes []float64
32}
33
34// NewBuddyInfo reads the buddyinfo statistics.
35func NewBuddyInfo() ([]BuddyInfo, error) {
36 fs, err := NewFS(DefaultMountPoint)
37 if err != nil {
38 return nil, err
39 }
40
41 return fs.NewBuddyInfo()
42}
43
44// NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem.
45func (fs FS) NewBuddyInfo() ([]BuddyInfo, error) {
46 file, err := os.Open(fs.Path("buddyinfo"))
47 if err != nil {
48 return nil, err
49 }
50 defer file.Close()
51
52 return parseBuddyInfo(file)
53}
54
55func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
56 var (
57 buddyInfo = []BuddyInfo{}
58 scanner = bufio.NewScanner(r)
59 bucketCount = -1
60 )
61
62 for scanner.Scan() {
63 var err error
64 line := scanner.Text()
65 parts := strings.Fields(line)
66
67 if len(parts) < 4 {
68 return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo")
69 }
70
71 node := strings.TrimRight(parts[1], ",")
72 zone := strings.TrimRight(parts[3], ",")
73 arraySize := len(parts[4:])
74
75 if bucketCount == -1 {
76 bucketCount = arraySize
77 } else {
78 if bucketCount != arraySize {
79 return nil, fmt.Errorf("mismatch in number of buddyinfo buckets, previous count %d, new count %d", bucketCount, arraySize)
80 }
81 }
82
83 sizes := make([]float64, arraySize)
84 for i := 0; i < arraySize; i++ {
85 sizes[i], err = strconv.ParseFloat(parts[i+4], 64)
86 if err != nil {
87 return nil, fmt.Errorf("invalid value in buddyinfo: %s", err)
88 }
89 }
90
91 buddyInfo = append(buddyInfo, BuddyInfo{node, zone, sizes})
92 }
93
94 return buddyInfo, scanner.Err()
95}