]> arthur.barton.de Git - netdata.git/blob - src/freebsd_stat.c
Add some basic system stats - load, cpu, interrupts, processes
[netdata.git] / src / freebsd_stat.c
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 }