numa basic meminfo (#18822)
* numa basic meminfo * collected values are kb
Costa Tsaousis committed
Oct 19, 2024 at 16:12 UTC
d09164949b34f5648cbf697299aedee1a780923a
2 files changed
+196
-92
src/collectors/all.h
+2
-1
@@ -112,7 +112,8 @@
112
#define NETDATA_CHART_PRIO_MEM_KSM_COW 1303
113
#define NETDATA_CHART_PRIO_MEM_BALLOON 1350
114
#define NETDATA_CHART_PRIO_MEM_NUMA 1400
115
-#define NETDATA_CHART_PRIO_MEM_NUMA_NODES 1410
115
+#define NETDATA_CHART_PRIO_MEM_NUMA_NODES_NUMASTAT 1410
116
+#define NETDATA_CHART_PRIO_MEM_NUMA_NODES_MEMINFO 1411
117
#define NETDATA_CHART_PRIO_MEM_PAGEFRAG 1450
118
#define NETDATA_CHART_PRIO_MEM_HW 1500
119
#define NETDATA_CHART_PRIO_MEM_HW_ECC_CE 1550
src/collectors/proc.plugin/sys_devices_system_node.c
+194
-91
@@ -4,12 +4,23 @@
4
5
struct node {
6
char *name;
7
- char *numastat_filename;
8
- procfile *numastat_ff;
9
- RRDSET *numastat_st;
7
+
8
+ struct {
9
+ char *filename;
10
+ procfile *ff;
11
+ RRDSET *st;
12
+ } numastat;
13
+
14
+ struct {
15
+ char *filename;
16
+ procfile *ff;
17
+ RRDSET *st;
18
+ } meminfo;
19
+
20
struct node *next;
21
};
22
static struct node *numa_root = NULL;
23
+static int numa_node_count = 0;
24
25
static int find_all_nodes() {
26
int numa_node_count = 0;
@@ -47,8 +58,16 @@ static int find_all_nodes() {
58
freez(m);
59
continue;
60
}
61
+ m->numastat.filename = strdupz(name);
62
51
- m->numastat_filename = strdupz(name);
63
+ snprintfz(name, FILENAME_MAX, "%s/%s/meminfo", dirname, de->d_name);
64
+ if(stat(name, &st) == -1) {
65
+ freez(m->numastat.filename);
66
+ freez(m->name);
67
+ freez(m);
68
+ continue;
69
+ }
70
+ m->meminfo.filename = strdupz(name);
71
72
m->next = numa_root;
73
numa_root = m;
@@ -59,22 +78,12 @@ static int find_all_nodes() {
78
return numa_node_count;
79
}
80
62
-int do_proc_sys_devices_system_node(int update_every, usec_t dt) {
63
- (void)dt;
64
-
81
+static void do_muma_numastat(struct node *m, int update_every) {
82
static uint32_t hash_local_node = 0, hash_numa_foreign = 0, hash_interleave_hit = 0, hash_other_node = 0, hash_numa_hit = 0, hash_numa_miss = 0;
66
- static int do_numastat = -1, numa_node_count = 0;
67
- struct node *m;
68
-
69
- if(unlikely(numa_root == NULL)) {
70
- numa_node_count = find_all_nodes();
71
- if(unlikely(numa_root == NULL))
72
- return 1;
73
- }
74
-
75
- if(unlikely(do_numastat == -1)) {
76
- do_numastat = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/node", "enable per-node numa metrics", CONFIG_BOOLEAN_AUTO);
83
+ static bool initialized = false;
84
85
+ if(unlikely(!initialized)) {
86
+ initialized = true;
87
hash_local_node = simple_hash("local_node");
88
hash_numa_foreign = simple_hash("numa_foreign");
89
hash_interleave_hit = simple_hash("interleave_hit");
@@ -83,82 +92,176 @@ int do_proc_sys_devices_system_node(int update_every, usec_t dt) {
92
hash_numa_miss = simple_hash("numa_miss");
93
}
94
86
- if (do_numastat == CONFIG_BOOLEAN_YES || (do_numastat == CONFIG_BOOLEAN_AUTO && numa_node_count >= 2)) {
87
- for(m = numa_root; m; m = m->next) {
88
- if(m->numastat_filename) {
89
-
90
- if(unlikely(!m->numastat_ff)) {
91
- m->numastat_ff = procfile_open(m->numastat_filename, " ", PROCFILE_FLAG_DEFAULT);
92
-
93
- if(unlikely(!m->numastat_ff))
94
- continue;
95
- }
96
-
97
- m->numastat_ff = procfile_readall(m->numastat_ff);
98
- if(unlikely(!m->numastat_ff || procfile_lines(m->numastat_ff) < 1 || procfile_linewords(m->numastat_ff, 0) < 1))
99
- continue;
100
-
101
- if(unlikely(!m->numastat_st)) {
102
- m->numastat_st = rrdset_create_localhost(
103
- "mem"
104
- , m->name
105
- , NULL
106
- , "numa"
107
- , "mem.numa_nodes"
108
- , "NUMA events"
109
- , "events/s"
110
- , PLUGIN_PROC_NAME
111
- , "/sys/devices/system/node"
112
- , NETDATA_CHART_PRIO_MEM_NUMA_NODES
113
- , update_every
114
- , RRDSET_TYPE_LINE
115
- );
116
-
117
- rrdlabels_add(m->numastat_st->rrdlabels, "numa_node", m->name, RRDLABEL_SRC_AUTO);
118
-
119
- rrdset_flag_set(m->numastat_st, RRDSET_FLAG_DETAIL);
120
-
121
- rrddim_add(m->numastat_st, "numa_hit", "hit", 1, 1, RRD_ALGORITHM_INCREMENTAL);
122
- rrddim_add(m->numastat_st, "numa_miss", "miss", 1, 1, RRD_ALGORITHM_INCREMENTAL);
123
- rrddim_add(m->numastat_st, "local_node", "local", 1, 1, RRD_ALGORITHM_INCREMENTAL);
124
- rrddim_add(m->numastat_st, "numa_foreign", "foreign", 1, 1, RRD_ALGORITHM_INCREMENTAL);
125
- rrddim_add(m->numastat_st, "interleave_hit", "interleave", 1, 1, RRD_ALGORITHM_INCREMENTAL);
126
- rrddim_add(m->numastat_st, "other_node", "other", 1, 1, RRD_ALGORITHM_INCREMENTAL);
127
-
128
- }
129
-
130
- size_t lines = procfile_lines(m->numastat_ff), l;
131
- for(l = 0; l < lines; l++) {
132
- size_t words = procfile_linewords(m->numastat_ff, l);
133
-
134
- if(unlikely(words < 2)) {
135
- if(unlikely(words))
136
- collector_error("Cannot read %s numastat line %zu. Expected 2 params, read %zu.", m->name, l, words);
137
- continue;
138
- }
139
-
140
- char *name = procfile_lineword(m->numastat_ff, l, 0);
141
- char *value = procfile_lineword(m->numastat_ff, l, 1);
142
-
143
- if (unlikely(!name || !*name || !value || !*value))
144
- continue;
145
-
146
- uint32_t hash = simple_hash(name);
147
- if(likely(
148
- (hash == hash_numa_hit && !strcmp(name, "numa_hit"))
149
- || (hash == hash_numa_miss && !strcmp(name, "numa_miss"))
150
- || (hash == hash_local_node && !strcmp(name, "local_node"))
151
- || (hash == hash_numa_foreign && !strcmp(name, "numa_foreign"))
152
- || (hash == hash_interleave_hit && !strcmp(name, "interleave_hit"))
153
- || (hash == hash_other_node && !strcmp(name, "other_node"))
154
- ))
155
- rrddim_set(m->numastat_st, name, (collected_number)str2kernel_uint_t(value));
156
- }
95
+ if (m->numastat.filename) {
96
+ if(unlikely(!m->numastat.ff)) {
97
+ m->numastat.ff = procfile_open(m->numastat.filename, " ", PROCFILE_FLAG_DEFAULT);
98
158
- rrdset_done(m->numastat_st);
99
+ if(unlikely(!m->numastat.ff))
100
+ return;
101
+ }
102
+
103
+ m->numastat.ff = procfile_readall(m->numastat.ff);
104
+ if(unlikely(!m->numastat.ff || procfile_lines(m->numastat.ff) < 1 || procfile_linewords(m->numastat.ff, 0) < 1))
105
+ return;
106
+
107
+ if(unlikely(!m->numastat.st)) {
108
+ m->numastat.st = rrdset_create_localhost(
109
+ "numa_node_stat"
110
+ , m->name
111
+ , NULL
112
+ , "numa"
113
+ , "mem.numa_node_stat"
114
+ , "NUMA Node Memory Allocation Events"
115
+ , "events/s"
116
+ , PLUGIN_PROC_NAME
117
+ , "/sys/devices/system/node"
118
+ , NETDATA_CHART_PRIO_MEM_NUMA_NODES_NUMASTAT
119
+ , update_every
120
+ , RRDSET_TYPE_LINE
121
+ );
122
+
123
+ rrdlabels_add(m->numastat.st->rrdlabels, "numa_node", m->name, RRDLABEL_SRC_AUTO);
124
+
125
+ rrdset_flag_set(m->numastat.st, RRDSET_FLAG_DETAIL);
126
+
127
+ rrddim_add(m->numastat.st, "numa_hit", "hit", 1, 1, RRD_ALGORITHM_INCREMENTAL);
128
+ rrddim_add(m->numastat.st, "numa_miss", "miss", 1, 1, RRD_ALGORITHM_INCREMENTAL);
129
+ rrddim_add(m->numastat.st, "local_node", "local", 1, 1, RRD_ALGORITHM_INCREMENTAL);
130
+ rrddim_add(m->numastat.st, "numa_foreign", "foreign", 1, 1, RRD_ALGORITHM_INCREMENTAL);
131
+ rrddim_add(m->numastat.st, "interleave_hit", "interleave", 1, 1, RRD_ALGORITHM_INCREMENTAL);
132
+ rrddim_add(m->numastat.st, "other_node", "other", 1, 1, RRD_ALGORITHM_INCREMENTAL);
133
+
134
+ }
135
+
136
+ size_t lines = procfile_lines(m->numastat.ff), l;
137
+ for(l = 0; l < lines; l++) {
138
+ size_t words = procfile_linewords(m->numastat.ff, l);
139
+
140
+ if(unlikely(words < 2)) {
141
+ if(unlikely(words))
142
+ collector_error("Cannot read %s line %zu. Expected 2 params, read %zu.", m->numastat.filename, l, words);
143
+ continue;
144
}
145
+
146
+ char *name = procfile_lineword(m->numastat.ff, l, 0);
147
+ char *value = procfile_lineword(m->numastat.ff, l, 1);
148
+
149
+ if (unlikely(!name || !*name || !value || !*value))
150
+ continue;
151
+
152
+ uint32_t hash = simple_hash(name);
153
+ if(likely(
154
+ (hash == hash_numa_hit && !strcmp(name, "numa_hit"))
155
+ || (hash == hash_numa_miss && !strcmp(name, "numa_miss"))
156
+ || (hash == hash_local_node && !strcmp(name, "local_node"))
157
+ || (hash == hash_numa_foreign && !strcmp(name, "numa_foreign"))
158
+ || (hash == hash_interleave_hit && !strcmp(name, "interleave_hit"))
159
+ || (hash == hash_other_node && !strcmp(name, "other_node"))
160
+ ))
161
+ rrddim_set(m->numastat.st, name, (collected_number)str2kernel_uint_t(value));
162
}
163
+
164
+ rrdset_done(m->numastat.st);
165
+ }
166
+}
167
+
168
+static void do_numa_meminfo(struct node *m, int update_every) {
169
+ static uint32_t hash_MemFree = 0, hash_MemUsed = 0;
170
+ static bool initialized = false;
171
+
172
+ if(unlikely(!initialized)) {
173
+ initialized = true;
174
+ hash_MemFree = simple_hash("MemFree");
175
+ hash_MemUsed = simple_hash("MemUsed");
176
+ }
177
+
178
+ if (m->meminfo.filename) {
179
+ if(unlikely(!m->meminfo.ff)) {
180
+ m->meminfo.ff = procfile_open(m->meminfo.filename, " :", PROCFILE_FLAG_DEFAULT);
181
+ if(unlikely(!m->meminfo.ff))
182
+ return;
183
+ }
184
+
185
+ m->meminfo.ff = procfile_readall(m->meminfo.ff);
186
+ if(unlikely(!m->meminfo.ff || procfile_lines(m->meminfo.ff) < 1 || procfile_linewords(m->meminfo.ff, 0) < 1))
187
+ return;
188
+
189
+ if(unlikely(!m->meminfo.st)) {
190
+ m->meminfo.st = rrdset_create_localhost(
191
+ "numa_node_mem_usage"
192
+ , m->name
193
+ , NULL
194
+ , "numa"
195
+ , "mem.numa_node_mem_usage"
196
+ , "NUMA Node Memory Usage"
197
+ , "bytes"
198
+ , PLUGIN_PROC_NAME
199
+ , "/sys/devices/system/node"
200
+ , NETDATA_CHART_PRIO_MEM_NUMA_NODES_MEMINFO
201
+ , update_every
202
+ , RRDSET_TYPE_STACKED
203
+ );
204
+
205
+ rrdlabels_add(m->meminfo.st->rrdlabels, "numa_node", m->name, RRDLABEL_SRC_AUTO);
206
+
207
+ rrdset_flag_set(m->meminfo.st, RRDSET_FLAG_DETAIL);
208
+
209
+ rrddim_add(m->meminfo.st, "MemFree", "free", 1, 1, RRD_ALGORITHM_ABSOLUTE);
210
+ rrddim_add(m->meminfo.st, "MemUsed", "used", 1, 1, RRD_ALGORITHM_ABSOLUTE);
211
+ }
212
+
213
+ size_t lines = procfile_lines(m->meminfo.ff), l;
214
+ for(l = 0; l < lines; l++) {
215
+ size_t words = procfile_linewords(m->meminfo.ff, l);
216
+
217
+ if(unlikely(words < 4)) {
218
+ if(unlikely(words))
219
+ collector_error("Cannot read %s line %zu. Expected 4 params, read %zu.", m->meminfo.filename, l, words);
220
+ continue;
221
+ }
222
+
223
+ char *name = procfile_lineword(m->meminfo.ff, l, 2);
224
+ char *value = procfile_lineword(m->meminfo.ff, l, 3);
225
+
226
+ if (unlikely(!name || !*name || !value || !*value))
227
+ continue;
228
+
229
+ uint32_t hash = simple_hash(name);
230
+ if(likely(
231
+ (hash == hash_MemFree && !strcmp(name, "MemFree"))
232
+ || (hash == hash_MemUsed && !strcmp(name, "MemUsed"))
233
+ ))
234
+ rrddim_set(m->meminfo.st, name, (collected_number)str2kernel_uint_t(value) * 1024);
235
+ }
236
+
237
+ rrdset_done(m->meminfo.st);
238
+ }
239
+}
240
+
241
+int do_proc_sys_devices_system_node(int update_every, usec_t dt) {
242
+ (void)dt;
243
+ struct node *m;
244
+
245
+ static int do_numastat = -1;
246
+
247
+ if(unlikely(do_numastat == -1)) {
248
+ do_numastat = config_get_boolean_ondemand(
249
+ "plugin:proc:/sys/devices/system/node", "enable per-node numa metrics", CONFIG_BOOLEAN_AUTO);
250
+ }
251
+
252
+ if(unlikely(numa_root == NULL)) {
253
+ numa_node_count = find_all_nodes();
254
+ if(unlikely(numa_root == NULL))
255
+ return 1;
256
+ }
257
+
258
+ if (do_numastat == CONFIG_BOOLEAN_YES || (do_numastat == CONFIG_BOOLEAN_AUTO && numa_node_count >= 2)) {
259
+ for (m = numa_root; m; m = m->next) {
260
+ do_muma_numastat(m, update_every);
261
+ do_numa_meminfo(m, update_every);
262
+ }
263
+ return 0;
264
}
265
163
- return 0;
266
+ return 1;
267
}