@cryptotaxi247 / netdata-1 / commits / 2ebb9ab48

Add some basic system stats - load, cpu, interrupts, processes

Vladimir Kobal committed Dec 3, 2016 at 23:17 UTC 2ebb9ab48f89c573ce4e051c42ef08c4200f686c
6 files changed +379 -4
src/Makefile.am
+2
@@ -62,6 +62,8 @@ netdata_SOURCES = \
62 if FREEBSD
63 netdata_SOURCES += \
64 plugin_freebsd.c plugin_freebsd.h \
65 + freebsd_loadavg.c \
66 + freebsd_stat.c \
67 $(NULL)
68 else
69 netdata_SOURCES += \
src/freebsd_loadavg.c new
+78
@@ -0,0 +1,78 @@
1 +#include "common.h"
2 +#include <sys/vmmeter.h>
3 +
4 +// FreeBSD calculates this once every 5 seconds
5 +#define MIN_LOADAVG_UPDATE_EVERY 5
6 +
7 +int do_proc_loadavg(int update_every, unsigned long long dt) {
8 + (void)dt;
9 +
10 + static int do_loadavg = -1, do_all_processes = -1;
11 + static unsigned long long last_loadavg_usec = 0;
12 + static RRDSET *load_chart = NULL, *processes_chart = NULL;
13 +
14 + if(unlikely(do_loadavg == -1)) {
15 + do_loadavg = config_get_boolean("plugin:proc:/proc/loadavg", "enable load average", 1);
16 + do_all_processes = config_get_boolean("plugin:proc:/proc/loadavg", "enable total processes", 1);
17 + }
18 +
19 + struct loadavg sysload;
20 +
21 + if (unlikely(GETSYSCTL("vm.loadavg", sysload)))
22 + return 1;
23 +
24 + double load1 = (double)sysload.ldavg[0] / sysload.fscale;
25 + double load5 = (double)sysload.ldavg[1] / sysload.fscale;
26 + double load15 = (double)sysload.ldavg[2] / sysload.fscale;
27 +
28 + struct vmtotal total;
29 +
30 + if (unlikely(GETSYSCTL("vm.vmtotal", total)))
31 + return 1;
32 +
33 + unsigned long long active_processes = total.t_rq + total.t_dw + total.t_pw + total.t_sl + total.t_sw;
34 +
35 + // --------------------------------------------------------------------
36 +
37 + if(last_loadavg_usec <= dt) {
38 + if(likely(do_loadavg)) {
39 + if(unlikely(!load_chart)) {
40 + load_chart = rrdset_find_byname("system.load");
41 + if(unlikely(!load_chart)) {
42 + load_chart = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE);
43 + rrddim_add(load_chart, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
44 + rrddim_add(load_chart, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
45 + rrddim_add(load_chart, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE);
46 + }
47 + }
48 + else
49 + rrdset_next(load_chart);
50 +
51 + rrddim_set(load_chart, "load1", (collected_number) (load1 * 1000));
52 + rrddim_set(load_chart, "load5", (collected_number) (load5 * 1000));
53 + rrddim_set(load_chart, "load15", (collected_number) (load15 * 1000));
54 + rrdset_done(load_chart);
55 + }
56 +
57 + last_loadavg_usec = load_chart->update_every * 1000000ULL;
58 + }
59 + else last_loadavg_usec -= dt;
60 +
61 + // --------------------------------------------------------------------
62 +
63 + if(likely(do_all_processes)) {
64 + if(unlikely(!processes_chart)) {
65 + processes_chart = rrdset_find_byname("system.active_processes");
66 + if(unlikely(!processes_chart)) {
67 + processes_chart = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE);
68 + rrddim_add(processes_chart, "active", NULL, 1, 1, RRDDIM_ABSOLUTE);
69 + }
70 + }
71 + else rrdset_next(processes_chart);
72 +
73 + rrddim_set(processes_chart, "active", active_processes);
74 + rrdset_done(processes_chart);
75 + }
76 +
77 + return 0;
78 +}
src/freebsd_stat.c new
+254
@@ -0,0 +1,254 @@
1 +#include "common.h"
2 +#include <sys/vmmeter.h>
3 +
4 +int do_proc_stat(int update_every, unsigned long long dt) {
5 + (void)dt;
6 +
7 + static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1;
8 +
9 + if(unlikely(do_cpu == -1)) {
10 + do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", 1);
11 + do_cpu_cores = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", 1);
12 + do_interrupts = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", 1);
13 + do_context = config_get_boolean("plugin:proc:/proc/stat", "context switches", 1);
14 + do_forks = config_get_boolean("plugin:proc:/proc/stat", "processes started", 1);
15 + do_processes = config_get_boolean("plugin:proc:/proc/stat", "processes running", 1);
16 + }
17 +
18 + RRDSET *st;
19 +
20 + char cpuid[5] = "cpu0";
21 + unsigned long long user = 0, nice = 0, system = 0, interrupt = 0, idle = 0;
22 + u_int vm_stat;
23 + size_t intrcnt_size;
24 + unsigned long nintr = 0;
25 + unsigned long *intrcnt;
26 + unsigned long long totalintr = 0;
27 + unsigned long long running = 0 , blocked = 0;
28 +
29 + long multiplier = 1;
30 + long divisor = 1; // sysconf(_SC_CLK_TCK);
31 +
32 + long cp_time[CPUSTATES];
33 + long *pcpu_cp_time;
34 +
35 + int i, ncpus;
36 +
37 + struct vmtotal total;
38 +
39 + if(likely(do_cpu)) {
40 + if (unlikely(CPUSTATES != 5)) {
41 + error("There are %d CPU states (5 was expected)", CPUSTATES);
42 + do_cpu = 0;
43 + error("Total CPU utilization stats was switched off");
44 + return 0;
45 + }
46 + if (unlikely(GETSYSCTL("kern.cp_time", cp_time))) {
47 + do_cpu = 0;
48 + error("Total CPU utilization stats was switched off");
49 + return 0;
50 + }
51 + user = cp_time[0];
52 + nice = cp_time[1];
53 + system = cp_time[2];
54 + interrupt = cp_time[3];
55 + idle = cp_time[4];
56 +
57 + st = rrdset_find_bytype("system", "cpu");
58 + if(unlikely(!st)) {
59 + st = rrdset_create("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization", "percentage", 100, update_every, RRDSET_TYPE_STACKED);
60 +
61 + rrddim_add(st, "user", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
62 + rrddim_add(st, "system", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
63 + rrddim_add(st, "interrupt", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
64 + rrddim_add(st, "nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
65 + rrddim_add(st, "idle", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
66 + rrddim_hide(st, "idle");
67 + }
68 + else rrdset_next(st);
69 +
70 + rrddim_set(st, "user", user);
71 + rrddim_set(st, "system", system);
72 + rrddim_set(st, "interrupt", interrupt);
73 + rrddim_set(st, "nice", nice);
74 + rrddim_set(st, "idle", idle);
75 + rrdset_done(st);
76 + }
77 +
78 + // --------------------------------------------------------------------
79 +
80 + if(likely(do_cpu_cores)) {
81 + if (unlikely(CPUSTATES != 5)) {
82 + error("There are %d CPU states (5 was expected)", CPUSTATES);
83 + do_cpu_cores = 0;
84 + error("CPU cores utilization stats was switched off");
85 + return 0;
86 + }
87 + if (unlikely(GETSYSCTL("kern.smp.cpus", ncpus))) {
88 + do_cpu_cores = 0;
89 + error("CPU cores utilization stats was switched off");
90 + return 0;
91 + }
92 + pcpu_cp_time = malloc(sizeof(cp_time) * ncpus);
93 +
94 + for (i = 0; i < ncpus; i++) {
95 + if (unlikely(getsysctl("kern.cp_times", pcpu_cp_time, sizeof(cp_time) * ncpus))) {
96 + do_cpu_cores = 0;
97 + error("CPU cores utilization stats was switched off");
98 + return 0;
99 + }
100 + cpuid[3] = '0' + i;
101 + user = pcpu_cp_time[i * 5 + 0];
102 + nice = pcpu_cp_time[i * 5 + 1];
103 + system = pcpu_cp_time[i * 5 + 2];
104 + interrupt = pcpu_cp_time[i * 5 + 3];
105 + idle = pcpu_cp_time[i * 5 + 4];
106 +
107 + st = rrdset_find_bytype("cpu", cpuid);
108 + if(unlikely(!st)) {
109 + st = rrdset_create("cpu", cpuid, NULL, "utilization", "cpu.cpu", "Core utilization", "percentage", 1000, update_every, RRDSET_TYPE_STACKED);
110 +
111 + rrddim_add(st, "user", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
112 + rrddim_add(st, "system", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
113 + rrddim_add(st, "interrupt", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
114 + rrddim_add(st, "nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
115 + rrddim_add(st, "idle", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
116 + rrddim_hide(st, "idle");
117 + }
118 + else rrdset_next(st);
119 +
120 + rrddim_set(st, "user", user);
121 + rrddim_set(st, "system", system);
122 + rrddim_set(st, "interrupt", interrupt);
123 + rrddim_set(st, "nice", nice);
124 + rrddim_set(st, "idle", idle);
125 + rrdset_done(st);
126 + }
127 + free(pcpu_cp_time);
128 + }
129 +
130 + // --------------------------------------------------------------------
131 +
132 + if(likely(do_interrupts)) {
133 + if (unlikely(sysctlbyname("hw.intrcnt", NULL, &intrcnt_size, NULL, 0) == -1)) {
134 + error("sysctl(hw.intrcnt...) failed: %s", strerror(errno));
135 + do_interrupts = 0;
136 + error("Total device interrupts stats was switched off");
137 + return 0;
138 + }
139 + nintr = intrcnt_size / sizeof(u_long);
140 + intrcnt = malloc(nintr * sizeof(u_long));
141 + if (unlikely(getsysctl("hw.intrcnt", intrcnt, nintr * sizeof(u_long)))){
142 + do_interrupts = 0;
143 + error("Total device interrupts stats was switched off");
144 + return 0;
145 + }
146 + for (i = 0; i < nintr; i++)
147 + totalintr += intrcnt[i];
148 + free(intrcnt);
149 +
150 + st = rrdset_find_bytype("system", "intr");
151 + if(unlikely(!st)) {
152 + st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "Total Device Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
153 + st->isdetail = 1;
154 +
155 + rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL);
156 + }
157 + else rrdset_next(st);
158 +
159 + rrddim_set(st, "interrupts", totalintr);
160 + rrdset_done(st);
161 + }
162 +
163 +/* Temporarily switched off
164 + if(likely(do_interrupts)) {
165 + if (unlikely(GETSYSCTL("vm.stats.sys.v_intr", vm_stat))) {
166 + do_interrupts = 0;
167 + error("Device interrupts utilization stats was switched off");
168 + return 0;
169 + }
170 +
171 + st = rrdset_find_bytype("system", "intr");
172 + if(unlikely(!st)) {
173 + st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "Device Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
174 + st->isdetail = 1;
175 +
176 + rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL);
177 + }
178 + else rrdset_next(st);
179 +
180 + rrddim_set(st, "interrupts", vm_stat);
181 + rrdset_done(st);
182 + }
183 +*/
184 + // --------------------------------------------------------------------
185 +
186 + if(likely(do_context)) {
187 + if (unlikely(GETSYSCTL("vm.stats.sys.v_swtch", vm_stat))) {
188 + do_context = 0;
189 + error("CPU context switches stats was switched off");
190 + return 0;
191 + }
192 +
193 + st = rrdset_find_bytype("system", "ctxt");
194 + if(unlikely(!st)) {
195 + st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE);
196 +
197 + rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL);
198 + }
199 + else rrdset_next(st);
200 +
201 + rrddim_set(st, "switches", vm_stat);
202 + rrdset_done(st);
203 + }
204 +
205 + // --------------------------------------------------------------------
206 +
207 + if(likely(do_forks)) {
208 + if (unlikely(GETSYSCTL("vm.stats.vm.v_forks", vm_stat))) {
209 + do_forks = 0;
210 + error("Fork stats was switched off");
211 + return 0;
212 + }
213 +
214 + st = rrdset_find_bytype("system", "forks");
215 + if(unlikely(!st)) {
216 + st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE);
217 + st->isdetail = 1;
218 +
219 + rrddim_add(st, "started", NULL, 1, 1, RRDDIM_INCREMENTAL);
220 + }
221 + else rrdset_next(st);
222 +
223 + rrddim_set(st, "started", vm_stat);
224 + rrdset_done(st);
225 + }
226 +
227 + // --------------------------------------------------------------------
228 +
229 + if(likely(do_processes)) {
230 + if (unlikely(GETSYSCTL("vm.vmtotal", total))) {
231 + do_processes = 0;
232 + error("System processes stats was switched off");
233 + return 0;
234 + }
235 +
236 + running = total.t_rq;
237 + blocked = total.t_dw + total.t_pw;
238 +
239 + st = rrdset_find_bytype("system", "processes");
240 + if(unlikely(!st)) {
241 + st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
242 +
243 + rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
244 + rrddim_add(st, "blocked", NULL, -1, 1, RRDDIM_ABSOLUTE);
245 + }
246 + else rrdset_next(st);
247 +
248 + rrddim_set(st, "running", running);
249 + rrddim_set(st, "blocked", blocked);
250 + rrdset_done(st);
251 + }
252 +
253 + return 0;
254 +}
\ No newline at end of file
src/main.c
+1 -1
@@ -48,7 +48,7 @@ struct netdata_static_thread {
48 #ifndef __FreeBSD__
49 {"proc", "plugins", "proc", 1, NULL, NULL, proc_main},
50 #else
51 - {"freebsd", "plugins", "freebsd", 1, NULL, NULL, freebsd_main},
51 + {"proc", "plugins", "proc", 1, NULL, NULL, freebsd_main},
52 #endif /* __FreeBSD__ */
53
54 {"cgroups", "plugins", "cgroups", 1, NULL, NULL, cgroups_main},
src/plugin_freebsd.c
+38 -2
@@ -42,7 +42,8 @@ void *freebsd_main(void *ptr)
42 int vdo_sys_kernel_mm_ksm = !config_get_boolean("plugin:proc", "/sys/kernel/mm/ksm", 1);
43 */
44 int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1);
45 -
45 + int vdo_proc_stat = !config_get_boolean("plugin:proc", "/proc/stat", 1);
46 + int vdo_proc_loadavg = !config_get_boolean("plugin:proc", "/proc/loadavg", 1);
47
48 // keep track of the time each module was called
49 /*
@@ -67,6 +68,8 @@ void *freebsd_main(void *ptr)
68 unsigned long long sutime_ipc = 0ULL;
69 unsigned long long sutime_sys_kernel_mm_ksm = 0ULL;
70 */
71 + unsigned long long sutime_proc_stat = 0ULL;
72 + unsigned long long sutime_proc_loadavg = 0ULL;
73
74 unsigned long long step = rrd_update_every * 1000000ULL;
75 for(;;) {
@@ -243,7 +246,23 @@ void *freebsd_main(void *ptr)
246 sutime_proc_net_rpc_nfs = now;
247 }
248 if(unlikely(netdata_exit)) break;
246 - */
249 + */
250 +
251 + if(!vdo_proc_stat) {
252 + debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat().");
253 + now = time_usec();
254 + vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?now - sutime_proc_stat:0ULL);
255 + sutime_proc_stat = now;
256 + }
257 + if(unlikely(netdata_exit)) break;
258 +
259 + if(!vdo_proc_loadavg) {
260 + debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg().");
261 + now = time_usec();
262 + vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?now - sutime_proc_loadavg:0ULL);
263 + sutime_proc_loadavg = now;
264 + }
265 + if(unlikely(netdata_exit)) break;
266
267 // END -- the job is done
268
@@ -260,3 +279,20 @@ void *freebsd_main(void *ptr)
279 pthread_exit(NULL);
280 return NULL;
281 }
282 +
283 +int getsysctl(const char *name, void *ptr, size_t len)
284 +{
285 + size_t nlen = len;
286 +
287 + if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) {
288 + error("FREEBSD: sysctl(%s...) failed: %s\n", name,
289 + strerror(errno));
290 + return 1;
291 + }
292 + if (unlikely(nlen != len)) {
293 + error("FREEBSD: sysctl(%s...) expected %lu, got %lu\n",
294 + name, (unsigned long)len, (unsigned long)nlen);
295 + return 1;
296 + }
297 + return 0;
298 +}
\ No newline at end of file
src/plugin_freebsd.h
+6 -1
@@ -1,8 +1,12 @@
1 #ifndef NETDATA_PLUGIN_FREEBSD_H
2 #define NETDATA_PLUGIN_FREEBSD_H 1
3
4 +#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
5 +
6 void *freebsd_main(void *ptr);
7
8 +extern int getsysctl(const char *name, void *ptr, size_t len);
9 +
10 /*
11 extern int do_proc_net_dev(int update_every, unsigned long long dt);
12 extern int do_proc_diskstats(int update_every, unsigned long long dt);
@@ -11,7 +15,6 @@ extern int do_proc_net_snmp6(int update_every, unsigned long long dt);
15 extern int do_proc_net_netstat(int update_every, unsigned long long dt);
16 extern int do_proc_net_stat_conntrack(int update_every, unsigned long long dt);
17 extern int do_proc_net_ip_vs_stats(int update_every, unsigned long long dt);
14 -extern int do_proc_stat(int update_every, unsigned long long dt);
18 extern int do_proc_meminfo(int update_every, unsigned long long dt);
19 extern int do_proc_vmstat(int update_every, unsigned long long dt);
20 extern int do_proc_net_rpc_nfs(int update_every, unsigned long long dt);
@@ -24,5 +27,7 @@ extern int do_proc_loadavg(int update_every, unsigned long long dt);
27 extern int do_proc_net_stat_synproxy(int update_every, unsigned long long dt);
28 extern int do_proc_net_softnet_stat(int update_every, unsigned long long dt);
29 */
30 +extern int do_proc_stat(int update_every, unsigned long long dt);
31 +extern int do_proc_loadavg(int update_every, unsigned long long dt);
32
33 #endif /* NETDATA_FREEBSD_PROC_H */