...

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

Documentation: github.com/prometheus/procfs

     1  // Copyright 2019 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  //go:build !windows
    15  // +build !windows
    16  
    17  package procfs
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"os"
    23  	"regexp"
    24  	"strings"
    25  
    26  	"github.com/prometheus/procfs/internal/util"
    27  )
    28  
    29  // Zoneinfo holds info parsed from /proc/zoneinfo.
    30  type Zoneinfo struct {
    31  	Node                       string
    32  	Zone                       string
    33  	NrFreePages                *int64
    34  	Min                        *int64
    35  	Low                        *int64
    36  	High                       *int64
    37  	Scanned                    *int64
    38  	Spanned                    *int64
    39  	Present                    *int64
    40  	Managed                    *int64
    41  	NrActiveAnon               *int64
    42  	NrInactiveAnon             *int64
    43  	NrIsolatedAnon             *int64
    44  	NrAnonPages                *int64
    45  	NrAnonTransparentHugepages *int64
    46  	NrActiveFile               *int64
    47  	NrInactiveFile             *int64
    48  	NrIsolatedFile             *int64
    49  	NrFilePages                *int64
    50  	NrSlabReclaimable          *int64
    51  	NrSlabUnreclaimable        *int64
    52  	NrMlockStack               *int64
    53  	NrKernelStack              *int64
    54  	NrMapped                   *int64
    55  	NrDirty                    *int64
    56  	NrWriteback                *int64
    57  	NrUnevictable              *int64
    58  	NrShmem                    *int64
    59  	NrDirtied                  *int64
    60  	NrWritten                  *int64
    61  	NumaHit                    *int64
    62  	NumaMiss                   *int64
    63  	NumaForeign                *int64
    64  	NumaInterleave             *int64
    65  	NumaLocal                  *int64
    66  	NumaOther                  *int64
    67  	Protection                 []*int64
    68  }
    69  
    70  var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`)
    71  
    72  // Zoneinfo parses an zoneinfo-file (/proc/zoneinfo) and returns a slice of
    73  // structs containing the relevant info.  More information available here:
    74  // https://www.kernel.org/doc/Documentation/sysctl/vm.txt
    75  func (fs FS) Zoneinfo() ([]Zoneinfo, error) {
    76  	data, err := os.ReadFile(fs.proc.Path("zoneinfo"))
    77  	if err != nil {
    78  		return nil, fmt.Errorf("%s: error reading zoneinfo %q: %w", ErrFileRead, fs.proc.Path("zoneinfo"), err)
    79  	}
    80  	zoneinfo, err := parseZoneinfo(data)
    81  	if err != nil {
    82  		return nil, fmt.Errorf("%s: error parsing zoneinfo %q: %w", ErrFileParse, fs.proc.Path("zoneinfo"), err)
    83  	}
    84  	return zoneinfo, nil
    85  }
    86  
    87  func parseZoneinfo(zoneinfoData []byte) ([]Zoneinfo, error) {
    88  
    89  	zoneinfo := []Zoneinfo{}
    90  
    91  	zoneinfoBlocks := bytes.Split(zoneinfoData, []byte("\nNode"))
    92  	for _, block := range zoneinfoBlocks {
    93  		var zoneinfoElement Zoneinfo
    94  		lines := strings.Split(string(block), "\n")
    95  		for _, line := range lines {
    96  
    97  			if nodeZone := nodeZoneRE.FindStringSubmatch(line); nodeZone != nil {
    98  				zoneinfoElement.Node = nodeZone[1]
    99  				zoneinfoElement.Zone = nodeZone[2]
   100  				continue
   101  			}
   102  			if strings.HasPrefix(strings.TrimSpace(line), "per-node stats") {
   103  				continue
   104  			}
   105  			parts := strings.Fields(strings.TrimSpace(line))
   106  			if len(parts) < 2 {
   107  				continue
   108  			}
   109  			vp := util.NewValueParser(parts[1])
   110  			switch parts[0] {
   111  			case "nr_free_pages":
   112  				zoneinfoElement.NrFreePages = vp.PInt64()
   113  			case "min":
   114  				zoneinfoElement.Min = vp.PInt64()
   115  			case "low":
   116  				zoneinfoElement.Low = vp.PInt64()
   117  			case "high":
   118  				zoneinfoElement.High = vp.PInt64()
   119  			case "scanned":
   120  				zoneinfoElement.Scanned = vp.PInt64()
   121  			case "spanned":
   122  				zoneinfoElement.Spanned = vp.PInt64()
   123  			case "present":
   124  				zoneinfoElement.Present = vp.PInt64()
   125  			case "managed":
   126  				zoneinfoElement.Managed = vp.PInt64()
   127  			case "nr_active_anon":
   128  				zoneinfoElement.NrActiveAnon = vp.PInt64()
   129  			case "nr_inactive_anon":
   130  				zoneinfoElement.NrInactiveAnon = vp.PInt64()
   131  			case "nr_isolated_anon":
   132  				zoneinfoElement.NrIsolatedAnon = vp.PInt64()
   133  			case "nr_anon_pages":
   134  				zoneinfoElement.NrAnonPages = vp.PInt64()
   135  			case "nr_anon_transparent_hugepages":
   136  				zoneinfoElement.NrAnonTransparentHugepages = vp.PInt64()
   137  			case "nr_active_file":
   138  				zoneinfoElement.NrActiveFile = vp.PInt64()
   139  			case "nr_inactive_file":
   140  				zoneinfoElement.NrInactiveFile = vp.PInt64()
   141  			case "nr_isolated_file":
   142  				zoneinfoElement.NrIsolatedFile = vp.PInt64()
   143  			case "nr_file_pages":
   144  				zoneinfoElement.NrFilePages = vp.PInt64()
   145  			case "nr_slab_reclaimable":
   146  				zoneinfoElement.NrSlabReclaimable = vp.PInt64()
   147  			case "nr_slab_unreclaimable":
   148  				zoneinfoElement.NrSlabUnreclaimable = vp.PInt64()
   149  			case "nr_mlock_stack":
   150  				zoneinfoElement.NrMlockStack = vp.PInt64()
   151  			case "nr_kernel_stack":
   152  				zoneinfoElement.NrKernelStack = vp.PInt64()
   153  			case "nr_mapped":
   154  				zoneinfoElement.NrMapped = vp.PInt64()
   155  			case "nr_dirty":
   156  				zoneinfoElement.NrDirty = vp.PInt64()
   157  			case "nr_writeback":
   158  				zoneinfoElement.NrWriteback = vp.PInt64()
   159  			case "nr_unevictable":
   160  				zoneinfoElement.NrUnevictable = vp.PInt64()
   161  			case "nr_shmem":
   162  				zoneinfoElement.NrShmem = vp.PInt64()
   163  			case "nr_dirtied":
   164  				zoneinfoElement.NrDirtied = vp.PInt64()
   165  			case "nr_written":
   166  				zoneinfoElement.NrWritten = vp.PInt64()
   167  			case "numa_hit":
   168  				zoneinfoElement.NumaHit = vp.PInt64()
   169  			case "numa_miss":
   170  				zoneinfoElement.NumaMiss = vp.PInt64()
   171  			case "numa_foreign":
   172  				zoneinfoElement.NumaForeign = vp.PInt64()
   173  			case "numa_interleave":
   174  				zoneinfoElement.NumaInterleave = vp.PInt64()
   175  			case "numa_local":
   176  				zoneinfoElement.NumaLocal = vp.PInt64()
   177  			case "numa_other":
   178  				zoneinfoElement.NumaOther = vp.PInt64()
   179  			case "protection:":
   180  				protectionParts := strings.Split(line, ":")
   181  				protectionValues := strings.Replace(protectionParts[1], "(", "", 1)
   182  				protectionValues = strings.Replace(protectionValues, ")", "", 1)
   183  				protectionValues = strings.TrimSpace(protectionValues)
   184  				protectionStringMap := strings.Split(protectionValues, ", ")
   185  				val, err := util.ParsePInt64s(protectionStringMap)
   186  				if err == nil {
   187  					zoneinfoElement.Protection = val
   188  				}
   189  			}
   190  
   191  		}
   192  
   193  		zoneinfo = append(zoneinfo, zoneinfoElement)
   194  	}
   195  	return zoneinfo, nil
   196  }
   197  

View as plain text