@cryptotaxi247 / netdata-1 / commits / c2ae46d72

added softirqs collection from /proc/softirqs; fixed idlejitter time shift;

Costa Tsaousis (ktsaou) committed Dec 19, 2015 at 14:38 UTC c2ae46d7260d538da587b48fe1a043ea7631cc35
6 files changed +164 -1
src/Makefile.am
+1
@@ -39,6 +39,7 @@ netdata_SOURCES = \
39 popen.c popen.h \
40 proc_diskstats.c \
41 proc_interrupts.c \
42 + proc_softirqs.c \
43 proc_meminfo.c \
44 proc_net_dev.c \
45 proc_net_ip_vs_stats.c \
src/plugin_idlejitter.c
+1 -1
@@ -57,7 +57,7 @@ void *cpuidlejitter_main(void *ptr)
57 }
58 usec -= (sleep_ms * 1000);
59
60 - if(counter) rrdset_next_usec(st, susec);
60 + if(counter) rrdset_next(st);
61 rrddim_set(st, "jitter", usec);
62 rrdset_done(st);
63 }
src/plugin_proc.c
+5
@@ -49,6 +49,7 @@ void *proc_main(void *ptr)
49 int vdo_proc_net_rpc_nfsd = !config_get_boolean("plugin:proc", "/proc/net/rpc/nfsd", 1);
50 int vdo_proc_sys_kernel_random_entropy_avail = !config_get_boolean("plugin:proc", "/proc/sys/kernel/random/entropy_avail", 1);
51 int vdo_proc_interrupts = !config_get_boolean("plugin:proc", "/proc/interrupts", 1);
52 + int vdo_proc_softirqs = !config_get_boolean("plugin:proc", "/proc/softirqs", 1);
53 int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1);
54
55 RRDSET *stcpu = NULL, *stcpu_thread = NULL, *stclients = NULL, *streqs = NULL, *stbytes = NULL;
@@ -64,6 +65,10 @@ void *proc_main(void *ptr)
65 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts().");
66 vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, usec+susec);
67 }
68 + if(!vdo_proc_softirqs) {
69 + debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs().");
70 + vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, usec+susec);
71 + }
72 if(!vdo_proc_sys_kernel_random_entropy_avail) {
73 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail().");
74 vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, usec+susec);
src/plugin_proc.h
+1
@@ -15,5 +15,6 @@ extern int do_proc_vmstat(int update_every, unsigned long long dt);
15 extern int do_proc_net_rpc_nfsd(int update_every, unsigned long long dt);
16 extern int do_proc_sys_kernel_random_entropy_avail(int update_every, unsigned long long dt);
17 extern int do_proc_interrupts(int update_every, unsigned long long dt);
18 +extern int do_proc_softirqs(int update_every, unsigned long long dt);
19
20 #endif /* NETDATA_PLUGIN_PROC_H */
src/proc_softirqs.c new
+155
@@ -0,0 +1,155 @@
1 +#ifdef HAVE_CONFIG_H
2 +#include <config.h>
3 +#endif
4 +#include <stdio.h>
5 +#include <stdlib.h>
6 +#include <string.h>
7 +#include <ctype.h>
8 +
9 +#include "common.h"
10 +#include "appconfig.h"
11 +#include "procfile.h"
12 +#include "rrd.h"
13 +#include "plugin_proc.h"
14 +#include "log.h"
15 +
16 +#define MAX_INTERRUPTS 256
17 +#define MAX_INTERRUPT_CPUS 256
18 +#define MAX_INTERRUPT_NAME 50
19 +
20 +struct interrupt {
21 + int used;
22 + char *id;
23 + char name[MAX_INTERRUPT_NAME + 1];
24 + unsigned long long value[MAX_INTERRUPT_CPUS];
25 + unsigned long long total;
26 +};
27 +
28 +int do_proc_softirqs(int update_every, unsigned long long dt) {
29 + static procfile *ff = NULL;
30 + static int cpus = -1, do_per_core = -1;
31 +
32 + if(dt) {};
33 +
34 + if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1);
35 +
36 + if(!ff) {
37 + char filename[FILENAME_MAX + 1];
38 + snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/softirqs");
39 + ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
40 + }
41 + if(!ff) return 1;
42 +
43 + ff = procfile_readall(ff);
44 + if(!ff) return 0; // we return 0, so that we will retry to open it next time
45 +
46 + uint32_t lines = procfile_lines(ff), l;
47 + uint32_t words = procfile_linewords(ff, 0), w;
48 +
49 + // find how many CPUs are there
50 + if(cpus == -1) {
51 + cpus = 0;
52 + for(w = 0; w < words ; w++) {
53 + if(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0)
54 + cpus++;
55 + }
56 +
57 + if(cpus > MAX_INTERRUPT_CPUS) cpus = MAX_INTERRUPT_CPUS;
58 + }
59 +
60 + if(!cpus) {
61 + error("PLUGIN: PROC_SOFTIRQS: Cannot find the number of CPUs in /proc/softirqs");
62 + return 1;
63 + }
64 +
65 + // allocate the size we need;
66 + struct interrupt irrs[lines];
67 + irrs[0].used = 0;
68 +
69 + // loop through all lines
70 + for(l = 1; l < lines ;l++) {
71 + struct interrupt *irr = &irrs[l];
72 + irr->used = 0;
73 + irr->total = 0;
74 +
75 + words = procfile_linewords(ff, l);
76 + if(!words) continue;
77 +
78 + irr->id = procfile_lineword(ff, l, 0);
79 + if(!irr->id || !irr->id[0]) continue;
80 +
81 + int idlen = strlen(irr->id);
82 + if(irr->id[idlen - 1] == ':')
83 + irr->id[idlen - 1] = '\0';
84 +
85 + int c;
86 + for(c = 0; c < cpus ;c++) {
87 + if((c + 1) < (int)words)
88 + irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
89 + else
90 + irr->value[c] = 0;
91 +
92 + irr->total += irr->value[c];
93 + }
94 +
95 + strncpy(irr->name, irr->id, MAX_INTERRUPT_NAME);
96 + irr->name[MAX_INTERRUPT_NAME] = '\0';
97 +
98 + irr->used = 1;
99 + }
100 +
101 + RRDSET *st;
102 +
103 + // --------------------------------------------------------------------
104 +
105 + st = rrdset_find_bytype("system", "softirqs");
106 + if(!st) {
107 + st = rrdset_create("system", "softirqs", NULL, "system", "System softirqs", "softirqs/s", 1001, update_every, RRDSET_TYPE_STACKED);
108 +
109 + for(l = 0; l < lines ;l++) {
110 + if(!irrs[l].used) continue;
111 + rrddim_add(st, irrs[l].id, irrs[l].name, 1, 1, RRDDIM_INCREMENTAL);
112 + }
113 + }
114 + else rrdset_next(st);
115 +
116 + for(l = 0; l < lines ;l++) {
117 + if(!irrs[l].used) continue;
118 + rrddim_set(st, irrs[l].id, irrs[l].total);
119 + }
120 + rrdset_done(st);
121 +
122 + if(do_per_core) {
123 + int c;
124 +
125 + for(c = 0; c < cpus ; c++) {
126 + char family[256];
127 + snprintf(family, 256, "cpu%d", c);
128 +
129 + char id[256];
130 + snprintf(id, 256, "cpu%d_softirqs", c);
131 +
132 + st = rrdset_find_bytype("cpu", id);
133 + if(!st) {
134 + char name[256], title[256];
135 + snprintf(name, 256, "cpu%d_softirqs", c);
136 + snprintf(title, 256, "CPU%d softirqs", c);
137 + st = rrdset_create("cpu", id, name, family, title, "softirqs/s", 3000 + c, update_every, RRDSET_TYPE_STACKED);
138 +
139 + for(l = 0; l < lines ;l++) {
140 + if(!irrs[l].used) continue;
141 + rrddim_add(st, irrs[l].id, irrs[l].name, 1, 1, RRDDIM_INCREMENTAL);
142 + }
143 + }
144 + else rrdset_next(st);
145 +
146 + for(l = 0; l < lines ;l++) {
147 + if(!irrs[l].used) continue;
148 + rrddim_set(st, irrs[l].id, irrs[l].value[c]);
149 + }
150 + rrdset_done(st);
151 + }
152 + }
153 +
154 + return 0;
155 +}
web/dashboard_full.html
+1
@@ -391,6 +391,7 @@ var messages = {
391 'system.forks': 'The number of new processes created per second, read from <code>/proc/stat</code>.',
392 '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.',
393 '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.',
394 + '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.',
395 '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.',
396 '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.',
397 '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).',