5 char *numastat_filename;
10 static struct node *numa_root = NULL;
12 static int find_all_nodes() {
13 int numa_node_count = 0;
14 char name[FILENAME_MAX + 1];
15 snprintfz(name, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/node");
16 char *dirname = config_get("plugin:proc:/sys/devices/system/node", "directory to monitor", name);
18 DIR *dir = opendir(dirname);
20 error("Cannot read NUMA node directory '%s'", dirname);
24 struct dirent *de = NULL;
25 while((de = readdir(dir))) {
26 if(de->d_type != DT_DIR)
29 if(strncmp(de->d_name, "node", 4) != 0)
32 if(!isdigit(de->d_name[4]))
37 struct node *m = callocz(1, sizeof(struct node));
38 m->name = strdupz(de->d_name);
42 snprintfz(name, FILENAME_MAX, "%s/%s/numastat", dirname, de->d_name);
43 if(stat(name, &st) == -1) {
49 m->numastat_filename = strdupz(name);
57 return numa_node_count;
60 int do_proc_sys_devices_system_node(int update_every, usec_t dt) {
63 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;
64 static int do_numastat = -1, numa_node_count = 0;
67 if(unlikely(numa_root == NULL)) {
68 numa_node_count = find_all_nodes();
69 if(unlikely(numa_root == NULL))
73 if(unlikely(do_numastat == -1)) {
74 do_numastat = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/node", "enable per-node numa metrics", CONFIG_BOOLEAN_AUTO);
76 hash_local_node = simple_hash("local_node");
77 hash_numa_foreign = simple_hash("numa_foreign");
78 hash_interleave_hit = simple_hash("interleave_hit");
79 hash_other_node = simple_hash("other_node");
80 hash_numa_hit = simple_hash("numa_hit");
81 hash_numa_miss = simple_hash("numa_miss");
84 if(do_numastat == CONFIG_BOOLEAN_YES || (do_numastat == CONFIG_BOOLEAN_AUTO && numa_node_count >= 2)) {
85 for(m = numa_root; m; m = m->next) {
86 if(m->numastat_filename) {
88 if(unlikely(!m->numastat_ff)) {
89 m->numastat_ff = procfile_open(m->numastat_filename, " ", PROCFILE_FLAG_DEFAULT);
91 if(unlikely(!m->numastat_ff))
95 m->numastat_ff = procfile_readall(m->numastat_ff);
96 if(unlikely(!m->numastat_ff || procfile_lines(m->numastat_ff) < 1 || procfile_linewords(m->numastat_ff, 0) < 1))
99 if(unlikely(!m->numastat_st)) {
100 m->numastat_st = rrdset_create_localhost(
113 rrdset_flag_set(m->numastat_st, RRDSET_FLAG_DETAIL);
115 rrddim_add(m->numastat_st, "numa_hit", "hit", 1, 1, RRD_ALGORITHM_INCREMENTAL);
116 rrddim_add(m->numastat_st, "numa_miss", "miss", 1, 1, RRD_ALGORITHM_INCREMENTAL);
117 rrddim_add(m->numastat_st, "local_node", "local", 1, 1, RRD_ALGORITHM_INCREMENTAL);
118 rrddim_add(m->numastat_st, "numa_foreign", "foreign", 1, 1, RRD_ALGORITHM_INCREMENTAL);
119 rrddim_add(m->numastat_st, "interleave_hit", "interleave", 1, 1, RRD_ALGORITHM_INCREMENTAL);
120 rrddim_add(m->numastat_st, "other_node", "other", 1, 1, RRD_ALGORITHM_INCREMENTAL);
123 else rrdset_next(m->numastat_st);
125 size_t lines = procfile_lines(m->numastat_ff), l;
126 for(l = 0; l < lines; l++) {
127 size_t words = procfile_linewords(m->numastat_ff, l);
129 if(unlikely(words < 2)) {
131 error("Cannot read %s numastat line %zu. Expected 2 params, read %zu.", m->name, l, words);
135 char *name = procfile_lineword(m->numastat_ff, l, 0);
136 char *value = procfile_lineword(m->numastat_ff, l, 1);
138 if (unlikely(!name || !*name || !value || !*value))
141 uint32_t hash = simple_hash(name);
143 (hash == hash_numa_hit && !strcmp(name, "numa_hit"))
144 || (hash == hash_numa_miss && !strcmp(name, "numa_miss"))
145 || (hash == hash_local_node && !strcmp(name, "local_node"))
146 || (hash == hash_numa_foreign && !strcmp(name, "numa_foreign"))
147 || (hash == hash_interleave_hit && !strcmp(name, "interleave_hit"))
148 || (hash == hash_other_node && !strcmp(name, "other_node"))
150 rrddim_set(m->numastat_st, name, (collected_number)str2kernel_uint_t(value));
153 rrdset_done(m->numastat_st);