...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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
73
74
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