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;