]> arthur.barton.de Git - netdata.git/commitdiff
added softirqs collection from /proc/softirqs; fixed idlejitter time shift;
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sat, 19 Dec 2015 12:38:53 +0000 (14:38 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sat, 19 Dec 2015 12:38:53 +0000 (14:38 +0200)
src/Makefile.am
src/plugin_idlejitter.c
src/plugin_proc.c
src/plugin_proc.h
src/proc_softirqs.c [new file with mode: 0755]
web/dashboard_full.html

index 92f91a0f29b90e60656c06d76723bc1476124683..0f89cf1e82ee44c1cf6e7c1edb866a0f5da95e57 100644 (file)
@@ -39,6 +39,7 @@ netdata_SOURCES = \
        popen.c popen.h \
        proc_diskstats.c \
        proc_interrupts.c \
+       proc_softirqs.c \
        proc_meminfo.c \
        proc_net_dev.c \
        proc_net_ip_vs_stats.c \
index 92b9b393d3242e5dca6d6cfd54c4b6f5d72fa97e..b5ec8009647a07b5eafd8797b7895b08c277cd9c 100755 (executable)
@@ -57,7 +57,7 @@ void *cpuidlejitter_main(void *ptr)
                }
                usec -= (sleep_ms * 1000);
 
-               if(counter) rrdset_next_usec(st, susec);
+               if(counter) rrdset_next(st);
                rrddim_set(st, "jitter", usec);
                rrdset_done(st);
        }
index 40ec38aab647c0a3b393353a5d0a6b057ff89013..f9ae82755d2b50e792d8a8e0a2d1a7807c01b1ab 100755 (executable)
@@ -49,6 +49,7 @@ void *proc_main(void *ptr)
        int vdo_proc_net_rpc_nfsd               = !config_get_boolean("plugin:proc", "/proc/net/rpc/nfsd", 1);
        int vdo_proc_sys_kernel_random_entropy_avail    = !config_get_boolean("plugin:proc", "/proc/sys/kernel/random/entropy_avail", 1);
        int vdo_proc_interrupts                 = !config_get_boolean("plugin:proc", "/proc/interrupts", 1);
+       int vdo_proc_softirqs                   = !config_get_boolean("plugin:proc", "/proc/softirqs", 1);
        int vdo_cpu_netdata                     = !config_get_boolean("plugin:proc", "netdata server resources", 1);
 
        RRDSET *stcpu = NULL, *stcpu_thread = NULL, *stclients = NULL, *streqs = NULL, *stbytes = NULL;
@@ -64,6 +65,10 @@ void *proc_main(void *ptr)
                        debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts().");
                        vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, usec+susec);
                }
+               if(!vdo_proc_softirqs) {
+                       debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs().");
+                       vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, usec+susec);
+               }
                if(!vdo_proc_sys_kernel_random_entropy_avail) {
                        debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail().");
                        vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, usec+susec);
index fa074ac13bb57c6f5bb7a13202a9701444848183..41ba785c38735c95905e054adf537613fb11c969 100755 (executable)
@@ -15,5 +15,6 @@ extern int do_proc_vmstat(int update_every, unsigned long long dt);
 extern int do_proc_net_rpc_nfsd(int update_every, unsigned long long dt);
 extern int do_proc_sys_kernel_random_entropy_avail(int update_every, unsigned long long dt);
 extern int do_proc_interrupts(int update_every, unsigned long long dt);
+extern int do_proc_softirqs(int update_every, unsigned long long dt);
 
 #endif /* NETDATA_PLUGIN_PROC_H */
