@cryptotaxi247 / netdata-1 / commits / 2a22545ae

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)