buddyinfo.go 2.4 KB

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