diff --git a/src/proc_softirqs.c b/src/proc_softirqs.c
new file mode 100755 (executable)
index 0000000..d212281
--- /dev/null
@@ -0,0 +1,155 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "common.h"
+#include "appconfig.h"
+#include "procfile.h"
+#include "rrd.h"
+#include "plugin_proc.h"
+#include "log.h"
+
+#define MAX_INTERRUPTS 256
+#define MAX_INTERRUPT_CPUS 256
+#define MAX_INTERRUPT_NAME 50
+
+struct interrupt {
+       int used;
+       char *id;
+       char name[MAX_INTERRUPT_NAME + 1];
+       unsigned long long value[MAX_INTERRUPT_CPUS];
+       unsigned long long total;
+};
+
+int do_proc_softirqs(int update_every, unsigned long long dt) {
+       static procfile *ff = NULL;
+       static int cpus = -1, do_per_core = -1;
+
+       if(dt) {};
+
+       if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1);
+
+       if(!ff) {
+               char filename[FILENAME_MAX + 1];
+               snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/softirqs");
+               ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
+       }
+       if(!ff) return 1;
+
+       ff = procfile_readall(ff);
+       if(!ff) return 0; // we return 0, so that we will retry to open it next time
+
+       uint32_t lines = procfile_lines(ff), l;
+       uint32_t words = procfile_linewords(ff, 0), w;
+
+       // find how many CPUs are there
+       if(cpus == -1) {
+               cpus = 0;
+               for(w = 0; w < words ; w++) {
+                       if(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0)
+                               cpus++;
+               }
+
+               if(cpus > MAX_INTERRUPT_CPUS) cpus = MAX_INTERRUPT_CPUS;
+       }
+
+       if(!cpus) {
+               error("PLUGIN: PROC_SOFTIRQS: Cannot find the number of CPUs in /proc/softirqs");
+               return 1;
+       }
+
+       // allocate the size we need;
+       struct interrupt irrs[lines];
+       irrs[0].used = 0;
+
+       // loop through all lines
+       for(l = 1; l < lines ;l++) {
+               struct interrupt *irr = &irrs[l];
+               irr->used = 0;
+               irr->total = 0;
+
+               words = procfile_linewords(ff, l);
+               if(!words) continue;
+
+               irr->id = procfile_lineword(ff, l, 0);
+               if(!irr->id || !irr->id[0]) continue;
+
+               int idlen = strlen(irr->id);
+               if(irr->id[idlen - 1] == ':')
+                       irr->id[idlen - 1] = '\0';
+
+               int c;
+               for(c = 0; c < cpus ;c++) {
+                       if((c + 1) < (int)words)
+                               irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
+                       else
+                               irr->value[c] = 0;
+
+                       irr->total += irr->value[c];
+               }
+
+               strncpy(irr->name, irr->id, MAX_INTERRUPT_NAME);
+               irr->name[MAX_INTERRUPT_NAME] = '\0';
+
+               irr->used = 1;
+       }
+
+       RRDSET *st;
+
+       // --------------------------------------------------------------------
+
+       st = rrdset_find_bytype("system", "softirqs");
+       if(!st) {
+               st = rrdset_create("system", "softirqs", NULL, "system", "System softirqs", "softirqs/s", 1001, update_every, RRDSET_TYPE_STACKED);
+
+               for(l = 0; l < lines ;l++) {
+                       if(!irrs[l].used) continue;
+                       rrddim_add(st, irrs[l].id, irrs[l].name, 1, 1, RRDDIM_INCREMENTAL);
+               }
+       }
+       else rrdset_next(st);
+
+       for(l = 0; l < lines ;l++) {
+               if(!irrs[l].used) continue;
+               rrddim_set(st, irrs[l].id, irrs[l].total);
+       }
+       rrdset_done(st);
+
+       if(do_per_core) {
+               int c;
+
+               for(c = 0; c < cpus ; c++) {
+                       char family[256];
+                       snprintf(family, 256, "cpu%d", c);
+
+                       char id[256];
+                       snprintf(id, 256, "cpu%d_softirqs", c);
+
+                       st = rrdset_find_bytype("cpu", id);
+                       if(!st) {
+                               char name[256], title[256];
+                               snprintf(name, 256, "cpu%d_softirqs", c);
+                               snprintf(title, 256, "CPU%d softirqs", c);
+                               st = rrdset_create("cpu", id, name, family, title, "softirqs/s", 3000 + c, update_every, RRDSET_TYPE_STACKED);
+
+                               for(l = 0; l < lines ;l++) {
+                                       if(!irrs[l].used) continue;
+                                       rrddim_add(st, irrs[l].id, irrs[l].name, 1, 1, RRDDIM_INCREMENTAL);
+                               }
+                       }
+                       else rrdset_next(st);
+
+                       for(l = 0; l < lines ;l++) {
+                               if(!irrs[l].used) continue;
+                               rrddim_set(st, irrs[l].id, irrs[l].value[c]);
+                       }
+                       rrdset_done(st);
+               }
+       }
+
+       return 0;
+}
index 66e82aa23fc4ffc16041b465d4541134e14a823f..29db4db395e5afe4e33894eead1120dc3642730c 100755 (executable)
@@ -391,6 +391,7 @@ var messages = {
        'system.forks': 'The number of new processes created per second, read from <code>/proc/stat</code>.',
        'system.intr': 'Total number of CPU interrupts, read from <code>/proc/stat</code>. Check <code>system.interrupts</code> that gives more detail about each interrupt and also the <a href="#cpu">CPUs</a> section where interrupts are analyzed per CPU core.',
        'system.interrupts': 'CPU interrupts in detail, read from <code>/proc/interrupts</code>. At the <a href="#cpu">CPUs</a> section, interrupts are analyzed per CPU core.',
+       'system.softirqs': 'CPU softirqs in detail, read from <code>/proc/softirqs</code>. At the <a href="#cpu">CPUs</a> section, softirqs are analyzed per CPU core.',
        'system.processes': 'System processes, read from <code>/proc/stat</code>. <b>Blocked</b> are processes that are willing to execute but they cannot, e.g. because they wait for disk activity.',
        'system.ctxt': '<a href="https://en.wikipedia.org/wiki/Context_switch" target="_blank">Context Switches</a>, read from <code>/proc/stat</code>, is the switching of the CPU from one process, task or thread to another. If there are many processes or threads willing to execute and very few CPU cores available to handle them, the system is making more context switching to balance the CPU resources among them. The whole process is computationally intensive. The more the context switches, the slower the system gets.',
        'system.idlejitter': 'Idle jitter is calculated by netdata. A thread is spawned that requests to sleep for a few microseconds. When the system wakes it up, it measures how many microseconds have passed. The different between the requested and the actual duration of the sleep, is the <b>idle jitter</b>. This number is useful in realtime environments, where CPU jitter can affect the quality of the service (like VoIP media gateways).',