diff options
Diffstat (limited to 'vendor/github.com/prometheus/procfs/proc_smaps.go')
-rw-r--r-- | vendor/github.com/prometheus/procfs/proc_smaps.go | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/vendor/github.com/prometheus/procfs/proc_smaps.go b/vendor/github.com/prometheus/procfs/proc_smaps.go new file mode 100644 index 0000000..a576a72 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_smaps.go | |||
@@ -0,0 +1,165 @@ | |||
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 | |||
14 | // +build !windows | ||
15 | |||
16 | package procfs | ||
17 | |||
18 | import ( | ||
19 | "bufio" | ||
20 | "errors" | ||
21 | "fmt" | ||
22 | "os" | ||
23 | "regexp" | ||
24 | "strconv" | ||
25 | "strings" | ||
26 | |||
27 | "github.com/prometheus/procfs/internal/util" | ||
28 | ) | ||
29 | |||
30 | var ( | ||
31 | // match the header line before each mapped zone in /proc/pid/smaps | ||
32 | procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`) | ||
33 | ) | ||
34 | |||
35 | type ProcSMapsRollup struct { | ||
36 | // Amount of the mapping that is currently resident in RAM | ||
37 | Rss uint64 | ||
38 | // Process's proportional share of this mapping | ||
39 | Pss uint64 | ||
40 | // Size in bytes of clean shared pages | ||
41 | SharedClean uint64 | ||
42 | // Size in bytes of dirty shared pages | ||
43 | SharedDirty uint64 | ||
44 | // Size in bytes of clean private pages | ||
45 | PrivateClean uint64 | ||
46 | // Size in bytes of dirty private pages | ||
47 | PrivateDirty uint64 | ||
48 | // Amount of memory currently marked as referenced or accessed | ||
49 | Referenced uint64 | ||
50 | // Amount of memory that does not belong to any file | ||
51 | Anonymous uint64 | ||
52 | // Amount would-be-anonymous memory currently on swap | ||
53 | Swap uint64 | ||
54 | // Process's proportional memory on swap | ||
55 | SwapPss uint64 | ||
56 | } | ||
57 | |||
58 | // ProcSMapsRollup reads from /proc/[pid]/smaps_rollup to get summed memory information of the | ||
59 | // process. | ||
60 | // | ||
61 | // If smaps_rollup does not exists (require kernel >= 4.15), the content of /proc/pid/smaps will | ||
62 | // we read and summed. | ||
63 | func (p Proc) ProcSMapsRollup() (ProcSMapsRollup, error) { | ||
64 | data, err := util.ReadFileNoStat(p.path("smaps_rollup")) | ||
65 | if err != nil && os.IsNotExist(err) { | ||
66 | return p.procSMapsRollupManual() | ||
67 | } | ||
68 | if err != nil { | ||
69 | return ProcSMapsRollup{}, err | ||
70 | } | ||
71 | |||
72 | lines := strings.Split(string(data), "\n") | ||
73 | smaps := ProcSMapsRollup{} | ||
74 | |||
75 | // skip first line which don't contains information we need | ||
76 | lines = lines[1:] | ||
77 | for _, line := range lines { | ||
78 | if line == "" { | ||
79 | continue | ||
80 | } | ||
81 | |||
82 | if err := smaps.parseLine(line); err != nil { | ||
83 | return ProcSMapsRollup{}, err | ||
84 | } | ||
85 | } | ||
86 | |||
87 | return smaps, nil | ||
88 | } | ||
89 | |||
90 | // Read /proc/pid/smaps and do the roll-up in Go code. | ||
91 | func (p Proc) procSMapsRollupManual() (ProcSMapsRollup, error) { | ||
92 | file, err := os.Open(p.path("smaps")) | ||
93 | if err != nil { | ||
94 | return ProcSMapsRollup{}, err | ||
95 | } | ||
96 | defer file.Close() | ||
97 | |||
98 | smaps := ProcSMapsRollup{} | ||
99 | scan := bufio.NewScanner(file) | ||
100 | |||
101 | for scan.Scan() { | ||
102 | line := scan.Text() | ||
103 | |||
104 | if procSMapsHeaderLine.MatchString(line) { | ||
105 | continue | ||
106 | } | ||
107 | |||
108 | if err := smaps.parseLine(line); err != nil { | ||
109 | return ProcSMapsRollup{}, err | ||
110 | } | ||
111 | } | ||
112 | |||
113 | return smaps, nil | ||
114 | } | ||
115 | |||
116 | func (s *ProcSMapsRollup) parseLine(line string) error { | ||
117 | kv := strings.SplitN(line, ":", 2) | ||
118 | if len(kv) != 2 { | ||
119 | fmt.Println(line) | ||
120 | return errors.New("invalid net/dev line, missing colon") | ||
121 | } | ||
122 | |||
123 | k := kv[0] | ||
124 | if k == "VmFlags" { | ||
125 | return nil | ||
126 | } | ||
127 | |||
128 | v := strings.TrimSpace(kv[1]) | ||
129 | v = strings.TrimRight(v, " kB") | ||
130 | |||
131 | vKBytes, err := strconv.ParseUint(v, 10, 64) | ||
132 | if err != nil { | ||
133 | return err | ||
134 | } | ||
135 | vBytes := vKBytes * 1024 | ||
136 | |||
137 | s.addValue(k, v, vKBytes, vBytes) | ||
138 | |||
139 | return nil | ||
140 | } | ||
141 | |||
142 | func (s *ProcSMapsRollup) addValue(k string, vString string, vUint uint64, vUintBytes uint64) { | ||
143 | switch k { | ||
144 | case "Rss": | ||
145 | s.Rss += vUintBytes | ||
146 | case "Pss": | ||
147 | s.Pss += vUintBytes | ||
148 | case "Shared_Clean": | ||
149 | s.SharedClean += vUintBytes | ||
150 | case "Shared_Dirty": | ||
151 | s.SharedDirty += vUintBytes | ||
152 | case "Private_Clean": | ||
153 | s.PrivateClean += vUintBytes | ||
154 | case "Private_Dirty": | ||
155 | s.PrivateDirty += vUintBytes | ||
156 | case "Referenced": | ||
157 | s.Referenced += vUintBytes | ||
158 | case "Anonymous": | ||
159 | s.Anonymous += vUintBytes | ||
160 | case "Swap": | ||
161 | s.Swap += vUintBytes | ||
162 | case "SwapPss": | ||
163 | s.SwapPss += vUintBytes | ||
164 | } | ||
165 | } | ||