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