1// Copyright 2020 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 sysfs 15 16import ( 17 "bufio" 18 "bytes" 19 "fmt" 20 "path/filepath" 21 "regexp" 22 "strconv" 23 "strings" 24 25 "github.com/prometheus/procfs/internal/util" 26) 27 28var ( 29 nodePattern = "devices/system/node/node[0-9]*" 30 nodeNumberRegexp = regexp.MustCompile(`.*devices/system/node/node([0-9]*)`) 31) 32 33type VMStat struct { 34 NrFreePages uint64 35 NrZoneInactiveAnon uint64 36 NrZoneActiveAnon uint64 37 NrZoneInactiveFile uint64 38 NrZoneActiveFile uint64 39 NrZoneUnevictable uint64 40 NrZoneWritePending uint64 41 NrMlock uint64 42 NrPageTablePages uint64 43 NrKernelStack uint64 44 NrBounce uint64 45 NrZspages uint64 46 NrFreeCma uint64 47 NumaHit uint64 48 NumaMiss uint64 49 NumaForeign uint64 50 NumaInterleave uint64 51 NumaLocal uint64 52 NumaOther uint64 53 NrInactiveAnon uint64 54 NrActiveAnon uint64 55 NrInactiveFile uint64 56 NrActiveFile uint64 57 NrUnevictable uint64 58 NrSlabReclaimable uint64 59 NrSlabUnreclaimable uint64 60 NrIsolatedAnon uint64 61 NrIsolatedFile uint64 62 WorkingsetNodes uint64 63 WorkingsetRefault uint64 64 WorkingsetActivate uint64 65 WorkingsetRestore uint64 66 WorkingsetNodereclaim uint64 67 NrAnonPages uint64 68 NrMapped uint64 69 NrFilePages uint64 70 NrDirty uint64 71 NrWriteback uint64 72 NrWritebackTemp uint64 73 NrShmem uint64 74 NrShmemHugepages uint64 75 NrShmemPmdmapped uint64 76 NrFileHugepages uint64 77 NrFilePmdmapped uint64 78 NrAnonTransparentHugepages uint64 79 NrVmscanWrite uint64 80 NrVmscanImmediateReclaim uint64 81 NrDirtied uint64 82 NrWritten uint64 83 NrKernelMiscReclaimable uint64 84 NrFollPinAcquired uint64 85 NrFollPinReleased uint64 86} 87 88func (fs FS) VMStatNUMA() (map[int]VMStat, error) { 89 m := make(map[int]VMStat) 90 nodes, err := filepath.Glob(fs.sys.Path(nodePattern)) 91 if err != nil { 92 return nil, err 93 } 94 95 for _, node := range nodes { 96 nodeNumbers := nodeNumberRegexp.FindStringSubmatch(node) 97 if len(nodeNumbers) != 2 { 98 continue 99 } 100 nodeNumber, err := strconv.Atoi(nodeNumbers[1]) 101 if err != nil { 102 return nil, err 103 } 104 file, err := util.ReadFileNoStat(filepath.Join(node, "vmstat")) 105 if err != nil { 106 return nil, err 107 } 108 nodeStats, err := parseVMStatNUMA(file) 109 if err != nil { 110 return nil, err 111 } 112 m[nodeNumber] = nodeStats 113 } 114 return m, nil 115} 116 117func parseVMStatNUMA(r []byte) (VMStat, error) { 118 var ( 119 vmStat = VMStat{} 120 scanner = bufio.NewScanner(bytes.NewReader(r)) 121 ) 122 123 for scanner.Scan() { 124 line := strings.TrimSpace(scanner.Text()) 125 if line == "" { 126 continue 127 } 128 parts := strings.Fields(line) 129 if len(parts) != 2 { 130 return vmStat, fmt.Errorf("line scan did not return 2 fields: %s", line) 131 } 132 133 fv, err := strconv.ParseUint(parts[1], 10, 64) 134 if err != nil { 135 return vmStat, fmt.Errorf("invalid value in vmstat: %w", err) 136 } 137 switch parts[0] { 138 case "nr_free_pages": 139 vmStat.NrFreePages = fv 140 case "nr_zone_inactive_anon": 141 vmStat.NrZoneInactiveAnon = fv 142 case "nr_zone_active_anon": 143 vmStat.NrZoneActiveAnon = fv 144 case "nr_zone_inactive_file": 145 vmStat.NrZoneActiveFile = fv 146 case "nr_zone_active_file": 147 vmStat.NrZoneActiveFile = fv 148 case "nr_zone_unevictable": 149 vmStat.NrZoneUnevictable = fv 150 case "nr_zone_write_pending": 151 vmStat.NrZoneWritePending = fv 152 case "nr_mlock": 153 vmStat.NrMlock = fv 154 case "nr_page_table_pages": 155 vmStat.NrPageTablePages = fv 156 case "nr_kernel_stack": 157 vmStat.NrKernelStack = fv 158 case "nr_bounce": 159 vmStat.NrBounce = fv 160 case "nr_zspages": 161 vmStat.NrZspages = fv 162 case "nr_free_cma": 163 vmStat.NrFreeCma = fv 164 case "numa_hit": 165 vmStat.NumaHit = fv 166 case "numa_miss": 167 vmStat.NumaMiss = fv 168 case "numa_foreign": 169 vmStat.NumaForeign = fv 170 case "numa_interleave": 171 vmStat.NumaInterleave = fv 172 case "numa_local": 173 vmStat.NumaLocal = fv 174 case "numa_other": 175 vmStat.NumaOther = fv 176 case "nr_inactive_anon": 177 vmStat.NrInactiveAnon = fv 178 case "nr_active_anon": 179 vmStat.NrActiveAnon = fv 180 case "nr_inactive_file": 181 vmStat.NrInactiveFile = fv 182 case "nr_active_file": 183 vmStat.NrActiveFile = fv 184 case "nr_unevictable": 185 vmStat.NrUnevictable = fv 186 case "nr_slab_reclaimable": 187 vmStat.NrSlabReclaimable = fv 188 case "nr_slab_unreclaimable": 189 vmStat.NrSlabUnreclaimable = fv 190 case "nr_isolated_anon": 191 vmStat.NrIsolatedAnon = fv 192 case "nr_isolated_file": 193 vmStat.NrIsolatedFile = fv 194 case "workingset_nodes": 195 vmStat.WorkingsetNodes = fv 196 case "workingset_refault": 197 vmStat.WorkingsetRefault = fv 198 case "workingset_activate": 199 vmStat.WorkingsetActivate = fv 200 case "workingset_restore": 201 vmStat.WorkingsetRestore = fv 202 case "workingset_nodereclaim": 203 vmStat.WorkingsetNodereclaim = fv 204 case "nr_anon_pages": 205 vmStat.NrAnonPages = fv 206 case "nr_mapped": 207 vmStat.NrMapped = fv 208 case "nr_file_pages": 209 vmStat.NrFilePages = fv 210 case "nr_dirty": 211 vmStat.NrDirty = fv 212 case "nr_writeback": 213 vmStat.NrWriteback = fv 214 case "nr_writeback_temp": 215 vmStat.NrWritebackTemp = fv 216 case "nr_shmem": 217 vmStat.NrShmem = fv 218 case "nr_shmem_hugepages": 219 vmStat.NrShmemHugepages = fv 220 case "nr_shmem_pmdmapped": 221 vmStat.NrShmemPmdmapped = fv 222 case "nr_file_hugepages": 223 vmStat.NrFileHugepages = fv 224 case "nr_file_pmdmapped": 225 vmStat.NrFilePmdmapped = fv 226 case "nr_anon_transparent_hugepages": 227 vmStat.NrAnonTransparentHugepages = fv 228 case "nr_vmscan_write": 229 vmStat.NrVmscanWrite = fv 230 case "nr_vmscan_immediate_reclaim": 231 vmStat.NrVmscanImmediateReclaim = fv 232 case "nr_dirtied": 233 vmStat.NrDirtied = fv 234 case "nr_written": 235 vmStat.NrWritten = fv 236 case "nr_kernel_misc_reclaimable": 237 vmStat.NrKernelMiscReclaimable = fv 238 case "nr_foll_pin_acquired": 239 vmStat.NrFollPinAcquired = fv 240 case "nr_foll_pin_released": 241 vmStat.NrFollPinReleased = fv 242 } 243 244 } 245 return vmStat, scanner.Err() 246} 247