@cryptotaxi247 / netdata-1 / commits / 7f8bd4182

Fix process statistics collection for FreeBSD in apps.plugin (#5038)

* Read all threads * Fix CPU time factor for FreeBSD * Eliminate spikes for CPU time

Vladimir Kobal committed Dec 28, 2018 at 15:14 UTC 7f8bd41824423e821fa1ef6c087e06b75d54aacc
1 file changed +72 -27
collectors/apps.plugin/apps_plugin.c
+72 -27
@@ -99,6 +99,9 @@ static inline void debug_log_dummy(void) {}
99 // etc.
100 #define RATES_DETAIL 10000ULL
101
102 +// ----------------------------------------------------------------------------
103 +// factor for calculating correct CPU time values depending on units of raw data
104 +static unsigned int time_factor = 0;
105
106 // ----------------------------------------------------------------------------
107 // to avoid reallocating too frequently, we can increase the number of spare
@@ -107,7 +110,6 @@ static inline void debug_log_dummy(void) {}
110 // having a lot of spares, increases the CPU utilization of the plugin.
111 #define MAX_SPARE_FDS 1
112
110 -
113 // ----------------------------------------------------------------------------
114 // command line options
115
@@ -166,12 +168,10 @@ static size_t
168 // metric.
169
170 // the total system time, as reported by /proc/stat
169 -#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
171 static kernel_uint_t
172 global_utime = 0,
173 global_stime = 0,
174 global_gtime = 0;
174 -#endif
175
176 // the normalization ratios, as calculated by normalize_utilization()
177 double utime_fix_ratio = 1.0,
@@ -1327,8 +1327,8 @@ cleanup:
1327 #endif
1328 }
1329
1330 -#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
1331 -static inline int read_proc_stat() {
1330 +#ifndef __FreeBSD__
1331 +static inline int read_global_time() {
1332 static char filename[FILENAME_MAX + 1] = "";
1333 static procfile *ff = NULL;
1334 static kernel_uint_t utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0;
@@ -1386,10 +1386,50 @@ cleanup:
1386 return 0;
1387 }
1388 #else
1389 -static inline int read_proc_stat() {
1389 +static inline int read_global_time() {
1390 + static kernel_uint_t utime_raw = 0, stime_raw = 0, gtime_raw = 0, ntime_raw = 0;
1391 + static usec_t collected_usec = 0, last_collected_usec = 0;
1392 + long cp_time[CPUSTATES];
1393 +
1394 + if (unlikely(CPUSTATES != 5)) {
1395 + goto cleanup;
1396 + } else {
1397 + static int mib[2] = {0, 0};
1398 +
1399 + if (unlikely(GETSYSCTL_SIMPLE("kern.cp_time", mib, cp_time))) {
1400 + goto cleanup;
1401 + }
1402 + }
1403 +
1404 + last_collected_usec = collected_usec;
1405 + collected_usec = now_monotonic_usec();
1406 +
1407 + calls_counter++;
1408 +
1409 + // temporary - it is added global_ntime;
1410 + kernel_uint_t global_ntime = 0;
1411 +
1412 + incremental_rate(global_utime, utime_raw, cp_time[0] * 100LLU / system_hz, collected_usec, last_collected_usec);
1413 + incremental_rate(global_ntime, ntime_raw, cp_time[1] * 100LLU / system_hz, collected_usec, last_collected_usec);
1414 + incremental_rate(global_stime, stime_raw, cp_time[2] * 100LLU / system_hz, collected_usec, last_collected_usec);
1415 +
1416 + global_utime += global_ntime;
1417 +
1418 + if(unlikely(global_iterations_counter == 1)) {
1419 + global_utime = 0;
1420 + global_stime = 0;
1421 + global_gtime = 0;
1422 + }
1423 +
1424 + return 1;
1425 +
1426 +cleanup:
1427 + global_utime = 0;
1428 + global_stime = 0;
1429 + global_gtime = 0;
1430 return 0;
1431 }
1392 -#endif
1432 +#endif /* !__FreeBSD__ */
1433
1434 // ----------------------------------------------------------------------------
1435
@@ -2289,7 +2329,7 @@ static int collect_data_for_all_processes(void) {
2329
2330 size_t new_procbase_size;
2331
2292 - int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC };
2332 + int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
2333 if (unlikely(sysctl(mib, 3, NULL, &new_procbase_size, NULL, 0))) {
2334 error("sysctl error: Can't get processes data size");
2335 return 0;
@@ -2396,7 +2436,7 @@ static int collect_data_for_all_processes(void) {
2436 return 0;
2437
2438 // we need /proc/stat to normalize the cpu consumption of the exited childs
2399 - read_proc_stat();
2439 + read_global_time();
2440
2441 // build the process tree
2442 link_all_processes_to_their_parents();
@@ -2884,7 +2924,6 @@ void send_resource_usage_to_netdata(usec_t dt) {
2924 , update_every
2925 );
2926
2887 -#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
2927 fprintf(stdout,
2928 "CHART netdata.apps_fix '' 'Apps Plugin Normalization Ratios' 'percentage' apps.plugin netdata.apps_fix line 140002 %1$d\n"
2929 "DIMENSION utime '' absolute 1 %2$llu\n"
@@ -2907,7 +2946,6 @@ void send_resource_usage_to_netdata(usec_t dt) {
2946 , update_every
2947 , RATES_DETAIL
2948 );
2910 -#endif
2949
2950 }
2951
@@ -2942,7 +2980,6 @@ void send_resource_usage_to_netdata(usec_t dt) {
2980 , targets_assignment_counter
2981 );
2982
2945 -#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
2983 fprintf(stdout,
2984 "BEGIN netdata.apps_fix %llu\n"
2985 "SET utime = %u\n"
@@ -2975,10 +3012,8 @@ void send_resource_usage_to_netdata(usec_t dt) {
3012 , (unsigned int)(cminflt_fix_ratio * 100 * RATES_DETAIL)
3013 , (unsigned int)(cmajflt_fix_ratio * 100 * RATES_DETAIL)
3014 );
2978 -#endif
3015 }
3016
2981 -#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
3017 static void normalize_utilization(struct target *root) {
3018 struct target *w;
3019
@@ -2986,7 +3021,7 @@ static void normalize_utilization(struct target *root) {
3021 // here we try to eliminate them by disabling childs processing either for specific dimensions
3022 // or entirely. Of course, either way, we disable it just a single iteration.
3023
2989 - kernel_uint_t max_time = processors * system_hz * RATES_DETAIL;
3024 + kernel_uint_t max_time = processors * time_factor * RATES_DETAIL;
3025 kernel_uint_t utime = 0, cutime = 0, stime = 0, cstime = 0, gtime = 0, cgtime = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0;
3026
3027 if(global_utime > max_time) global_utime = max_time;
@@ -3009,7 +3044,7 @@ static void normalize_utilization(struct target *root) {
3044 cmajflt += w->cmajflt;
3045 }
3046
3012 - if((global_utime || global_stime || global_gtime) && (utime || stime || gtime)) {
3047 + if(global_utime || global_stime || global_gtime) {
3048 if(global_utime + global_stime + global_gtime > utime + cutime + stime + cstime + gtime + cgtime) {
3049 // everything we collected fits
3050 utime_fix_ratio =
@@ -3019,7 +3054,7 @@ static void normalize_utilization(struct target *root) {
3054 cstime_fix_ratio =
3055 cgtime_fix_ratio = 1.0; //(double)(global_utime + global_stime) / (double)(utime + cutime + stime + cstime);
3056 }
3022 - else if(global_utime + global_stime > utime + stime) {
3057 + else if((global_utime + global_stime > utime + stime) && (cutime || cstime)) {
3058 // childrens resources are too high
3059 // lower only the children resources
3060 utime_fix_ratio =
@@ -3029,7 +3064,7 @@ static void normalize_utilization(struct target *root) {
3064 cstime_fix_ratio =
3065 cgtime_fix_ratio = (double)((global_utime + global_stime) - (utime + stime)) / (double)(cutime + cstime);
3066 }
3032 - else {
3067 + else if(utime || stime) {
3068 // even running processes are unrealistic
3069 // zero the children resources
3070 // lower the running processes resources
@@ -3040,6 +3075,14 @@ static void normalize_utilization(struct target *root) {
3075 cstime_fix_ratio =
3076 cgtime_fix_ratio = 0.0;
3077 }
3078 + else {
3079 + utime_fix_ratio =
3080 + stime_fix_ratio =
3081 + gtime_fix_ratio =
3082 + cutime_fix_ratio =
3083 + cstime_fix_ratio =
3084 + cgtime_fix_ratio = 0.0;
3085 + }
3086 }
3087 else {
3088 utime_fix_ratio =
@@ -3121,11 +3164,6 @@ static void normalize_utilization(struct target *root) {
3164 , (kernel_uint_t)(cgtime * cgtime_fix_ratio)
3165 );
3166 }
3124 -#else // ALL_PIDS_ARE_READ_INSTANTLY == 1
3125 -static void normalize_utilization(struct target *root) {
3126 - (void)root;
3127 -}
3128 -#endif // ALL_PIDS_ARE_READ_INSTANTLY
3167
3168 static void send_collected_data_to_netdata(struct target *root, const char *type, usec_t dt) {
3169 struct target *w;
@@ -3293,7 +3331,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3331 fprintf(stdout, "CHART %s.cpu '' '%s CPU Time (%d%% = %d core%s)' 'percentage' cpu %s.cpu stacked 20001 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
3332 for (w = root; w ; w = w->next) {
3333 if(unlikely(w->exposed))
3296 - fprintf(stdout, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, system_hz * RATES_DETAIL / 100, w->hidden ? "hidden" : "");
3334 + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, time_factor * RATES_DETAIL / 100, w->hidden ? "hidden" : "");
3335 }
3336
3337 fprintf(stdout, "CHART %s.mem '' '%s Real Memory (w/o shared)' 'MiB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every);
@@ -3323,20 +3361,20 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3361 fprintf(stdout, "CHART %s.cpu_user '' '%s CPU User Time (%d%% = %d core%s)' 'percentage' cpu %s.cpu_user stacked 20020 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
3362 for (w = root; w ; w = w->next) {
3363 if(unlikely(w->exposed))
3326 - fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, system_hz * RATES_DETAIL / 100LLU);
3364 + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, time_factor * RATES_DETAIL / 100LLU);
3365 }
3366
3367 fprintf(stdout, "CHART %s.cpu_system '' '%s CPU System Time (%d%% = %d core%s)' 'percentage' cpu %s.cpu_system stacked 20021 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
3368 for (w = root; w ; w = w->next) {
3369 if(unlikely(w->exposed))
3332 - fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, system_hz * RATES_DETAIL / 100LLU);
3370 + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, time_factor * RATES_DETAIL / 100LLU);
3371 }
3372
3373 if(show_guest_time) {
3374 fprintf(stdout, "CHART %s.cpu_guest '' '%s CPU Guest Time (%d%% = %d core%s)' 'percentage' cpu %s.cpu_system stacked 20022 %d\n", type, title, (processors * 100), processors, (processors > 1) ? "s" : "", type, update_every);
3375 for (w = root; w; w = w->next) {
3376 if(unlikely(w->exposed))
3339 - fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, system_hz * RATES_DETAIL / 100LLU);
3377 + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, time_factor * RATES_DETAIL / 100LLU);
3378 }
3379 }
3380
@@ -3710,7 +3748,14 @@ int main(int argc, char **argv) {
3748 procfile_adaptive_initial_allocation = 1;
3749
3750 time_t started_t = now_monotonic_sec();
3751 +
3752 get_system_HZ();
3753 +#ifdef __FreeBSD__
3754 + time_factor = 1000000ULL / RATES_DETAIL; // FreeBSD uses usecs
3755 +#else
3756 + time_factor = system_hz; // Linux uses clock ticks
3757 +#endif
3758 +
3759 get_system_pid_max();
3760 get_system_cpus();
3761