Browse Source

numa basic meminfo (#18822)

* numa basic meminfo

* collected values are kb
Costa Tsaousis 4 months ago
parent
commit
d09164949b
2 changed files with 196 additions and 92 deletions
  1. 2 1
      src/collectors/all.h
  2. 194 91
      src/collectors/proc.plugin/sys_devices_system_node.c

+ 2 - 1
src/collectors/all.h

@@ -112,7 +112,8 @@
 #define NETDATA_CHART_PRIO_MEM_KSM_COW                1303
 #define NETDATA_CHART_PRIO_MEM_BALLOON                1350
 #define NETDATA_CHART_PRIO_MEM_NUMA                   1400
-#define NETDATA_CHART_PRIO_MEM_NUMA_NODES             1410
+#define NETDATA_CHART_PRIO_MEM_NUMA_NODES_NUMASTAT    1410
+#define NETDATA_CHART_PRIO_MEM_NUMA_NODES_MEMINFO     1411
 #define NETDATA_CHART_PRIO_MEM_PAGEFRAG               1450
 #define NETDATA_CHART_PRIO_MEM_HW                     1500
 #define NETDATA_CHART_PRIO_MEM_HW_ECC_CE              1550

+ 194 - 91
src/collectors/proc.plugin/sys_devices_system_node.c

@@ -4,12 +4,23 @@
 
 struct node {
     char *name;
-    char *numastat_filename;
-    procfile *numastat_ff;
-    RRDSET *numastat_st;
+
+    struct {
+        char *filename;
+        procfile *ff;
+        RRDSET *st;
+    } numastat;
+
+    struct {
+        char *filename;
+        procfile *ff;
+        RRDSET *st;
+    } meminfo;
+
     struct node *next;
 };
 static struct node *numa_root = NULL;
+static int numa_node_count = 0;
 
 static int find_all_nodes() {
     int numa_node_count = 0;
@@ -47,8 +58,16 @@ static int find_all_nodes() {
             freez(m);
             continue;
         }
+        m->numastat.filename = strdupz(name);
 
-        m->numastat_filename = strdupz(name);
+        snprintfz(name, FILENAME_MAX, "%s/%s/meminfo", dirname, de->d_name);
+        if(stat(name, &st) == -1) {
+            freez(m->numastat.filename);
+            freez(m->name);
+            freez(m);
+            continue;
+        }
+        m->meminfo.filename = strdupz(name);
 
         m->next = numa_root;
         numa_root = m;
@@ -59,22 +78,12 @@ static int find_all_nodes() {
     return numa_node_count;
 }
 
-int do_proc_sys_devices_system_node(int update_every, usec_t dt) {
-    (void)dt;
-
+static void do_muma_numastat(struct node *m, int update_every) {
     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;
-    static int do_numastat = -1, numa_node_count = 0;
-    struct node *m;
-
-    if(unlikely(numa_root == NULL)) {
-        numa_node_count = find_all_nodes();
-        if(unlikely(numa_root == NULL))
-            return 1;
-    }
-
-    if(unlikely(do_numastat == -1)) {
-        do_numastat = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/node", "enable per-node numa metrics", CONFIG_BOOLEAN_AUTO);
+    static bool initialized = false;
 
+    if(unlikely(!initialized)) {
+        initialized = true;
         hash_local_node     = simple_hash("local_node");
         hash_numa_foreign   = simple_hash("numa_foreign");
         hash_interleave_hit = simple_hash("interleave_hit");
@@ -83,82 +92,176 @@ int do_proc_sys_devices_system_node(int update_every, usec_t dt) {
         hash_numa_miss      = simple_hash("numa_miss");
     }
 
-    if (do_numastat == CONFIG_BOOLEAN_YES || (do_numastat == CONFIG_BOOLEAN_AUTO && numa_node_count >= 2)) {
-        for(m = numa_root; m; m = m->next) {
-            if(m->numastat_filename) {
-
-                if(unlikely(!m->numastat_ff)) {
-                    m->numastat_ff = procfile_open(m->numastat_filename, " ", PROCFILE_FLAG_DEFAULT);
-
-                    if(unlikely(!m->numastat_ff))
-                        continue;
-                }
-
-                m->numastat_ff = procfile_readall(m->numastat_ff);
-                if(unlikely(!m->numastat_ff || procfile_lines(m->numastat_ff) < 1 || procfile_linewords(m->numastat_ff, 0) < 1))
-                    continue;
-
-                if(unlikely(!m->numastat_st)) {
-                    m->numastat_st = rrdset_create_localhost(
-                            "mem"
-                            , m->name
-                            , NULL
-                            , "numa"
-                            , "mem.numa_nodes"
-                            , "NUMA events"
-                            , "events/s"
-                            , PLUGIN_PROC_NAME
-                            , "/sys/devices/system/node"
-                            , NETDATA_CHART_PRIO_MEM_NUMA_NODES
-                            , update_every
-                            , RRDSET_TYPE_LINE
-                    );
-
-                    rrdlabels_add(m->numastat_st->rrdlabels, "numa_node", m->name, RRDLABEL_SRC_AUTO);
-
-                    rrdset_flag_set(m->numastat_st, RRDSET_FLAG_DETAIL);
-
-                    rrddim_add(m->numastat_st, "numa_hit",       "hit",        1, 1, RRD_ALGORITHM_INCREMENTAL);
-                    rrddim_add(m->numastat_st, "numa_miss",      "miss",       1, 1, RRD_ALGORITHM_INCREMENTAL);
-                    rrddim_add(m->numastat_st, "local_node",     "local",      1, 1, RRD_ALGORITHM_INCREMENTAL);
-                    rrddim_add(m->numastat_st, "numa_foreign",   "foreign",    1, 1, RRD_ALGORITHM_INCREMENTAL);
-                    rrddim_add(m->numastat_st, "interleave_hit", "interleave", 1, 1, RRD_ALGORITHM_INCREMENTAL);
-                    rrddim_add(m->numastat_st, "other_node",     "other",      1, 1, RRD_ALGORITHM_INCREMENTAL);
-
-                }
-
-                size_t lines = procfile_lines(m->numastat_ff), l;
-                for(l = 0; l < lines; l++) {
-                    size_t words = procfile_linewords(m->numastat_ff, l);
-
-                    if(unlikely(words < 2)) {
-                        if(unlikely(words))
-                            collector_error("Cannot read %s numastat line %zu. Expected 2 params, read %zu.", m->name, l, words);
-                        continue;
-                    }
-
-                    char *name  = procfile_lineword(m->numastat_ff, l, 0);
-                    char *value = procfile_lineword(m->numastat_ff, l, 1);
-
-                    if (unlikely(!name || !*name || !value || !*value))
-                        continue;
-
-                    uint32_t hash = simple_hash(name);
-                    if(likely(
-                               (hash == hash_numa_hit       && !strcmp(name, "numa_hit"))
-                            || (hash == hash_numa_miss      && !strcmp(name, "numa_miss"))
-                            || (hash == hash_local_node     && !strcmp(name, "local_node"))
-                            || (hash == hash_numa_foreign   && !strcmp(name, "numa_foreign"))
-                            || (hash == hash_interleave_hit && !strcmp(name, "interleave_hit"))
-                            || (hash == hash_other_node     && !strcmp(name, "other_node"))
-                    ))
-                        rrddim_set(m->numastat_st, name, (collected_number)str2kernel_uint_t(value));
-                }
+    if (m->numastat.filename) {
+        if(unlikely(!m->numastat.ff)) {
+            m->numastat.ff = procfile_open(m->numastat.filename, " ", PROCFILE_FLAG_DEFAULT);
 
-                rrdset_done(m->numastat_st);
+            if(unlikely(!m->numastat.ff))
+                return;
+        }
+
+        m->numastat.ff = procfile_readall(m->numastat.ff);
+        if(unlikely(!m->numastat.ff || procfile_lines(m->numastat.ff) < 1 || procfile_linewords(m->numastat.ff, 0) < 1))
+            return;
+
+        if(unlikely(!m->numastat.st)) {
+            m->numastat.st = rrdset_create_localhost(
+                "numa_node_stat"
+                , m->name
+                , NULL
+                , "numa"
+                , "mem.numa_node_stat"
+                , "NUMA Node Memory Allocation Events"
+                , "events/s"
+                , PLUGIN_PROC_NAME
+                , "/sys/devices/system/node"
+                , NETDATA_CHART_PRIO_MEM_NUMA_NODES_NUMASTAT
+                , update_every
+                , RRDSET_TYPE_LINE
+            );
+
+            rrdlabels_add(m->numastat.st->rrdlabels, "numa_node", m->name, RRDLABEL_SRC_AUTO);
+
+            rrdset_flag_set(m->numastat.st, RRDSET_FLAG_DETAIL);
+
+            rrddim_add(m->numastat.st, "numa_hit",       "hit",        1, 1, RRD_ALGORITHM_INCREMENTAL);
+            rrddim_add(m->numastat.st, "numa_miss",      "miss",       1, 1, RRD_ALGORITHM_INCREMENTAL);
+            rrddim_add(m->numastat.st, "local_node",     "local",      1, 1, RRD_ALGORITHM_INCREMENTAL);
+            rrddim_add(m->numastat.st, "numa_foreign",   "foreign",    1, 1, RRD_ALGORITHM_INCREMENTAL);
+            rrddim_add(m->numastat.st, "interleave_hit", "interleave", 1, 1, RRD_ALGORITHM_INCREMENTAL);
+            rrddim_add(m->numastat.st, "other_node",     "other",      1, 1, RRD_ALGORITHM_INCREMENTAL);
+
+        }
+
+        size_t lines = procfile_lines(m->numastat.ff), l;
+        for(l = 0; l < lines; l++) {
+            size_t words = procfile_linewords(m->numastat.ff, l);
+
+            if(unlikely(words < 2)) {
+                if(unlikely(words))
+                    collector_error("Cannot read %s line %zu. Expected 2 params, read %zu.", m->numastat.filename, l, words);
+                continue;
             }
+
+            char *name  = procfile_lineword(m->numastat.ff, l, 0);
+            char *value = procfile_lineword(m->numastat.ff, l, 1);
+
+            if (unlikely(!name || !*name || !value || !*value))
+                continue;
+
+            uint32_t hash = simple_hash(name);
+            if(likely(
+                       (hash == hash_numa_hit       && !strcmp(name, "numa_hit"))
+                    || (hash == hash_numa_miss      && !strcmp(name, "numa_miss"))
+                    || (hash == hash_local_node     && !strcmp(name, "local_node"))
+                    || (hash == hash_numa_foreign   && !strcmp(name, "numa_foreign"))
+                    || (hash == hash_interleave_hit && !strcmp(name, "interleave_hit"))
+                    || (hash == hash_other_node     && !strcmp(name, "other_node"))
+                        ))
+                rrddim_set(m->numastat.st, name, (collected_number)str2kernel_uint_t(value));
         }
+
+        rrdset_done(m->numastat.st);
+    }
+}
+
+static void do_numa_meminfo(struct node *m, int update_every) {
+    static uint32_t hash_MemFree = 0, hash_MemUsed = 0;
+    static bool initialized = false;
+    
+    if(unlikely(!initialized)) {
+        initialized = true;
+        hash_MemFree = simple_hash("MemFree");
+        hash_MemUsed = simple_hash("MemUsed");
+    }
+
+    if (m->meminfo.filename) {
+        if(unlikely(!m->meminfo.ff)) {
+            m->meminfo.ff = procfile_open(m->meminfo.filename, " :", PROCFILE_FLAG_DEFAULT);
+            if(unlikely(!m->meminfo.ff))
+                return;
+        }
+
+        m->meminfo.ff = procfile_readall(m->meminfo.ff);
+        if(unlikely(!m->meminfo.ff || procfile_lines(m->meminfo.ff) < 1 || procfile_linewords(m->meminfo.ff, 0) < 1))
+            return;
+
+        if(unlikely(!m->meminfo.st)) {
+            m->meminfo.st = rrdset_create_localhost(
+                "numa_node_mem_usage"
+                , m->name
+                , NULL
+                , "numa"
+                , "mem.numa_node_mem_usage"
+                , "NUMA Node Memory Usage"
+                , "bytes"
+                , PLUGIN_PROC_NAME
+                , "/sys/devices/system/node"
+                , NETDATA_CHART_PRIO_MEM_NUMA_NODES_MEMINFO
+                , update_every
+                , RRDSET_TYPE_STACKED
+            );
+
+            rrdlabels_add(m->meminfo.st->rrdlabels, "numa_node", m->name, RRDLABEL_SRC_AUTO);
+
+            rrdset_flag_set(m->meminfo.st, RRDSET_FLAG_DETAIL);
+
+            rrddim_add(m->meminfo.st, "MemFree", "free", 1, 1, RRD_ALGORITHM_ABSOLUTE);
+            rrddim_add(m->meminfo.st, "MemUsed", "used", 1, 1, RRD_ALGORITHM_ABSOLUTE);
+        }
+
+        size_t lines = procfile_lines(m->meminfo.ff), l;
+        for(l = 0; l < lines; l++) {
+            size_t words = procfile_linewords(m->meminfo.ff, l);
+
+            if(unlikely(words < 4)) {
+                if(unlikely(words))
+                    collector_error("Cannot read %s line %zu. Expected 4 params, read %zu.", m->meminfo.filename, l, words);
+                continue;
+            }
+
+            char *name  = procfile_lineword(m->meminfo.ff, l, 2);
+            char *value = procfile_lineword(m->meminfo.ff, l, 3);
+
+            if (unlikely(!name || !*name || !value || !*value))
+                continue;
+
+            uint32_t hash = simple_hash(name);
+            if(likely(
+                       (hash == hash_MemFree && !strcmp(name, "MemFree"))
+                    || (hash == hash_MemUsed && !strcmp(name, "MemUsed"))
+                    ))
+                rrddim_set(m->meminfo.st, name, (collected_number)str2kernel_uint_t(value) * 1024);
+        }
+
+        rrdset_done(m->meminfo.st);
+    }
+}
+
+int do_proc_sys_devices_system_node(int update_every, usec_t dt) {
+    (void)dt;
+    struct node *m;
+
+    static int do_numastat = -1;
+
+    if(unlikely(do_numastat == -1)) {
+        do_numastat = config_get_boolean_ondemand(
+            "plugin:proc:/sys/devices/system/node", "enable per-node numa metrics", CONFIG_BOOLEAN_AUTO);
+    }
+
+    if(unlikely(numa_root == NULL)) {
+        numa_node_count = find_all_nodes();
+        if(unlikely(numa_root == NULL))
+            return 1;
+    }
+
+    if (do_numastat == CONFIG_BOOLEAN_YES || (do_numastat == CONFIG_BOOLEAN_AUTO && numa_node_count >= 2)) {
+        for (m = numa_root; m; m = m->next) {
+            do_muma_numastat(m, update_every);
+            do_numa_meminfo(m, update_every);
+        }
+        return 0;
     }
 
-    return 0;
+    return 1;
 }