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