yet another rewrite of apps.plugin to fix cpu spikes on slow systems; fixes #644
Costa Tsaousis (ktsaou) committed
Jul 8, 2016 at 02:41 UTC
8e5c1eaafce5f7c4f6c270c3b29c2ada0e9cd9b1
1 file changed
+667
-513
src/apps_plugin.c
+667
-513
@@ -48,12 +48,14 @@ pid_t pid_max = 32768;
48
int debug = 0;
49
50
int update_every = 1;
51
+unsigned long long global_iterations_counter = 1;
52
unsigned long long file_counter = 0;
53
int proc_pid_cmdline_is_needed = 0;
54
int include_exited_childs = 1;
55
char *host_prefix = "";
56
char *config_dir = CONFIG_DIR;
57
58
+pid_t *all_pids_sortlist = NULL;
59
60
// ----------------------------------------------------------------------------
61
@@ -146,15 +148,6 @@ struct target {
148
unsigned long long num_threads;
149
unsigned long long rss;
150
149
- long long fix_minflt;
150
- long long fix_cminflt;
151
- long long fix_majflt;
152
- long long fix_cmajflt;
153
- long long fix_utime;
154
- long long fix_stime;
155
- long long fix_cutime;
156
- long long fix_cstime;
157
-
151
unsigned long long statm_size;
152
unsigned long long statm_resident;
153
unsigned long long statm_share;
@@ -171,14 +164,6 @@ struct target {
164
unsigned long long io_storage_bytes_written;
165
unsigned long long io_cancelled_write_bytes;
166
174
- unsigned long long fix_io_logical_bytes_read;
175
- unsigned long long fix_io_logical_bytes_written;
176
- unsigned long long fix_io_read_calls;
177
- unsigned long long fix_io_write_calls;
178
- unsigned long long fix_io_storage_bytes_read;
179
- unsigned long long fix_io_storage_bytes_written;
180
- unsigned long long fix_io_cancelled_write_bytes;
181
-
167
int *fds;
168
unsigned long long openfiles;
169
unsigned long long openpipes;
@@ -459,6 +444,18 @@ struct pid_stat {
444
// int32_t tty_nr;
445
// int32_t tpgid;
446
// uint64_t flags;
447
+
448
+ // these are raw values collected
449
+ unsigned long long minflt_raw;
450
+ unsigned long long cminflt_raw;
451
+ unsigned long long majflt_raw;
452
+ unsigned long long cmajflt_raw;
453
+ unsigned long long utime_raw;
454
+ unsigned long long stime_raw;
455
+ unsigned long long cutime_raw;
456
+ unsigned long long cstime_raw;
457
+
458
+ // these are rates
459
unsigned long long minflt;
460
unsigned long long cminflt;
461
unsigned long long majflt;
@@ -467,6 +464,7 @@ struct pid_stat {
464
unsigned long long stime;
465
unsigned long long cutime;
466
unsigned long long cstime;
467
+
468
// int64_t priority;
469
// int64_t nice;
470
int32_t num_threads;
@@ -506,6 +504,14 @@ struct pid_stat {
504
unsigned long long statm_data;
505
unsigned long long statm_dirty;
506
507
+ unsigned long long io_logical_bytes_read_raw;
508
+ unsigned long long io_logical_bytes_written_raw;
509
+ unsigned long long io_read_calls_raw;
510
+ unsigned long long io_write_calls_raw;
511
+ unsigned long long io_storage_bytes_read_raw;
512
+ unsigned long long io_storage_bytes_written_raw;
513
+ unsigned long long io_cancelled_write_bytes_raw;
514
+
515
unsigned long long io_logical_bytes_read;
516
unsigned long long io_logical_bytes_written;
517
unsigned long long io_read_calls;
@@ -514,61 +520,42 @@ struct pid_stat {
520
unsigned long long io_storage_bytes_written;
521
unsigned long long io_cancelled_write_bytes;
522
517
- // we need the last values
518
- // for all incremental counters
519
- // so that when a process switches users/groups
520
- // we will subtract these values from the old
521
- // target
522
- unsigned long long last_minflt;
523
- unsigned long long last_majflt;
524
- unsigned long long last_utime;
525
- unsigned long long last_stime;
526
-
527
- unsigned long long last_cminflt;
528
- unsigned long long last_cmajflt;
529
- unsigned long long last_cutime;
530
- unsigned long long last_cstime;
531
-
532
- unsigned long long last_fix_cminflt;
533
- unsigned long long last_fix_cmajflt;
534
- unsigned long long last_fix_cutime;
535
- unsigned long long last_fix_cstime;
536
-
537
- unsigned long long last_io_logical_bytes_read;
538
- unsigned long long last_io_logical_bytes_written;
539
- unsigned long long last_io_read_calls;
540
- unsigned long long last_io_write_calls;
541
- unsigned long long last_io_storage_bytes_read;
542
- unsigned long long last_io_storage_bytes_written;
543
- unsigned long long last_io_cancelled_write_bytes;
544
-
545
- unsigned long long fix_cminflt;
546
- unsigned long long fix_cmajflt;
547
- unsigned long long fix_cutime;
548
- unsigned long long fix_cstime;
549
-
523
int *fds; // array of fds it uses
524
int fds_size; // the size of the fds array
525
526
int children_count; // number of processes directly referencing this
554
- int updated; // 1 when update
527
+ int keep; // 1 when we need to keep this process in memory even after it exited
528
+ int keeploops; // increases by 1 every time keep is 1 and updated 0
529
+ int updated; // 1 when the process is currently running
530
int merged; // 1 when it has been merged to its parent
556
- int new_entry;
531
+ int new_entry; // 1 when this is a new process, just saw for the first time
532
+ int read; // 1 when we have already read this process for this iteration
533
+ int sortlist; // higher numbers = top on the process tree
534
+ // each process gets a unique number
535
536
struct target *target; // app_groups.conf targets
537
struct target *user_target; // uid based targets
538
struct target *group_target; // gid based targets
539
540
+ unsigned long long stat_collected_usec;
541
+ unsigned long long last_stat_collected_usec;
542
+
543
+ unsigned long long io_collected_usec;
544
+ unsigned long long last_io_collected_usec;
545
+
546
+ char *stat_filename;
547
+ char *statm_filename;
548
+ char *io_filename;
549
+ char *cmdline_filename;
550
+
551
struct pid_stat *parent;
552
struct pid_stat *prev;
553
struct pid_stat *next;
565
-
554
} *root_of_pids = NULL, **all_pids;
555
556
long all_pids_count = 0;
557
570
-struct pid_stat *get_pid_entry(pid_t pid)
571
-{
558
+struct pid_stat *get_pid_entry(pid_t pid) {
559
if(all_pids[pid]) {
560
all_pids[pid]->new_entry = 0;
561
return all_pids[pid];
@@ -592,12 +579,16 @@ struct pid_stat *get_pid_entry(pid_t pid)
579
all_pids[pid]->pid = pid;
580
all_pids[pid]->new_entry = 1;
581
582
+ all_pids_count++;
583
+
584
return all_pids[pid];
585
}
586
598
-void del_pid_entry(pid_t pid)
599
-{
600
- if(!all_pids[pid]) return;
587
+void del_pid_entry(pid_t pid) {
588
+ if(!all_pids[pid]) {
589
+ error("attempted to free pid %d that is not allocated.", pid);
590
+ return;
591
+ }
592
593
if(unlikely(debug))
594
fprintf(stderr, "apps.plugin: process %d %s exited, deleting it.\n", pid, all_pids[pid]->comm);
@@ -607,8 +598,14 @@ void del_pid_entry(pid_t pid)
598
if(all_pids[pid]->prev) all_pids[pid]->prev->next = all_pids[pid]->next;
599
600
if(all_pids[pid]->fds) free(all_pids[pid]->fds);
601
+ if(all_pids[pid]->stat_filename) free(all_pids[pid]->stat_filename);
602
+ if(all_pids[pid]->statm_filename) free(all_pids[pid]->statm_filename);
603
+ if(all_pids[pid]->io_filename) free(all_pids[pid]->io_filename);
604
+ if(all_pids[pid]->cmdline_filename) free(all_pids[pid]->cmdline_filename);
605
free(all_pids[pid]);
606
+
607
all_pids[pid] = NULL;
608
+ all_pids_count--;
609
}
610
611
@@ -616,42 +613,51 @@ void del_pid_entry(pid_t pid)
613
// update pids from proc
614
615
int read_proc_pid_cmdline(struct pid_stat *p) {
619
- char filename[FILENAME_MAX + 1];
620
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/cmdline", host_prefix, p->pid);
616
+
617
+ if(unlikely(!p->cmdline_filename)) {
618
+ char filename[FILENAME_MAX + 1];
619
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/cmdline", host_prefix, p->pid);
620
+ if(!(p->cmdline_filename = strdup(filename)))
621
+ fatal("Cannot allocate memory for filename '%s'", filename);
622
+ }
623
622
- int fd = open(filename, O_RDONLY, 0666);
623
- if(unlikely(fd == -1)) return 1;
624
+ int fd = open(p->cmdline_filename, O_RDONLY, 0666);
625
+ if(unlikely(fd == -1)) goto cleanup;
626
627
int i, bytes = read(fd, p->cmdline, MAX_CMDLINE);
628
close(fd);
629
628
- if(bytes <= 0) {
629
- // copy the command to the command line
630
- strncpyz(p->cmdline, p->comm, MAX_CMDLINE);
631
- return 0;
632
- }
630
+ if(unlikely(bytes <= 0)) goto cleanup;
631
632
p->cmdline[bytes] = '\0';
633
for(i = 0; i < bytes ; i++)
636
- if(!p->cmdline[i]) p->cmdline[i] = ' ';
634
+ if(unlikely(!p->cmdline[i])) p->cmdline[i] = ' ';
635
636
if(unlikely(debug))
639
- fprintf(stderr, "Read file '%s' contents: %s\n", filename, p->cmdline);
637
+ fprintf(stderr, "Read file '%s' contents: %s\n", p->cmdline_filename, p->cmdline);
638
+
639
+ return 0;
640
641
+cleanup:
642
+ // copy the command to the command line
643
+ strncpyz(p->cmdline, p->comm, MAX_CMDLINE);
644
return 0;
645
}
646
647
int read_proc_pid_ownership(struct pid_stat *p) {
645
- char filename[FILENAME_MAX + 1];
646
-
647
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d", host_prefix, p->pid);
648
+ if(unlikely(!p->stat_filename)) {
649
+ error("pid %d does not have a stat_filename", p->pid);
650
+ return 1;
651
+ }
652
653
// ----------------------------------------
654
// read uid and gid
655
656
struct stat st;
653
- if(stat(filename, &st) != 0)
657
+ if(stat(p->stat_filename, &st) != 0) {
658
+ error("Cannot stat file '%s'", p->stat_filename);
659
return 1;
660
+ }
661
662
p->uid = st.st_uid;
663
p->gid = st.st_gid;
@@ -662,26 +668,26 @@ int read_proc_pid_ownership(struct pid_stat *p) {
668
int read_proc_pid_stat(struct pid_stat *p) {
669
static procfile *ff = NULL;
670
665
- char filename[FILENAME_MAX + 1];
666
-
667
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/stat", host_prefix, p->pid);
668
-
669
- // ----------------------------------------
671
+ if(unlikely(!p->stat_filename)) {
672
+ char filename[FILENAME_MAX + 1];
673
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/stat", host_prefix, p->pid);
674
+ if(!(p->stat_filename = strdup(filename)))
675
+ fatal("Cannot allocate memory for filename '%s'", filename);
676
+ }
677
678
int set_quotes = (!ff)?1:0;
679
673
- ff = procfile_reopen(ff, filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
674
- if(!ff) return 1;
680
+ ff = procfile_reopen(ff, p->stat_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
681
+ if(unlikely(!ff)) goto cleanup;
682
683
// if(set_quotes) procfile_set_quotes(ff, "()");
684
if(set_quotes) procfile_set_open_close(ff, "(", ")");
685
686
ff = procfile_readall(ff);
680
- if(!ff) {
681
- // procfile_close(ff);
682
- return 1;
683
- }
687
+ if(unlikely(!ff)) goto cleanup;
688
689
+ p->last_stat_collected_usec = p->stat_collected_usec;
690
+ p->stat_collected_usec = timems();
691
file_counter++;
692
693
// parse the process name
@@ -697,14 +703,41 @@ int read_proc_pid_stat(struct pid_stat *p) {
703
// p->tty_nr = atol(procfile_lineword(ff, 0, 6+i));
704
// p->tpgid = atol(procfile_lineword(ff, 0, 7+i));
705
// p->flags = strtoull(procfile_lineword(ff, 0, 8+i), NULL, 10);
700
- p->minflt = strtoull(procfile_lineword(ff, 0, 9+i), NULL, 10);
701
- p->cminflt = strtoull(procfile_lineword(ff, 0, 10+i), NULL, 10);
702
- p->majflt = strtoull(procfile_lineword(ff, 0, 11+i), NULL, 10);
703
- p->cmajflt = strtoull(procfile_lineword(ff, 0, 12+i), NULL, 10);
704
- p->utime = strtoull(procfile_lineword(ff, 0, 13+i), NULL, 10);
705
- p->stime = strtoull(procfile_lineword(ff, 0, 14+i), NULL, 10);
706
- p->cutime = strtoull(procfile_lineword(ff, 0, 15+i), NULL, 10);
707
- p->cstime = strtoull(procfile_lineword(ff, 0, 16+i), NULL, 10);
706
+
707
+ unsigned long long last;
708
+
709
+ last = p->minflt_raw;
710
+ p->minflt_raw = strtoull(procfile_lineword(ff, 0, 9+i), NULL, 10);
711
+ p->minflt = (p->minflt_raw - last) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
712
+
713
+ last = p->cminflt_raw;
714
+ p->cminflt_raw = strtoull(procfile_lineword(ff, 0, 10+i), NULL, 10);
715
+ p->cminflt = (p->cminflt_raw - last) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
716
+
717
+ last = p->majflt_raw;
718
+ p->majflt_raw = strtoull(procfile_lineword(ff, 0, 11+i), NULL, 10);
719
+ p->majflt = (p->majflt_raw - last) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
720
+
721
+ last = p->cmajflt_raw;
722
+ p->cmajflt_raw = strtoull(procfile_lineword(ff, 0, 12+i), NULL, 10);
723
+ p->cmajflt = (p->cmajflt_raw - last) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
724
+
725
+ last = p->utime_raw;
726
+ p->utime_raw = strtoull(procfile_lineword(ff, 0, 13+i), NULL, 10);
727
+ p->utime = (p->utime_raw - last) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
728
+
729
+ last = p->stime_raw;
730
+ p->stime_raw = strtoull(procfile_lineword(ff, 0, 14+i), NULL, 10);
731
+ p->stime = (p->stime_raw - last) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
732
+
733
+ last = p->cutime_raw;
734
+ p->cutime_raw = strtoull(procfile_lineword(ff, 0, 15+i), NULL, 10);
735
+ p->cutime = (p->cutime_raw - last) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
736
+
737
+ last = p->cstime_raw;
738
+ p->cstime_raw = strtoull(procfile_lineword(ff, 0, 16+i), NULL, 10);
739
+ p->cstime = (p->cstime_raw - last) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
740
+
741
// p->priority = strtoull(procfile_lineword(ff, 0, 17+i), NULL, 10);
742
// p->nice = strtoull(procfile_lineword(ff, 0, 18+i), NULL, 10);
743
p->num_threads = (int32_t) atol(procfile_lineword(ff, 0, 19 + i));
@@ -734,27 +767,50 @@ int read_proc_pid_stat(struct pid_stat *p) {
767
// p->cguest_time = strtoull(procfile_lineword(ff, 0, 43), NULL, 10);
768
769
if(unlikely(debug || (p->target && p->target->debug)))
737
- fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' VALUES: utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, threads=%d\n", host_prefix, p->pid, p->comm, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
770
+ fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' on target '%s' (dt=%llu) VALUES: utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, threads=%d\n", host_prefix, p->pid, p->comm, (p->target)?p->target->name:"UNSET", p->stat_collected_usec - p->last_stat_collected_usec, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
771
+
772
+ if(unlikely(global_iterations_counter == 1)) {
773
+ p->minflt = 0;
774
+ p->cminflt = 0;
775
+ p->majflt = 0;
776
+ p->cmajflt = 0;
777
+ p->utime = 0;
778
+ p->stime = 0;
779
+ p->cutime = 0;
780
+ p->cstime = 0;
781
+ }
782
739
- // procfile_close(ff);
783
return 0;
784
+
785
+cleanup:
786
+ p->minflt = 0;
787
+ p->cminflt = 0;
788
+ p->majflt = 0;
789
+ p->cmajflt = 0;
790
+ p->utime = 0;
791
+ p->stime = 0;
792
+ p->cutime = 0;
793
+ p->cstime = 0;
794
+ p->num_threads = 0;
795
+ p->rss = 0;
796
+ return 1;
797
}
798
799
int read_proc_pid_statm(struct pid_stat *p) {
800
static procfile *ff = NULL;
801
746
- char filename[FILENAME_MAX + 1];
747
-
748
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/statm", host_prefix, p->pid);
802
+ if(unlikely(!p->statm_filename)) {
803
+ char filename[FILENAME_MAX + 1];
804
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/statm", host_prefix, p->pid);
805
+ if(!(p->statm_filename = strdup(filename)))
806
+ fatal("Cannot allocate memory for filename '%s'", filename);
807
+ }
808
750
- ff = procfile_reopen(ff, filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
751
- if(!ff) return 1;
809
+ ff = procfile_reopen(ff, p->statm_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
810
+ if(unlikely(!ff)) goto cleanup;
811
812
ff = procfile_readall(ff);
754
- if(!ff) {
755
- // procfile_close(ff);
756
- return 1;
757
- }
813
+ if(unlikely(!ff)) goto cleanup;
814
815
file_counter++;
816
@@ -766,38 +822,92 @@ int read_proc_pid_statm(struct pid_stat *p) {
822
p->statm_data = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
823
p->statm_dirty = strtoull(procfile_lineword(ff, 0, 6), NULL, 10);
824
769
- // procfile_close(ff);
825
return 0;
826
+
827
+cleanup:
828
+ p->statm_size = 0;
829
+ p->statm_resident = 0;
830
+ p->statm_share = 0;
831
+ p->statm_text = 0;
832
+ p->statm_lib = 0;
833
+ p->statm_data = 0;
834
+ p->statm_dirty = 0;
835
+ return 1;
836
}
837
838
int read_proc_pid_io(struct pid_stat *p) {
839
static procfile *ff = NULL;
840
776
- char filename[FILENAME_MAX + 1];
777
-
778
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/io", host_prefix, p->pid);
841
+ if(unlikely(!p->io_filename)) {
842
+ char filename[FILENAME_MAX + 1];
843
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/io", host_prefix, p->pid);
844
+ if(!(p->io_filename = strdup(filename)))
845
+ fatal("Cannot allocate memory for filename '%s'", filename);
846
+ }
847
780
- ff = procfile_reopen(ff, filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
781
- if(!ff) return 1;
848
+ // open the file
849
+ ff = procfile_reopen(ff, p->io_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
850
+ if(unlikely(!ff)) goto cleanup;
851
852
ff = procfile_readall(ff);
784
- if(!ff) {
785
- // procfile_close(ff);
786
- return 1;
787
- }
853
+ if(unlikely(!ff)) goto cleanup;
854
855
file_counter++;
856
791
- p->io_logical_bytes_read = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
792
- p->io_logical_bytes_written = strtoull(procfile_lineword(ff, 1, 1), NULL, 10);
793
- p->io_read_calls = strtoull(procfile_lineword(ff, 2, 1), NULL, 10);
794
- p->io_write_calls = strtoull(procfile_lineword(ff, 3, 1), NULL, 10);
795
- p->io_storage_bytes_read = strtoull(procfile_lineword(ff, 4, 1), NULL, 10);
796
- p->io_storage_bytes_written = strtoull(procfile_lineword(ff, 5, 1), NULL, 10);
797
- p->io_cancelled_write_bytes = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
857
+ p->last_io_collected_usec = p->io_collected_usec;
858
+ p->io_collected_usec = timems();
859
+
860
+ unsigned long long last;
861
+
862
+ last = p->io_logical_bytes_read_raw;
863
+ p->io_logical_bytes_read_raw = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
864
+ p->io_logical_bytes_read = (p->io_logical_bytes_read_raw - last) * (update_every * 1000000 * 100) / (p->io_collected_usec - p->last_io_collected_usec);
865
+
866
+ last = p->io_logical_bytes_written_raw;
867
+ p->io_logical_bytes_written_raw = strtoull(procfile_lineword(ff, 1, 1), NULL, 10);
868
+ p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (update_every * 1000000 * 100) / (p->io_collected_usec - p->last_io_collected_usec);
869
+
870
+ last = p->io_read_calls_raw;
871
+ p->io_read_calls_raw = strtoull(procfile_lineword(ff, 2, 1), NULL, 10);
872
+ p->io_read_calls = (p->io_read_calls_raw - last) * (update_every * 1000000 * 100) / (p->io_collected_usec - p->last_io_collected_usec);
873
+
874
+ last = p->io_write_calls_raw;
875
+ p->io_write_calls_raw = strtoull(procfile_lineword(ff, 3, 1), NULL, 10);
876
+ p->io_write_calls = (p->io_write_calls_raw - last) * (update_every * 1000000 * 100) / (p->io_collected_usec - p->last_io_collected_usec);
877
+
878
+ last = p->io_storage_bytes_read_raw;
879
+ p->io_storage_bytes_read_raw = strtoull(procfile_lineword(ff, 4, 1), NULL, 10);
880
+ p->io_storage_bytes_read = (p->io_storage_bytes_read_raw - last) * (update_every * 1000000 * 100) / (p->io_collected_usec - p->last_io_collected_usec);
881
+
882
+ last = p->io_storage_bytes_written_raw;
883
+ p->io_storage_bytes_written_raw = strtoull(procfile_lineword(ff, 5, 1), NULL, 10);
884
+ p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (update_every * 1000000 * 100) / (p->io_collected_usec - p->last_io_collected_usec);
885
+
886
+ last = p->io_cancelled_write_bytes_raw;
887
+ p->io_cancelled_write_bytes_raw = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
888
+ p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (update_every * 1000000 * 100) / (p->io_collected_usec - p->last_io_collected_usec);
889
+
890
+ if(unlikely(global_iterations_counter == 1)) {
891
+ p->io_logical_bytes_read = 0;
892
+ p->io_logical_bytes_written = 0;
893
+ p->io_read_calls = 0;
894
+ p->io_write_calls = 0;
895
+ p->io_storage_bytes_read = 0;
896
+ p->io_storage_bytes_written = 0;
897
+ p->io_cancelled_write_bytes = 0;
898
+ }
899
799
- // procfile_close(ff);
900
return 0;
901
+
902
+cleanup:
903
+ p->io_logical_bytes_read = 0;
904
+ p->io_logical_bytes_written = 0;
905
+ p->io_read_calls = 0;
906
+ p->io_write_calls = 0;
907
+ p->io_storage_bytes_read = 0;
908
+ p->io_storage_bytes_written = 0;
909
+ p->io_cancelled_write_bytes = 0;
910
+ return 1;
911
}
912
913
@@ -1120,6 +1230,173 @@ int read_pid_file_descriptors(struct pid_stat *p) {
1230
1231
// ----------------------------------------------------------------------------
1232
1233
+#ifdef NETDATA_INTERNAL_CHECKS
1234
+void find_lost_child_debug(struct pid_stat *pe, struct pid_stat *ppe, unsigned long long lost, int type) {
1235
+ int found = 0;
1236
+ struct pid_stat *p = NULL, *pp = pe->parent;
1237
+
1238
+ log_date(stderr);
1239
+ fprintf(stderr, "Searching for candidate of lost resources of process %d (%s, %s) which is aggregated on %d (%s, %s)\n", pe->pid, pe->comm, pe->updated?"running":"exited", ppe->pid, ppe->comm, ppe->updated?"running":"exited");
1240
+ while(pp) {
1241
+ fprintf(stderr, " >> parent %d (%s, %s)\n", pp->pid, pp->comm, pp->updated?"running":"exited");
1242
+ pp = pp->parent;
1243
+ }
1244
+
1245
+ for(p = root_of_pids; p ; p = p->next) {
1246
+ if(p == pe) continue;
1247
+
1248
+ switch(type) {
1249
+ case 1:
1250
+ if(p->cminflt > lost) {
1251
+ fprintf(stderr, " > process %d (%s) could use the lost exited child minflt %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1252
+ found++;
1253
+ }
1254
+ break;
1255
+
1256
+ case 2:
1257
+ if(p->cmajflt > lost) {
1258
+ fprintf(stderr, " > process %d (%s) could use the lost exited child majflt %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1259
+ found++;
1260
+ }
1261
+ break;
1262
+
1263
+ case 3:
1264
+ if(p->cutime > lost) {
1265
+ fprintf(stderr, " > process %d (%s) could use the lost exited child utime %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1266
+ found++;
1267
+ }
1268
+ break;
1269
+
1270
+ case 4:
1271
+ if(p->cstime > lost) {
1272
+ fprintf(stderr, " > process %d (%s) could use the lost exited child stime %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1273
+ found++;
1274
+ }
1275
+ break;
1276
+ }
1277
+ }
1278
+
1279
+ if(!found) {
1280
+ switch(type) {
1281
+ case 1:
1282
+ fprintf(stderr, " > cannot find any process to use the lost exited child minflt %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1283
+ break;
1284
+
1285
+ case 2:
1286
+ fprintf(stderr, " > cannot find any process to use the lost exited child majflt %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1287
+ break;
1288
+
1289
+ case 3:
1290
+ fprintf(stderr, " > cannot find any process to use the lost exited child utime %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1291
+ break;
1292
+
1293
+ case 4:
1294
+ fprintf(stderr, " > cannot find any process to use the lost exited child stime %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1295
+ break;
1296
+ }
1297
+ }
1298
+}
1299
+#endif /* NETDATA_INTERNAL_CHECKS */
1300
+
1301
+void remove_exited_child_from_parent(unsigned long long *field, unsigned long long *pfield, unsigned long long *ifield, struct pid_stat *pe, struct pid_stat *ppe, int type) {
1302
+ if(pfield) {
1303
+ if(*field > *pfield) {
1304
+ *field -= *pfield;
1305
+ *pfield = 0;
1306
+ }
1307
+ else {
1308
+ *pfield -= *field;
1309
+ *field = 0;
1310
+ }
1311
+ }
1312
+
1313
+ if(*field) {
1314
+ if(ifield && ifield != pfield) {
1315
+ if(*field > *ifield) {
1316
+ *field -= *ifield;
1317
+ *ifield = 0;
1318
+ }
1319
+ else {
1320
+ *ifield -= *field;
1321
+ *field = 0;
1322
+ }
1323
+ }
1324
+ }
1325
+
1326
+ if(*field) {
1327
+#ifdef NETDATA_INTERNAL_CHECKS
1328
+ find_lost_child_debug(pe, ppe, *field, type);
1329
+#endif
1330
+ while(pe && !pe->updated) {
1331
+ pe->keep = 1;
1332
+ pe = pe->parent;
1333
+ }
1334
+ }
1335
+}
1336
+
1337
+void process_exited_processes() {
1338
+ struct pid_stat *init = all_pids[1];
1339
+ struct pid_stat *p;
1340
+
1341
+ for(p = root_of_pids; p ; p = p->next) {
1342
+ if(p->updated || !p->stat_collected_usec) continue;
1343
+
1344
+ struct pid_stat *pp = p->parent;
1345
+
1346
+ // find the first parent that is running
1347
+ while(pp && !pp->updated)
1348
+ pp = pp->parent;
1349
+
1350
+ unsigned long long rate;
1351
+
1352
+ rate = (p->utime_raw + p->cutime_raw) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
1353
+ remove_exited_child_from_parent(&rate, (pp)?&pp->cutime:NULL, (init)?&init->cutime:NULL, p, pp, 3);
1354
+ p->cutime_raw = 0;
1355
+ p->utime_raw = rate * (p->stat_collected_usec - p->last_stat_collected_usec) / (update_every * 1000000 * 100);
1356
+
1357
+ rate = (p->stime_raw + p->cstime_raw) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
1358
+ remove_exited_child_from_parent(&rate, (pp)?&pp->cstime:NULL, (init)?&init->cstime:NULL, p, pp, 4);
1359
+ p->cstime_raw = 0;
1360
+ p->stime_raw = rate * (p->stat_collected_usec - p->last_stat_collected_usec) / (update_every * 1000000 * 100);
1361
+
1362
+ rate = (p->minflt_raw + p->cminflt_raw) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
1363
+ remove_exited_child_from_parent(&rate, (pp)?&pp->cminflt:NULL, (init)?&init->cminflt:NULL, p, pp, 1);
1364
+ p->cminflt_raw = 0;
1365
+ p->minflt_raw = rate * (p->stat_collected_usec - p->last_stat_collected_usec) / (update_every * 1000000 * 100);
1366
+
1367
+ rate = (p->majflt_raw + p->cmajflt_raw) * (update_every * 1000000 * 100) / (p->stat_collected_usec - p->last_stat_collected_usec);
1368
+ remove_exited_child_from_parent(&rate, (pp)?&pp->cmajflt:NULL, (init)?&init->cmajflt:NULL, p, pp, 2);
1369
+ p->cmajflt_raw = 0;
1370
+ p->majflt_raw = rate * (p->stat_collected_usec - p->last_stat_collected_usec) / (update_every * 1000000 * 100);
1371
+ }
1372
+}
1373
+
1374
+void link_all_processes_to_their_parents(void) {
1375
+ struct pid_stat *p = NULL;
1376
+
1377
+ // link all children to their parents
1378
+ // and update children count on parents
1379
+ for(p = root_of_pids; p ; p = p->next) {
1380
+ // for each process found running
1381
+
1382
+ if(likely(p->ppid > 0 && all_pids[p->ppid])) {
1383
+ // valid parent processes
1384
+
1385
+ struct pid_stat *pp;
1386
+
1387
+ p->parent = pp = all_pids[p->ppid];
1388
+ p->parent->children_count++;
1389
+
1390
+ if(unlikely(debug || (p->target && p->target->debug)))
1391
+ fprintf(stderr, "apps.plugin: \tchild %d (%s, %s) on target '%s' has parent %d (%s, %s). Parent: utime=%llu, stime=%llu, minflt=%llu, majflt=%llu, cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, p->updated?"running":"exited", (p->target)?p->target->name:"UNSET", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cminflt, pp->cmajflt);
1392
+ }
1393
+ else if(unlikely(p->ppid != 0))
1394
+ error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
1395
+ }
1396
+}
1397
+
1398
+// ----------------------------------------------------------------------------
1399
+
1400
// 1. read all files in /proc
1401
// 2. for each numeric directory:
1402
// i. read /proc/pid/stat
@@ -1136,173 +1413,186 @@ int read_pid_file_descriptors(struct pid_stat *p) {
1413
// to avoid filling up all disk space
1414
// if debug is enabled, all errors are printed
1415
1139
-int collect_data_for_all_processes_from_proc(void)
1140
-{
1141
- char dirname[FILENAME_MAX + 1];
1416
+static int compar_pid(const void *pid1, const void *pid2) {
1417
1143
- snprintfz(dirname, FILENAME_MAX, "%s/proc", host_prefix);
1144
- DIR *dir = opendir(dirname);
1145
- if(!dir) return 0;
1418
+ struct pid_stat *p1 = all_pids[*((pid_t *)pid1)];
1419
+ struct pid_stat *p2 = all_pids[*((pid_t *)pid2)];
1420
1147
- struct dirent *file = NULL;
1148
- struct pid_stat *p = NULL;
1149
-
1150
- // mark them all as un-updated
1151
- all_pids_count = 0;
1152
- for(p = root_of_pids; p ; p = p->next) {
1153
- all_pids_count++;
1421
+ if(p1->sortlist > p2->sortlist)
1422
+ return -1;
1423
+ else
1424
+ return 1;
1425
+}
1426
1155
- p->parent = NULL;
1427
+void collect_data_for_pid(pid_t pid) {
1428
+ if(unlikely(pid <= 0 || pid > pid_max)) {
1429
+ error("Invalid pid %d read (expected 1 to %d). Ignoring process.", pid, pid_max);
1430
+ return;
1431
+ }
1432
1157
- p->updated = 0;
1158
- p->children_count = 0;
1159
- p->merged = 0;
1160
- p->new_entry = 0;
1433
+ struct pid_stat *p = get_pid_entry(pid);
1434
+ if(unlikely(!p || p->read)) return;
1435
1162
- p->last_minflt = p->minflt;
1163
- p->last_majflt = p->majflt;
1164
- p->last_utime = p->utime;
1165
- p->last_stime = p->stime;
1436
+ // fprintf(stderr, "Reading process %d (%s), sortlist %d\n", p->pid, p->comm, p->sortlist);
1437
1167
- p->last_cminflt = p->cminflt;
1168
- p->last_cmajflt = p->cmajflt;
1169
- p->last_cutime = p->cutime;
1170
- p->last_cstime = p->cstime;
1438
+ p->read = 1;
1439
+ p->sortlist = 0;
1440
1172
- p->last_fix_cminflt = p->fix_cminflt;
1173
- p->last_fix_cmajflt = p->fix_cmajflt;
1174
- p->last_fix_cutime = p->fix_cutime;
1175
- p->last_fix_cstime = p->fix_cstime;
1441
+ // --------------------------------------------------------------------
1442
+ // /proc/<pid>/stat
1443
1177
- p->last_io_logical_bytes_read = p->io_logical_bytes_read;
1178
- p->last_io_logical_bytes_written = p->io_logical_bytes_written;
1179
- p->last_io_read_calls = p->io_read_calls;
1180
- p->last_io_write_calls = p->io_write_calls;
1181
- p->last_io_storage_bytes_read = p->io_storage_bytes_read;
1182
- p->last_io_storage_bytes_written = p->io_storage_bytes_written;
1183
- p->last_io_cancelled_write_bytes = p->io_cancelled_write_bytes;
1444
+ if(unlikely(read_proc_pid_stat(p))) {
1445
+ error("Cannot process %s/proc/%d/stat", host_prefix, pid);
1446
+ // there is no reason to proceed if we cannot get its status
1447
+ return;
1448
}
1449
1186
- while((file = readdir(dir))) {
1187
- char *endptr = file->d_name;
1188
- pid_t pid = (pid_t) strtoul(file->d_name, &endptr, 10);
1450
+ read_proc_pid_ownership(p);
1451
1190
- // make sure we read a valid number
1191
- if(unlikely(endptr == file->d_name || *endptr != '\0'))
1192
- continue;
1452
+ // check its parent pid
1453
+ if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
1454
+ error("Pid %d states invalid parent pid %d. Using 0.", pid, p->ppid);
1455
+ p->ppid = 0;
1456
+ }
1457
1194
- if(unlikely(pid <= 0 || pid > pid_max)) {
1195
- error("Invalid pid %d read (expected 1 to %d). Ignoring process.", pid, pid_max);
1196
- continue;
1197
- }
1458
+ // --------------------------------------------------------------------
1459
+ // /proc/<pid>/io
1460
1199
- p = get_pid_entry(pid);
1200
- if(unlikely(!p)) continue;
1461
+ if(unlikely(read_proc_pid_io(p)))
1462
+ error("Cannot process %s/proc/%d/io", host_prefix, pid);
1463
1464
+ // --------------------------------------------------------------------
1465
+ // /proc/<pid>/statm
1466
1203
- // --------------------------------------------------------------------
1204
- // /proc/<pid>/stat
1467
+ if(unlikely(read_proc_pid_statm(p))) {
1468
+ error("Cannot process %s/proc/%d/statm", host_prefix, pid);
1469
+ // there is no reason to proceed if we cannot get its memory status
1470
+ return;
1471
+ }
1472
1206
- if(unlikely(read_proc_pid_stat(p))) {
1207
- error("Cannot process %s/proc/%d/stat", host_prefix, pid);
1208
- // there is no reason to proceed if we cannot get its status
1209
- continue;
1210
- }
1473
+ // --------------------------------------------------------------------
1474
+ // link it
1475
1212
- // check its parent pid
1213
- if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
1214
- error("Pid %d states invalid parent pid %d. Using 0.", pid, p->ppid);
1215
- p->ppid = 0;
1476
+ // check if it is target
1477
+ // we do this only once, the first time this pid is loaded
1478
+ if(unlikely(p->new_entry)) {
1479
+ // /proc/<pid>/cmdline
1480
+ if(likely(proc_pid_cmdline_is_needed)) {
1481
+ if(unlikely(read_proc_pid_cmdline(p)))
1482
+ error("Cannot process %s/proc/%d/cmdline", host_prefix, pid);
1483
}
1484
1218
- // --------------------------------------------------------------------
1219
- // /proc/<pid>/statm
1485
+ if(unlikely(debug))
1486
+ fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", pid, p->comm);
1487
+
1488
+ uint32_t hash = simple_hash(p->comm);
1489
+ size_t pclen = strlen(p->comm);
1490
+
1491
+ struct target *w;
1492
+ for(w = apps_groups_root_target; w ; w = w->next) {
1493
+ // if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: \t\tcomparing '%s' with '%s'\n", w->compare, p->comm);
1494
+
1495
+ // find it - 4 cases:
1496
+ // 1. the target is not a pattern
1497
+ // 2. the target has the prefix
1498
+ // 3. the target has the suffix
1499
+ // 4. the target is something inside cmdline
1500
+ if( (!w->starts_with && !w->ends_with && w->comparehash == hash && !strcmp(w->compare, p->comm))
1501
+ || (w->starts_with && !w->ends_with && !strncmp(w->compare, p->comm, w->comparelen))
1502
+ || (!w->starts_with && w->ends_with && pclen >= w->comparelen && !strcmp(w->compare, &p->comm[pclen - w->comparelen]))
1503
+ || (proc_pid_cmdline_is_needed && w->starts_with && w->ends_with && strstr(p->cmdline, w->compare))
1504
+ ) {
1505
+ if(w->target) p->target = w->target;
1506
+ else p->target = w;
1507
1221
- if(unlikely(read_proc_pid_statm(p))) {
1222
- error("Cannot process %s/proc/%d/statm", host_prefix, pid);
1223
- // there is no reason to proceed if we cannot get its memory status
1224
- continue;
1508
+ if(debug || (p->target && p->target->debug))
1509
+ fprintf(stderr, "apps.plugin: \t\t%s linked to target %s\n", p->comm, p->target->name);
1510
+
1511
+ break;
1512
+ }
1513
}
1514
+ }
1515
1516
+ // --------------------------------------------------------------------
1517
+ // /proc/<pid>/fd
1518
1228
- // --------------------------------------------------------------------
1229
- // /proc/<pid>/io
1519
+ if(unlikely(read_pid_file_descriptors(p))) {
1520
+ error("Cannot process entries in %s/proc/%d/fd", host_prefix, pid);
1521
+ }
1522
1231
- if(unlikely(read_proc_pid_io(p))) {
1232
- error("Cannot process %s/proc/%d/io", host_prefix, pid);
1523
+ // --------------------------------------------------------------------
1524
+ // done!
1525
1234
- // on systems without /proc/X/io
1235
- // allow proceeding without I/O information
1236
- // continue;
1237
- }
1526
+ if(p->ppid && all_pids[p->ppid] && !all_pids[p->ppid]->read)
1527
+ error("read process %d (%s), but its parent %d (%s) is not read\n", p->pid, p->comm, all_pids[p->ppid]->pid, all_pids[p->ppid]->comm);
1528
1239
- // --------------------------------------------------------------------
1240
- // <pid> ownership
1529
+ // mark it as updated
1530
+ p->updated = 1;
1531
+ p->keep = 0;
1532
+ p->keeploops = 0;
1533
+}
1534
1242
- if(unlikely(read_proc_pid_ownership(p))) {
1243
- error("Cannot stat %s/proc/%d", host_prefix, pid);
1535
+int collect_data_for_all_processes_from_proc(void) {
1536
+ struct pid_stat *p = NULL;
1537
+
1538
+ if(all_pids_count) {
1539
+ // read parents before childs
1540
+ // this is needed to prevent a situation where
1541
+ // a child is found running, but until we read
1542
+ // its parent, it has exited and its parent
1543
+ // has accumulated its resources
1544
+
1545
+ long slc = 0;
1546
+ for(p = root_of_pids; p ; p = p->next) {
1547
+ p->read = 0;
1548
+ p->updated = 0;
1549
+ p->new_entry = 0;
1550
+ p->merged = 0;
1551
+ p->children_count = 0;
1552
+ p->parent = NULL;
1553
+
1554
+#ifdef NETDATA_INTERNAL_CHECKS
1555
+ if(unlikely(slc >= all_pids_count))
1556
+ error("Internal error: I was thinking I had %ld processes in my arrays, but it seems there are more.", all_pids_count);
1557
+#endif
1558
+ all_pids_sortlist[slc++] = p->pid;
1559
}
1560
1246
- // --------------------------------------------------------------------
1247
- // link it
1248
-
1249
- // check if it is target
1250
- // we do this only once, the first time this pid is loaded
1251
- if(unlikely(p->new_entry)) {
1252
- // /proc/<pid>/cmdline
1253
- if(proc_pid_cmdline_is_needed) {
1254
- if(unlikely(read_proc_pid_cmdline(p))) {
1255
- error("Cannot process %s/proc/%d/cmdline", host_prefix, pid);
1256
- }
1257
- }
1561
+ qsort((void *)all_pids_sortlist, all_pids_count, sizeof(pid_t), compar_pid);
1562
1259
- if(unlikely(debug))
1260
- fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", pid, p->comm);
1261
-
1262
- uint32_t hash = simple_hash(p->comm);
1263
- size_t pclen = strlen(p->comm);
1264
-
1265
- struct target *w;
1266
- for(w = apps_groups_root_target; w ; w = w->next) {
1267
- // if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: \t\tcomparing '%s' with '%s'\n", w->compare, p->comm);
1268
-
1269
- // find it - 4 cases:
1270
- // 1. the target is not a pattern
1271
- // 2. the target has the prefix
1272
- // 3. the target has the suffix
1273
- // 4. the target is something inside cmdline
1274
- if( (!w->starts_with && !w->ends_with && w->comparehash == hash && !strcmp(w->compare, p->comm))
1275
- || (w->starts_with && !w->ends_with && !strncmp(w->compare, p->comm, w->comparelen))
1276
- || (!w->starts_with && w->ends_with && pclen >= w->comparelen && !strcmp(w->compare, &p->comm[pclen - w->comparelen]))
1277
- || (proc_pid_cmdline_is_needed && w->starts_with && w->ends_with && strstr(p->cmdline, w->compare))
1278
- ) {
1279
- if(w->target) p->target = w->target;
1280
- else p->target = w;
1563
+ for(slc = 0; slc < all_pids_count; slc++)
1564
+ collect_data_for_pid(all_pids_sortlist[slc]);
1565
+ }
1566
1282
- if(debug || (p->target && p->target->debug))
1283
- fprintf(stderr, "apps.plugin: \t\t%s linked to target %s\n", p->comm, p->target->name);
1567
+ char dirname[FILENAME_MAX + 1];
1568
1285
- break;
1286
- }
1287
- }
1288
- }
1569
+ snprintfz(dirname, FILENAME_MAX, "%s/proc", host_prefix);
1570
+ DIR *dir = opendir(dirname);
1571
+ if(!dir) return 0;
1572
1290
- // --------------------------------------------------------------------
1291
- // /proc/<pid>/fd
1573
+ struct dirent *file = NULL;
1574
1293
- if(unlikely(read_pid_file_descriptors(p))) {
1294
- error("Cannot process entries in %s/proc/%d/fd", host_prefix, pid);
1295
- }
1575
+ while((file = readdir(dir))) {
1576
+ char *endptr = file->d_name;
1577
+ pid_t pid = (pid_t) strtoul(file->d_name, &endptr, 10);
1578
1297
- // --------------------------------------------------------------------
1298
- // done!
1579
+ // make sure we read a valid number
1580
+ if(unlikely(endptr == file->d_name || *endptr != '\0'))
1581
+ continue;
1582
1300
- // mark it as updated
1301
- p->updated = 1;
1583
+ collect_data_for_pid(pid);
1584
}
1303
-
1585
closedir(dir);
1586
1587
+ // normally this is done
1588
+ // however we may have processes exited while we collected values
1589
+ // so let's find the exited ones
1590
+ // we do this by collecting the ownership of process
1591
+ // if we manage to get the ownership, the process still runs
1592
+
1593
+ link_all_processes_to_their_parents();
1594
+ process_exited_processes();
1595
+
1596
return 1;
1597
}
1598
@@ -1322,128 +1612,19 @@ int collect_data_for_all_processes_from_proc(void)
1612
// 9. find the unique file count for each target
1613
// check: update_apps_groups_statistics()
1614
1325
-void link_all_processes_to_their_parents(void) {
1326
- struct pid_stat *init = all_pids[1];
1327
- struct pid_stat *p = NULL;
1328
-
1329
- // link all children to their parents
1330
- // and update children count on parents
1331
- for(p = root_of_pids; p ; p = p->next) {
1332
- // for each process found running
1333
-
1334
- if(likely(p->new_entry && p->updated)) {
1335
- // the first time we see an entry
1336
- // we remove the exited children figures
1337
- // to avoid spikes
1338
- p->fix_cminflt = p->cminflt;
1339
- p->fix_cmajflt = p->cmajflt;
1340
- p->fix_cutime = p->cutime;
1341
- p->fix_cstime = p->cstime;
1342
- }
1343
-
1344
- if(likely(p->ppid > 0 && all_pids[p->ppid])) {
1345
- // valid parent processes
1346
-
1347
- struct pid_stat *pp;
1348
-
1349
- p->parent = pp = all_pids[p->ppid];
1350
- p->parent->children_count++;
1351
-
1352
- if(unlikely(debug || (p->target && p->target->debug)))
1353
- fprintf(stderr, "apps.plugin: \tchild %d (%s, %s) has parent %d (%s, %s). Parent: utime=%llu, stime=%llu, minflt=%llu, majflt=%llu, cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu, fix_cutime=%llu, fix_cstime=%llu, fix_cminflt=%llu, fix_cmajflt=%llu\n", p->pid, p->comm, p->updated?"running":"exited", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cminflt, pp->cmajflt, pp->fix_cutime, pp->fix_cstime, pp->fix_cminflt, pp->fix_cmajflt);
1354
-
1355
- if(unlikely(!p->updated)) {
1356
- // this process has exit
1357
-
1358
- // find the first parent that has been updated
1359
- while(pp && !pp->updated) {
1360
- // we may have to forward link it to its parent
1361
- if(unlikely(!pp->parent && pp->ppid > 0 && all_pids[pp->ppid]))
1362
- pp->parent = all_pids[pp->ppid];
1363
-
1364
- // check again for parent
1365
- pp = pp->parent;
1366
- }
1367
-
1368
- if(likely(pp)) {
1369
- // this is an exited child with a parent
1370
- // remove the known time from the parent's data
1371
- pp->fix_cminflt += p->last_minflt + p->last_cminflt + p->last_fix_cminflt;
1372
- pp->fix_cmajflt += p->last_majflt + p->last_cmajflt + p->last_fix_cmajflt;
1373
- pp->fix_cutime += p->last_utime + p->last_cutime + p->last_fix_cutime;
1374
- pp->fix_cstime += p->last_stime + p->last_cstime + p->last_fix_cstime;
1375
-
1376
- // The known exited children (the ones we track) may have
1377
- // contributed more than the value accumulated into the process
1378
- // by the kernel.
1379
- // This can happen if the parent process has not waited-for
1380
- // its children (check: man 2 times).
1381
- // In this case, the kernel adds these resources to init (pid 1).
1382
- //
1383
- // The following code, attempts to fix this.
1384
- // Without this code, the charts will have random spikes
1385
- // for example, when an SSH session ends (sshd forks a child
1386
- // to serve the session, but when this session ends, sshd
1387
- // does not wait-for its child, thus all the resources of the
1388
- // ssh session get added to init, resulting in a huge spike on
1389
- // the charts).
1390
-
1391
- if(unlikely(pp->cminflt < pp->fix_cminflt)) {
1392
- if(likely(init && pp != init)) {
1393
- unsigned long long have = pp->fix_cminflt - pp->cminflt;
1394
- unsigned long long max = init->cminflt - init->fix_cminflt;
1395
- if(have > max) have = max;
1396
- init->fix_cminflt += have;
1397
- }
1398
- pp->fix_cminflt = pp->cminflt;
1399
- }
1400
- if(unlikely(pp->cmajflt < pp->fix_cmajflt)) {
1401
- if(likely(init && pp != init)) {
1402
- unsigned long long have = pp->fix_cmajflt - pp->cmajflt;
1403
- unsigned long long max = init->cmajflt - init->fix_cmajflt;
1404
- if(have > max) have = max;
1405
- init->fix_cmajflt += have;
1406
- }
1407
- pp->fix_cmajflt = pp->cmajflt;
1408
- }
1409
- if(unlikely(pp->cutime < pp->fix_cutime)) {
1410
- if(likely(init && pp != init)) {
1411
- unsigned long long have = pp->fix_cutime - pp->cutime;
1412
- unsigned long long max = init->cutime - init->fix_cutime;
1413
- if(have > max) have = max;
1414
- init->fix_cutime += have;
1415
- }
1416
- pp->fix_cutime = pp->cutime;
1417
- }
1418
- if(unlikely(pp->cstime < pp->fix_cstime)) {
1419
- if(likely(init && pp != init)) {
1420
- unsigned long long have = pp->fix_cstime - pp->cstime;
1421
- unsigned long long max = init->cstime - init->fix_cstime;
1422
- if(have > max) have = max;
1423
- init->fix_cstime += have;
1424
- }
1425
- pp->fix_cstime = pp->cstime;
1426
- }
1427
-
1428
- if(unlikely(debug))
1429
- fprintf(stderr, "apps.plugin: \tupdating child metrics of %d (%s, %s) to its parent %d (%s, %s). Parent has now: utime=%llu, stime=%llu, minflt=%llu, majflt=%llu, cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu, fix_cutime=%llu, fix_cstime=%llu, fix_cminflt=%llu, fix_cmajflt=%llu\n", p->pid, p->comm, p->updated?"running":"exited", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cminflt, pp->cmajflt, pp->fix_cutime, pp->fix_cstime, pp->fix_cminflt, pp->fix_cmajflt);
1430
- }
1431
- }
1432
- }
1433
- else if(unlikely(p->ppid != 0))
1434
- error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
1435
- }
1436
-}
1437
-
1438
-
1439
-void cleanup_non_existing_pids(void) {
1615
+void cleanup_exited_pids(void) {
1616
int c;
1617
struct pid_stat *p = NULL;
1618
1619
for(p = root_of_pids; p ;) {
1444
- if(!p->updated) {
1620
+ if(!p->updated && (!p->keep || p->keeploops > 1)) {
1621
// 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);
1622
1623
+#ifdef NETDATA_INTERNAL_CHECKS
1624
+ if(p->keep)
1625
+ fprintf(stderr, " > cannot keep exited process %d (%s) anymore - removing it.\n", p->pid, p->comm);
1626
+#endif
1627
+
1628
for(c = 0 ; c < p->fds_size ; c++) if(p->fds[c] > 0) {
1629
file_descriptor_not_used(p->fds[c]);
1630
p->fds[c] = 0;
@@ -1453,7 +1634,11 @@ void cleanup_non_existing_pids(void) {
1634
p = p->next;
1635
del_pid_entry(r);
1636
}
1456
- else p = p->next;
1637
+ else {
1638
+ if(unlikely(p->keep)) p->keeploops++;
1639
+ p->keep = 0;
1640
+ p = p->next;
1641
+ }
1642
}
1643
}
1644
@@ -1481,13 +1666,14 @@ void apply_apps_groups_targets_inheritance(void) {
1666
}
1667
}
1668
1484
-
1669
// find all the procs with 0 childs and merge them to their parents
1670
// repeat, until nothing more can be done.
1671
+ int sortlist = 1;
1672
found = 1;
1673
while(found) {
1674
if(unlikely(debug)) loops++;
1675
found = 0;
1676
+
1677
for(p = root_of_pids; p ; p = p->next) {
1678
// if this process does not have any children
1679
// and is not already merged
@@ -1517,10 +1703,15 @@ void apply_apps_groups_targets_inheritance(void) {
1703
1704
found++;
1705
}
1706
+
1707
+ // since this process does not have any childs
1708
+ // assign it to the current sortlist
1709
+ if(unlikely(!p->sortlist && !p->children_count))
1710
+ p->sortlist = sortlist++;
1711
}
1712
1713
if(unlikely(debug))
1523
- fprintf(stderr, "apps.plugin: merged %d processes\n", found);
1714
+ fprintf(stderr, "apps.plugin: TARGET INHERITANCE: merged %d processes\n", found);
1715
}
1716
1717
// init goes always to default target
@@ -1532,8 +1723,12 @@ void apply_apps_groups_targets_inheritance(void) {
1723
for(p = root_of_pids; p ; p = p->next) {
1724
// if the process is not merged itself
1725
// then is is a top level process
1535
- if(!p->merged && !p->target)
1726
+ if(unlikely(!p->merged && !p->target))
1727
p->target = apps_groups_default_target;
1728
+
1729
+ // make sure all processes have a sortlist
1730
+ if(unlikely(!p->sortlist))
1731
+ p->sortlist = sortlist++;
1732
}
1733
1734
// give a target to all merged child processes
@@ -1599,6 +1794,8 @@ long zero_all_targets(struct target *root) {
1794
}
1795
1796
void aggregate_pid_on_target(struct target *w, struct pid_stat *p, struct target *o) {
1797
+ (void)o;
1798
+
1799
if(unlikely(!w->fds)) {
1800
w->fds = calloc(sizeof(int), (size_t) all_files_size);
1801
if(unlikely(!w->fds))
@@ -1606,26 +1803,16 @@ void aggregate_pid_on_target(struct target *w, struct pid_stat *p, struct target
1803
}
1804
1805
if(likely(p->updated)) {
1609
- if(unlikely(debug && (p->fix_cutime || p->fix_cstime || p->fix_cminflt || p->fix_cmajflt)))
1610
- fprintf(stderr, "apps.plugin: \tadding child counters of %d (%s) to target %s. Currents: cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu, Fixes: cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, w->name, p->cutime, p->cstime, p->cminflt, p->cmajflt, p->fix_cutime, p->fix_cstime, p->fix_cminflt, p->fix_cmajflt);
1611
-
1612
- w->cutime += p->cutime - p->fix_cutime;
1613
- w->cstime += p->cstime - p->fix_cstime;
1614
- w->cminflt += p->cminflt - p->fix_cminflt;
1615
- w->cmajflt += p->cmajflt - p->fix_cmajflt;
1616
-
1617
- w->utime += p->utime; //+ (p->pid != 1)?(p->cutime - p->fix_cutime):0;
1618
- w->stime += p->stime; //+ (p->pid != 1)?(p->cstime - p->fix_cstime):0;
1619
- w->minflt += p->minflt; //+ (p->pid != 1)?(p->cminflt - p->fix_cminflt):0;
1620
- w->majflt += p->majflt; //+ (p->pid != 1)?(p->cmajflt - p->fix_cmajflt):0;
1806
+ w->cutime += p->cutime;
1807
+ w->cstime += p->cstime;
1808
+ w->cminflt += p->cminflt;
1809
+ w->cmajflt += p->cmajflt;
1810
1622
- //if(p->num_threads < 0)
1623
- // error("Negative threads number for pid '%s' (%d): %d", p->comm, p->pid, p->num_threads);
1811
+ w->utime += p->utime;
1812
+ w->stime += p->stime;
1813
+ w->minflt += p->minflt;
1814
+ w->majflt += p->majflt;
1815
1625
- //if(p->num_threads > 10000)
1626
- // error("Excessive threads number for pid '%s' (%d): %d", p->comm, p->pid, p->num_threads);
1627
-
1628
- w->num_threads += p->num_threads;
1816
w->rss += p->rss;
1817
1818
w->statm_size += p->statm_size;
@@ -1636,15 +1823,16 @@ void aggregate_pid_on_target(struct target *w, struct pid_stat *p, struct target
1823
w->statm_data += p->statm_data;
1824
w->statm_dirty += p->statm_dirty;
1825
1639
- w->io_logical_bytes_read += p->io_logical_bytes_read;
1826
+ w->io_logical_bytes_read += p->io_logical_bytes_read;
1827
w->io_logical_bytes_written += p->io_logical_bytes_written;
1641
- w->io_read_calls += p->io_read_calls;
1642
- w->io_write_calls += p->io_write_calls;
1643
- w->io_storage_bytes_read += p->io_storage_bytes_read;
1828
+ w->io_read_calls += p->io_read_calls;
1829
+ w->io_write_calls += p->io_write_calls;
1830
+ w->io_storage_bytes_read += p->io_storage_bytes_read;
1831
w->io_storage_bytes_written += p->io_storage_bytes_written;
1832
w->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
1833
1834
w->processes++;
1835
+ w->num_threads += p->num_threads;
1836
1837
if(likely(w->fds)) {
1838
int c;
@@ -1660,103 +1848,8 @@ void aggregate_pid_on_target(struct target *w, struct pid_stat *p, struct target
1848
}
1849
1850
if(unlikely(debug || w->debug))
1663
- fprintf(stderr, "apps.plugin: \tAggregating %s pid %d on %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, fix_cutime=%llu, fix_cstime=%llu, fix_cminflt=%llu, fix_cmajflt=%llu\n", p->comm, p->pid, w->name, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->fix_cutime, p->fix_cstime, p->fix_cminflt, p->fix_cmajflt);
1664
-
1665
-/* 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);
1666
- 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);
1667
- 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);
1668
- 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);
1669
- 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);
1670
- 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);
1671
- 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);
1672
- 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);
1673
-*/
1674
-
1675
- if(o) {
1676
- // since the process switched target
1677
- // for all incremental values
1678
- // we have to subtract its OLD values from the new target
1679
- // and add its OLD values to the old target
1680
-
1681
- // IMPORTANT
1682
- // We add/subtract the last/OLD values we added to the target
1683
-
1684
- unsigned long long cutime = p->last_cutime - p->last_fix_cutime;
1685
- unsigned long long cstime = p->last_cstime - p->last_fix_cstime;
1686
- unsigned long long cminflt = p->last_cminflt - p->last_fix_cminflt;
1687
- unsigned long long cmajflt = p->last_cmajflt - p->last_fix_cmajflt;
1688
-
1689
- w->fix_cutime -= cutime;
1690
- w->fix_cstime -= cstime;
1691
- w->fix_cminflt -= cminflt;
1692
- w->fix_cmajflt -= cmajflt;
1693
-
1694
- w->fix_utime -= p->last_utime;
1695
- w->fix_stime -= p->last_stime;
1696
- w->fix_minflt -= p->last_minflt;
1697
- w->fix_majflt -= p->last_majflt;
1698
-
1699
- w->fix_io_logical_bytes_read -= p->last_io_logical_bytes_read;
1700
- w->fix_io_logical_bytes_written -= p->last_io_logical_bytes_written;
1701
- w->fix_io_read_calls -= p->last_io_read_calls;
1702
- w->fix_io_write_calls -= p->last_io_write_calls;
1703
- w->fix_io_storage_bytes_read -= p->last_io_storage_bytes_read;
1704
- w->fix_io_storage_bytes_written -= p->last_io_storage_bytes_written;
1705
- w->fix_io_cancelled_write_bytes -= p->last_io_cancelled_write_bytes;
1706
-
1707
- // ---
1708
-
1709
- o->fix_cutime += cutime;
1710
- o->fix_cstime += cstime;
1711
- o->fix_cminflt += cminflt;
1712
- o->fix_cmajflt += cmajflt;
1713
-
1714
- o->fix_utime += p->last_utime;
1715
- o->fix_stime += p->last_stime;
1716
- o->fix_minflt += p->last_minflt;
1717
- o->fix_majflt += p->last_majflt;
1718
-
1719
- o->fix_io_logical_bytes_read += p->last_io_logical_bytes_read;
1720
- o->fix_io_logical_bytes_written += p->last_io_logical_bytes_written;
1721
- o->fix_io_read_calls += p->last_io_read_calls;
1722
- o->fix_io_write_calls += p->last_io_write_calls;
1723
- o->fix_io_storage_bytes_read += p->last_io_storage_bytes_read;
1724
- o->fix_io_storage_bytes_written += p->last_io_storage_bytes_written;
1725
- o->fix_io_cancelled_write_bytes += p->last_io_cancelled_write_bytes;
1726
- }
1727
- }
1728
- else {
1729
- // if(o) fprintf(stderr, "apps.plugin: \t\tpid %d (%s) is not updated by OLD target %s (%s) is present.\n", p->pid, p->comm, o->id, o->name);
1730
-
1731
- // since the process has exited, the user
1732
- // will see a drop in our charts, because the incremental
1733
- // values of this process will not be there from now on
1734
-
1735
- // add them to the fix_* values and they will be added to
1736
- // the reported values, so that the report goes steady
1737
-
1738
- w->fix_minflt += p->last_minflt;
1739
- w->fix_majflt += p->last_majflt;
1740
- w->fix_utime += p->last_utime;
1741
- w->fix_stime += p->last_stime;
1742
-
1743
- w->fix_cminflt += (p->last_cminflt - p->last_fix_cminflt);
1744
- w->fix_cmajflt += (p->last_cmajflt - p->last_fix_cmajflt);
1745
- w->fix_cutime += (p->last_cutime - p->last_fix_cutime);
1746
- w->fix_cstime += (p->last_cstime - p->last_fix_cstime);
1747
-
1748
- w->fix_io_logical_bytes_read += p->last_io_logical_bytes_read;
1749
- w->fix_io_logical_bytes_written += p->last_io_logical_bytes_written;
1750
- w->fix_io_read_calls += p->last_io_read_calls;
1751
- w->fix_io_write_calls += p->last_io_write_calls;
1752
- w->fix_io_storage_bytes_read += p->last_io_storage_bytes_read;
1753
- w->fix_io_storage_bytes_written += p->last_io_storage_bytes_written;
1754
- w->fix_io_cancelled_write_bytes += p->last_io_cancelled_write_bytes;
1851
+ fprintf(stderr, "apps.plugin: \taggregating '%s' pid %d on target '%s' utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->comm, p->pid, w->name, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
1852
}
1756
-
1757
- //if((long long)w->cutime + w->fix_cutime < 0)
1758
- // error("Negative total cutime (%llu - %lld) on target %s after adding process %d (%s, %s) with utime=%llu, stime=%llu, minflt=%llu, majflt=%llu, cutime=%llu, cstime=%llu, cminflt=%llu, cmajflt=%llu, fix_cutime=%llu, fix_cstime=%llu, fix_cminflt=%llu, fix_cmajflt=%llu\n",
1759
- // w->cutime, w->fix_cutime, w->name, p->pid, p->comm, p->updated?"running":"exited", p->utime, p->stime, p->minflt, p->majflt, p->cutime, p->cstime, p->cminflt, p->cmajflt, p->fix_cutime, p->fix_cstime, p->fix_cminflt, p->fix_cmajflt);
1853
}
1854
1855
void count_targets_fds(struct target *root) {
@@ -1821,9 +1914,7 @@ void count_targets_fds(struct target *root) {
1914
}
1915
}
1916
1824
-void calculate_netdata_statistics(void)
1825
-{
1826
- link_all_processes_to_their_parents();
1917
+void calculate_netdata_statistics(void) {
1918
apply_apps_groups_targets_inheritance();
1919
1920
zero_all_targets(users_root_target);
@@ -1886,7 +1977,7 @@ void calculate_netdata_statistics(void)
1977
count_targets_fds(users_root_target);
1978
count_targets_fds(groups_root_target);
1979
1889
- cleanup_non_existing_pids();
1980
+ cleanup_exited_pids();
1981
}
1982
1983
// ----------------------------------------------------------------------------
@@ -1944,12 +2035,68 @@ unsigned long long send_resource_usage_to_netdata() {
2035
void send_collected_data_to_netdata(struct target *root, const char *type, unsigned long long usec)
2036
{
2037
struct target *w;
2038
+ int childs = include_exited_childs;
2039
+
2040
+ {
2041
+ // childs processing introduces spikes
2042
+ // here we try to eliminate them by disabling childs processing either for specific dimensions
2043
+ // or entirely. Of course, either way, we disable it just a single iteration.
2044
+
2045
+ unsigned long long max = update_every * processors * 100 * 100;
2046
+ unsigned long long utime = 0, cutime = 0, stime = 0, cstime = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0;
2047
+
2048
+ for (w = root; w ; w = w->next) {
2049
+ if(w->target || (!w->processes && !w->exposed)) continue;
2050
+
2051
+ if((w->utime + w->stime + w->cutime + w->cstime) > max) {
2052
+#ifdef NETDATA_INTERNAL_CHECKS
2053
+ log_date(stderr);
2054
+ fprintf(stderr, "Prevented a spike on target '%s', reported CPU time = %llu (without childs = %llu)\n", w->name, (w->utime + w->stime + w->cutime + w->cstime) / 100, (w->utime + w->stime) / 100);
2055
+#endif
2056
+ w->cutime = w->cstime = w->cminflt = w->majflt = 0;
2057
+ }
2058
+
2059
+ utime += w->utime;
2060
+ cutime += w->cutime;
2061
+ stime += w->stime;
2062
+ cstime += w->cstime;
2063
+ minflt += w->minflt;
2064
+ cminflt += w->cminflt;
2065
+ majflt += w->majflt;
2066
+ cmajflt += w->cmajflt;
2067
+ }
2068
+
2069
+ if((utime + stime + cutime + cstime) > max) {
2070
+ childs = 0;
2071
+#ifdef NETDATA_INTERNAL_CHECKS
2072
+ log_date(stderr);
2073
+ fprintf(stderr, "Prevented a spike because the total CPU of all dimensions = %llu (without childs = %llu)\n", (utime + stime + cutime + cstime) / 100, (utime + stime) / 100);
2074
+#endif
2075
+ }
2076
+
2077
+ if((utime + stime) > max) {
2078
+ childs = 0;
2079
+ unsigned long long multiplier = max, divider = utime + stime;
2080
+ for (w = root; w ; w = w->next) {
2081
+ w->utime = w->utime * multiplier / divider;
2082
+ w->stime = w->stime * multiplier / divider;
2083
+ w->minflt = w->minflt * multiplier / divider;
2084
+ w->majflt = w->majflt * multiplier / divider;
2085
+ }
2086
+
2087
+#ifdef NETDATA_INTERNAL_CHECKS
2088
+ log_date(stderr);
2089
+ fprintf(stderr, "Reduced processes utilization (without childs) by %0.2f%% (CPU was %llu)\n", (float)((utime + stime - max * 100.0)/(float)max), (utime + stime) / 100);
2090
+#endif
2091
+ }
2092
+
2093
+ }
2094
2095
fprintf(stdout, "BEGIN %s.cpu %llu\n", type, usec);
2096
for (w = root; w ; w = w->next) {
2097
if(w->target || (!w->processes && !w->exposed)) continue;
2098
1952
- fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->stime + w->fix_utime + w->fix_stime + (include_exited_childs?(w->cutime + w->cstime + w->fix_cutime + w->fix_cstime):0));
2099
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->stime + (childs?(w->cutime + w->cstime):0));
2100
}
2101
fprintf(stdout, "END\n");
2102
@@ -1957,7 +2104,7 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2104
for (w = root; w ; w = w->next) {
2105
if(w->target || (!w->processes && !w->exposed)) continue;
2106
1960
- fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + w->fix_utime + (include_exited_childs?(w->cutime + w->fix_cutime):0));
2107
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->utime + (childs?(w->cutime):0));
2108
}
2109
fprintf(stdout, "END\n");
2110
@@ -1965,7 +2112,7 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2112
for (w = root; w ; w = w->next) {
2113
if(w->target || (!w->processes && !w->exposed)) continue;
2114
1968
- fprintf(stdout, "SET %s = %llu\n", w->name, w->stime + w->fix_stime + (include_exited_childs?(w->cstime + w->fix_cstime):0));
2115
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->stime + (childs?(w->cstime):0));
2116
}
2117
fprintf(stdout, "END\n");
2118
@@ -1997,7 +2144,7 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2144
for (w = root; w ; w = w->next) {
2145
if(w->target || (!w->processes && !w->exposed)) continue;
2146
2000
- fprintf(stdout, "SET %s = %llu\n", w->name, w->minflt + w->fix_minflt + (include_exited_childs?(w->cminflt + w->fix_cminflt):0));
2147
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->minflt + (childs?(w->cminflt):0));
2148
}
2149
fprintf(stdout, "END\n");
2150
@@ -2005,7 +2152,7 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2152
for (w = root; w ; w = w->next) {
2153
if(w->target || (!w->processes && !w->exposed)) continue;
2154
2008
- fprintf(stdout, "SET %s = %llu\n", w->name, w->majflt + w->fix_majflt + (include_exited_childs?(w->cmajflt + w->fix_cmajflt):0));
2155
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->majflt + (childs?(w->cmajflt):0));
2156
}
2157
fprintf(stdout, "END\n");
2158
@@ -2013,7 +2160,7 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2160
for (w = root; w ; w = w->next) {
2161
if(w->target || (!w->processes && !w->exposed)) continue;
2162
2016
- fprintf(stdout, "SET %s = %llu\n", w->name, w->io_logical_bytes_read + w->fix_io_logical_bytes_read);
2163
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->io_logical_bytes_read);
2164
}
2165
fprintf(stdout, "END\n");
2166
@@ -2021,7 +2168,7 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2168
for (w = root; w ; w = w->next) {
2169
if(w->target || (!w->processes && !w->exposed)) continue;
2170
2024
- fprintf(stdout, "SET %s = %llu\n", w->name, w->io_logical_bytes_written + w->fix_io_logical_bytes_written);
2171
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->io_logical_bytes_written);
2172
}
2173
fprintf(stdout, "END\n");
2174
@@ -2029,7 +2176,7 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2176
for (w = root; w ; w = w->next) {
2177
if(w->target || (!w->processes && !w->exposed)) continue;
2178
2032
- fprintf(stdout, "SET %s = %llu\n", w->name, w->io_storage_bytes_read + w->fix_io_storage_bytes_read);
2179
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->io_storage_bytes_read);
2180
}
2181
fprintf(stdout, "END\n");
2182
@@ -2037,7 +2184,7 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2184
for (w = root; w ; w = w->next) {
2185
if(w->target || (!w->processes && !w->exposed)) continue;
2186
2040
- fprintf(stdout, "SET %s = %llu\n", w->name, w->io_storage_bytes_written + w->fix_io_storage_bytes_written);
2187
+ fprintf(stdout, "SET %s = %llu\n", w->name, w->io_storage_bytes_written);
2188
}
2189
fprintf(stdout, "END\n");
2190
@@ -2093,7 +2240,7 @@ void send_charts_updates_to_netdata(struct target *root, const char *type, const
2240
for (w = root; w ; w = w->next) {
2241
if(w->target || (!w->processes && !w->exposed)) continue;
2242
2096
- fprintf(stdout, "DIMENSION %s '' incremental 100 %u %s\n", w->name, hz, w->hidden ? "hidden,noreset" : "noreset");
2243
+ fprintf(stdout, "DIMENSION %s '' absolute 1 %u %s\n", w->name, hz, w->hidden ? "hidden,noreset" : "noreset");
2244
}
2245
2246
fprintf(stdout, "CHART %s.mem '' '%s Dedicated Memory (w/o shared)' 'MB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every);
@@ -2121,56 +2268,56 @@ void send_charts_updates_to_netdata(struct target *root, const char *type, const
2268
for (w = root; w ; w = w->next) {
2269
if(w->target || (!w->processes && !w->exposed)) continue;
2270
2124
- fprintf(stdout, "DIMENSION %s '' incremental 100 %u noreset\n", w->name, hz);
2271
+ fprintf(stdout, "DIMENSION %s '' absolute 1 %u noreset\n", w->name, hz);
2272
}
2273
2274
fprintf(stdout, "CHART %s.cpu_system '' '%s CPU System Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20021 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
2275
for (w = root; w ; w = w->next) {
2276
if(w->target || (!w->processes && !w->exposed)) continue;
2277
2131
- fprintf(stdout, "DIMENSION %s '' incremental 100 %u noreset\n", w->name, hz);
2278
+ fprintf(stdout, "DIMENSION %s '' absolute 1 %u noreset\n", w->name, hz);
2279
}
2280
2281
fprintf(stdout, "CHART %s.major_faults '' '%s Major Page Faults (swap read)' 'page faults/s' swap %s.major_faults stacked 20010 %d\n", type, title, type, update_every);
2282
for (w = root; w ; w = w->next) {
2283
if(w->target || (!w->processes && !w->exposed)) continue;
2284
2138
- fprintf(stdout, "DIMENSION %s '' incremental 1 1 noreset\n", w->name);
2285
+ fprintf(stdout, "DIMENSION %s '' absolute 1 100 noreset\n", w->name);
2286
}
2287
2288
fprintf(stdout, "CHART %s.minor_faults '' '%s Minor Page Faults' 'page faults/s' mem %s.minor_faults stacked 20011 %d\n", type, title, type, update_every);
2289
for (w = root; w ; w = w->next) {
2290
if(w->target || (!w->processes && !w->exposed)) continue;
2291
2145
- fprintf(stdout, "DIMENSION %s '' incremental 1 1 noreset\n", w->name);
2292
+ fprintf(stdout, "DIMENSION %s '' absolute 1 100 noreset\n", w->name);
2293
}
2294
2295
fprintf(stdout, "CHART %s.lreads '' '%s Disk Logical Reads' 'kilobytes/s' disk %s.lreads stacked 20042 %d\n", type, title, type, update_every);
2296
for (w = root; w ; w = w->next) {
2297
if(w->target || (!w->processes && !w->exposed)) continue;
2298
2152
- fprintf(stdout, "DIMENSION %s '' incremental 1 %d noreset\n", w->name, 1024);
2299
+ fprintf(stdout, "DIMENSION %s '' incremental 1 %d noreset\n", w->name, 1024*100);
2300
}
2301
2302
fprintf(stdout, "CHART %s.lwrites '' '%s I/O Logical Writes' 'kilobytes/s' disk %s.lwrites stacked 20042 %d\n", type, title, type, update_every);
2303
for (w = root; w ; w = w->next) {
2304
if(w->target || (!w->processes && !w->exposed)) continue;
2305
2159
- fprintf(stdout, "DIMENSION %s '' incremental 1 %d noreset\n", w->name, 1024);
2306
+ fprintf(stdout, "DIMENSION %s '' incremental 1 %d noreset\n", w->name, 1024*100);
2307
}
2308
2309
fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'kilobytes/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
2310
for (w = root; w ; w = w->next) {
2311
if(w->target || (!w->processes && !w->exposed)) continue;
2312
2166
- fprintf(stdout, "DIMENSION %s '' incremental 1 %d noreset\n", w->name, 1024);
2313
+ fprintf(stdout, "DIMENSION %s '' incremental 1 %d noreset\n", w->name, 1024*100);
2314
}
2315
2316
fprintf(stdout, "CHART %s.pwrites '' '%s Disk Writes' 'kilobytes/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every);
2317
for (w = root; w ; w = w->next) {
2318
if(w->target || (!w->processes && !w->exposed)) continue;
2319
2173
- fprintf(stdout, "DIMENSION %s '' incremental 1 %d noreset\n", w->name, 1024);
2320
+ fprintf(stdout, "DIMENSION %s '' incremental 1 %d noreset\n", w->name, 1024*100);
2321
}
2322
2323
fprintf(stdout, "CHART %s.files '' '%s Open Files' 'open files' disk %s.files stacked 20050 %d\n", type, title, type, update_every);
@@ -2215,7 +2362,7 @@ void parse_args(int argc, char **argv)
2362
2363
if(strcmp("debug", argv[i]) == 0) {
2364
debug = 1;
2218
- debug_flags = 0xffffffff;
2365
+ // debug_flags = 0xffffffff;
2366
continue;
2367
}
2368
@@ -2294,6 +2441,13 @@ int main(int argc, char **argv)
2441
2442
parse_args(argc, argv);
2443
2444
+ all_pids_sortlist = calloc(sizeof(pid_t), (size_t)pid_max);
2445
+ if(!all_pids_sortlist) {
2446
+ error("Cannot allocate %lu bytes of memory.", sizeof(pid_t) * pid_max);
2447
+ printf("DISABLE\n");
2448
+ exit(1);
2449
+ }
2450
+
2451
all_pids = calloc(sizeof(struct pid_stat *), (size_t) pid_max);
2452
if(!all_pids) {
2453
error("Cannot allocate %lu bytes of memory.", sizeof(struct pid_stat *) * pid_max);
@@ -2315,8 +2469,8 @@ int main(int argc, char **argv)
2469
unsigned long long sunow;
2470
#endif /* PROFILING_MODE */
2471
2318
- unsigned long long counter = 1;
2319
- for(;1; counter++) {
2472
+ global_iterations_counter = 1;
2473
+ for(;1; global_iterations_counter++) {
2474
#ifndef PROFILING_MODE
2475
// delay until it is our time to run
2476
while((sunow = timems()) < sunext)
@@ -2347,7 +2501,7 @@ int main(int argc, char **argv)
2501
send_collected_data_to_netdata(groups_root_target, "groups", dt);
2502
2503
if(unlikely(debug))
2350
- fprintf(stderr, "apps.plugin: done Loop No %llu\n", counter);
2504
+ fprintf(stderr, "apps.plugin: done Loop No %llu\n", global_iterations_counter);
2505
2506
current_t = time(NULL);
2507