@cryptotaxi247 / netdata-1 / commits / f17da0af9

apps.plugin changes for better cross system adaptation

Costa Tsaousis (ktsaou) committed Feb 27, 2017 at 16:28 UTC f17da0af9d0edb9d78fd2d4946081328319a9396
1 file changed +105 -110
src/apps_plugin.c
+105 -110
@@ -7,6 +7,20 @@
7
8 #include "common.h"
9
10 +// ----------------------------------------------------------------------------
11 +// per O/S configuration
12 +
13 +// the minimum PID of the system
14 +// this is also the pid of the init process
15 +#define INIT_PID 1
16 +
17 +// if the way apps.plugin will work, will read the entire process list,
18 +// including the resource utilization of each process, instantly
19 +// set this to 1
20 +// when set to 0, apps.plugin builds a sort list of processes, in order
21 +// to process children processes, before parent processes
22 +#define ALL_PIDS_ARE_READ_INSTANTLY 0
23 +
24
25 // ----------------------------------------------------------------------------
26 // string lengths
@@ -337,6 +351,7 @@ static struct pid_stat
351 static size_t
352 all_pids_count = 0; // the number of processes running
353
354 +#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
355 // Another pre-allocated list of all possible pids.
356 // We need it to pids and assign them a unique sortlist id, so that we
357 // read parents before children. This is needed to prevent a situation where
@@ -344,7 +359,7 @@ static size_t
359 // its parent has accumulated its resources.
360 static pid_t
361 *all_pids_sortlist = NULL;
347 -
362 +#endif
363
364 // ----------------------------------------------------------------------------
365 // file descriptor
@@ -788,7 +803,9 @@ cleanup:
803 return 0;
804 }
805
791 -static inline int read_proc_pid_ownership(struct pid_stat *p) {
806 +static inline int read_proc_pid_ownership(struct pid_stat *p, void *ptr) {
807 + (void)ptr;
808 +
809 if(unlikely(!p->stat_filename)) {
810 error("pid %d does not have a stat_filename", p->pid);
811 return 0;
@@ -809,7 +826,27 @@ static inline int read_proc_pid_ownership(struct pid_stat *p) {
826 return 1;
827 }
828
812 -static inline int read_proc_pid_stat(struct pid_stat *p) {
829 +// ----------------------------------------------------------------------------
830 +// macro to calculate the incremental rate of a value
831 +// each parameter is accessed only ONCE - so it is safe to pass function calls
832 +// or other macros as parameters
833 +
834 +#define incremental_rate(rate_variable, last_kernel_variable, new_kernel_value, collected_usec, last_collected_usec) { \
835 + kernel_uint_t _new_tmp = new_kernel_value; \
836 + rate_variable = (_new_tmp - last_kernel_variable) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec); \
837 + last_kernel_variable = _new_tmp; \
838 + }
839 +
840 +// the same macro for struct pid members
841 +#define pid_incremental_rate(type, var, value) \
842 + incremental_rate(var, var##_raw, value, p->type##_collected_usec, p->last_##type##_collected_usec)
843 +
844 +
845 +// ----------------------------------------------------------------------------
846 +
847 +static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
848 + (void)ptr;
849 +
850 static procfile *ff = NULL;
851
852 if(unlikely(!p->stat_filename)) {
@@ -861,37 +898,14 @@ static inline int read_proc_pid_stat(struct pid_stat *p) {
898 assign_target_to_pid(p);
899 }
900
864 - kernel_uint_t last = p->minflt_raw;
865 - p->minflt_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 9));
866 - p->minflt = (p->minflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
867 -
868 - last = p->cminflt_raw;
869 - p->cminflt_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 10));
870 - p->cminflt = (p->cminflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
871 -
872 - last = p->majflt_raw;
873 - p->majflt_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 11));
874 - p->majflt = (p->majflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
875 -
876 - last = p->cmajflt_raw;
877 - p->cmajflt_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 12));
878 - p->cmajflt = (p->cmajflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
879 -
880 - last = p->utime_raw;
881 - p->utime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 13));
882 - p->utime = (p->utime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
883 -
884 - last = p->stime_raw;
885 - p->stime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 14));
886 - p->stime = (p->stime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
887 -
888 - last = p->cutime_raw;
889 - p->cutime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 15));
890 - p->cutime = (p->cutime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
891 -
892 - last = p->cstime_raw;
893 - p->cstime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 16));
894 - p->cstime = (p->cstime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
901 + pid_incremental_rate(stat, p->minflt, str2kernel_uint_t(procfile_lineword(ff, 0, 9)));
902 + pid_incremental_rate(stat, p->cminflt, str2kernel_uint_t(procfile_lineword(ff, 0, 10)));
903 + pid_incremental_rate(stat, p->majflt, str2kernel_uint_t(procfile_lineword(ff, 0, 11)));
904 + pid_incremental_rate(stat, p->cmajflt, str2kernel_uint_t(procfile_lineword(ff, 0, 12)));
905 + pid_incremental_rate(stat, p->utime, str2kernel_uint_t(procfile_lineword(ff, 0, 13)));
906 + pid_incremental_rate(stat, p->stime, str2kernel_uint_t(procfile_lineword(ff, 0, 14)));
907 + pid_incremental_rate(stat, p->cutime, str2kernel_uint_t(procfile_lineword(ff, 0, 15)));
908 + pid_incremental_rate(stat, p->cstime, str2kernel_uint_t(procfile_lineword(ff, 0, 16)));
909
910 // p->priority = str2kernel_uint_t(procfile_lineword(ff, 0, 17));
911 // p->nice = str2kernel_uint_t(procfile_lineword(ff, 0, 18));
@@ -920,13 +934,9 @@ static inline int read_proc_pid_stat(struct pid_stat *p) {
934 // p->delayacct_blkio_ticks = str2kernel_uint_t(procfile_lineword(ff, 0, 41));
935
936 if(enable_guest_charts) {
923 - last = p->gtime_raw;
924 - p->gtime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 42));
925 - p->gtime = (p->gtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
937
927 - last = p->cgtime_raw;
928 - p->cgtime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 43));
929 - p->cgtime = (p->cgtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
938 + pid_incremental_rate(stat, p->gtime, str2kernel_uint_t(procfile_lineword(ff, 0, 42)));
939 + pid_incremental_rate(stat, p->cgtime, str2kernel_uint_t(procfile_lineword(ff, 0, 43)));
940
941 if (show_guest_time || p->gtime || p->cgtime) {
942 p->utime -= (p->utime >= p->gtime) ? p->gtime : p->utime;
@@ -969,7 +979,9 @@ cleanup:
979 return 0;
980 }
981
972 -static inline int read_proc_pid_statm(struct pid_stat *p) {
982 +static inline int read_proc_pid_statm(struct pid_stat *p, void *ptr) {
983 + (void)ptr;
984 +
985 static procfile *ff = NULL;
986
987 if(unlikely(!p->statm_filename)) {
@@ -1007,7 +1019,9 @@ cleanup:
1019 return 0;
1020 }
1021
1010 -static inline int read_proc_pid_io(struct pid_stat *p) {
1022 +static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) {
1023 + (void)ptr;
1024 +
1025 static procfile *ff = NULL;
1026
1027 if(unlikely(!p->io_filename)) {
@@ -1028,35 +1042,13 @@ static inline int read_proc_pid_io(struct pid_stat *p) {
1042 p->last_io_collected_usec = p->io_collected_usec;
1043 p->io_collected_usec = now_monotonic_usec();
1044
1031 - kernel_uint_t last;
1032 -
1033 - last = p->io_logical_bytes_read_raw;
1034 - p->io_logical_bytes_read_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 1));
1035 - p->io_logical_bytes_read = (p->io_logical_bytes_read_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
1036 -
1037 - last = p->io_logical_bytes_written_raw;
1038 - p->io_logical_bytes_written_raw = str2kernel_uint_t(procfile_lineword(ff, 1, 1));
1039 - p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
1040 -
1041 - // last = p->io_read_calls_raw;
1042 - // p->io_read_calls_raw = str2kernel_uint_t(procfile_lineword(ff, 2, 1));
1043 - // p->io_read_calls = (p->io_read_calls_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
1044 -
1045 - // last = p->io_write_calls_raw;
1046 - // p->io_write_calls_raw = str2kernel_uint_t(procfile_lineword(ff, 3, 1));
1047 - // p->io_write_calls = (p->io_write_calls_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
1048 -
1049 - last = p->io_storage_bytes_read_raw;
1050 - p->io_storage_bytes_read_raw = str2kernel_uint_t(procfile_lineword(ff, 4, 1));
1051 - p->io_storage_bytes_read = (p->io_storage_bytes_read_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
1052 -
1053 - last = p->io_storage_bytes_written_raw;
1054 - p->io_storage_bytes_written_raw = str2kernel_uint_t(procfile_lineword(ff, 5, 1));
1055 - p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
1056 -
1057 - // last = p->io_cancelled_write_bytes_raw;
1058 - // p->io_cancelled_write_bytes_raw = str2kernel_uint_t(procfile_lineword(ff, 6, 1));
1059 - // p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
1045 + pid_incremental_rate(io, p->io_logical_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 0, 1)));
1046 + pid_incremental_rate(io, p->io_logical_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 1, 1)));
1047 + // pid_incremental_rate(io, p->io_read_calls, str2kernel_uint_t(procfile_lineword(ff, 2, 1)));
1048 + // pid_incremental_rate(io, p->io_write_calls, str2kernel_uint_t(procfile_lineword(ff, 3, 1)));
1049 + pid_incremental_rate(io, p->io_storage_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 4, 1)));
1050 + pid_incremental_rate(io, p->io_storage_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 5, 1)));
1051 + // pid_incremental_rate(io, p->io_cancelled_write_bytes, str2kernel_uint_t(procfile_lineword(ff, 6, 1)));
1052
1053 if(unlikely(global_iterations_counter == 1)) {
1054 p->io_logical_bytes_read = 0;
@@ -1101,30 +1093,24 @@ static inline int read_proc_stat() {
1093
1094 calls_counter++;
1095
1104 - kernel_uint_t last;
1096 + // temporary - it is added global_ntime;
1097 + kernel_uint_t global_ntime = 0;
1098
1106 - last = utime_raw;
1107 - utime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 1));
1108 - global_utime = (utime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
1099 + incremental_rate(global_utime, utime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 1)), collected_usec, last_collected_usec);
1100 + incremental_rate(global_ntime, ntime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 2)), collected_usec, last_collected_usec);
1101 + incremental_rate(global_stime, stime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 3)), collected_usec, last_collected_usec);
1102 + incremental_rate(global_gtime, gtime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 10)), collected_usec, last_collected_usec);
1103
1110 - // nice time, on user time
1111 - last = ntime_raw;
1112 - ntime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 2));
1113 - global_utime += (ntime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
1114 -
1115 - last = stime_raw;
1116 - stime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 3));
1117 - global_stime = (stime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
1118 -
1119 - last = gtime_raw;
1120 - gtime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 10));
1121 - global_gtime = (gtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
1104 + global_utime += global_ntime;
1105
1106 if(enable_guest_charts) {
1107 + // temporary - it is added global_ntime;
1108 + kernel_uint_t global_gntime = 0;
1109 +
1110 // guest nice time, on guest time
1125 - last = gntime_raw;
1126 - gntime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 11));
1127 - global_gtime += (gntime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
1111 + incremental_rate(global_gntime, gntime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 11)), collected_usec, last_collected_usec);
1112 +
1113 + global_gtime += global_gntime;
1114
1115 // remove guest time from user time
1116 global_utime -= (global_utime > global_gtime) ? global_gtime : global_utime;
@@ -1405,7 +1391,9 @@ static inline void zero_pid_fds(struct pid_stat *p, int first, int size) {
1391 while(fd < end) *fd++ = 0;
1392 }
1393
1408 -static inline int read_pid_file_descriptors(struct pid_stat *p) {
1394 +static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) {
1395 + (void)ptr;
1396 +
1397 if(unlikely(!p->fds_dirname)) {
1398 char dirname[FILENAME_MAX+1];
1399 snprintfz(dirname, FILENAME_MAX, "%s/proc/%d/fd", netdata_configured_host_prefix, p->pid);
@@ -1631,11 +1619,11 @@ static inline void process_exited_processes() {
1619 if(p->updated || !p->stat_collected_usec)
1620 continue;
1621
1634 - kernel_uint_t utime = (p->utime_raw + p->cutime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1635 - kernel_uint_t stime = (p->stime_raw + p->cstime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1636 - kernel_uint_t gtime = (p->gtime_raw + p->cgtime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1637 - kernel_uint_t minflt = (p->minflt_raw + p->cminflt_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1638 - kernel_uint_t majflt = (p->majflt_raw + p->cmajflt_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1622 + kernel_uint_t utime = (p->utime_raw + p->cutime_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1623 + kernel_uint_t stime = (p->stime_raw + p->cstime_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1624 + kernel_uint_t gtime = (p->gtime_raw + p->cgtime_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1625 + kernel_uint_t minflt = (p->minflt_raw + p->cminflt_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1626 + kernel_uint_t majflt = (p->majflt_raw + p->cmajflt_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1627
1628 if(utime + stime + gtime + minflt + majflt == 0)
1629 continue;
@@ -1796,9 +1784,9 @@ static int compar_pid(const void *pid1, const void *pid2) {
1784 return 1;
1785 }
1786
1799 -static inline int collect_data_for_pid(pid_t pid) {
1800 - if(unlikely(pid <= 0 || pid > pid_max)) {
1801 - error("Invalid pid %d read (expected 1 to %d). Ignoring process.", pid, pid_max);
1787 +static inline int collect_data_for_pid(pid_t pid, void *ptr) {
1788 + if(unlikely(pid < INIT_PID || pid > pid_max)) {
1789 + error("Invalid pid %d read (expected %d to %d). Ignoring process.", pid, INIT_PID, pid_max);
1790 return 0;
1791 }
1792
@@ -1811,11 +1799,11 @@ static inline int collect_data_for_pid(pid_t pid) {
1799 // --------------------------------------------------------------------
1800 // /proc/<pid>/stat
1801
1814 - if(unlikely(!managed_log(p, PID_LOG_STAT, read_proc_pid_stat(p))))
1802 + if(unlikely(!managed_log(p, PID_LOG_STAT, read_proc_pid_stat(p, ptr))))
1803 // there is no reason to proceed if we cannot get its status
1804 return 0;
1805
1818 - read_proc_pid_ownership(p);
1806 + read_proc_pid_ownership(p, ptr);
1807
1808 // check its parent pid
1809 if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
@@ -1826,12 +1814,12 @@ static inline int collect_data_for_pid(pid_t pid) {
1814 // --------------------------------------------------------------------
1815 // /proc/<pid>/io
1816
1829 - managed_log(p, PID_LOG_IO, read_proc_pid_io(p));
1817 + managed_log(p, PID_LOG_IO, read_proc_pid_io(p, ptr));
1818
1819 // --------------------------------------------------------------------
1820 // /proc/<pid>/statm
1821
1834 - if(unlikely(!managed_log(p, PID_LOG_STATM, read_proc_pid_statm(p))))
1822 + if(unlikely(!managed_log(p, PID_LOG_STATM, read_proc_pid_statm(p, ptr))))
1823 // there is no reason to proceed if we cannot get its memory status
1824 return 0;
1825
@@ -1839,7 +1827,7 @@ static inline int collect_data_for_pid(pid_t pid) {
1827 // /proc/<pid>/fd
1828
1829 if(enable_file_charts)
1842 - managed_log(p, PID_LOG_FDS, read_pid_file_descriptors(p));
1830 + managed_log(p, PID_LOG_FDS, read_pid_file_descriptors(p, ptr));
1831
1832 // --------------------------------------------------------------------
1833 // done!
@@ -1867,9 +1855,12 @@ static int collect_data_for_all_processes(void) {
1855 p->children_count = 0;
1856 p->parent = NULL;
1857
1858 +#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
1859 all_pids_sortlist[slc++] = p->pid;
1860 +#endif
1861 }
1862
1863 +#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
1864 if(unlikely(slc != all_pids_count)) {
1865 error("Internal error: I was thinking I had %zu processes in my arrays, but it seems there are more.", all_pids_count);
1866 all_pids_count = slc;
@@ -1886,10 +1877,11 @@ static int collect_data_for_all_processes(void) {
1877
1878 // we forward read all running processes
1879 // collect_data_for_pid() is smart enough,
1889 - // not to read the same pid twice per iterations
1880 + // not to read the same pid twice per iteration
1881 for(slc = 0; slc < all_pids_count; slc++)
1891 - collect_data_for_pid(all_pids_sortlist[slc]);
1882 + collect_data_for_pid(all_pids_sortlist[slc], NULL);
1883 }
1884 +#endif
1885 }
1886
1887 char dirname[FILENAME_MAX + 1];
@@ -1912,7 +1904,7 @@ static int collect_data_for_all_processes(void) {
1904 if(unlikely(endptr == de->d_name || *endptr != '\0'))
1905 continue;
1906
1915 - collect_data_for_pid(pid);
1907 + collect_data_for_pid(pid, NULL);
1908 }
1909 closedir(dir);
1910
@@ -2027,7 +2019,7 @@ static void apply_apps_groups_targets_inheritance(void) {
2019 && p->parent
2020 && p->parent->children_count
2021 && (p->target == p->parent->target || !p->parent->target)
2030 - && p->ppid != 1
2022 + && p->ppid != INIT_PID
2023 )) {
2024 p->parent->children_count--;
2025 p->merged = 1;
@@ -2049,8 +2041,8 @@ static void apply_apps_groups_targets_inheritance(void) {
2041 }
2042
2043 // init goes always to default target
2052 - if(all_pids[1])
2053 - all_pids[1]->target = apps_groups_default_target;
2044 + if(all_pids[INIT_PID])
2045 + all_pids[INIT_PID]->target = apps_groups_default_target;
2046
2047 // give a default target on all top level processes
2048 if(unlikely(debug)) loops++;
@@ -3180,7 +3172,10 @@ int main(int argc, char **argv) {
3172
3173 info("started on pid %d", getpid());
3174
3175 +#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
3176 all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max);
3177 +#endif
3178 +
3179 all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max);
3180
3181 usec_t step = update_every * USEC_PER_SEC;