@cryptotaxi247 / netdata-1 / commits / 7629ce955

cleanup

Costa Tsaousis (ktsaou) committed May 10, 2014 at 17:30 UTC 7629ce9554acbbb1d76f42a840e87670eeb83752
5 files changed +1291 -1251
Makefile
+21 -9
@@ -1,11 +1,27 @@
1
2 +CONFIG_DIR = "conf.d"
3 +LOG_DIR = "log"
4 +PLUGINS_DIR = "plugins.d"
5 +
6 +COMMON_FLAGS = -DCONFIG_DIR='$(CONFIG_DIR)' -DLOG_DIR='$(LOG_DIR)' -DPLUGINS_DIR='$(PLUGINS_DIR)'
7 +
8 ifdef debug
3 -CFLAGS=-Wall -Wextra -ggdb
9 +CFLAGS = $(COMMON_FLAGS) -Wall -Wextra -ggdb
10 else
5 -CFLAGS=-Wall -Wextra -O3
11 +CFLAGS = $(COMMON_FLAGS) -Wall -Wextra -O3
12 endif
13
8 -all: netdata plugins
14 +all: setuid
15 +
16 +bin: netdata plugins
17 +
18 +setuid: bin
19 + @echo
20 + @echo " >>> apps.plugin requires root access to access files in /proc"
21 + @echo " >>> Please authorize it!"
22 + @echo
23 + sudo chown root plugins.d/apps.plugin
24 + sudo chmod 4775 plugins.d/apps.plugin
25
26 netdata: netdata.c
27 $(CC) $(CFLAGS) -o netdata netdata.c -lpthread -lz
@@ -14,15 +30,11 @@ plugins: plugins.d/apps.plugin
30
31 plugins.d/apps.plugin: apps_plugin.c
32 $(CC) $(CFLAGS) -o plugins.d/apps.plugin apps_plugin.c
17 - @echo
18 - @echo "apps.plugin requires root access to access files in /proc"
19 - @echo "Please authorize it."
20 - sudo chown root plugins.d/apps.plugin
21 - sudo chmod 4775 plugins.d/apps.plugin
33
34 clean:
35 rm -f *.o netdata plugins.d/apps.plugin core
36
37 getconf:
38 + wget -O conf.d/netdata.conf.new "http://localhost:19999/netdata.conf"
39 mv conf.d/netdata.conf conf.d/netdata.conf.old
28 - wget -O conf.d/netdata.conf "http://localhost:19999/netdata.conf"
40 + mv conf.d/netdata.conf.new conf.d/netdata.conf
apps_plugin.c
+1211 -1139
@@ -1,1139 +1,1211 @@
1 -#include <stdio.h>
2 -#include <stdlib.h>
3 -#include <string.h>
4 -#include <time.h>
5 -#include <unistd.h>
6 -#include <sys/types.h>
7 -#include <sys/time.h>
8 -#include <sys/wait.h>
9 -
10 -#include <sys/resource.h>
11 -#include <sys/stat.h>
12 -
13 -#include <errno.h>
14 -#include <stdarg.h>
15 -#include <locale.h>
16 -#include <ctype.h>
17 -#include <fcntl.h>
18 -
19 -#include <malloc.h>
20 -#include <inttypes.h>
21 -#include <dirent.h>
22 -#include <arpa/inet.h>
23 -
24 -#define MAX_COMPARE_NAME 15
25 -#define MAX_NAME 100
26 -
27 -
28 -unsigned long long Hertz = 1;
29 -
30 -long processors = 1;
31 -long pid_max = 32768;
32 -int debug = 0;
33 -
34 -struct wanted {
35 - char compare[MAX_COMPARE_NAME + 1];
36 - char id[MAX_NAME + 1];
37 - char name[MAX_NAME + 1];
38 -
39 - unsigned long long minflt;
40 - unsigned long long cminflt;
41 - unsigned long long majflt;
42 - unsigned long long cmajflt;
43 - unsigned long long utime;
44 - unsigned long long stime;
45 - unsigned long long cutime;
46 - unsigned long long cstime;
47 - unsigned long long num_threads;
48 - unsigned long long rss;
49 -
50 - unsigned long long fix_minflt;
51 - unsigned long long fix_cminflt;
52 - unsigned long long fix_majflt;
53 - unsigned long long fix_cmajflt;
54 - unsigned long long fix_utime;
55 - unsigned long long fix_stime;
56 - unsigned long long fix_cutime;
57 - unsigned long long fix_cstime;
58 -
59 - unsigned long long statm_size;
60 - unsigned long long statm_resident;
61 - unsigned long long statm_share;
62 - unsigned long long statm_text;
63 - unsigned long long statm_lib;
64 - unsigned long long statm_data;
65 - unsigned long long statm_dirty;
66 -
67 - unsigned long long io_logical_bytes_read;
68 - unsigned long long io_logical_bytes_written;
69 - unsigned long long io_read_calls;
70 - unsigned long long io_write_calls;
71 - unsigned long long io_storage_bytes_read;
72 - unsigned long long io_storage_bytes_written;
73 - unsigned long long io_cancelled_write_bytes;
74 -
75 - unsigned long long fix_io_logical_bytes_read;
76 - unsigned long long fix_io_logical_bytes_written;
77 - unsigned long long fix_io_read_calls;
78 - unsigned long long fix_io_write_calls;
79 - unsigned long long fix_io_storage_bytes_read;
80 - unsigned long long fix_io_storage_bytes_written;
81 - unsigned long long fix_io_cancelled_write_bytes;
82 -
83 - unsigned long processes; // how many processes have been merged to this
84 - int exposed; // if set, we have sent this to netdata
85 -
86 - struct wanted *target; // the one that will be reported to netdata
87 - struct wanted *next;
88 -} *wanted_root = NULL, *default_target = NULL;
89 -
90 -int update_every = 1;
91 -unsigned long long file_counter = 0;
92 -
93 -struct wanted *get_wanted(const char *id, struct wanted *target)
94 -{
95 - struct wanted *w;
96 - for(w = wanted_root ; w ; w = w->next)
97 - if(strncmp(id, w->id, MAX_NAME) == 0) return w;
98 -
99 - w = calloc(sizeof(struct wanted), 1);
100 - if(!w) {
101 - fprintf(stderr, "Cannot allocate %lu bytes of memory\n", sizeof(struct wanted));
102 - return NULL;
103 - }
104 -
105 - strncpy(w->id, id, MAX_NAME);
106 - strncpy(w->name, id, MAX_NAME);
107 - strncpy(w->compare, id, MAX_COMPARE_NAME);
108 - w->target = target;
109 -
110 - w->next = wanted_root;
111 - wanted_root = w;
112 -
113 - if(debug) fprintf(stderr, "Adding hook for process '%s', compare '%s' on target '%s'\n", w->id, w->compare, w->target?w->target->id:"");
114 -
115 - return w;
116 -}
117 -
118 -void parse_args(int argc, char **argv)
119 -{
120 - int i = 1;
121 -
122 - debug = 0;
123 - if(i < argc && strcmp(argv[i], "debug") == 0) {
124 - debug = 1;
125 - i++;
126 - }
127 -
128 - if(i < argc) {
129 - update_every = atoi(argv[i++]);
130 - if(update_every == 0) {
131 - i = 1;
132 - update_every = 1;
133 - }
134 - }
135 -
136 - for(; i < argc ; i++) {
137 - struct wanted *w = NULL;
138 - char *s = argv[i];
139 - char *t;
140 -
141 - while((t = strsep(&s, " "))) {
142 - if(w && strcmp(t, "as") == 0 && s && *s) {
143 - strncpy(w->name, s, MAX_NAME);
144 - if(debug) fprintf(stderr, "Setting dimension name to '%s' on target '%s'\n", w->name, w->id);
145 - break;
146 - }
147 -
148 - struct wanted *n = get_wanted(t, w);
149 - if(!w) w = n;
150 - }
151 - }
152 -
153 - default_target = get_wanted("all_other_processes", NULL);
154 - strncpy(default_target->name, "other", MAX_NAME);
155 -}
156 -
157 -// see: man proc
158 -struct pid_stat {
159 - int32_t pid;
160 - char comm[MAX_COMPARE_NAME + 1];
161 - char state;
162 - int32_t ppid;
163 - int32_t pgrp;
164 - int32_t session;
165 - int32_t tty_nr;
166 - int32_t tpgid;
167 - uint64_t flags;
168 - unsigned long long minflt;
169 - unsigned long long cminflt;
170 - unsigned long long majflt;
171 - unsigned long long cmajflt;
172 - unsigned long long utime;
173 - unsigned long long stime;
174 - unsigned long long cutime;
175 - unsigned long long cstime;
176 - int64_t priority;
177 - int64_t nice;
178 - int32_t num_threads;
179 - int64_t itrealvalue;
180 - unsigned long long starttime;
181 - unsigned long long vsize;
182 - unsigned long long rss;
183 - unsigned long long rsslim;
184 - unsigned long long starcode;
185 - unsigned long long endcode;
186 - unsigned long long startstack;
187 - unsigned long long kstkesp;
188 - unsigned long long kstkeip;
189 - uint64_t signal;
190 - uint64_t blocked;
191 - uint64_t sigignore;
192 - uint64_t sigcatch;
193 - uint64_t wchan;
194 - uint64_t nswap;
195 - uint64_t cnswap;
196 - int32_t exit_signal;
197 - int32_t processor;
198 - uint32_t rt_priority;
199 - uint32_t policy;
200 - unsigned long long delayacct_blkio_ticks;
201 - uint64_t guest_time;
202 - int64_t cguest_time;
203 -
204 - unsigned long long statm_size;
205 - unsigned long long statm_resident;
206 - unsigned long long statm_share;
207 - unsigned long long statm_text;
208 - unsigned long long statm_lib;
209 - unsigned long long statm_data;
210 - unsigned long long statm_dirty;
211 -
212 - unsigned long long io_logical_bytes_read;
213 - unsigned long long io_logical_bytes_written;
214 - unsigned long long io_read_calls;
215 - unsigned long long io_write_calls;
216 - unsigned long long io_storage_bytes_read;
217 - unsigned long long io_storage_bytes_written;
218 - unsigned long long io_cancelled_write_bytes;
219 -
220 -/* unsigned long long old_utime;
221 - unsigned long long old_stime;
222 - unsigned long long old_minflt;
223 - unsigned long long old_majflt;
224 -
225 - unsigned long long old_cutime;
226 - unsigned long long old_cstime;
227 - unsigned long long old_cminflt;
228 - unsigned long long old_cmajflt;
229 -
230 - unsigned long long fix_cutime;
231 - unsigned long long fix_cstime;
232 - unsigned long long fix_cminflt;
233 - unsigned long long fix_cmajflt;
234 -
235 - unsigned long long diff_cutime;
236 - unsigned long long diff_cstime;
237 - unsigned long long diff_cminflt;
238 - unsigned long long diff_cmajflt;
239 -*/
240 -
241 - int childs; // number of processes directly referencing this
242 - int updated;
243 - int merged;
244 - int new_entry;
245 - struct wanted *target;
246 - struct pid_stat *parent;
247 - struct pid_stat *prev;
248 - struct pid_stat *next;
249 -} *root = NULL;
250 -
251 -struct pid_stat **all_pids;
252 -
253 -#define PROC_BUFFER 4096
254 -
255 -struct pid_stat *get_entry(pid_t pid)
256 -{
257 - if(all_pids[pid]) {
258 - all_pids[pid]->new_entry = 0;
259 - return all_pids[pid];
260 - }
261 -
262 - all_pids[pid] = calloc(sizeof(struct pid_stat), 1);
263 - if(!all_pids[pid]) {
264 - fprintf(stderr, "Cannot allocate %lu bytes of memory", sizeof(struct pid_stat));
265 - return NULL;
266 - }
267 -
268 - if(root) root->prev = all_pids[pid];
269 - all_pids[pid]->next = root;
270 - root = all_pids[pid];
271 -
272 - all_pids[pid]->new_entry = 1;
273 -
274 - return all_pids[pid];
275 -}
276 -
277 -void del_entry(pid_t pid)
278 -{
279 - if(!all_pids[pid]) return;
280 -
281 - if(debug) fprintf(stderr, "Process %d %s exited, deleting it.\n", pid, all_pids[pid]->comm);
282 -
283 - if(root == all_pids[pid]) root = all_pids[pid]->next;
284 - if(all_pids[pid]->next) all_pids[pid]->next->prev = all_pids[pid]->prev;
285 - if(all_pids[pid]->prev) all_pids[pid]->prev->next = all_pids[pid]->next;
286 -
287 - free(all_pids[pid]);
288 - all_pids[pid] = NULL;
289 -}
290 -
291 -int update_from_proc(void)
292 -{
293 - static long count_open_errors = 0;
294 -
295 - char buffer[PROC_BUFFER + 1];
296 - char name[PROC_BUFFER + 1];
297 - char filename[FILENAME_MAX+1];
298 - DIR *dir = opendir("/proc");
299 - if(!dir) return 0;
300 -
301 - struct dirent *file = NULL;
302 - struct pid_stat *p = NULL;
303 -
304 - // mark them all as un-updated
305 - for(p = root; p ; p = p->next) {
306 - p->parent = NULL;
307 - p->updated = 0;
308 - p->childs = 0;
309 - p->merged = 0;
310 - p->new_entry = 0;
311 - }
312 -
313 - while((file = readdir(dir))) {
314 - char *endptr = file->d_name;
315 - pid_t pid = strtoul(file->d_name, &endptr, 10);
316 - if(pid <= 0 || pid > pid_max || endptr == file->d_name || *endptr != '\0') continue;
317 -
318 -
319 - // --------------------------------------------------------------------
320 - // /proc/<pid>/stat
321 -
322 - snprintf(filename, FILENAME_MAX, "/proc/%s/stat", file->d_name);
323 - int fd = open(filename, O_RDONLY);
324 - if(fd == -1) {
325 - if(errno != ENOENT && errno != ESRCH) {
326 - if(!count_open_errors) fprintf(stderr, "Cannot open file '%s' for reading (%d, %s).\n", filename, errno, strerror(errno));
327 - count_open_errors++;
328 - }
329 - continue;
330 - }
331 - file_counter++;
332 -
333 - int bytes = read(fd, buffer, PROC_BUFFER);
334 - close(fd);
335 -
336 - if(bytes == -1) {
337 - fprintf(stderr, "Cannot read from file '%s' (%s).\n", filename, strerror(errno));
338 - continue;
339 - }
340 -
341 - if(bytes < 10) continue;
342 - buffer[bytes] = '\0';
343 - if(debug) fprintf(stderr, "READ stat: %s", buffer);
344 -
345 - p = get_entry(pid);
346 - if(!p) continue;
347 -
348 - int parsed = sscanf(buffer,
349 - "%d (%[^)]) %c" // pid, comm, state
350 - " %d %d %d %d %d" // ppid, pgrp, session, tty_nr, tpgid
351 - " %lu %llu %llu %llu %llu" // flags, minflt, cminflt, majflt, cmajflt
352 - " %llu %llu %llu %llu" // utime, stime, cutime, cstime
353 - " %ld %ld" // priority, nice
354 - " %d" // num_threads
355 - " %ld" // itrealvalue
356 - " %llu" // starttime
357 - " %llu" // vsize
358 - " %llu" // rss
359 - " %llu %llu %llu %llu %llu %llu" // rsslim, starcode, endcode, startstack, kstkesp, kstkeip
360 - " %lu %lu %lu %lu" // signal, blocked, sigignore, sigcatch
361 - " %lu %lu %lu" // wchan, nswap, cnswap
362 - " %d %d" // exit_signal, processor
363 - " %u %u" // rt_priority, policy
364 - " %llu %lu %ld"
365 - , &p->pid, name, &p->state
366 - , &p->ppid, &p->pgrp, &p->session, &p->tty_nr, &p->tpgid
367 - , &p->flags, &p->minflt, &p->cminflt, &p->majflt, &p->cmajflt
368 - , &p->utime, &p->stime, &p->cutime, &p->cstime
369 - , &p->priority, &p->nice
370 - , &p->num_threads
371 - , &p->itrealvalue
372 - , &p->starttime
373 - , &p->vsize
374 - , &p->rss
375 - , &p->rsslim, &p->starcode, &p->endcode, &p->startstack, &p->kstkesp, &p->kstkeip
376 - , &p->signal, &p->blocked, &p->sigignore, &p->sigcatch
377 - , &p->wchan, &p->nswap, &p->cnswap
378 - , &p->exit_signal, &p->processor
379 - , &p->rt_priority, &p->policy
380 - , &p->delayacct_blkio_ticks, &p->guest_time, &p->cguest_time
381 - );
382 - strncpy(p->comm, name, MAX_COMPARE_NAME);
383 - p->comm[MAX_COMPARE_NAME] = '\0';
384 -
385 - if(debug) fprintf(stderr, "VALUES: %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->comm, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
386 -
387 - if(parsed < 39) fprintf(stderr, "file %s gave %d results (expected 44)\n", filename, parsed);
388 -
389 - // check if it is wanted
390 - // we do this only once, the first time this pid is loaded
391 - if(p->new_entry) {
392 - if(debug) fprintf(stderr, "\tJust added %s\n", p->comm);
393 -
394 - struct wanted *w;
395 - for(w = wanted_root; w ; w = w->next) {
396 - // if(debug) fprintf(stderr, "\t\tcomparing '%s' with '%s'\n", w->compare, p->comm);
397 -
398 - if(strcmp(w->compare, p->comm) == 0) {
399 - if(w->target) p->target = w->target;
400 - else p->target = w;
401 -
402 - if(debug) fprintf(stderr, "\t\t%s linked to target %s\n", p->comm, p->target->name);
403 - }
404 - }
405 - }
406 -
407 - // just a few checks
408 - if(p->ppid < 0 || p->ppid > pid_max) p->ppid = 0;
409 -
410 -
411 - // --------------------------------------------------------------------
412 - // /proc/<pid>/statm
413 -
414 - snprintf(filename, FILENAME_MAX, "/proc/%s/statm", file->d_name);
415 - fd = open(filename, O_RDONLY);
416 - if(fd == -1) {
417 - if(errno != ENOENT && errno != ESRCH) {
418 - if(!count_open_errors) fprintf(stderr, "Cannot open file '%s' for reading (%d, %s).\n", filename, errno, strerror(errno));
419 - count_open_errors++;
420 - }
421 - }
422 - else {
423 - file_counter++;
424 - bytes = read(fd, buffer, PROC_BUFFER);
425 - close(fd);
426 -
427 - if(bytes == -1) {
428 - fprintf(stderr, "Cannot read from file '%s' (%s).\n", filename, strerror(errno));
429 - }
430 - else if(bytes > 10) {
431 - buffer[bytes] = '\0';
432 - if(debug) fprintf(stderr, "READ statm: %s", buffer);
433 -
434 - parsed = sscanf(buffer,
435 - "%llu %llu %llu %llu %llu %llu %llu"
436 - , &p->statm_size
437 - , &p->statm_resident
438 - , &p->statm_share
439 - , &p->statm_text
440 - , &p->statm_lib
441 - , &p->statm_data
442 - , &p->statm_dirty
443 - );
444 -
445 - if(parsed < 7) fprintf(stderr, "file %s gave %d results (expected 7)\n", filename, parsed);
446 - }
447 - }
448 -
449 - // --------------------------------------------------------------------
450 - // /proc/<pid>/io
451 -
452 - snprintf(filename, FILENAME_MAX, "/proc/%s/io", file->d_name);
453 - fd = open(filename, O_RDONLY);
454 - if(fd == -1) {
455 - if(errno != ENOENT && errno != ESRCH) {
456 - if(!count_open_errors) fprintf(stderr, "Cannot open file '%s' for reading (%d, %s).\n", filename, errno, strerror(errno));
457 - count_open_errors++;
458 - }
459 - }
460 - else {
461 - file_counter++;
462 - bytes = read(fd, buffer, PROC_BUFFER);
463 - close(fd);
464 -
465 - if(bytes == -1) {
466 - fprintf(stderr, "Cannot read from file '%s' (%s).\n", filename, strerror(errno));
467 - }
468 - else if(bytes > 10) {
469 - buffer[bytes] = '\0';
470 - if(debug) fprintf(stderr, "READ io: %s", buffer);
471 -
472 - parsed = sscanf(buffer,
473 - "rchar: %llu\nwchar: %llu\nsyscr: %llu\nsyscw: %llu\nread_bytes: %llu\nwrite_bytes: %llu\ncancelled_write_bytes: %llu"
474 - , &p->io_logical_bytes_read
475 - , &p->io_logical_bytes_written
476 - , &p->io_read_calls
477 - , &p->io_write_calls
478 - , &p->io_storage_bytes_read
479 - , &p->io_storage_bytes_written
480 - , &p->io_cancelled_write_bytes
481 - );
482 -
483 - if(parsed < 7) fprintf(stderr, "file %s gave %d results (expected 7)\n", filename, parsed);
484 - }
485 - }
486 -
487 -
488 - // --------------------------------------------------------------------
489 - // done!
490 -
491 - // mark it as updated
492 - p->updated = 1;
493 - }
494 - if(count_open_errors > 1 && count_open_errors > 1000) {
495 - fprintf(stderr, "file open errors repeated %ld times\n", count_open_errors - 1);
496 - count_open_errors = 0;
497 - }
498 -
499 - closedir(dir);
500 -
501 - return 1;
502 -}
503 -/*
504 -int walk_down(pid_t pid, int level) {
505 - struct pid_stat *p = NULL;
506 - char b[level+3];
507 - int i, ret = 0;
508 -
509 - for(i = 0; i < level; i++) b[i] = '\t';
510 - b[level] = '|';
511 - b[level+1] = '-';
512 - b[level+2] = '\0';
513 -
514 - for(p = root; p ; p = p->next) {
515 - if(p->ppid == pid) {
516 - ret += walk_down(p->pid, level+1);
517 - }
518 - }
519 -
520 - p = all_pids[pid];
521 - if(p) {
522 - if(!p->updated) ret += 1;
523 - if(ret) fprintf(stderr, "%s %s %d [%s, %s] c=%d u=%llu+%llu, s=%llu+%llu, cu=%llu+%llu, cs=%llu+%llu, n=%llu+%llu, j=%llu+%llu, cn=%llu+%llu, cj=%llu+%llu\n"
524 - , b, p->comm, p->pid, p->updated?"OK":"KILLED", p->target->name, p->childs
525 - , p->utime, p->utime - p->old_utime
526 - , p->stime, p->stime - p->old_stime
527 - , p->cutime, p->cutime - p->old_cutime
528 - , p->cstime, p->cstime - p->old_cstime
529 - , p->minflt, p->minflt - p->old_minflt
530 - , p->majflt, p->majflt - p->old_majflt
531 - , p->cminflt, p->cminflt - p->old_cminflt
532 - , p->cmajflt, p->cmajflt - p->old_cmajflt
533 - );
534 - }
535 -
536 - return ret;
537 -}
538 -*/
539 -
540 -void update_statistics(void)
541 -{
542 - struct pid_stat *p = NULL;
543 -
544 - // link all parents and update childs count
545 - for(p = root; p ; p = p->next) {
546 - if(p->ppid > 0 && p->ppid <= pid_max && all_pids[p->ppid]) {
547 - if(debug) fprintf(stderr, "\tParent of %d %s is %d %s\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm);
548 -
549 - p->parent = all_pids[p->ppid];
550 - p->parent->childs++;
551 - }
552 - else if(p->ppid != 0) fprintf(stderr, "\t\tWRONG! pid %d %s states parent %d, but the later does not exist.\n", p->pid, p->comm, p->ppid);
553 - }
554 -
555 - // find all the procs with 0 childs and merge them to their parents
556 - // repeat, until nothing more can be done.
557 - int found = 1;
558 - while(found) {
559 - found = 0;
560 - for(p = root; p ; p = p->next) {
561 - // if this process does not have any childs, and
562 - // is not already merged, and
563 - // its parent has childs waiting to be merged, and
564 - // the target of this process and its parent is the same, or the parent does not have a target, or this process does not have a parent
565 - // and its parent is not init
566 - // then... merge them!
567 - if(!p->childs && !p->merged && p->parent && p->parent->childs && (p->target == p->parent->target || !p->parent->target || !p->target) && p->ppid != 1) {
568 - p->parent->childs--;
569 - p->merged = 1;
570 -
571 - // the parent inherits the child's target, if it does not have a target itself
572 - if(p->target && !p->parent->target) {
573 - p->parent->target = p->target;
574 - if(debug) fprintf(stderr, "\t\ttarget %s is inherited by %d %s from its child %d %s.\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm);
575 - }
576 -
577 - found++;
578 - }
579 - }
580 - if(debug) fprintf(stderr, "Merged %d processes\n", found);
581 - }
582 -
583 - // give a default target on all top level processes
584 - // init goes always to default target
585 - if(all_pids[1]) all_pids[1]->target = default_target;
586 -
587 - for(p = root; p ; p = p->next) {
588 - // if the process is not merged itself
589 - // then is is a top level process
590 - if(!p->merged && !p->target) p->target = default_target;
591 -
592 -/* // by the way, update the diffs
593 - // will be used later for substracting killed process times
594 - p->diff_cutime = p->utime - p->cutime;
595 - p->diff_cstime = p->stime - p->cstime;
596 - p->diff_cminflt = p->minflt - p->cminflt;
597 - p->diff_cmajflt = p->majflt - p->cmajflt;
598 -*/ }
599 -
600 - // give a target to all merged child processes
601 - found = 1;
602 - while(found) {
603 - found = 0;
604 - for(p = root; p ; p = p->next) {
605 - if(!p->target && p->merged && p->parent && p->parent->target) {
606 - p->target = p->parent->target;
607 - found++;
608 - }
609 - }
610 - }
611 -
612 -/* // for each killed process, remove its values from the parents
613 - // sums (we had already added them in a previous loop)
614 - for(p = root; p ; p = p->next) {
615 - if(p->updated) continue;
616 -
617 - fprintf(stderr, "UNMERGING %d %s\n", p->pid, p->comm);
618 -
619 - unsigned long long diff_utime = p->utime + p->cutime + p->fix_cutime;
620 - unsigned long long diff_stime = p->stime + p->cstime + p->fix_cstime;
621 - unsigned long long diff_minflt = p->minflt + p->cminflt + p->fix_cminflt;
622 - unsigned long long diff_majflt = p->majflt + p->cmajflt + p->fix_cmajflt;
623 -
624 - struct pid_stat *t = p;
625 - while((t = t->parent)) {
626 - if(!t->updated) continue;
627 -
628 - unsigned long long x;
629 - if(diff_utime && t->diff_cutime) {
630 - x = (t->diff_cutime < diff_utime)?t->diff_cutime:diff_utime;
631 - diff_utime -= x;
632 - t->diff_cutime -= x;
633 - t->fix_cutime += x;
634 - fprintf(stderr, "\t cutime %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
635 - }
636 - if(diff_stime && t->diff_cstime) {
637 - x = (t->diff_cstime < diff_stime)?t->diff_cstime:diff_stime;
638 - diff_stime -= x;
639 - t->diff_cstime -= x;
640 - t->fix_cstime += x;
641 - fprintf(stderr, "\t cstime %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
642 - }
643 - if(diff_minflt && t->diff_cminflt) {
644 - x = (t->diff_cminflt < diff_minflt)?t->diff_cminflt:diff_minflt;
645 - diff_minflt -= x;
646 - t->diff_cminflt -= x;
647 - t->fix_cminflt += x;
648 - fprintf(stderr, "\t cminflt %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
649 - }
650 - if(diff_majflt && t->diff_cmajflt) {
651 - x = (t->diff_cmajflt < diff_majflt)?t->diff_cmajflt:diff_majflt;
652 - diff_majflt -= x;
653 - t->diff_cmajflt -= x;
654 - t->fix_cmajflt += x;
655 - fprintf(stderr, "\t cmajflt %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
656 - }
657 - }
658 -
659 - if(diff_utime) fprintf(stderr, "\t cannot fix up utime %llu\n", diff_utime);
660 - if(diff_stime) fprintf(stderr, "\t cannot fix up stime %llu\n", diff_stime);
661 - if(diff_minflt) fprintf(stderr, "\t cannot fix up minflt %llu\n", diff_minflt);
662 - if(diff_majflt) fprintf(stderr, "\t cannot fix up majflt %llu\n", diff_majflt);
663 - }
664 -*/
665 - // zero all the targets
666 - struct wanted *w;
667 - for (w = wanted_root; w ; w = w->next) {
668 - w->minflt = 0;
669 - w->majflt = 0;
670 - w->utime = 0;
671 - w->stime = 0;
672 - w->cminflt = 0;
673 - w->cmajflt = 0;
674 - w->cutime = 0;
675 - w->cstime = 0;
676 - w->num_threads = 0;
677 - w->rss = 0;
678 - w->processes = 0;
679 -
680 - w->statm_size = 0;
681 - w->statm_resident = 0;
682 - w->statm_share = 0;
683 - w->statm_text = 0;
684 - w->statm_lib = 0;
685 - w->statm_data = 0;
686 - w->statm_dirty = 0;
687 -
688 - w->io_logical_bytes_read = 0;
689 - w->io_logical_bytes_written = 0;
690 - w->io_read_calls = 0;
691 - w->io_write_calls = 0;
692 - w->io_storage_bytes_read = 0;
693 - w->io_storage_bytes_written = 0;
694 - w->io_cancelled_write_bytes = 0;
695 - }
696 -
697 -/* walk_down(0, 1);
698 -*/
699 - // concentrate everything on the targets
700 - for(p = root; p ; p = p->next) {
701 - if(!p->target) {
702 - fprintf(stderr, "WRONG! pid %d %s was left without a target!\n", p->pid, p->comm);
703 - continue;
704 - }
705 -
706 - if(p->updated) {
707 - p->target->cutime += p->cutime; // - p->fix_cutime;
708 - p->target->cstime += p->cstime; // - p->fix_cstime;
709 - p->target->cminflt += p->cminflt; // - p->fix_cminflt;
710 - p->target->cmajflt += p->cmajflt; // - p->fix_cmajflt;
711 -
712 - p->target->utime += p->utime; //+ (p->pid != 1)?(p->cutime - p->fix_cutime):0;
713 - p->target->stime += p->stime; //+ (p->pid != 1)?(p->cstime - p->fix_cstime):0;
714 - p->target->minflt += p->minflt; //+ (p->pid != 1)?(p->cminflt - p->fix_cminflt):0;
715 - p->target->majflt += p->majflt; //+ (p->pid != 1)?(p->cmajflt - p->fix_cmajflt):0;
716 -
717 - p->target->num_threads += p->num_threads;
718 - p->target->rss += p->rss;
719 -
720 - p->target->statm_size += p->statm_size;
721 - p->target->statm_resident += p->statm_resident;
722 - p->target->statm_share += p->statm_share;
723 - p->target->statm_text += p->statm_text;
724 - p->target->statm_lib += p->statm_lib;
725 - p->target->statm_data += p->statm_data;
726 - p->target->statm_dirty += p->statm_dirty;
727 -
728 - p->target->io_logical_bytes_read += p->io_logical_bytes_read;
729 - p->target->io_logical_bytes_written += p->io_logical_bytes_written;
730 - p->target->io_read_calls += p->io_read_calls;
731 - p->target->io_write_calls += p->io_write_calls;
732 - p->target->io_storage_bytes_read += p->io_storage_bytes_read;
733 - p->target->io_storage_bytes_written += p->io_storage_bytes_written;
734 - p->target->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
735 -
736 - p->target->processes++;
737 -
738 - if(debug) fprintf(stderr, "\tAgregating %s pid %d on %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->comm, p->pid, p->target->name, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
739 -
740 -/* if(p->utime - p->old_utime > 100) fprintf(stderr, "BIG CHANGE: %d %s utime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->utime - p->old_utime, p->old_utime, p->utime);
741 - if(p->cutime - p->old_cutime > 100) fprintf(stderr, "BIG CHANGE: %d %s cutime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cutime - p->old_cutime, p->old_cutime, p->cutime);
742 - if(p->stime - p->old_stime > 100) fprintf(stderr, "BIG CHANGE: %d %s stime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->stime - p->old_stime, p->old_stime, p->stime);
743 - if(p->cstime - p->old_cstime > 100) fprintf(stderr, "BIG CHANGE: %d %s cstime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cstime - p->old_cstime, p->old_cstime, p->cstime);
744 - if(p->minflt - p->old_minflt > 5000) fprintf(stderr, "BIG CHANGE: %d %s minflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->minflt - p->old_minflt, p->old_minflt, p->minflt);
745 - if(p->majflt - p->old_majflt > 5000) fprintf(stderr, "BIG CHANGE: %d %s majflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->majflt - p->old_majflt, p->old_majflt, p->majflt);
746 - if(p->cminflt - p->old_cminflt > 15000) fprintf(stderr, "BIG CHANGE: %d %s cminflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cminflt - p->old_cminflt, p->old_cminflt, p->cminflt);
747 - if(p->cmajflt - p->old_cmajflt > 15000) fprintf(stderr, "BIG CHANGE: %d %s cmajflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cmajflt - p->old_cmajflt, p->old_cmajflt, p->cmajflt);
748 -
749 - p->old_utime = p->utime;
750 - p->old_cutime = p->cutime;
751 - p->old_stime = p->stime;
752 - p->old_cstime = p->cstime;
753 - p->old_minflt = p->minflt;
754 - p->old_majflt = p->majflt;
755 - p->old_cminflt = p->cminflt;
756 - p->old_cmajflt = p->cmajflt;
757 -*/ }
758 - else {
759 - // since the process has exited, the user
760 - // will see a drop in our charts, because the incremental
761 - // values of this process will not be there
762 -
763 - // add them to the fix_* values and they will be added to
764 - // the reported values, so that the report goes steady
765 - p->target->fix_minflt += p->minflt;
766 - p->target->fix_majflt += p->majflt;
767 - p->target->fix_utime += p->utime;
768 - p->target->fix_stime += p->stime;
769 - p->target->fix_cminflt += p->cminflt;
770 - p->target->fix_cmajflt += p->cmajflt;
771 - p->target->fix_cutime += p->cutime;
772 - p->target->fix_cstime += p->cstime;
773 -
774 - p->target->fix_io_logical_bytes_read += p->io_logical_bytes_read;
775 - p->target->fix_io_logical_bytes_written += p->io_logical_bytes_written;
776 - p->target->fix_io_read_calls += p->io_read_calls;
777 - p->target->fix_io_write_calls += p->io_write_calls;
778 - p->target->fix_io_storage_bytes_read += p->io_storage_bytes_read;
779 - p->target->fix_io_storage_bytes_written += p->io_storage_bytes_written;
780 - p->target->fix_io_cancelled_write_bytes += p->io_cancelled_write_bytes;
781 - }
782 - }
783 -
784 -/* fprintf(stderr, "\n");
785 -*/
786 - // cleanup all un-updated processed (exited, killed, etc)
787 - int c;
788 - for(p = root, c = 0; p ; c++) {
789 - if(!p->updated) {
790 -/* fprintf(stderr, "\tEXITED %d %s [parent %d %s, target %s] utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, p->parent->pid, p->parent->comm, p->target->name, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
791 -*/
792 - pid_t r = p->pid;
793 - p = p->next;
794 - del_entry(r);
795 - }
796 - else p = p->next;
797 - }
798 -}
799 -
800 -
801 -void show_dimensions(void)
802 -{
803 - struct wanted *w;
804 -
805 - fprintf(stdout, "BEGIN apps.cpu\n");
806 - for (w = wanted_root; w ; w = w->next) {
807 - if(w->target || (!w->processes && !w->exposed)) continue;
808 -
809 - fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->stime + w->fix_utime + w->fix_stime);
810 - }
811 - fprintf(stdout, "END\n");
812 -
813 - fprintf(stdout, "BEGIN apps.cpu_user\n");
814 - for (w = wanted_root; w ; w = w->next) {
815 - if(w->target || (!w->processes && !w->exposed)) continue;
816 -
817 - fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->fix_utime);
818 - }
819 - fprintf(stdout, "END\n");
820 -
821 - fprintf(stdout, "BEGIN apps.cpu_system\n");
822 - for (w = wanted_root; w ; w = w->next) {
823 - if(w->target || (!w->processes && !w->exposed)) continue;
824 -
825 - fprintf(stdout, "SET %s = %llu\n", w->name, w->stime + w->fix_stime);
826 - }
827 - fprintf(stdout, "END\n");
828 -
829 - fprintf(stdout, "BEGIN apps.threads\n");
830 - for (w = wanted_root; w ; w = w->next) {
831 - if(w->target || (!w->processes && !w->exposed)) continue;
832 -
833 - fprintf(stdout, "SET %s = %llu\n", w->name, w->num_threads);
834 - }
835 - fprintf(stdout, "END\n");
836 -
837 - fprintf(stdout, "BEGIN apps.processes\n");
838 - for (w = wanted_root; w ; w = w->next) {
839 - if(w->target || (!w->processes && !w->exposed)) continue;
840 -
841 - fprintf(stdout, "SET %s = %lu\n", w->name, w->processes);
842 - }
843 - fprintf(stdout, "END\n");
844 -
845 - fprintf(stdout, "BEGIN apps.mem\n");
846 - for (w = wanted_root; w ; w = w->next) {
847 - if(w->target || (!w->processes && !w->exposed)) continue;
848 -
849 - fprintf(stdout, "SET %s = %lld\n", w->name, (long long)w->statm_resident - (long long)w->statm_share);
850 - }
851 - fprintf(stdout, "END\n");
852 -
853 - fprintf(stdout, "BEGIN apps.minor_faults\n");
854 - for (w = wanted_root; w ; w = w->next) {
855 - if(w->target || (!w->processes && !w->exposed)) continue;
856 -
857 - fprintf(stdout, "SET %s = %llu\n", w->name, w->minflt + w->fix_minflt);
858 - }
859 - fprintf(stdout, "END\n");
860 -
861 - fprintf(stdout, "BEGIN apps.major_faults\n");
862 - for (w = wanted_root; w ; w = w->next) {
863 - if(w->target || (!w->processes && !w->exposed)) continue;
864 -
865 - fprintf(stdout, "SET %s = %llu\n", w->name, w->majflt + w->fix_majflt);
866 - }
867 - fprintf(stdout, "END\n");
868 -
869 - fprintf(stdout, "BEGIN apps.lreads\n");
870 - for (w = wanted_root; w ; w = w->next) {
871 - if(w->target || (!w->processes && !w->exposed)) continue;
872 -
873 - fprintf(stdout, "SET %s = %llu\n", w->name, w->io_logical_bytes_read);
874 - }
875 - fprintf(stdout, "END\n");
876 -
877 - fprintf(stdout, "BEGIN apps.lwrites\n");
878 - for (w = wanted_root; w ; w = w->next) {
879 - if(w->target || (!w->processes && !w->exposed)) continue;
880 -
881 - fprintf(stdout, "SET %s = %llu\n", w->name, w->io_logical_bytes_written);
882 - }
883 - fprintf(stdout, "END\n");
884 -
885 - fprintf(stdout, "BEGIN apps.preads\n");
886 - for (w = wanted_root; w ; w = w->next) {
887 - if(w->target || (!w->processes && !w->exposed)) continue;
888 -
889 - fprintf(stdout, "SET %s = %llu\n", w->name, w->io_storage_bytes_read);
890 - }
891 - fprintf(stdout, "END\n");
892 -
893 - fprintf(stdout, "BEGIN apps.pwrites\n");
894 - for (w = wanted_root; w ; w = w->next) {
895 - if(w->target || (!w->processes && !w->exposed)) continue;
896 -
897 - fprintf(stdout, "SET %s = %llu\n", w->name, w->io_storage_bytes_written);
898 - }
899 - fprintf(stdout, "END\n");
900 -}
901 -
902 -void show_charts(void)
903 -{
904 - struct wanted *w;
905 - int newly_added = 0;
906 -
907 - for(w = wanted_root ; w ; w = w->next)
908 - if(!w->exposed && w->processes) {
909 - newly_added++;
910 - w->exposed = 1;
911 - if(debug) fprintf(stderr, "%s just added - regenerating charts.\n", w->name);
912 - }
913 -
914 - // nothing more to show
915 - if(!newly_added) return;
916 -
917 - // we have something new to show
918 - // update the charts
919 - fprintf(stdout, "CHART apps.cpu '' 'Apps CPU Time (%ld%% = %ld core%s)' 'cpu time %%' apps apps stacked 20001 %d\n", (processors * 100), processors, (processors>1)?"s":"", update_every);
920 - for (w = wanted_root; w ; w = w->next) {
921 - if(w->target || (!w->processes && !w->exposed)) continue;
922 -
923 - fprintf(stdout, "DIMENSION %s '' incremental 100 %llu\n", w->name, Hertz);
924 - }
925 -
926 - fprintf(stdout, "CHART apps.mem '' 'Apps Dedicated Memory (w/o shared)' 'MB' apps apps stacked 20003 %d\n", update_every);
927 - for (w = wanted_root; w ; w = w->next) {
928 - if(w->target || (!w->processes && !w->exposed)) continue;
929 -
930 - fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L);
931 - }
932 -
933 - fprintf(stdout, "CHART apps.threads '' 'Apps Threads' 'threads' apps apps stacked 20005 %d\n", update_every);
934 - for (w = wanted_root; w ; w = w->next) {
935 - if(w->target || (!w->processes && !w->exposed)) continue;
936 -
937 - fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
938 - }
939 -
940 - fprintf(stdout, "CHART apps.processes '' 'Apps Processes' 'processes' apps apps stacked 20004 %d\n", update_every);
941 - for (w = wanted_root; w ; w = w->next) {
942 - if(w->target || (!w->processes && !w->exposed)) continue;
943 -
944 - fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
945 - }
946 -
947 - fprintf(stdout, "CHART apps.cpu_user '' 'Apps CPU User Time (%ld%% = %ld core%s)' 'cpu time %%' apps none stacked 20020 %d\n", (processors * 100), processors, (processors>1)?"s":"", update_every);
948 - for (w = wanted_root; w ; w = w->next) {
949 - if(w->target || (!w->processes && !w->exposed)) continue;
950 -
951 - fprintf(stdout, "DIMENSION %s '' incremental 100 %llu\n", w->name, Hertz * processors);
952 - }
953 -
954 - fprintf(stdout, "CHART apps.cpu_system '' 'Apps CPU System Time (%ld%% = %ld core%s)' 'cpu time %%' apps none stacked 20021 %d\n", (processors * 100), processors, (processors>1)?"s":"", update_every);
955 - for (w = wanted_root; w ; w = w->next) {
956 - if(w->target || (!w->processes && !w->exposed)) continue;
957 -
958 - fprintf(stdout, "DIMENSION %s '' incremental 100 %llu\n", w->name, Hertz * processors);
959 - }
960 -
961 - fprintf(stdout, "CHART apps.major_faults '' 'Apps Major Page Faults (swaps in)' 'page faults/s' apps apps stacked 20010 %d\n", update_every);
962 - for (w = wanted_root; w ; w = w->next) {
963 - if(w->target || (!w->processes && !w->exposed)) continue;
964 -
965 - fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w->name);
966 - }
967 -
968 - fprintf(stdout, "CHART apps.minor_faults '' 'Apps Minor Page Faults' 'page faults/s' apps apps stacked 20011 %d\n", update_every);
969 - for (w = wanted_root; w ; w = w->next) {
970 - if(w->target || (!w->processes && !w->exposed)) continue;
971 -
972 - fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w->name);
973 - }
974 -
975 - fprintf(stdout, "CHART apps.lreads '' 'Apps Logical Reads' 'kilobytes/s' apps apps stacked 20042 %d\n", update_every);
976 - for (w = wanted_root; w ; w = w->next) {
977 - if(w->target || (!w->processes && !w->exposed)) continue;
978 -
979 - fprintf(stdout, "DIMENSION %s '' incremental 1 1024\n", w->name);
980 - }
981 -
982 - fprintf(stdout, "CHART apps.lwrites '' 'Apps Logical Writes' 'kilobytes/s' apps apps stacked 20042 %d\n", update_every);
983 - for (w = wanted_root; w ; w = w->next) {
984 - if(w->target || (!w->processes && !w->exposed)) continue;
985 -
986 - fprintf(stdout, "DIMENSION %s '' incremental 1 1024\n", w->name);
987 - }
988 -
989 - fprintf(stdout, "CHART apps.preads '' 'Apps Reads' 'kilobytes/s' apps apps stacked 20002 %d\n", update_every);
990 - for (w = wanted_root; w ; w = w->next) {
991 - if(w->target || (!w->processes && !w->exposed)) continue;
992 -
993 - fprintf(stdout, "DIMENSION %s '' incremental 1 1024\n", w->name);
994 - }
995 -
996 - fprintf(stdout, "CHART apps.pwrites '' 'Apps Writes' 'kilobytes/s' apps apps stacked 20002 %d\n", update_every);
997 - for (w = wanted_root; w ; w = w->next) {
998 - if(w->target || (!w->processes && !w->exposed)) continue;
999 -
1000 - fprintf(stdout, "DIMENSION %s '' incremental 1 1024\n", w->name);
1001 - }
1002 -}
1003 -
1004 -unsigned long long get_hertz(void)
1005 -{
1006 - unsigned long long hz = 1;
1007 -
1008 -#ifdef _SC_CLK_TCK
1009 - if((hz = sysconf(_SC_CLK_TCK)) > 0) {
1010 - return hz;
1011 - }
1012 -#endif
1013 -
1014 -#ifdef HZ
1015 - hz = (unsigned long long)HZ; /* <asm/param.h> */
1016 -#else
1017 - /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */
1018 - hz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL;
1019 -#endif
1020 -
1021 - fprintf(stderr, "Unknown HZ value. Assuming %llu.\n", hz);
1022 - return hz;
1023 -}
1024 -
1025 -long get_processors(void)
1026 -{
1027 - char buffer[1025], *s;
1028 - int processors = 0;
1029 -
1030 - FILE *fp = fopen("/proc/stat", "r");
1031 - if(!fp) return 1;
1032 -
1033 - while((s = fgets(buffer, 1024, fp))) {
1034 - if(strncmp(buffer, "cpu", 3) == 0) processors++;
1035 - }
1036 - fclose(fp);
1037 - processors--;
1038 - if(processors < 1) processors = 1;
1039 - return processors;
1040 -}
1041 -
1042 -long get_pid_max(void)
1043 -{
1044 - char buffer[1025], *s;
1045 - long mpid = 32768;
1046 -
1047 - FILE *fp = fopen("/proc/sys/kernel/pid_max", "r");
1048 - if(!fp) return 1;
1049 -
1050 - s = fgets(buffer, 1024, fp);
1051 - if(s) mpid = atol(buffer);
1052 - fclose(fp);
1053 - if(mpid < 32768) mpid = 32768;
1054 - return mpid;
1055 -}
1056 -
1057 -unsigned long long usecdiff(struct timeval *now, struct timeval *last) {
1058 - return ((((now->tv_sec * 1000000ULL) + now->tv_usec) - ((last->tv_sec * 1000000ULL) + last->tv_usec)));
1059 -}
1060 -
1061 -int main(int argc, char **argv)
1062 -{
1063 - Hertz = get_hertz();
1064 - pid_max = get_pid_max();
1065 - processors = get_processors();
1066 -
1067 - parse_args(argc, argv);
1068 -
1069 - all_pids = calloc(sizeof(struct pid_stat *), pid_max);
1070 - if(!all_pids) {
1071 - fprintf(stderr, "Cannot allocate %lu bytes of memory.\n", sizeof(struct pid_stat *) * pid_max);
1072 - printf("DISABLE\n");
1073 - exit(1);
1074 - }
1075 -
1076 - int created_usage_chart = 0;
1077 - struct rusage me, me_last;
1078 - unsigned long long counter = 1;
1079 - unsigned long long usec = 0, susec = 0;
1080 - struct timeval last, now;
1081 - gettimeofday(&last, NULL);
1082 - getrusage(RUSAGE_SELF, &me_last);
1083 -
1084 - for(;1; counter++) {
1085 - if(!update_from_proc()) {
1086 - fprintf(stderr, "Cannot allocate %lu bytes of memory.\n", sizeof(struct pid_stat *) * pid_max);
1087 - printf("DISABLE\n");
1088 - exit(1);
1089 - }
1090 -
1091 - update_statistics();
1092 - show_charts(); // this is smart enough to show only newly added apps, when needed
1093 - show_dimensions();
1094 -
1095 - if(getrusage(RUSAGE_SELF, &me) == 0) {
1096 - unsigned long long cpuuser = me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec;
1097 - unsigned long long cpusyst = me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec;
1098 -
1099 - if(!created_usage_chart) {
1100 - created_usage_chart = 1;
1101 - fprintf(stdout, "CHART netdata.apps_cpu '' 'Apps Plugin CPU' 'milliseconds/s' netdata netdata stacked 10000 %d\n", update_every);
1102 - fprintf(stdout, "DIMENSION user '' incremental 1 1000\n");
1103 - fprintf(stdout, "DIMENSION system '' incremental 1 1000\n");
1104 -
1105 - fprintf(stdout, "CHART netdata.apps_files '' 'Apps Plugin Files' 'files/s' netdata netdata line 10001 %d\n", update_every);
1106 - fprintf(stdout, "DIMENSION files '' incremental 1 1\n");
1107 - }
1108 -
1109 - fprintf(stdout, "BEGIN netdata.apps_cpu\n");
1110 - fprintf(stdout, "SET user = %llu\n", cpuuser);
1111 - fprintf(stdout, "SET system = %llu\n", cpusyst);
1112 - fprintf(stdout, "END\n");
1113 -
1114 - fprintf(stdout, "BEGIN netdata.apps_files\n");
1115 - fprintf(stdout, "SET files = %llu\n", file_counter);
1116 - fprintf(stdout, "END\n");
1117 -
1118 - bcopy(&me, &me_last, sizeof(struct rusage));
1119 - }
1120 -
1121 - if(debug) fprintf(stderr, "Done Loop No %llu\n", counter);
1122 - // if(counter == 1000) exit(0);
1123 -
1124 - gettimeofday(&now, NULL);
1125 -
1126 - usec = usecdiff(&now, &last) - susec;
1127 - if(debug) fprintf(stderr, "last loop took %llu usec (worked for %llu, sleeped for %llu).\n", usec + susec, usec, susec);
1128 -
1129 - // if the last loop took less than half the time
1130 - // wait the rest of the time
1131 - if(usec < (update_every * 1000000ULL / 2)) susec = (update_every * 1000000ULL) - usec;
1132 - else susec = update_every * 1000000ULL / 2;
1133 -
1134 - fflush(NULL);
1135 - usleep(susec);
1136 -
1137 - bcopy(&now, &last, sizeof(struct timeval));
1138 - }
1139 -}
1 +#include <stdio.h>
2 +#include <stdlib.h>
3 +#include <string.h>
4 +#include <time.h>
5 +#include <unistd.h>
6 +#include <sys/types.h>
7 +#include <sys/time.h>
8 +#include <sys/wait.h>
9 +
10 +#include <sys/resource.h>
11 +#include <sys/stat.h>
12 +
13 +#include <errno.h>
14 +#include <stdarg.h>
15 +#include <locale.h>
16 +#include <ctype.h>
17 +#include <fcntl.h>
18 +
19 +#include <malloc.h>
20 +#include <inttypes.h>
21 +#include <dirent.h>
22 +#include <arpa/inet.h>
23 +
24 +#define MAX_COMPARE_NAME 15
25 +#define MAX_NAME 100
26 +
27 +unsigned long long Hertz = 1;
28 +
29 +long processors = 1;
30 +long pid_max = 32768;
31 +int debug = 0;
32 +
33 +struct target {
34 + char compare[MAX_COMPARE_NAME + 1];
35 + char id[MAX_NAME + 1];
36 + char name[MAX_NAME + 1];
37 +
38 + unsigned long long minflt;
39 + unsigned long long cminflt;
40 + unsigned long long majflt;
41 + unsigned long long cmajflt;
42 + unsigned long long utime;
43 + unsigned long long stime;
44 + unsigned long long cutime;
45 + unsigned long long cstime;
46 + unsigned long long num_threads;
47 + unsigned long long rss;
48 +
49 + unsigned long long fix_minflt;
50 + unsigned long long fix_cminflt;
51 + unsigned long long fix_majflt;
52 + unsigned long long fix_cmajflt;
53 + unsigned long long fix_utime;
54 + unsigned long long fix_stime;
55 + unsigned long long fix_cutime;
56 + unsigned long long fix_cstime;
57 +
58 + unsigned long long statm_size;
59 + unsigned long long statm_resident;
60 + unsigned long long statm_share;
61 + unsigned long long statm_text;
62 + unsigned long long statm_lib;
63 + unsigned long long statm_data;
64 + unsigned long long statm_dirty;
65 +
66 + unsigned long long io_logical_bytes_read;
67 + unsigned long long io_logical_bytes_written;
68 + unsigned long long io_read_calls;
69 + unsigned long long io_write_calls;
70 + unsigned long long io_storage_bytes_read;
71 + unsigned long long io_storage_bytes_written;
72 + unsigned long long io_cancelled_write_bytes;
73 +
74 + unsigned long long fix_io_logical_bytes_read;
75 + unsigned long long fix_io_logical_bytes_written;
76 + unsigned long long fix_io_read_calls;
77 + unsigned long long fix_io_write_calls;
78 + unsigned long long fix_io_storage_bytes_read;
79 + unsigned long long fix_io_storage_bytes_written;
80 + unsigned long long fix_io_cancelled_write_bytes;
81 +
82 + unsigned long processes; // how many processes have been merged to this
83 + int exposed; // if set, we have sent this to netdata
84 +
85 + struct target *target; // the one that will be reported to netdata
86 + struct target *next;
87 +} *target_root = NULL, *default_target = NULL;
88 +
89 +int update_every = 1;
90 +unsigned long long file_counter = 0;
91 +
92 +struct target *get_target(const char *id, struct target *target)
93 +{
94 + struct target *w;
95 + for(w = target_root ; w ; w = w->next)
96 + if(strncmp(id, w->id, MAX_NAME) == 0) return w;
97 +
98 + w = calloc(sizeof(struct target), 1);
99 + if(!w) {
100 + fprintf(stderr, "Cannot allocate %lu bytes of memory\n", sizeof(struct target));
101 + return NULL;
102 + }
103 +
104 + strncpy(w->id, id, MAX_NAME);
105 + strncpy(w->name, id, MAX_NAME);
106 + strncpy(w->compare, id, MAX_COMPARE_NAME);
107 + w->target = target;
108 +
109 + w->next = target_root;
110 + target_root = w;
111 +
112 + if(debug) fprintf(stderr, "Adding hook for process '%s', compare '%s' on target '%s'\n", w->id, w->compare, w->target?w->target->id:"");
113 +
114 + return w;
115 +}
116 +
117 +char *trim(char *s)
118 +{
119 + // skip leading spaces
120 + while(*s && isspace(*s)) s++;
121 + if(!*s) return NULL;
122 +
123 + // skip tailing spaces
124 + int c = strlen(s) - 1;
125 + while(c >= 0 && isspace(s[c])) {
126 + s[c] = '\0';
127 + c--;
128 + }
129 + if(c < 0) return NULL;
130 + if(!*s) return NULL;
131 + return s;
132 +}
133 +
134 +int read_process_groups(const char *name)
135 +{
136 + char buffer[4096+1];
137 + char filename[FILENAME_MAX + 1];
138 +
139 + snprintf(filename, FILENAME_MAX, "%s/apps_%s.conf", CONFIG_DIR, name);
140 +
141 + if(debug) fprintf(stderr, "Process groups file: '%s'\n", filename);
142 + FILE *fp = fopen(filename, "r");
143 + if(!fp) {
144 + fprintf(stderr, "Cannot open file '%s' (%s)\n", filename, strerror(errno));
145 + return 1;
146 + }
147 +
148 + long line = 0;
149 + while(fgets(buffer, 4096, fp) != NULL) {
150 + line++;
151 +
152 + // if(debug) fprintf(stderr, "\tread %s\n", buffer);
153 +
154 + char *s = buffer, *t, *p;
155 + s = trim(s);
156 + if(!s || !*s || *s == '#') continue;
157 +
158 + if(debug) fprintf(stderr, "\tread %s\n", s);
159 +
160 + // the target name
161 + t = strsep(&s, ":");
162 + if(t) t = trim(t);
163 + if(!t || !*t) continue;
164 +
165 + if(debug) fprintf(stderr, "\t\ttarget %s\n", t);
166 +
167 + struct target *w = NULL;
168 + long count = 0;
169 +
170 + // the process names
171 + while((p = strsep(&s, " "))) {
172 + p = trim(p);
173 + if(!p || !*p) continue;
174 +
175 + struct target *n = get_target(p, w);
176 + if(!w) w = n;
177 +
178 + count++;
179 + }
180 +
181 + if(w) strncpy(w->name, t, MAX_NAME);
182 + if(!count) fprintf(stderr, "the line %ld on file '%s', for group '%s' does not state any process names.\n", line, filename, t);
183 + }
184 + fclose(fp);
185 +
186 + default_target = get_target("+p!o@w#e$i^r&7*5(-i)l-o_", NULL); // match nothing
187 + strncpy(default_target->name, "other", MAX_NAME);
188 +
189 + return 0;
190 +}
191 +
192 +void parse_args(int argc, char **argv)
193 +{
194 + int i, freq = 0;
195 + char *name = NULL;
196 +
197 + for(i = 1; i < argc; i++) {
198 + if(!freq) {
199 + int n = atoi(argv[i]);
200 + if(n > 0) {
201 + freq = n;
202 + continue;
203 + }
204 + }
205 +
206 + if(strcmp("debug", argv[i]) == 0) {
207 + debug = 1;
208 + continue;
209 + }
210 +
211 + if(!name) {
212 + name = argv[i];
213 + continue;
214 + }
215 +
216 + fprintf(stderr, "Cannot understand option %s\n", argv[i]);
217 + exit(1);
218 + }
219 +
220 + if(freq > 0) update_every = freq;
221 + if(!name) name = "groups";
222 +
223 + if(read_process_groups(name)) {
224 + fprintf(stderr, "Cannot read process groups %s\n", name);
225 + exit(1);
226 + }
227 +}
228 +
229 +// see: man proc
230 +struct pid_stat {
231 + int32_t pid;
232 + char comm[MAX_COMPARE_NAME + 1];
233 + char state;
234 + int32_t ppid;
235 + int32_t pgrp;
236 + int32_t session;
237 + int32_t tty_nr;
238 + int32_t tpgid;
239 + uint64_t flags;
240 + unsigned long long minflt;
241 + unsigned long long cminflt;
242 + unsigned long long majflt;
243 + unsigned long long cmajflt;
244 + unsigned long long utime;
245 + unsigned long long stime;
246 + unsigned long long cutime;
247 + unsigned long long cstime;
248 + int64_t priority;
249 + int64_t nice;
250 + int32_t num_threads;
251 + int64_t itrealvalue;
252 + unsigned long long starttime;
253 + unsigned long long vsize;
254 + unsigned long long rss;
255 + unsigned long long rsslim;
256 + unsigned long long starcode;
257 + unsigned long long endcode;
258 + unsigned long long startstack;
259 + unsigned long long kstkesp;
260 + unsigned long long kstkeip;
261 + uint64_t signal;
262 + uint64_t blocked;
263 + uint64_t sigignore;
264 + uint64_t sigcatch;
265 + uint64_t wchan;
266 + uint64_t nswap;
267 + uint64_t cnswap;
268 + int32_t exit_signal;
269 + int32_t processor;
270 + uint32_t rt_priority;
271 + uint32_t policy;
272 + unsigned long long delayacct_blkio_ticks;
273 + uint64_t guest_time;
274 + int64_t cguest_time;
275 +
276 + unsigned long long statm_size;
277 + unsigned long long statm_resident;
278 + unsigned long long statm_share;
279 + unsigned long long statm_text;
280 + unsigned long long statm_lib;
281 + unsigned long long statm_data;
282 + unsigned long long statm_dirty;
283 +
284 + unsigned long long io_logical_bytes_read;
285 + unsigned long long io_logical_bytes_written;
286 + unsigned long long io_read_calls;
287 + unsigned long long io_write_calls;
288 + unsigned long long io_storage_bytes_read;
289 + unsigned long long io_storage_bytes_written;
290 + unsigned long long io_cancelled_write_bytes;
291 +
292 +/* unsigned long long old_utime;
293 + unsigned long long old_stime;
294 + unsigned long long old_minflt;
295 + unsigned long long old_majflt;
296 +
297 + unsigned long long old_cutime;
298 + unsigned long long old_cstime;
299 + unsigned long long old_cminflt;
300 + unsigned long long old_cmajflt;
301 +
302 + unsigned long long fix_cutime;
303 + unsigned long long fix_cstime;
304 + unsigned long long fix_cminflt;
305 + unsigned long long fix_cmajflt;
306 +
307 + unsigned long long diff_cutime;
308 + unsigned long long diff_cstime;
309 + unsigned long long diff_cminflt;
310 + unsigned long long diff_cmajflt;
311 +*/
312 +
313 + int childs; // number of processes directly referencing this
314 + int updated;
315 + int merged;
316 + int new_entry;
317 + struct target *target;
318 + struct pid_stat *parent;
319 + struct pid_stat *prev;
320 + struct pid_stat *next;
321 +} *root = NULL;
322 +
323 +struct pid_stat **all_pids;
324 +
325 +#define PROC_BUFFER 4096
326 +
327 +struct pid_stat *get_entry(pid_t pid)
328 +{
329 + if(all_pids[pid]) {
330 + all_pids[pid]->new_entry = 0;
331 + return all_pids[pid];
332 + }
333 +
334 + all_pids[pid] = calloc(sizeof(struct pid_stat), 1);
335 + if(!all_pids[pid]) {
336 + fprintf(stderr, "Cannot allocate %lu bytes of memory", sizeof(struct pid_stat));
337 + return NULL;
338 + }
339 +
340 + if(root) root->prev = all_pids[pid];
341 + all_pids[pid]->next = root;
342 + root = all_pids[pid];
343 +
344 + all_pids[pid]->new_entry = 1;
345 +
346 + return all_pids[pid];
347 +}
348 +
349 +void del_entry(pid_t pid)
350 +{
351 + if(!all_pids[pid]) return;
352 +
353 + if(debug) fprintf(stderr, "Process %d %s exited, deleting it.\n", pid, all_pids[pid]->comm);
354 +
355 + if(root == all_pids[pid]) root = all_pids[pid]->next;
356 + if(all_pids[pid]->next) all_pids[pid]->next->prev = all_pids[pid]->prev;
357 + if(all_pids[pid]->prev) all_pids[pid]->prev->next = all_pids[pid]->next;
358 +
359 + free(all_pids[pid]);
360 + all_pids[pid] = NULL;
361 +}
362 +
363 +int update_from_proc(void)
364 +{
365 + static long count_open_errors = 0;
366 +
367 + char buffer[PROC_BUFFER + 1];
368 + char name[PROC_BUFFER + 1];
369 + char filename[FILENAME_MAX+1];
370 + DIR *dir = opendir("/proc");
371 + if(!dir) return 0;
372 +
373 + struct dirent *file = NULL;
374 + struct pid_stat *p = NULL;
375 +
376 + // mark them all as un-updated
377 + for(p = root; p ; p = p->next) {
378 + p->parent = NULL;
379 + p->updated = 0;
380 + p->childs = 0;
381 + p->merged = 0;
382 + p->new_entry = 0;
383 + }
384 +
385 + while((file = readdir(dir))) {
386 + char *endptr = file->d_name;
387 + pid_t pid = strtoul(file->d_name, &endptr, 10);
388 + if(pid <= 0 || pid > pid_max || endptr == file->d_name || *endptr != '\0') continue;
389 +
390 +
391 + // --------------------------------------------------------------------
392 + // /proc/<pid>/stat
393 +
394 + snprintf(filename, FILENAME_MAX, "/proc/%s/stat", file->d_name);
395 + int fd = open(filename, O_RDONLY);
396 + if(fd == -1) {
397 + if(errno != ENOENT && errno != ESRCH) {
398 + if(!count_open_errors) fprintf(stderr, "Cannot open file '%s' for reading (%d, %s).\n", filename, errno, strerror(errno));
399 + count_open_errors++;
400 + }
401 + continue;
402 + }
403 + file_counter++;
404 +
405 + int bytes = read(fd, buffer, PROC_BUFFER);
406 + close(fd);
407 +
408 + if(bytes == -1) {
409 + fprintf(stderr, "Cannot read from file '%s' (%s).\n", filename, strerror(errno));
410 + continue;
411 + }
412 +
413 + if(bytes < 10) continue;
414 + buffer[bytes] = '\0';
415 + if(debug) fprintf(stderr, "READ stat: %s", buffer);
416 +
417 + p = get_entry(pid);
418 + if(!p) continue;
419 +
420 + int parsed = sscanf(buffer,
421 + "%d (%[^)]) %c" // pid, comm, state
422 + " %d %d %d %d %d" // ppid, pgrp, session, tty_nr, tpgid
423 + " %lu %llu %llu %llu %llu" // flags, minflt, cminflt, majflt, cmajflt
424 + " %llu %llu %llu %llu" // utime, stime, cutime, cstime
425 + " %ld %ld" // priority, nice
426 + " %d" // num_threads
427 + " %ld" // itrealvalue
428 + " %llu" // starttime
429 + " %llu" // vsize
430 + " %llu" // rss
431 + " %llu %llu %llu %llu %llu %llu" // rsslim, starcode, endcode, startstack, kstkesp, kstkeip
432 + " %lu %lu %lu %lu" // signal, blocked, sigignore, sigcatch
433 + " %lu %lu %lu" // wchan, nswap, cnswap
434 + " %d %d" // exit_signal, processor
435 + " %u %u" // rt_priority, policy
436 + " %llu %lu %ld"
437 + , &p->pid, name, &p->state
438 + , &p->ppid, &p->pgrp, &p->session, &p->tty_nr, &p->tpgid
439 + , &p->flags, &p->minflt, &p->cminflt, &p->majflt, &p->cmajflt
440 + , &p->utime, &p->stime, &p->cutime, &p->cstime
441 + , &p->priority, &p->nice
442 + , &p->num_threads
443 + , &p->itrealvalue
444 + , &p->starttime
445 + , &p->vsize
446 + , &p->rss
447 + , &p->rsslim, &p->starcode, &p->endcode, &p->startstack, &p->kstkesp, &p->kstkeip
448 + , &p->signal, &p->blocked, &p->sigignore, &p->sigcatch
449 + , &p->wchan, &p->nswap, &p->cnswap
450 + , &p->exit_signal, &p->processor
451 + , &p->rt_priority, &p->policy
452 + , &p->delayacct_blkio_ticks, &p->guest_time, &p->cguest_time
453 + );
454 + strncpy(p->comm, name, MAX_COMPARE_NAME);
455 + p->comm[MAX_COMPARE_NAME] = '\0';
456 +
457 + if(debug) fprintf(stderr, "VALUES: %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->comm, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
458 +
459 + if(parsed < 39) fprintf(stderr, "file %s gave %d results (expected 44)\n", filename, parsed);
460 +
461 + // check if it is target
462 + // we do this only once, the first time this pid is loaded
463 + if(p->new_entry) {
464 + if(debug) fprintf(stderr, "\tJust added %s\n", p->comm);
465 +
466 + struct target *w;
467 + for(w = target_root; w ; w = w->next) {
468 + // if(debug) fprintf(stderr, "\t\tcomparing '%s' with '%s'\n", w->compare, p->comm);
469 +
470 + if(strcmp(w->compare, p->comm) == 0) {
471 + if(w->target) p->target = w->target;
472 + else p->target = w;
473 +
474 + if(debug) fprintf(stderr, "\t\t%s linked to target %s\n", p->comm, p->target->name);
475 + }
476 + }
477 + }
478 +
479 + // just a few checks
480 + if(p->ppid < 0 || p->ppid > pid_max) p->ppid = 0;
481 +
482 +
483 + // --------------------------------------------------------------------
484 + // /proc/<pid>/statm
485 +
486 + snprintf(filename, FILENAME_MAX, "/proc/%s/statm", file->d_name);
487 + fd = open(filename, O_RDONLY);
488 + if(fd == -1) {
489 + if(errno != ENOENT && errno != ESRCH) {
490 + if(!count_open_errors) fprintf(stderr, "Cannot open file '%s' for reading (%d, %s).\n", filename, errno, strerror(errno));
491 + count_open_errors++;
492 + }
493 + }
494 + else {
495 + file_counter++;
496 + bytes = read(fd, buffer, PROC_BUFFER);
497 + close(fd);
498 +
499 + if(bytes == -1) {
500 + fprintf(stderr, "Cannot read from file '%s' (%s).\n", filename, strerror(errno));
501 + }
502 + else if(bytes > 10) {
503 + buffer[bytes] = '\0';
504 + if(debug) fprintf(stderr, "READ statm: %s", buffer);
505 +
506 + parsed = sscanf(buffer,
507 + "%llu %llu %llu %llu %llu %llu %llu"
508 + , &p->statm_size
509 + , &p->statm_resident
510 + , &p->statm_share
511 + , &p->statm_text
512 + , &p->statm_lib
513 + , &p->statm_data
514 + , &p->statm_dirty
515 + );
516 +
517 + if(parsed < 7) fprintf(stderr, "file %s gave %d results (expected 7)\n", filename, parsed);
518 + }
519 + }
520 +
521 + // --------------------------------------------------------------------
522 + // /proc/<pid>/io
523 +
524 + snprintf(filename, FILENAME_MAX, "/proc/%s/io", file->d_name);
525 + fd = open(filename, O_RDONLY);
526 + if(fd == -1) {
527 + if(errno != ENOENT && errno != ESRCH) {
528 + if(!count_open_errors) fprintf(stderr, "Cannot open file '%s' for reading (%d, %s).\n", filename, errno, strerror(errno));
529 + count_open_errors++;
530 + }
531 + }
532 + else {
533 + file_counter++;
534 + bytes = read(fd, buffer, PROC_BUFFER);
535 + close(fd);
536 +
537 + if(bytes == -1) {
538 + fprintf(stderr, "Cannot read from file '%s' (%s).\n", filename, strerror(errno));
539 + }
540 + else if(bytes > 10) {
541 + buffer[bytes] = '\0';
542 + if(debug) fprintf(stderr, "READ io: %s", buffer);
543 +
544 + parsed = sscanf(buffer,
545 + "rchar: %llu\nwchar: %llu\nsyscr: %llu\nsyscw: %llu\nread_bytes: %llu\nwrite_bytes: %llu\ncancelled_write_bytes: %llu"
546 + , &p->io_logical_bytes_read
547 + , &p->io_logical_bytes_written
548 + , &p->io_read_calls
549 + , &p->io_write_calls
550 + , &p->io_storage_bytes_read
551 + , &p->io_storage_bytes_written
552 + , &p->io_cancelled_write_bytes
553 + );
554 +
555 + if(parsed < 7) fprintf(stderr, "file %s gave %d results (expected 7)\n", filename, parsed);
556 + }
557 + }
558 +
559 +
560 + // --------------------------------------------------------------------
561 + // done!
562 +
563 + // mark it as updated
564 + p->updated = 1;
565 + }
566 + if(count_open_errors > 1 && count_open_errors > 1000) {
567 + fprintf(stderr, "file open errors repeated %ld times\n", count_open_errors - 1);
568 + count_open_errors = 0;
569 + }
570 +
571 + closedir(dir);
572 +
573 + return 1;
574 +}
575 +/*
576 +int walk_down(pid_t pid, int level) {
577 + struct pid_stat *p = NULL;
578 + char b[level+3];
579 + int i, ret = 0;
580 +
581 + for(i = 0; i < level; i++) b[i] = '\t';
582 + b[level] = '|';
583 + b[level+1] = '-';
584 + b[level+2] = '\0';
585 +
586 + for(p = root; p ; p = p->next) {
587 + if(p->ppid == pid) {
588 + ret += walk_down(p->pid, level+1);
589 + }
590 + }
591 +
592 + p = all_pids[pid];
593 + if(p) {
594 + if(!p->updated) ret += 1;
595 + if(ret) fprintf(stderr, "%s %s %d [%s, %s] c=%d u=%llu+%llu, s=%llu+%llu, cu=%llu+%llu, cs=%llu+%llu, n=%llu+%llu, j=%llu+%llu, cn=%llu+%llu, cj=%llu+%llu\n"
596 + , b, p->comm, p->pid, p->updated?"OK":"KILLED", p->target->name, p->childs
597 + , p->utime, p->utime - p->old_utime
598 + , p->stime, p->stime - p->old_stime
599 + , p->cutime, p->cutime - p->old_cutime
600 + , p->cstime, p->cstime - p->old_cstime
601 + , p->minflt, p->minflt - p->old_minflt
602 + , p->majflt, p->majflt - p->old_majflt
603 + , p->cminflt, p->cminflt - p->old_cminflt
604 + , p->cmajflt, p->cmajflt - p->old_cmajflt
605 + );
606 + }
607 +
608 + return ret;
609 +}
610 +*/
611 +
612 +void update_statistics(void)
613 +{
614 + struct pid_stat *p = NULL;
615 +
616 + // link all parents and update childs count
617 + for(p = root; p ; p = p->next) {
618 + if(p->ppid > 0 && p->ppid <= pid_max && all_pids[p->ppid]) {
619 + if(debug) fprintf(stderr, "\tParent of %d %s is %d %s\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm);
620 +
621 + p->parent = all_pids[p->ppid];
622 + p->parent->childs++;
623 + }
624 + else if(p->ppid != 0) fprintf(stderr, "\t\tWRONG! pid %d %s states parent %d, but the later does not exist.\n", p->pid, p->comm, p->ppid);
625 + }
626 +
627 + // find all the procs with 0 childs and merge them to their parents
628 + // repeat, until nothing more can be done.
629 + int found = 1;
630 + while(found) {
631 + found = 0;
632 + for(p = root; p ; p = p->next) {
633 + // if this process does not have any childs, and
634 + // is not already merged, and
635 + // its parent has childs waiting to be merged, and
636 + // the target of this process and its parent is the same, or the parent does not have a target, or this process does not have a parent
637 + // and its parent is not init
638 + // then... merge them!
639 + if(!p->childs && !p->merged && p->parent && p->parent->childs && (p->target == p->parent->target || !p->parent->target || !p->target) && p->ppid != 1) {
640 + p->parent->childs--;
641 + p->merged = 1;
642 +
643 + // the parent inherits the child's target, if it does not have a target itself
644 + if(p->target && !p->parent->target) {
645 + p->parent->target = p->target;
646 + if(debug) fprintf(stderr, "\t\ttarget %s is inherited by %d %s from its child %d %s.\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm);
647 + }
648 +
649 + found++;
650 + }
651 + }
652 + if(debug) fprintf(stderr, "Merged %d processes\n", found);
653 + }
654 +
655 + // give a default target on all top level processes
656 + // init goes always to default target
657 + if(all_pids[1]) all_pids[1]->target = default_target;
658 +
659 + for(p = root; p ; p = p->next) {
660 + // if the process is not merged itself
661 + // then is is a top level process
662 + if(!p->merged && !p->target) p->target = default_target;
663 +
664 +/* // by the way, update the diffs
665 + // will be used later for substracting killed process times
666 + p->diff_cutime = p->utime - p->cutime;
667 + p->diff_cstime = p->stime - p->cstime;
668 + p->diff_cminflt = p->minflt - p->cminflt;
669 + p->diff_cmajflt = p->majflt - p->cmajflt;
670 +*/ }
671 +
672 + // give a target to all merged child processes
673 + found = 1;
674 + while(found) {
675 + found = 0;
676 + for(p = root; p ; p = p->next) {
677 + if(!p->target && p->merged && p->parent && p->parent->target) {
678 + p->target = p->parent->target;
679 + found++;
680 + }
681 + }
682 + }
683 +
684 +/* // for each killed process, remove its values from the parents
685 + // sums (we had already added them in a previous loop)
686 + for(p = root; p ; p = p->next) {
687 + if(p->updated) continue;
688 +
689 + fprintf(stderr, "UNMERGING %d %s\n", p->pid, p->comm);
690 +
691 + unsigned long long diff_utime = p->utime + p->cutime + p->fix_cutime;
692 + unsigned long long diff_stime = p->stime + p->cstime + p->fix_cstime;
693 + unsigned long long diff_minflt = p->minflt + p->cminflt + p->fix_cminflt;
694 + unsigned long long diff_majflt = p->majflt + p->cmajflt + p->fix_cmajflt;
695 +
696 + struct pid_stat *t = p;
697 + while((t = t->parent)) {
698 + if(!t->updated) continue;
699 +
700 + unsigned long long x;
701 + if(diff_utime && t->diff_cutime) {
702 + x = (t->diff_cutime < diff_utime)?t->diff_cutime:diff_utime;
703 + diff_utime -= x;
704 + t->diff_cutime -= x;
705 + t->fix_cutime += x;
706 + fprintf(stderr, "\t cutime %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
707 + }
708 + if(diff_stime && t->diff_cstime) {
709 + x = (t->diff_cstime < diff_stime)?t->diff_cstime:diff_stime;
710 + diff_stime -= x;
711 + t->diff_cstime -= x;
712 + t->fix_cstime += x;
713 + fprintf(stderr, "\t cstime %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
714 + }
715 + if(diff_minflt && t->diff_cminflt) {
716 + x = (t->diff_cminflt < diff_minflt)?t->diff_cminflt:diff_minflt;
717 + diff_minflt -= x;
718 + t->diff_cminflt -= x;
719 + t->fix_cminflt += x;
720 + fprintf(stderr, "\t cminflt %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
721 + }
722 + if(diff_majflt && t->diff_cmajflt) {
723 + x = (t->diff_cmajflt < diff_majflt)?t->diff_cmajflt:diff_majflt;
724 + diff_majflt -= x;
725 + t->diff_cmajflt -= x;
726 + t->fix_cmajflt += x;
727 + fprintf(stderr, "\t cmajflt %llu from %d %s %s\n", x, t->pid, t->comm, t->target->name);
728 + }
729 + }
730 +
731 + if(diff_utime) fprintf(stderr, "\t cannot fix up utime %llu\n", diff_utime);
732 + if(diff_stime) fprintf(stderr, "\t cannot fix up stime %llu\n", diff_stime);
733 + if(diff_minflt) fprintf(stderr, "\t cannot fix up minflt %llu\n", diff_minflt);
734 + if(diff_majflt) fprintf(stderr, "\t cannot fix up majflt %llu\n", diff_majflt);
735 + }
736 +*/
737 + // zero all the targets
738 + struct target *w;
739 + for (w = target_root; w ; w = w->next) {
740 + w->minflt = 0;
741 + w->majflt = 0;
742 + w->utime = 0;
743 + w->stime = 0;
744 + w->cminflt = 0;
745 + w->cmajflt = 0;
746 + w->cutime = 0;
747 + w->cstime = 0;
748 + w->num_threads = 0;
749 + w->rss = 0;
750 + w->processes = 0;
751 +
752 + w->statm_size = 0;
753 + w->statm_resident = 0;
754 + w->statm_share = 0;
755 + w->statm_text = 0;
756 + w->statm_lib = 0;
757 + w->statm_data = 0;
758 + w->statm_dirty = 0;
759 +
760 + w->io_logical_bytes_read = 0;
761 + w->io_logical_bytes_written = 0;
762 + w->io_read_calls = 0;
763 + w->io_write_calls = 0;
764 + w->io_storage_bytes_read = 0;
765 + w->io_storage_bytes_written = 0;
766 + w->io_cancelled_write_bytes = 0;
767 + }
768 +
769 +/* walk_down(0, 1);
770 +*/
771 + // concentrate everything on the targets
772 + for(p = root; p ; p = p->next) {
773 + if(!p->target) {
774 + fprintf(stderr, "WRONG! pid %d %s was left without a target!\n", p->pid, p->comm);
775 + continue;
776 + }
777 +
778 + if(p->updated) {
779 + p->target->cutime += p->cutime; // - p->fix_cutime;
780 + p->target->cstime += p->cstime; // - p->fix_cstime;
781 + p->target->cminflt += p->cminflt; // - p->fix_cminflt;
782 + p->target->cmajflt += p->cmajflt; // - p->fix_cmajflt;
783 +
784 + p->target->utime += p->utime; //+ (p->pid != 1)?(p->cutime - p->fix_cutime):0;
785 + p->target->stime += p->stime; //+ (p->pid != 1)?(p->cstime - p->fix_cstime):0;
786 + p->target->minflt += p->minflt; //+ (p->pid != 1)?(p->cminflt - p->fix_cminflt):0;
787 + p->target->majflt += p->majflt; //+ (p->pid != 1)?(p->cmajflt - p->fix_cmajflt):0;
788 +
789 + p->target->num_threads += p->num_threads;
790 + p->target->rss += p->rss;
791 +
792 + p->target->statm_size += p->statm_size;
793 + p->target->statm_resident += p->statm_resident;
794 + p->target->statm_share += p->statm_share;
795 + p->target->statm_text += p->statm_text;
796 + p->target->statm_lib += p->statm_lib;
797 + p->target->statm_data += p->statm_data;
798 + p->target->statm_dirty += p->statm_dirty;
799 +
800 + p->target->io_logical_bytes_read += p->io_logical_bytes_read;
801 + p->target->io_logical_bytes_written += p->io_logical_bytes_written;
802 + p->target->io_read_calls += p->io_read_calls;
803 + p->target->io_write_calls += p->io_write_calls;
804 + p->target->io_storage_bytes_read += p->io_storage_bytes_read;
805 + p->target->io_storage_bytes_written += p->io_storage_bytes_written;
806 + p->target->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
807 +
808 + p->target->processes++;
809 +
810 + if(debug) fprintf(stderr, "\tAgregating %s pid %d on %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->comm, p->pid, p->target->name, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
811 +
812 +/* if(p->utime - p->old_utime > 100) fprintf(stderr, "BIG CHANGE: %d %s utime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->utime - p->old_utime, p->old_utime, p->utime);
813 + if(p->cutime - p->old_cutime > 100) fprintf(stderr, "BIG CHANGE: %d %s cutime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cutime - p->old_cutime, p->old_cutime, p->cutime);
814 + if(p->stime - p->old_stime > 100) fprintf(stderr, "BIG CHANGE: %d %s stime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->stime - p->old_stime, p->old_stime, p->stime);
815 + if(p->cstime - p->old_cstime > 100) fprintf(stderr, "BIG CHANGE: %d %s cstime increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cstime - p->old_cstime, p->old_cstime, p->cstime);
816 + if(p->minflt - p->old_minflt > 5000) fprintf(stderr, "BIG CHANGE: %d %s minflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->minflt - p->old_minflt, p->old_minflt, p->minflt);
817 + if(p->majflt - p->old_majflt > 5000) fprintf(stderr, "BIG CHANGE: %d %s majflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->majflt - p->old_majflt, p->old_majflt, p->majflt);
818 + if(p->cminflt - p->old_cminflt > 15000) fprintf(stderr, "BIG CHANGE: %d %s cminflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cminflt - p->old_cminflt, p->old_cminflt, p->cminflt);
819 + if(p->cmajflt - p->old_cmajflt > 15000) fprintf(stderr, "BIG CHANGE: %d %s cmajflt increased by %llu from %llu to %llu\n", p->pid, p->comm, p->cmajflt - p->old_cmajflt, p->old_cmajflt, p->cmajflt);
820 +
821 + p->old_utime = p->utime;
822 + p->old_cutime = p->cutime;
823 + p->old_stime = p->stime;
824 + p->old_cstime = p->cstime;
825 + p->old_minflt = p->minflt;
826 + p->old_majflt = p->majflt;
827 + p->old_cminflt = p->cminflt;
828 + p->old_cmajflt = p->cmajflt;
829 +*/ }
830 + else {
831 + // since the process has exited, the user
832 + // will see a drop in our charts, because the incremental
833 + // values of this process will not be there
834 +
835 + // add them to the fix_* values and they will be added to
836 + // the reported values, so that the report goes steady
837 + p->target->fix_minflt += p->minflt;
838 + p->target->fix_majflt += p->majflt;
839 + p->target->fix_utime += p->utime;
840 + p->target->fix_stime += p->stime;
841 + p->target->fix_cminflt += p->cminflt;
842 + p->target->fix_cmajflt += p->cmajflt;
843 + p->target->fix_cutime += p->cutime;
844 + p->target->fix_cstime += p->cstime;
845 +
846 + p->target->fix_io_logical_bytes_read += p->io_logical_bytes_read;
847 + p->target->fix_io_logical_bytes_written += p->io_logical_bytes_written;
848 + p->target->fix_io_read_calls += p->io_read_calls;
849 + p->target->fix_io_write_calls += p->io_write_calls;
850 + p->target->fix_io_storage_bytes_read += p->io_storage_bytes_read;
851 + p->target->fix_io_storage_bytes_written += p->io_storage_bytes_written;
852 + p->target->fix_io_cancelled_write_bytes += p->io_cancelled_write_bytes;
853 + }
854 + }
855 +
856 +/* fprintf(stderr, "\n");
857 +*/
858 + // cleanup all un-updated processed (exited, killed, etc)
859 + int c;
860 + for(p = root, c = 0; p ; c++) {
861 + if(!p->updated) {
862 +/* fprintf(stderr, "\tEXITED %d %s [parent %d %s, target %s] utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, p->parent->pid, p->parent->comm, p->target->name, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
863 +*/
864 + pid_t r = p->pid;
865 + p = p->next;
866 + del_entry(r);
867 + }
868 + else p = p->next;
869 + }
870 +}
871 +
872 +
873 +void show_dimensions(void)
874 +{
875 + struct target *w;
876 +
877 + fprintf(stdout, "BEGIN apps.cpu\n");
878 + for (w = target_root; w ; w = w->next) {
879 + if(w->target || (!w->processes && !w->exposed)) continue;
880 +
881 + fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->stime + w->fix_utime + w->fix_stime);
882 + }
883 + fprintf(stdout, "END\n");
884 +
885 + fprintf(stdout, "BEGIN apps.cpu_user\n");
886 + for (w = target_root; w ; w = w->next) {
887 + if(w->target || (!w->processes && !w->exposed)) continue;
888 +
889 + fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->fix_utime);
890 + }
891 + fprintf(stdout, "END\n");
892 +
893 + fprintf(stdout, "BEGIN apps.cpu_system\n");
894 + for (w = target_root; w ; w = w->next) {
895 + if(w->target || (!w->processes && !w->exposed)) continue;
896 +
897 + fprintf(stdout, "SET %s = %llu\n", w->name, w->stime + w->fix_stime);
898 + }
899 + fprintf(stdout, "END\n");
900 +
901 + fprintf(stdout, "BEGIN apps.threads\n");
902 + for (w = target_root; w ; w = w->next) {
903 + if(w->target || (!w->processes && !w->exposed)) continue;
904 +
905 + fprintf(stdout, "SET %s = %llu\n", w->name, w->num_threads);
906 + }
907 + fprintf(stdout, "END\n");
908 +
909 + fprintf(stdout, "BEGIN apps.processes\n");
910 + for (w = target_root; w ; w = w->next) {
911 + if(w->target || (!w->processes && !w->exposed)) continue;
912 +
913 + fprintf(stdout, "SET %s = %lu\n", w->name, w->processes);
914 + }
915 + fprintf(stdout, "END\n");
916 +
917 + fprintf(stdout, "BEGIN apps.mem\n");
918 + for (w = target_root; w ; w = w->next) {
919 + if(w->target || (!w->processes && !w->exposed)) continue;
920 +
921 + fprintf(stdout, "SET %s = %lld\n", w->name, (long long)w->statm_resident - (long long)w->statm_share);
922 + }
923 + fprintf(stdout, "END\n");
924 +
925 + fprintf(stdout, "BEGIN apps.minor_faults\n");
926 + for (w = target_root; w ; w = w->next) {
927 + if(w->target || (!w->processes && !w->exposed)) continue;
928 +
929 + fprintf(stdout, "SET %s = %llu\n", w->name, w->minflt + w->fix_minflt);
930 + }
931 + fprintf(stdout, "END\n");
932 +
933 + fprintf(stdout, "BEGIN apps.major_faults\n");
934 + for (w = target_root; w ; w = w->next) {
935 + if(w->target || (!w->processes && !w->exposed)) continue;
936 +
937 + fprintf(stdout, "SET %s = %llu\n", w->name, w->majflt + w->fix_majflt);
938 + }
939 + fprintf(stdout, "END\n");
940 +
941 + fprintf(stdout, "BEGIN apps.lreads\n");
942 + for (w = target_root; w ; w = w->next) {
943 + if(w->target || (!w->processes && !w->exposed)) continue;
944 +
945 + fprintf(stdout, "SET %s = %llu\n", w->name, w->io_logical_bytes_read);
946 + }
947 + fprintf(stdout, "END\n");
948 +
949 + fprintf(stdout, "BEGIN apps.lwrites\n");
950 + for (w = target_root; w ; w = w->next) {
951 + if(w->target || (!w->processes && !w->exposed)) continue;
952 +
953 + fprintf(stdout, "SET %s = %llu\n", w->name, w->io_logical_bytes_written);
954 + }
955 + fprintf(stdout, "END\n");
956 +
957 + fprintf(stdout, "BEGIN apps.preads\n");
958 + for (w = target_root; w ; w = w->next) {
959 + if(w->target || (!w->processes && !w->exposed)) continue;
960 +
961 + fprintf(stdout, "SET %s = %llu\n", w->name, w->io_storage_bytes_read);
962 + }
963 + fprintf(stdout, "END\n");
964 +
965 + fprintf(stdout, "BEGIN apps.pwrites\n");
966 + for (w = target_root; w ; w = w->next) {
967 + if(w->target || (!w->processes && !w->exposed)) continue;
968 +
969 + fprintf(stdout, "SET %s = %llu\n", w->name, w->io_storage_bytes_written);
970 + }
971 + fprintf(stdout, "END\n");
972 +}
973 +
974 +void show_charts(void)
975 +{
976 + struct target *w;
977 + int newly_added = 0;
978 +
979 + for(w = target_root ; w ; w = w->next)
980 + if(!w->exposed && w->processes) {
981 + newly_added++;
982 + w->exposed = 1;
983 + if(debug) fprintf(stderr, "%s just added - regenerating charts.\n", w->name);
984 + }
985 +
986 + // nothing more to show
987 + if(!newly_added) return;
988 +
989 + // we have something new to show
990 + // update the charts
991 + fprintf(stdout, "CHART apps.cpu '' 'Apps CPU Time (%ld%% = %ld core%s)' 'cpu time %%' apps apps stacked 20001 %d\n", (processors * 100), processors, (processors>1)?"s":"", update_every);
992 + for (w = target_root; w ; w = w->next) {
993 + if(w->target || (!w->processes && !w->exposed)) continue;
994 +
995 + fprintf(stdout, "DIMENSION %s '' incremental 100 %llu\n", w->name, Hertz);
996 + }
997 +
998 + fprintf(stdout, "CHART apps.mem '' 'Apps Dedicated Memory (w/o shared)' 'MB' apps apps stacked 20003 %d\n", update_every);
999 + for (w = target_root; w ; w = w->next) {
1000 + if(w->target || (!w->processes && !w->exposed)) continue;
1001 +
1002 + fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L);
1003 + }
1004 +
1005 + fprintf(stdout, "CHART apps.threads '' 'Apps Threads' 'threads' apps apps stacked 20005 %d\n", update_every);
1006 + for (w = target_root; w ; w = w->next) {
1007 + if(w->target || (!w->processes && !w->exposed)) continue;
1008 +
1009 + fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
1010 + }
1011 +
1012 + fprintf(stdout, "CHART apps.processes '' 'Apps Processes' 'processes' apps apps stacked 20004 %d\n", update_every);
1013 + for (w = target_root; w ; w = w->next) {
1014 + if(w->target || (!w->processes && !w->exposed)) continue;
1015 +
1016 + fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
1017 + }
1018 +
1019 + fprintf(stdout, "CHART apps.cpu_user '' 'Apps CPU User Time (%ld%% = %ld core%s)' 'cpu time %%' apps none stacked 20020 %d\n", (processors * 100), processors, (processors>1)?"s":"", update_every);
1020 + for (w = target_root; w ; w = w->next) {
1021 + if(w->target || (!w->processes && !w->exposed)) continue;
1022 +
1023 + fprintf(stdout, "DIMENSION %s '' incremental 100 %llu\n", w->name, Hertz * processors);
1024 + }
1025 +
1026 + fprintf(stdout, "CHART apps.cpu_system '' 'Apps CPU System Time (%ld%% = %ld core%s)' 'cpu time %%' apps none stacked 20021 %d\n", (processors * 100), processors, (processors>1)?"s":"", update_every);
1027 + for (w = target_root; w ; w = w->next) {
1028 + if(w->target || (!w->processes && !w->exposed)) continue;
1029 +
1030 + fprintf(stdout, "DIMENSION %s '' incremental 100 %llu\n", w->name, Hertz * processors);
1031 + }
1032 +
1033 + fprintf(stdout, "CHART apps.major_faults '' 'Apps Major Page Faults (swaps in)' 'page faults/s' apps apps stacked 20010 %d\n", update_every);
1034 + for (w = target_root; w ; w = w->next) {
1035 + if(w->target || (!w->processes && !w->exposed)) continue;
1036 +
1037 + fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w->name);
1038 + }
1039 +
1040 + fprintf(stdout, "CHART apps.minor_faults '' 'Apps Minor Page Faults' 'page faults/s' apps apps stacked 20011 %d\n", update_every);
1041 + for (w = target_root; w ; w = w->next) {
1042 + if(w->target || (!w->processes && !w->exposed)) continue;
1043 +
1044 + fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w->name);
1045 + }
1046 +
1047 + fprintf(stdout, "CHART apps.lreads '' 'Apps Logical Reads' 'kilobytes/s' apps apps stacked 20042 %d\n", update_every);
1048 + for (w = target_root; w ; w = w->next) {
1049 + if(w->target || (!w->processes && !w->exposed)) continue;
1050 +
1051 + fprintf(stdout, "DIMENSION %s '' incremental 1 1024\n", w->name);
1052 + }
1053 +
1054 + fprintf(stdout, "CHART apps.lwrites '' 'Apps Logical Writes' 'kilobytes/s' apps apps stacked 20042 %d\n", update_every);
1055 + for (w = target_root; w ; w = w->next) {
1056 + if(w->target || (!w->processes && !w->exposed)) continue;
1057 +
1058 + fprintf(stdout, "DIMENSION %s '' incremental 1 1024\n", w->name);
1059 + }
1060 +
1061 + fprintf(stdout, "CHART apps.preads '' 'Apps Reads' 'kilobytes/s' apps apps stacked 20002 %d\n", update_every);
1062 + for (w = target_root; w ; w = w->next) {
1063 + if(w->target || (!w->processes && !w->exposed)) continue;
1064 +
1065 + fprintf(stdout, "DIMENSION %s '' incremental 1 1024\n", w->name);
1066 + }
1067 +
1068 + fprintf(stdout, "CHART apps.pwrites '' 'Apps Writes' 'kilobytes/s' apps apps stacked 20002 %d\n", update_every);
1069 + for (w = target_root; w ; w = w->next) {
1070 + if(w->target || (!w->processes && !w->exposed)) continue;
1071 +
1072 + fprintf(stdout, "DIMENSION %s '' incremental 1 1024\n", w->name);
1073 + }
1074 +}
1075 +
1076 +unsigned long long get_hertz(void)
1077 +{
1078 + unsigned long long hz = 1;
1079 +
1080 +#ifdef _SC_CLK_TCK
1081 + if((hz = sysconf(_SC_CLK_TCK)) > 0) {
1082 + return hz;
1083 + }
1084 +#endif
1085 +
1086 +#ifdef HZ
1087 + hz = (unsigned long long)HZ; /* <asm/param.h> */
1088 +#else
1089 + /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */
1090 + hz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL;
1091 +#endif
1092 +
1093 + fprintf(stderr, "Unknown HZ value. Assuming %llu.\n", hz);
1094 + return hz;
1095 +}
1096 +
1097 +long get_processors(void)
1098 +{
1099 + char buffer[1025], *s;
1100 + int processors = 0;
1101 +
1102 + FILE *fp = fopen("/proc/stat", "r");
1103 + if(!fp) return 1;
1104 +
1105 + while((s = fgets(buffer, 1024, fp))) {
1106 + if(strncmp(buffer, "cpu", 3) == 0) processors++;
1107 + }
1108 + fclose(fp);
1109 + processors--;
1110 + if(processors < 1) processors = 1;
1111 + return processors;
1112 +}
1113 +
1114 +long get_pid_max(void)
1115 +{
1116 + char buffer[1025], *s;
1117 + long mpid = 32768;
1118 +
1119 + FILE *fp = fopen("/proc/sys/kernel/pid_max", "r");
1120 + if(!fp) return 1;
1121 +
1122 + s = fgets(buffer, 1024, fp);
1123 + if(s) mpid = atol(buffer);
1124 + fclose(fp);
1125 + if(mpid < 32768) mpid = 32768;
1126 + return mpid;
1127 +}
1128 +
1129 +unsigned long long usecdiff(struct timeval *now, struct timeval *last) {
1130 + return ((((now->tv_sec * 1000000ULL) + now->tv_usec) - ((last->tv_sec * 1000000ULL) + last->tv_usec)));
1131 +}
1132 +
1133 +int main(int argc, char **argv)
1134 +{
1135 + Hertz = get_hertz();
1136 + pid_max = get_pid_max();
1137 + processors = get_processors();
1138 +
1139 + parse_args(argc, argv);
1140 +
1141 + all_pids = calloc(sizeof(struct pid_stat *), pid_max);
1142 + if(!all_pids) {
1143 + fprintf(stderr, "Cannot allocate %lu bytes of memory.\n", sizeof(struct pid_stat *) * pid_max);
1144 + printf("DISABLE\n");
1145 + exit(1);
1146 + }
1147 +
1148 + int created_usage_chart = 0;
1149 + struct rusage me, me_last;
1150 + unsigned long long counter = 1;
1151 + unsigned long long usec = 0, susec = 0;
1152 + struct timeval last, now;
1153 + gettimeofday(&last, NULL);
1154 + getrusage(RUSAGE_SELF, &me_last);
1155 +
1156 + for(;1; counter++) {
1157 + if(!update_from_proc()) {
1158 + fprintf(stderr, "Cannot allocate %lu bytes of memory.\n", sizeof(struct pid_stat *) * pid_max);
1159 + printf("DISABLE\n");
1160 + exit(1);
1161 + }
1162 +
1163 + update_statistics();
1164 + show_charts(); // this is smart enough to show only newly added apps, when needed
1165 + show_dimensions();
1166 +
1167 + if(getrusage(RUSAGE_SELF, &me) == 0) {
1168 + unsigned long long cpuuser = me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec;
1169 + unsigned long long cpusyst = me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec;
1170 +
1171 + if(!created_usage_chart) {
1172 + created_usage_chart = 1;
1173 + fprintf(stdout, "CHART netdata.apps_cpu '' 'Apps Plugin CPU' 'milliseconds/s' netdata netdata stacked 10000 %d\n", update_every);
1174 + fprintf(stdout, "DIMENSION user '' incremental 1 1000\n");
1175 + fprintf(stdout, "DIMENSION system '' incremental 1 1000\n");
1176 +
1177 + fprintf(stdout, "CHART netdata.apps_files '' 'Apps Plugin Files' 'files/s' netdata netdata line 10001 %d\n", update_every);
1178 + fprintf(stdout, "DIMENSION files '' incremental 1 1\n");
1179 + }
1180 +
1181 + fprintf(stdout, "BEGIN netdata.apps_cpu\n");
1182 + fprintf(stdout, "SET user = %llu\n", cpuuser);
1183 + fprintf(stdout, "SET system = %llu\n", cpusyst);
1184 + fprintf(stdout, "END\n");
1185 +
1186 + fprintf(stdout, "BEGIN netdata.apps_files\n");
1187 + fprintf(stdout, "SET files = %llu\n", file_counter);
1188 + fprintf(stdout, "END\n");
1189 +
1190 + bcopy(&me, &me_last, sizeof(struct rusage));
1191 + }
1192 +
1193 + if(debug) fprintf(stderr, "Done Loop No %llu\n", counter);
1194 + // if(counter == 1000) exit(0);
1195 +
1196 + gettimeofday(&now, NULL);
1197 +
1198 + usec = usecdiff(&now, &last) - susec;
1199 + if(debug) fprintf(stderr, "last loop took %llu usec (worked for %llu, sleeped for %llu).\n", usec + susec, usec, susec);
1200 +
1201 + // if the last loop took less than half the time
1202 + // wait the rest of the time
1203 + if(usec < (update_every * 1000000ULL / 2)) susec = (update_every * 1000000ULL) - usec;
1204 + else susec = update_every * 1000000ULL / 2;
1205 +
1206 + fflush(NULL);
1207 + usleep(susec);
1208 +
1209 + bcopy(&now, &last, sizeof(struct timeval));
1210 + }
1211 +}
netdata.c
+50 -78
@@ -36,6 +36,9 @@
36 #include <inttypes.h>
37 #include <dirent.h>
38
39 +// enabling this will detach the plugins from netdata
40 +// each plugin will have its own process group
41 +// #define DETACH_PLUGINS_FROM_NETDATA
42
43 #define RRD_TYPE_NET "net"
44 #define RRD_TYPE_NET_LEN strlen(RRD_TYPE_NET)
@@ -227,7 +230,8 @@ void info_int( const char *file, const char *function, const unsigned long line,
230 log_date(stderr);
231
232 va_start( args, fmt );
230 - fprintf(stderr, "INFO (%04lu@%-15.15s): ", line, function);
233 + if(debug_flags) fprintf(stderr, "INFO (%04lu@%-15.15s): ", line, function);
234 + else fprintf(stderr, "INFO: ");
235 vfprintf( stderr, fmt, args );
236 va_end( args );
237
@@ -235,7 +239,7 @@ void info_int( const char *file, const char *function, const unsigned long line,
239
240 if(error_log_syslog) {
241 va_start( args, fmt );
238 - vsyslog(LOG_ERR, fmt, args );
242 + vsyslog(LOG_INFO, fmt, args );
243 va_end( args );
244 }
245 }
@@ -250,7 +254,8 @@ void error_int( const char *file, const char *function, const unsigned long line
254 log_date(stderr);
255
256 va_start( args, fmt );
253 - fprintf(stderr, "ERROR (%04lu@%-15.15s): ", line, function);
257 + if(debug_flags) fprintf(stderr, "ERROR (%04lu@%-15.15s): ", line, function);
258 + else fprintf(stderr, "ERROR: ");
259 vfprintf( stderr, fmt, args );
260 va_end( args );
261
@@ -277,7 +282,8 @@ void fatal_int( const char *file, const char *function, const unsigned long line
282 log_date(stderr);
283
284 va_start( args, fmt );
280 - fprintf(stderr, "FATAL (%04lu@%-15.15s): ", line, function);
285 + if(debug_flags) fprintf(stderr, "FATAL (%04lu@%-15.15s): ", line, function);
286 + else fprintf(stderr, "FATAL: ");
287 vfprintf( stderr, fmt, args );
288 va_end( args );
289
@@ -367,7 +373,10 @@ FILE *mypopen(const char *command, pid_t *pidptr)
373 close(pipefd[PIPE_WRITE]);
374 }
375
370 -/*
376 +#ifdef DETACH_PLUGINS_FROM_NETDATA
377 + // this was an attempt to detach the child and use the suspend mode charts.d
378 + // unfortunatelly it does not work as expected.
379 +
380 // fork again to become session leader
381 pid = fork();
382 if(pid == -1) fprintf(stderr, "Cannot fork again on pid %d\n", getpid());
@@ -385,13 +394,13 @@ FILE *mypopen(const char *command, pid_t *pidptr)
394
395 if( setsid() != 0 )
396 fprintf(stderr, "Cannot set session id for pid %d (%s)\n", getpid(), strerror(errno));
388 -*/
389 -
390 - // ignore all signals
391 - for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV) signal(i, SIG_DFL);
397
398 fprintf(stdout, "MYPID %d\n", getpid());
399 fflush(NULL);
400 +#endif
401 +
402 + // ignore all signals
403 + for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV) signal(i, SIG_DFL);
404
405 fprintf(stderr, "executing command: '%s'\n", command);
406 execl("/bin/sh", "sh", "-c", command, NULL);
@@ -400,6 +409,10 @@ FILE *mypopen(const char *command, pid_t *pidptr)
409
410 void mypclose(FILE *fp)
411 {
412 + // this is a very poor implementation of pclose()
413 + // the caller should catch SIGCHLD and waitpid() on the exited child
414 + // otherwise the child will be a zombie forever
415 +
416 fclose(fp);
417 }
418
@@ -515,7 +528,7 @@ int create_listen_socket(int port)
528
529 #define CONFIG_MAX_NAME 1024
530 #define CONFIG_MAX_VALUE 4096
518 -#define CONFIG_FILENAME "conf.d/netdata.conf"
531 +#define CONFIG_FILENAME "netdata.conf"
532 #define CONFIG_FILE_LINE_MAX 4096
533
534 pthread_mutex_t config_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -629,10 +642,10 @@ int load_config(char *filename, int overwrite_used)
642
643 char buffer[CONFIG_FILE_LINE_MAX + 1], *s;
644
632 - if(!filename) filename = CONFIG_FILENAME;
645 + if(!filename) filename = CONFIG_DIR "/" CONFIG_FILENAME;
646 FILE *fp = fopen(filename, "r");
647 if(!fp) {
635 - error("Cannot open file '%s'", CONFIG_FILENAME);
648 + error("Cannot open file '%s'", CONFIG_DIR "/" CONFIG_FILENAME);
649 pthread_mutex_unlock(&config_mutex);
650 return 0;
651 }
@@ -5369,7 +5382,7 @@ void *proc_main(void *ptr)
5382
5383 if(!stclients) stclients = rrd_stats_find("netdata.clients");
5384 if(!stclients) {
5372 - stclients = rrd_stats_create("netdata", "clients", NULL, "netdata", "NetData Web Clients", "clients", 11000, update_every, CHART_TYPE_LINE);
5385 + stclients = rrd_stats_create("netdata", "clients", NULL, "netdata", "NetData Web Clients", "connected clients", 11000, update_every, CHART_TYPE_LINE);
5386
5387 rrd_stats_dimension_add(stclients, "clients", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
5388 }
@@ -5382,7 +5395,7 @@ void *proc_main(void *ptr)
5395
5396 if(!streqs) streqs = rrd_stats_find("netdata.requests");
5397 if(!streqs) {
5385 - streqs = rrd_stats_create("netdata", "requests", NULL, "netdata", "NetData Web Requests", "requests", 12000, update_every, CHART_TYPE_LINE);
5398 + streqs = rrd_stats_create("netdata", "requests", NULL, "netdata", "NetData Web Requests", "requests/s", 12000, update_every, CHART_TYPE_LINE);
5399
5400 rrd_stats_dimension_add(streqs, "requests", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
5401 }
@@ -5614,7 +5627,7 @@ void *tc_main(void *ptr)
5627 struct tc_device *device = NULL;
5628 struct tc_class *class = NULL;
5629
5617 - snprintf(buffer, TC_LINE_MAX, "exec %s %d", config_get("plugin:tc", "script to run to get tc values", "plugins.d/tc-qos-helper.sh"), update_every);
5630 + snprintf(buffer, TC_LINE_MAX, "exec %s %d", config_get("plugin:tc", "script to run to get tc values", PLUGINS_DIR "/tc-qos-helper.sh"), update_every);
5631 debug(D_TC_LOOP, "executing '%s'", buffer);
5632 // fp = popen(buffer, "r");
5633 fp = mypopen(buffer, &tc_child_pid);
@@ -5703,17 +5716,16 @@ void *tc_main(void *ptr)
5716 char *path = strsep(&b, " \n");
5717 if(id && *id && path && *path) tc_device_set_class_name(device, id, path);
5718 }
5719 +#ifdef DETACH_PLUGINS_FROM_NETDATA
5720 else if((strcmp(p, "MYPID") == 0)) {
5721 char *id = strsep(&b, " \n");
5722 pid_t pid = atol(id);
5723
5710 - if(pid != tc_child_pid)
5711 - error("tc-qos-helper reports wrong pid %d (expected %d).", pid, tc_child_pid);
5712 -
5713 - // tc_child_pid = pid;
5724 + if(pid) tc_child_pid = pid;
5725
5726 debug(D_TC_LOOP, "TC: Child PID is %d.", tc_child_pid);
5727 }
5728 +#endif
5729 }
5730 mypclose(fp);
5731
@@ -5843,8 +5855,10 @@ void *pluginsd_worker_thread(void *arg)
5855 struct plugind *cd = (struct plugind *)arg;
5856 char line[PLUGINSD_LINE_MAX + 1];
5857
5858 +#ifdef DETACH_PLUGINS_FROM_NETDATA
5859 unsigned long long usec = 0, susec = 0;
5860 struct timeval last = {0, 0} , now = {0, 0};
5861 +#endif
5862
5863 while(1) {
5864 // FILE *fp = popen(cd->cmd, "r");
@@ -6035,26 +6049,20 @@ void *pluginsd_worker_thread(void *arg)
6049 }
6050 else if(st->debug) debug(D_PLUGINSD, "PLUGINSD: dimension %s/%s already exists. Not adding it again.", st->id, id);
6051 }
6038 - else if(!strcmp(s, "MYPID")) {
6039 - char *pid_s = qstrsep(&p);
6040 - pid_t pid = atol(pid_s);
6041 -
6042 - if(pid != cd->pid) {
6043 - error("plugin %s reports wrong pid %d (expected %d). Disabling it.", cd->filename, pid, cd->pid);
6044 - cd->enabled = 0;
6045 - kill(cd->pid, SIGTERM);
6046 - break;
6047 - }
6048 - // cd->pid = pid;
6049 -
6050 - debug(D_PLUGINSD, "PLUGINSD: %s is on pid %d", cd->id, cd->pid);
6051 - }
6052 else if(!strcmp(s, "DISABLE")) {
6053 error("PLUGINSD: script '%s' called DISABLE. Disabling it.", cd->fullfilename);
6054 cd->enabled = 0;
6055 kill(cd->pid, SIGTERM);
6056 break;
6057 }
6058 +#ifdef DETACH_PLUGINS_FROM_NETDATA
6059 + else if(!strcmp(s, "MYPID")) {
6060 + char *pid_s = qstrsep(&p);
6061 + pid_t pid = atol(pid_s);
6062 +
6063 + if(pid) cd->pid = pid;
6064 + debug(D_PLUGINSD, "PLUGINSD: %s is on pid %d", cd->id, cd->pid);
6065 + }
6066 else if(!strcmp(s, "STOPPING_WAKE_ME_UP_PLEASE")) {
6067 error("PLUGINSD: script '%s' (pid %d) called STOPPING_WAKE_ME_UP_PLEASE.", cd->fullfilename, cd->pid);
6068
@@ -6071,12 +6079,13 @@ void *pluginsd_worker_thread(void *arg)
6079 else susec = 100000ULL;
6080 }
6081
6074 - error("PLUGINSD: %s sleeping for %llu. Will kill pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
6082 + error("PLUGINSD: %s sleeping for %llu. Will kill with SIGCONT pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
6083 usleep(susec);
6084 kill(cd->pid, SIGCONT);
6085 bcopy(&now, &last, sizeof(struct timeval));
6086 break;
6087 }
6088 +#endif
6089 else {
6090 error("PLUGINSD: script %s is sending command '%s' which is not known by netdata. Disabling it.", cd->fullfilename, s);
6091 cd->enabled = 0;
@@ -6105,7 +6114,7 @@ void *pluginsd_worker_thread(void *arg)
6114 void *pluginsd_main(void *ptr)
6115 {
6116 if(ptr) { ; }
6108 - char *dir_name = config_get("plugins", "plugins directory", "plugins.d");
6117 + char *dir_name = config_get("plugins", "plugins directory", PLUGINS_DIR);
6118 int automatic_run = config_get_boolean("plugins", "enable running new plugins", 0);
6119 int scan_frequency = config_get_number("plugins", "check for new plugins every", 60);
6120 DIR *dir = NULL;
@@ -6158,7 +6167,7 @@ void *pluginsd_main(void *ptr)
6167 // allocate a new one, or use the obsolete one
6168 if(!cd) {
6169 cd = calloc(sizeof(struct plugind), 1);
6161 - if(!cd) fatal("Cannot allocate memory for chart.d");
6170 + if(!cd) fatal("Cannot allocate memory for plugin.");
6171
6172 snprintf(cd->id, CONFIG_MAX_NAME, "plugin:%s", pluginname);
6173
@@ -6169,43 +6178,6 @@ void *pluginsd_main(void *ptr)
6178 cd->update_every = config_get_number(cd->id, "update every", update_every);
6179
6180 char *def = "";
6172 - if(strcmp(cd->id, "plugin:apps") == 0)
6173 - def =
6174 - " 'mplayer vlc xine mediatomb as media'"
6175 - " 'squid squid3 as squid'"
6176 - " 'apache apache2 as apache'"
6177 - " 'mysql mysqld as mysql'"
6178 - " asterisk"
6179 - " 'opensips opensips-mi-pro as opensips'"
6180 - " stund"
6181 - " 'radiusd radiusclient as radius'"
6182 - " 'fail2ban-server as fail2ban'"
6183 - " dovecot"
6184 - " nginx"
6185 - " lighttpd"
6186 - " 'proftpd in.tftpd as ftpd'"
6187 - " 'master as postfix'"
6188 - " 'smbd nmbd winbindd as samba'"
6189 - " 'rpcbind rpc.statd rpc.idmapd rpc.mountd nfsd4 nfsd4_callbacks nfsd nfsiod as nfs'"
6190 - " 'ssh sshd as ssh'"
6191 - " 'gdm X lightdm xdm gnome-session gconfd-2 gnome-terminal gnome-screensaver gnome-settings-daemon pulseaudio as X'"
6192 - " named"
6193 - " 'clamd freshclam as clam'"
6194 - " 'cupsd cups-browsed as cups'"
6195 - " 'ntpq ntpd as ntp'"
6196 - " 'deluge deluged as deluge'"
6197 - " 'vboxwebsrv VBoxXPCOMIPCD VBoxSVC as vbox'"
6198 - " 'ulogd syslogd syslog-ng rsyslogd logrotate as log'"
6199 - " 'snmpd vnstatd smokeping zabbix_agentd monit munin-node mon openhpid as nms'"
6200 - " 'ppp pppd pptpd pptpctrl as ppp'"
6201 - " 'inetd xinetd as inetd'"
6202 - " openvpn"
6203 - " 'cron atd as cron'"
6204 - " 'corosync hs_logd ha_logd stonithd as ha'"
6205 - " 'ipvs_syncmaster ipvs_syncbackup as ipvs'"
6206 - " 'kthreadd as kernel'"
6207 - " netdata"
6208 - ;
6181 snprintf(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def));
6182
6183 // link it
@@ -6523,7 +6495,7 @@ int main(int argc, char **argv)
6495 else {
6496 fprintf(stderr, "Cannot understand option '%s'.\n", argv[i]);
6497 fprintf(stderr, "\nUSAGE: %s [-d] [-l LINES_TO_SAVE] [-u UPDATE_TIMER] [-p LISTEN_PORT] [-dl debug log file] [-df debug flags].\n\n", argv[0]);
6526 - fprintf(stderr, " -c CONFIG FILE the configuration file to load. Default: %s.\n", CONFIG_FILENAME);
6498 + fprintf(stderr, " -c CONFIG FILE the configuration file to load. Default: %s.\n", CONFIG_DIR "/" CONFIG_FILENAME);
6499 fprintf(stderr, " -l LINES_TO_SAVE can be from 5 to %d lines in JSON data. Default: %d.\n", HISTORY_MAX, HISTORY);
6500 fprintf(stderr, " -t UPDATE_TIMER can be from 1 to %d seconds. Default: %d.\n", UPDATE_EVERY_MAX, UPDATE_EVERY);
6501 fprintf(stderr, " -p LISTEN_PORT can be from 1 to %d. Default: %d.\n", 65535, LISTEN_PORT);
@@ -6551,7 +6523,7 @@ int main(int argc, char **argv)
6523
6524 // --------------------------------------------------------------------
6525
6554 - output_log_file = config_get("global", "debug log", "log/debug.log");
6526 + output_log_file = config_get("global", "debug log", LOG_DIR "/debug.log");
6527 if(strcmp(output_log_file, "syslog") == 0) {
6528 output_log_syslog = 1;
6529 output_log_file = NULL;
@@ -6565,7 +6537,7 @@ int main(int argc, char **argv)
6537 // --------------------------------------------------------------------
6538
6539 silent = 0;
6568 - error_log_file = config_get("global", "error log", "log/error.log");
6540 + error_log_file = config_get("global", "error log", LOG_DIR "/error.log");
6541 if(strcmp(error_log_file, "syslog") == 0) {
6542 error_log_syslog = 1;
6543 error_log_file = NULL;
@@ -6579,7 +6551,7 @@ int main(int argc, char **argv)
6551
6552 // --------------------------------------------------------------------
6553
6582 - access_log_file = config_get("global", "access log", "log/access.log");
6554 + access_log_file = config_get("global", "access log", LOG_DIR "/access.log");
6555 if(strcmp(access_log_file, "syslog") == 0) {
6556 access_log_syslog = 1;
6557 access_log_file = NULL;
@@ -6610,7 +6582,7 @@ int main(int argc, char **argv)
6582
6583 // --------------------------------------------------------------------
6584
6613 - char *user = config_get("global", "run as user", "");
6585 + char *user = config_get("global", "run as user", (getuid() == 0)?"nobody":"");
6586 if(*user) {
6587 if(become_user(user) != 0) {
6588 fprintf(stderr, "Cannot become user %s.\n", user);
netdata.start
+9 -21
@@ -39,30 +39,18 @@ fi
39
40 if [ -f conf.d/netdata.conf ]
41 then
42 - x="`grep "\[global\]" conf.d/netdata.conf`"
43 - if [ -z "$x" ]
42 + # find if debug is enabled in the config
43 + df=`grep "debug flags = " conf.d/netdata.conf | tail -n 1 | cut -d '=' -f 2 | sed s"/ //g"`
44 + if [ -z "$df" -o "$df" = "0x00000000" -o $((df + 1 - 1)) -eq 0 ]
45 then
45 - # import the old values
46 - cat netdata.conf | grep ^NETDATA_CONFIG_ >netdata.conf.tmp
47 - . netdata.conf.tmp
48 - rm netdata.conf.tmp
49 -
50 - mv netdata.conf netdata.conf.old
51 - echo "You are having an old config. Moved to netdata.conf.old. New config is in conf.d/"
46 + NETDATA_CONFIG_DEBUG=0
47 else
53 - # find if debug is enabled in the config
54 - df=`grep "debug flags = " conf.d/netdata.conf | tail -n 1 | cut -d '=' -f 2 | sed s"/ //g"`
55 - if [ -z "$df" -o "$df" = "0x00000000" -o $((df + 1 - 1)) -eq 0 ]
56 - then
57 - NETDATA_CONFIG_DEBUG=0
58 - else
59 - NETDATA_CONFIG_DEBUG=1
60 - fi
61 -
62 - # find the user to run as
63 - NETDATA_CONFIG_USER="`grep 'run as user = ' conf.d/netdata.conf | head -n 1 | cut -d '=' -f 2 | sed s"/ //g"`"
64 - NETDATA_CONFIG_WEB_DIR="`grep 'web files directory = ' conf.d/netdata.conf | head -n 1 | cut -d '=' -f 2 | sed -e s"/^ \+//g" -e s"/ \+$//g"`"
48 + NETDATA_CONFIG_DEBUG=1
49 fi
50 +
51 + # find the user to run as
52 + NETDATA_CONFIG_USER="`grep 'run as user = ' conf.d/netdata.conf | head -n 1 | cut -d '=' -f 2 | sed s"/ //g"`"
53 + NETDATA_CONFIG_WEB_DIR="`grep 'web files directory = ' conf.d/netdata.conf | head -n 1 | cut -d '=' -f 2 | sed -e s"/^ \+//g" -e s"/ \+$//g"`"
54 fi
55
56 echo "Compiling netdata (debug=$NETDATA_CONFIG_DEBUG)"
plugins.d/tc-qos-helper.sh
-4
@@ -1,9 +1,5 @@
1 #!/bin/sh
2
3 -# let netdata know our PID
4 -# this is required to kill us when it exits
5 -echo "MYPID $$"
6 -
3 # default sleep function
4 loopsleepms() {
5 sleep $1