]> arthur.barton.de Git - netdata.git/blob - src/plugin_proc.c
handle usleep() on systems that do not accept more than 999999 usec; implement altern...
[netdata.git] / src / plugin_proc.c
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 #include <pthread.h>
5 #include <sys/time.h>
6 #include <sys/resource.h>
7 #include <strings.h>
8 #include <unistd.h>
9
10 #include "global_statistics.h"
11 #include "common.h"
12 #include "appconfig.h"
13 #include "log.h"
14 #include "rrd.h"
15 #include "plugin_proc.h"
16 #include "main.h"
17 #include "registry.h"
18
19 void *proc_main(void *ptr)
20 {
21         (void)ptr;
22
23         unsigned long long old_web_requests = 0, old_web_usec = 0,
24                         old_content_size = 0, old_compressed_content_size = 0;
25
26         collected_number compression_ratio = -1, average_response_time = -1;
27
28         info("PROC Plugin thread created with task id %d", gettid());
29
30         if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
31                 error("Cannot set pthread cancel type to DEFERRED.");
32
33         if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
34                 error("Cannot set pthread cancel state to ENABLE.");
35
36         struct rusage me, thread;
37
38         // disable (by default) various interface that are not needed
39         config_get_boolean("plugin:proc:/proc/net/dev:lo", "enabled", 0);
40         config_get_boolean("plugin:proc:/proc/net/dev:fireqos_monitor", "enabled", 0);
41
42         // when ZERO, attempt to do it
43         int vdo_proc_net_dev                    = !config_get_boolean("plugin:proc", "/proc/net/dev", 1);
44         int vdo_proc_diskstats                  = !config_get_boolean("plugin:proc", "/proc/diskstats", 1);
45         int vdo_proc_net_snmp                   = !config_get_boolean("plugin:proc", "/proc/net/snmp", 1);
46         int vdo_proc_net_snmp6                  = !config_get_boolean("plugin:proc", "/proc/net/snmp6", 1);
47         int vdo_proc_net_netstat                = !config_get_boolean("plugin:proc", "/proc/net/netstat", 1);
48         int vdo_proc_net_stat_conntrack = !config_get_boolean("plugin:proc", "/proc/net/stat/conntrack", 1);
49         int vdo_proc_net_ip_vs_stats    = !config_get_boolean("plugin:proc", "/proc/net/ip_vs/stats", 1);
50         int vdo_proc_net_stat_synproxy  = !config_get_boolean("plugin:proc", "/proc/net/stat/synproxy", 1);
51         int vdo_proc_stat                               = !config_get_boolean("plugin:proc", "/proc/stat", 1);
52         int vdo_proc_meminfo                    = !config_get_boolean("plugin:proc", "/proc/meminfo", 1);
53         int vdo_proc_vmstat                     = !config_get_boolean("plugin:proc", "/proc/vmstat", 1);
54         int vdo_proc_net_rpc_nfsd               = !config_get_boolean("plugin:proc", "/proc/net/rpc/nfsd", 1);
55         int vdo_proc_sys_kernel_random_entropy_avail    = !config_get_boolean("plugin:proc", "/proc/sys/kernel/random/entropy_avail", 1);
56         int vdo_proc_interrupts                 = !config_get_boolean("plugin:proc", "/proc/interrupts", 1);
57         int vdo_proc_softirqs                   = !config_get_boolean("plugin:proc", "/proc/softirqs", 1);
58         int vdo_proc_loadavg                    = !config_get_boolean("plugin:proc", "/proc/loadavg", 1);
59         int vdo_sys_kernel_mm_ksm               = !config_get_boolean("plugin:proc", "/sys/kernel/mm/ksm", 1);
60         int vdo_cpu_netdata                     = !config_get_boolean("plugin:proc", "netdata server resources", 1);
61
62         // keep track of the time each module was called
63         unsigned long long sutime_proc_net_dev = 0ULL;
64         unsigned long long sutime_proc_diskstats = 0ULL;
65         unsigned long long sutime_proc_net_snmp = 0ULL;
66         unsigned long long sutime_proc_net_snmp6 = 0ULL;
67         unsigned long long sutime_proc_net_netstat = 0ULL;
68         unsigned long long sutime_proc_net_stat_conntrack = 0ULL;
69         unsigned long long sutime_proc_net_ip_vs_stats = 0ULL;
70         unsigned long long sutime_proc_net_stat_synproxy = 0ULL;
71         unsigned long long sutime_proc_stat = 0ULL;
72         unsigned long long sutime_proc_meminfo = 0ULL;
73         unsigned long long sutime_proc_vmstat = 0ULL;
74         unsigned long long sutime_proc_net_rpc_nfsd = 0ULL;
75         unsigned long long sutime_proc_sys_kernel_random_entropy_avail = 0ULL;
76         unsigned long long sutime_proc_interrupts = 0ULL;
77         unsigned long long sutime_proc_softirqs = 0ULL;
78         unsigned long long sutime_proc_loadavg = 0ULL;
79         unsigned long long sutime_sys_kernel_mm_ksm = 0ULL;
80
81         // the next time we will run - aligned properly
82         unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
83         unsigned long long sunow;
84
85         RRDSET *stcpu = NULL, *stcpu_thread = NULL, *stclients = NULL, *streqs = NULL, *stbytes = NULL, *stduration = NULL,
86                         *stcompression = NULL;
87
88         for(;1;) {
89                 if(unlikely(netdata_exit)) break;
90
91                 // delay until it is our time to run
92                 while((sunow = timems()) < sunext)
93                         usecsleep(sunext - sunow);
94
95                 // find the next time we need to run
96                 while(timems() > sunext)
97                         sunext += rrd_update_every * 1000000ULL;
98
99                 if(unlikely(netdata_exit)) break;
100
101                 // BEGIN -- the job to be done
102
103                 if(!vdo_sys_kernel_mm_ksm) {
104                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_kernel_mm_ksm().");
105
106                         sunow = timems();
107                         vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?sunow - sutime_sys_kernel_mm_ksm:0ULL);
108                         sutime_sys_kernel_mm_ksm = sunow;
109                 }
110                 if(unlikely(netdata_exit)) break;
111
112                 if(!vdo_proc_loadavg) {
113                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg().");
114                         sunow = timems();
115                         vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?sunow - sutime_proc_loadavg:0ULL);
116                         sutime_proc_loadavg = sunow;
117                 }
118                 if(unlikely(netdata_exit)) break;
119
120                 if(!vdo_proc_interrupts) {
121                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts().");
122                         sunow = timems();
123                         vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?sunow - sutime_proc_interrupts:0ULL);
124                         sutime_proc_interrupts = sunow;
125                 }
126                 if(unlikely(netdata_exit)) break;
127
128                 if(!vdo_proc_softirqs) {
129                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs().");
130                         sunow = timems();
131                         vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?sunow - sutime_proc_softirqs:0ULL);
132                         sutime_proc_softirqs = sunow;
133                 }
134                 if(unlikely(netdata_exit)) break;
135
136                 if(!vdo_proc_sys_kernel_random_entropy_avail) {
137                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail().");
138                         sunow = timems();
139                         vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?sunow - sutime_proc_sys_kernel_random_entropy_avail:0ULL);
140                         sutime_proc_sys_kernel_random_entropy_avail = sunow;
141                 }
142                 if(unlikely(netdata_exit)) break;
143
144                 if(!vdo_proc_net_dev) {
145                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev().");
146                         sunow = timems();
147                         vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?sunow - sutime_proc_net_dev:0ULL);
148                         sutime_proc_net_dev = sunow;
149                 }
150                 if(unlikely(netdata_exit)) break;
151
152                 if(!vdo_proc_diskstats) {
153                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats().");
154                         sunow = timems();
155                         vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?sunow - sutime_proc_diskstats:0ULL);
156                         sutime_proc_diskstats = sunow;
157                 }
158                 if(unlikely(netdata_exit)) break;
159
160                 if(!vdo_proc_net_snmp) {
161                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp().");
162                         sunow = timems();
163                         vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?sunow - sutime_proc_net_snmp:0ULL);
164                         sutime_proc_net_snmp = sunow;
165                 }
166                 if(unlikely(netdata_exit)) break;
167
168                 if(!vdo_proc_net_snmp6) {
169                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp6().");
170                         sunow = timems();
171                         vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?sunow - sutime_proc_net_snmp6:0ULL);
172                         sutime_proc_net_snmp6 = sunow;
173                 }
174                 if(unlikely(netdata_exit)) break;
175
176                 if(!vdo_proc_net_netstat) {
177                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat().");
178                         sunow = timems();
179                         vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?sunow - sutime_proc_net_netstat:0ULL);
180                         sutime_proc_net_netstat = sunow;
181                 }
182                 if(unlikely(netdata_exit)) break;
183
184                 if(!vdo_proc_net_stat_conntrack) {
185                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack().");
186                         sunow = timems();
187                         vdo_proc_net_stat_conntrack     = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?sunow - sutime_proc_net_stat_conntrack:0ULL);
188                         sutime_proc_net_stat_conntrack = sunow;
189                 }
190                 if(unlikely(netdata_exit)) break;
191
192                 if(!vdo_proc_net_ip_vs_stats) {
193                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats().");
194                         sunow = timems();
195                         vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?sunow - sutime_proc_net_ip_vs_stats:0ULL);
196                         sutime_proc_net_ip_vs_stats = sunow;
197                 }
198                 if(unlikely(netdata_exit)) break;
199
200                 if(!vdo_proc_net_stat_synproxy) {
201                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy().");
202                         sunow = timems();
203                         vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?sunow - sutime_proc_net_stat_synproxy:0ULL);
204                         sutime_proc_net_stat_synproxy = sunow;
205                 }
206                 if(unlikely(netdata_exit)) break;
207
208                 if(!vdo_proc_stat) {
209                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat().");
210                         sunow = timems();
211                         vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?sunow - sutime_proc_stat:0ULL);
212                         sutime_proc_stat = sunow;
213                 }
214                 if(unlikely(netdata_exit)) break;
215
216                 if(!vdo_proc_meminfo) {
217                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo().");
218                         sunow = timems();
219                         vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?sunow - sutime_proc_meminfo:0ULL);
220                         sutime_proc_meminfo = sunow;
221                 }
222                 if(unlikely(netdata_exit)) break;
223
224                 if(!vdo_proc_vmstat) {
225                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat().");
226                         sunow = timems();
227                         vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?sunow - sutime_proc_vmstat:0ULL);
228                         sutime_proc_vmstat = sunow;
229                 }
230                 if(unlikely(netdata_exit)) break;
231
232                 if(!vdo_proc_net_rpc_nfsd) {
233                         debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd().");
234                         sunow = timems();
235                         vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?sunow - sutime_proc_net_rpc_nfsd:0ULL);
236                         sutime_proc_net_rpc_nfsd = sunow;
237                 }
238                 if(unlikely(netdata_exit)) break;
239
240                 // END -- the job is done
241
242                 // --------------------------------------------------------------------
243
244                 if(!vdo_cpu_netdata) {
245                         getrusage(RUSAGE_THREAD, &thread);
246                         getrusage(RUSAGE_SELF, &me);
247
248                         if(!stcpu_thread) stcpu_thread = rrdset_find("netdata.plugin_proc_cpu");
249                         if(!stcpu_thread) {
250                                 stcpu_thread = rrdset_create("netdata", "plugin_proc_cpu", NULL, "proc.internal", NULL, "NetData Proc Plugin CPU usage", "milliseconds/s", 132000, rrd_update_every, RRDSET_TYPE_STACKED);
251
252                                 rrddim_add(stcpu_thread, "user",  NULL,  1, 1000, RRDDIM_INCREMENTAL);
253                                 rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL);
254                         }
255                         else rrdset_next(stcpu_thread);
256
257                         rrddim_set(stcpu_thread, "user"  , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
258                         rrddim_set(stcpu_thread, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
259                         rrdset_done(stcpu_thread);
260
261                         // ----------------------------------------------------------------
262
263                         if(!stcpu) stcpu = rrdset_find("netdata.server_cpu");
264                         if(!stcpu) {
265                                 stcpu = rrdset_create("netdata", "server_cpu", NULL, "netdata", NULL, "NetData CPU usage", "milliseconds/s", 130000, rrd_update_every, RRDSET_TYPE_STACKED);
266
267                                 rrddim_add(stcpu, "user",  NULL,  1, 1000, RRDDIM_INCREMENTAL);
268                                 rrddim_add(stcpu, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL);
269                         }
270                         else rrdset_next(stcpu);
271
272                         rrddim_set(stcpu, "user"  , me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec);
273                         rrddim_set(stcpu, "system", me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec);
274                         rrdset_done(stcpu);
275
276                         // ----------------------------------------------------------------
277
278                         if(!stclients) stclients = rrdset_find("netdata.clients");
279                         if(!stclients) {
280                                 stclients = rrdset_create("netdata", "clients", NULL, "netdata", NULL, "NetData Web Clients", "connected clients", 130100, rrd_update_every, RRDSET_TYPE_LINE);
281
282                                 rrddim_add(stclients, "clients",  NULL,  1, 1, RRDDIM_ABSOLUTE);
283                         }
284                         else rrdset_next(stclients);
285
286                         rrddim_set(stclients, "clients", global_statistics.connected_clients);
287                         rrdset_done(stclients);
288
289                         // ----------------------------------------------------------------
290
291                         if(!streqs) streqs = rrdset_find("netdata.requests");
292                         if(!streqs) {
293                                 streqs = rrdset_create("netdata", "requests", NULL, "netdata", NULL, "NetData Web Requests", "requests/s", 130200, rrd_update_every, RRDSET_TYPE_LINE);
294
295                                 rrddim_add(streqs, "requests",  NULL,  1, 1, RRDDIM_INCREMENTAL);
296                         }
297                         else rrdset_next(streqs);
298
299                         rrddim_set(streqs, "requests", global_statistics.web_requests);
300                         rrdset_done(streqs);
301
302                         // ----------------------------------------------------------------
303
304                         if(!stbytes) stbytes = rrdset_find("netdata.net");
305                         if(!stbytes) {
306                                 stbytes = rrdset_create("netdata", "net", NULL, "netdata", NULL, "NetData Network Traffic", "kilobits/s", 130300, rrd_update_every, RRDSET_TYPE_AREA);
307
308                                 rrddim_add(stbytes, "in",  NULL,  8, 1024, RRDDIM_INCREMENTAL);
309                                 rrddim_add(stbytes, "out",  NULL,  -8, 1024, RRDDIM_INCREMENTAL);
310                         }
311                         else rrdset_next(stbytes);
312
313                         rrddim_set(stbytes, "in", global_statistics.bytes_received);
314                         rrddim_set(stbytes, "out", global_statistics.bytes_sent);
315                         rrdset_done(stbytes);
316
317                         // ----------------------------------------------------------------
318
319                         if(!stduration) stduration = rrdset_find("netdata.response_time");
320                         if(!stduration) {
321                                 stduration = rrdset_create("netdata", "response_time", NULL, "netdata", NULL, "NetData Average API Response Time", "ms/request", 130400, rrd_update_every, RRDSET_TYPE_LINE);
322
323                                 rrddim_add(stduration, "response_time", "response time",  1, 1000, RRDDIM_ABSOLUTE);
324                         }
325                         else rrdset_next(stduration);
326
327                         unsigned long long gweb_usec     = global_statistics.web_usec;
328                         unsigned long long gweb_requests = global_statistics.web_requests;
329
330                         unsigned long long web_usec     = gweb_usec     - old_web_usec;
331                         unsigned long long web_requests = gweb_requests - old_web_requests;
332
333                         old_web_usec     = gweb_usec;
334                         old_web_requests = gweb_requests;
335
336                         if(web_requests)
337                                 average_response_time =  web_usec / web_requests;
338
339                         if(average_response_time != -1)
340                                 rrddim_set(stduration, "response_time", average_response_time);
341
342                         rrdset_done(stduration);
343
344                         // ----------------------------------------------------------------
345
346                         if(!stcompression) stcompression = rrdset_find("netdata.compression_ratio");
347                         if(!stcompression) {
348                                 stcompression = rrdset_create("netdata", "compression_ratio", NULL, "netdata", NULL, "NetData API Responses Compression Savings Ratio", "percentage", 130500, rrd_update_every, RRDSET_TYPE_LINE);
349
350                                 rrddim_add(stcompression, "savings", NULL,  1, 1000, RRDDIM_ABSOLUTE);
351                         }
352                         else rrdset_next(stcompression);
353
354                         // since we don't lock here to read the global statistics
355                         // read the smaller value first
356                         unsigned long long gcompressed_content_size = global_statistics.compressed_content_size;
357                         unsigned long long gcontent_size            = global_statistics.content_size;
358
359                         unsigned long long compressed_content_size  = gcompressed_content_size - old_compressed_content_size;
360                         unsigned long long content_size             = gcontent_size            - old_content_size;
361
362                         old_compressed_content_size = gcompressed_content_size;
363                         old_content_size            = gcontent_size;
364
365                         if(content_size && content_size >= compressed_content_size)
366                                 compression_ratio = ((content_size - compressed_content_size) * 100 * 1000) / content_size;
367
368                         if(compression_ratio != -1)
369                                 rrddim_set(stcompression, "savings", compression_ratio);
370
371                         rrdset_done(stcompression);
372
373                         // ----------------------------------------------------------------
374
375                         registry_statistics();
376                 }
377         }
378
379         pthread_exit(NULL);
380         return NULL;
381 }