removed child resource usage from counter, they were causing sudden spikes in charts because linux migrates this usage to a process only when a child finishes, giving huge numbers at that second
Costa Tsaousis (ktsaou) committed
May 7, 2014 at 03:24 UTC
2a22545ae362ad62d65b9384f374f1f91d3cf57c
2 files changed
+83
-42
apps_plugin.c
+77
-40
@@ -25,8 +25,6 @@
25
#define MAX_NAME 100
26
27
28
-#define add_childs 1ULL
29
-
28
unsigned long long Hertz = 1;
29
30
long pid_max = 32768;
@@ -168,7 +166,6 @@ struct pid_stat {
166
int new_entry;
167
unsigned long merge_count;
168
struct wanted *target;
171
- int target_inherited;
169
struct pid_stat *parent;
170
struct pid_stat *prev;
171
struct pid_stat *next;
@@ -204,6 +201,8 @@ void del_entry(pid_t pid)
201
{
202
if(!all_pids[pid]) return;
203
204
+ if(debug) fprintf(stderr, "Process %d %s exited, deleting it.\n", pid, all_pids[pid]->comm);
205
+
206
if(root == all_pids[pid]) root = all_pids[pid]->next;
207
if(all_pids[pid]->next) all_pids[pid]->next->prev = all_pids[pid]->prev;
208
if(all_pids[pid]->prev) all_pids[pid]->prev->next = all_pids[pid]->next;
@@ -231,8 +230,6 @@ int update_from_proc(void)
230
p->merged = 0;
231
p->new_entry = 0;
232
p->merge_count = 0;
234
-
235
- if(p->target_inherited) p->target = NULL;
233
}
234
235
while((file = readdir(dir))) {
@@ -257,6 +254,8 @@ int update_from_proc(void)
254
255
close(fd);
256
if(bytes < 100) continue;
257
+ buffer[bytes] = '\0';
258
+ if(debug) fprintf(stderr, "READ: %s", buffer);
259
260
p = get_entry(pid);
261
if(!p) continue;
@@ -298,6 +297,8 @@ int update_from_proc(void)
297
strncpy(p->comm, name, MAX_COMPARE_NAME + 2);
298
p->comm[MAX_COMPARE_NAME + 2] = '\0';
299
300
+ 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);
301
+
302
if(parsed < 39) fprintf(stderr, "file %s gave %d results (expected 44)\n", filename, parsed);
303
304
// check if it is wanted
@@ -319,17 +320,18 @@ int update_from_proc(void)
320
}
321
322
// just a few checks
322
- if(p->ppid < 1 || p->ppid > pid_max) p->ppid = 1;
323
+ if(p->ppid < 0 || p->ppid > pid_max) p->ppid = 0;
324
325
// mark it as updated
326
p->updated = 1;
327
}
328
closedir(dir);
329
329
- // cleanup all un-updated
330
+ // cleanup all un-updated processed (exited, killed, etc)
331
int c;
332
for(p = root, c = 0; p ; c++) {
333
if(!p->updated) {
334
+
335
pid_t r = p->pid;
336
p = p->next;
337
del_entry(r);
@@ -337,43 +339,61 @@ int update_from_proc(void)
339
else p = p->next;
340
}
341
340
- if(debug) fprintf(stderr, "There are %d processes active\n", c);
341
-
342
return 1;
343
}
344
345
+void walk_down(pid_t pid, int level) {
346
+ struct pid_stat *p = NULL;
347
+ char b[level+3];
348
+ int i;
349
+
350
+ for(i = 0; i < level; i++) b[i] = '\t';
351
+ b[level] = '|';
352
+ b[level+1] = '-';
353
+ b[level+2] = '\0';
354
+
355
+ p = all_pids[pid];
356
+ if(p) fprintf(stderr, "%s %s %d [%s] c=%d u=%llu, s=%llu, cu=%llu, cs=%llu, n=%llu, j=%llu, cn=%llu, cj=%llu\n", b, p->comm, p->pid, p->updated?"OK":"KILLED", p->childs, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
357
+
358
+ for(p = root; p ; p = p->next) {
359
+ if(p->ppid == pid) {
360
+ walk_down(p->pid, level+1);
361
+ }
362
+ }
363
+}
364
+
365
void merge_processes(void)
366
{
367
struct pid_stat *p = NULL;
368
369
+ if(debug) walk_down(0, 1);
370
+
371
// link all parents and update childs count
372
for(p = root; p ; p = p->next) {
351
- if(p->ppid > 1 && p->ppid <= pid_max && all_pids[p->ppid]) {
373
+ if(p->ppid > 0 && p->ppid <= pid_max && all_pids[p->ppid]) {
374
if(debug) fprintf(stderr, "\tParent of %d %s is %d %s\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm);
375
376
p->parent = all_pids[p->ppid];
355
- if(!p->parent) {
356
- if(debug) fprintf(stderr, "\t\tpid %d %s states parent %d, but the later does not exist.\n", p->pid, p->comm, p->ppid);
357
- continue;
358
- }
359
-
377
p->parent->childs++;
378
}
379
+ 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);
380
}
381
382
// find all the procs with 0 childs and merge them to their parents
383
// repeat, until nothing more can be done.
384
int found = 1;
367
- for( ; found ; ) {
385
+ while(found) {
386
found = 0;
387
for(p = root; p ; p = p->next) {
370
- // if this process does not any childs, and
388
+ // if this process does not have any childs, and
389
// is not already merged, and
372
- // its parents has childs waiting to be merged, and
390
+ // its parent has childs waiting to be merged, and
391
// 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
392
+ // and its parent is not init
393
// then... merge them!
375
- if(!p->childs && !p->merged && p->parent && p->parent->childs && (p->target == p->parent->target || !p->parent->target || !p->target)) {
376
- if(debug) fprintf(stderr, "\tMerging %d %s to %d %s (count: %lu)\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm, p->parent->merge_count+1);
394
+ if(!p->childs && !p->merged && p->parent && p->parent->childs && (p->target == p->parent->target || !p->parent->target || !p->target) && p->ppid != 1) {
395
+
396
+ if(debug) fprintf(stderr, "\n\t\tPARENT BEFORE MERGE: %d %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->parent->pid, p->parent->comm, p->parent->utime, p->parent->stime, p->parent->cutime, p->parent->cstime, p->parent->minflt, p->parent->majflt, p->parent->cminflt, p->parent->cmajflt);
397
398
p->parent->minflt += p->minflt;
399
p->parent->majflt += p->majflt;
@@ -388,15 +408,18 @@ void merge_processes(void)
408
p->parent->num_threads += p->num_threads;
409
p->parent->rss += p->rss;
410
411
+ if(debug) fprintf(stderr, "\tMERGED %d %s to %d %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
412
+
413
p->parent->childs--;
414
p->merged = 1;
415
416
+ if(debug) fprintf(stderr, "\t\tPARENT AFTER MERGE: %d %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->parent->pid, p->parent->comm, p->parent->utime, p->parent->stime, p->parent->cutime, p->parent->cstime, p->parent->minflt, p->parent->majflt, p->parent->cminflt, p->parent->cmajflt);
417
+
418
p->parent->merge_count += p->merge_count + 1;
419
420
// the parent inherits the child's target, if it does not have a target itself
421
if(p->target && !p->parent->target) {
422
p->parent->target = p->target;
399
- p->parent->target_inherited = 1;
423
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);
424
}
425
@@ -406,16 +429,29 @@ void merge_processes(void)
429
if(debug) fprintf(stderr, "Merged %d processes\n", found);
430
}
431
409
- if(debug) {
410
- fprintf(stderr, "Root level processes: \n");
411
- for(p = root, found = 0; p ; p = p->next) {
412
- if(!p->childs && !p->merged && !p->parent) {
413
- fprintf(stderr, "\t\t%s %d on target %s\n", p->comm, p->pid, p->target?p->target->name:"-");
432
+ // give a default target on all top level processes
433
+ // init goes always to default target
434
+ if(all_pids[1]) all_pids[1]->target = default_target;
435
+
436
+ for(p = root, found = 0; p ; p = p->next) {
437
+ // if the process is not merged itself
438
+ // then is is a top level process
439
+ if(!p->merged && !p->target) p->target = default_target;
440
+ }
441
+
442
+ // give a target to all merged child processes
443
+ found = 1;
444
+ while(found) {
445
+ found = 0;
446
+ for(p = root; p ; p = p->next) {
447
+ if(!p->target && p->merged && p->parent && p->parent->target) {
448
+ p->target = p->parent->target;
449
+ found++;
450
}
451
}
452
}
453
418
- // zero the targets
454
+ // zero all the targets
455
struct wanted *w;
456
for (w = wanted_root; w ; w = w->next) {
457
w->minflt = 0;
@@ -435,14 +471,14 @@ void merge_processes(void)
471
for(p = root; p ; p = p->next) {
472
//if(p->parent && !p->merged) fprintf(stderr, "\tprocess %s pid %d has a parent, but has not been merged!\n", p->comm, p->pid);
473
//if(p->childs) fprintf(stderr, "\tprocess %s pid %d has %d childs that have not been merged!\n", p->comm, p->pid, p->childs);
438
- if(p->merged) continue;
474
475
if(!p->target) {
441
- p->target = default_target;
442
- p->target_inherited = 1;
443
- if(debug) fprintf(stderr, "\tprocess %s pid %d is orphan\n", p->comm, p->pid);
476
+ fprintf(stderr, "WRONG! pid %d %s was left without a target!\n", p->pid, p->comm);
477
+ continue;
478
}
479
480
+ if(p->merged) continue;
481
+
482
p->target->minflt += p->minflt;
483
p->target->majflt += p->majflt;
484
p->target->utime += p->utime;
@@ -455,7 +491,8 @@ void merge_processes(void)
491
p->target->rss += p->rss;
492
493
p->target->merge_count += p->merge_count + 1;
458
- if(debug) fprintf(stderr, "\tAgregating %s pid %d on %s (count: %lu)\n", p->comm, p->pid, p->target->name, p->target->merge_count);
494
+
495
+ if(debug) fprintf(stderr, "\tAgregating %s pid %d on %s (count: %lu) 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->target->merge_count, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
496
}
497
}
498
@@ -468,7 +505,7 @@ void show_dimensions(void)
505
for (w = wanted_root; w ; w = w->next) {
506
if(w->target || (!w->merge_count && !w->exposed)) continue;
507
471
- fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->stime + (w->cutime * add_childs) + (w->cstime * add_childs));
508
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->stime);
509
}
510
fprintf(stdout, "END\n");
511
@@ -476,7 +513,7 @@ void show_dimensions(void)
513
for (w = wanted_root; w ; w = w->next) {
514
if(w->target || (!w->merge_count && !w->exposed)) continue;
515
479
- fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + (w->cutime * add_childs));
516
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->utime);
517
}
518
fprintf(stdout, "END\n");
519
@@ -484,7 +521,7 @@ void show_dimensions(void)
521
for (w = wanted_root; w ; w = w->next) {
522
if(w->target || (!w->merge_count && !w->exposed)) continue;
523
487
- fprintf(stdout, "SET %s = %llu\n", w->name, w->stime + (w->cstime * add_childs));
524
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->stime);
525
}
526
fprintf(stdout, "END\n");
527
@@ -516,7 +553,7 @@ void show_dimensions(void)
553
for (w = wanted_root; w ; w = w->next) {
554
if(w->target || (!w->merge_count && !w->exposed)) continue;
555
519
- fprintf(stdout, "SET %s = %llu\n", w->name, w->minflt + (w->cminflt * add_childs));
556
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->minflt);
557
}
558
fprintf(stdout, "END\n");
559
@@ -524,11 +561,11 @@ void show_dimensions(void)
561
for (w = wanted_root; w ; w = w->next) {
562
if(w->target || (!w->merge_count && !w->exposed)) continue;
563
527
- fprintf(stdout, "SET %s = %llu\n", w->name, w->majflt + (w->cmajflt * add_childs));
564
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->majflt);
565
}
566
fprintf(stdout, "END\n");
567
531
- fflush(stdout);
568
+ fflush(NULL);
569
}
570
571
void show_charts(void)
@@ -604,7 +641,7 @@ void show_charts(void)
641
fprintf(stdout, "DIMENSION %s '' incremental 1 1\n", w->name);
642
}
643
607
- fflush(stdout);
644
+ fflush(NULL);
645
}
646
647
unsigned long long get_hertz(void)
@@ -624,7 +661,7 @@ unsigned long long get_hertz(void)
661
hz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL;
662
#endif
663
627
- fprintf(stderr, "Unknown HZ value. Assuming %llu", hz);
664
+ fprintf(stderr, "Unknown HZ value. Assuming %llu.\n", hz);
665
return hz;
666
}
667
netdata.c
+6
-2
@@ -1315,8 +1315,12 @@ unsigned long long rrd_stats_done(RRD_STATS *st)
1315
// we need the incremental calculation to produce per second results
1316
// so, we multiply with 1.000.000 and divide by the microseconds passed since
1317
// the last entry
1318
- if(rd->last_collected_value > rd->collected_value) rd->calculated_value = 0;
1319
- else rd->calculated_value =
1318
+
1319
+ // if the new is smaller than the old (an overflow, or reset), set the old equal to the new
1320
+ // to reset the calculation (it will give zero as the calculation for this second)
1321
+ if(rd->last_collected_value > rd->collected_value) rd->last_collected_value = rd->collected_value;
1322
+
1323
+ rd->calculated_value =
1324
(calculated_number)10
1325
* (calculated_number)1000000
1326
* (calculated_number)(rd->collected_value - rd->last_collected_value)