@cryptotaxi247 / netdata-1 / commits / 64375154f

introduce new chart for process states metrics (#12305)

* 12139: introduce new chart for process states metrics This commit introduces new chart for total number of processes in different states i.e running, sleeping, sleeping_d, zombie and stopped. * fix recursive chart generation issue * fix recursive chart addition * fixing comments * Update web/gui/dashboard_info.js Co-authored-by: Ilya Mashchenko <ilya@netdata.cloud> * Update collectors/apps.plugin/apps_plugin.c Co-authored-by: Ilya Mashchenko <ilya@netdata.cloud> * fixing commenets * Apply suggestions from code review * Update collectors/apps.plugin/apps_plugin.c * Update collectors/apps.plugin/apps_plugin.c Co-authored-by: Timotej S. <6674623+underhood@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Tina Luedtke <kickoke@users.noreply.github.com> Co-authored-by: Ilya Mashchenko <ilya@netdata.cloud> Co-authored-by: Timotej S. <6674623+underhood@users.noreply.github.com> Co-authored-by: Tina Luedtke <kickoke@users.noreply.github.com>

Suraj Neupane committed Mar 8, 2022 at 08:33 UTC 64375154fe518342e50c8d0608992ad374fa6a31
3 files changed +89 -9
collectors/all.h
+1
@@ -30,6 +30,7 @@
30 #define NETDATA_CHART_PRIO_SYSTEM_IP 501
31 #define NETDATA_CHART_PRIO_SYSTEM_IPV6 502
32 #define NETDATA_CHART_PRIO_SYSTEM_PROCESSES 600
33 +#define NETDATA_CHART_PRIO_SYSTEM_PROCESS_STATES 601
34 #define NETDATA_CHART_PRIO_SYSTEM_FORKS 700
35 #define NETDATA_CHART_PRIO_SYSTEM_ACTIVE_PROCESSES 750
36 #define NETDATA_CHART_PRIO_SYSTEM_CTXT 800
collectors/apps.plugin/apps_plugin.c
+75 -9
@@ -6,6 +6,7 @@
6 * Released under GPL v3+
7 */
8
9 +#include "collectors/all.h"
10 #include "libnetdata/libnetdata.h"
11 #include "libnetdata/required_dummies.h"
12
@@ -107,6 +108,25 @@ static int
108 static char *user_config_dir = CONFIG_DIR;
109 static char *stock_config_dir = LIBCONFIG_DIR;
110
111 +// some variables for keeping track of processes count by states
112 +typedef enum {
113 + PROC_STATUS_RUNNING = 0,
114 + PROC_STATUS_SLEEPING_D, // uninterruptible sleep
115 + PROC_STATUS_SLEEPING, // interruptible sleep
116 + PROC_STATUS_ZOMBIE,
117 + PROC_STATUS_STOPPED,
118 + PROC_STATUS_END, //place holder for ending enum fields
119 +} proc_state;
120 +
121 +static proc_state proc_state_count[PROC_STATUS_END];
122 +static const char *proc_states[] = {
123 + [PROC_STATUS_RUNNING] = "running",
124 + [PROC_STATUS_SLEEPING] = "sleeping_interruptible",
125 + [PROC_STATUS_SLEEPING_D] = "sleeping_uninterruptible",
126 + [PROC_STATUS_ZOMBIE] = "zombie",
127 + [PROC_STATUS_STOPPED] = "stopped",
128 + };
129 +
130 // ----------------------------------------------------------------------------
131 // internal flags
132 // handled in code (automatically set)
@@ -286,7 +306,7 @@ struct pid_stat {
306
307 uint32_t log_thrown;
308
289 - // char state;
309 + char state;
310 int32_t ppid;
311 // int32_t pgrp;
312 // int32_t session;
@@ -1234,6 +1254,28 @@ void arl_callback_status_rssshmem(const char *name, uint32_t hash, const char *v
1254 }
1255 #endif // !__FreeBSD__
1256
1257 +static void update_proc_state_count(char proc_state) {
1258 + switch (proc_state) {
1259 + case 'S':
1260 + proc_state_count[PROC_STATUS_SLEEPING] += 1;
1261 + break;
1262 + case 'R':
1263 + proc_state_count[PROC_STATUS_RUNNING] += 1;
1264 + break;
1265 + case 'D':
1266 + proc_state_count[PROC_STATUS_SLEEPING_D] += 1;
1267 + break;
1268 + case 'Z':
1269 + proc_state_count[PROC_STATUS_ZOMBIE] += 1;
1270 + break;
1271 + case 'T':
1272 + proc_state_count[PROC_STATUS_STOPPED] += 1;
1273 + break;
1274 + default:
1275 + break;
1276 + }
1277 +}
1278 +
1279 static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) {
1280 p->status_vmsize = 0;
1281 p->status_vmrss = 0;
@@ -1268,6 +1310,7 @@ static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) {
1310 arl_expect_custom(p->status_arl, "VmSwap", arl_callback_status_vmswap, &arl_ptr);
1311 }
1312
1313 +
1314 if(unlikely(!p->status_filename)) {
1315 char filename[FILENAME_MAX + 1];
1316 snprintfz(filename, FILENAME_MAX, "%s/proc/%d/status", netdata_configured_host_prefix, p->pid);
@@ -1313,7 +1356,6 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
1356
1357 #ifdef __FreeBSD__
1358 struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
1316 -
1359 if (unlikely(proc_info->ki_tdflags & TDF_IDLETD))
1360 goto cleanup;
1361 #else
@@ -1348,7 +1390,7 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
1390 #else
1391 // p->pid = str2pid_t(procfile_lineword(ff, 0, 0));
1392 char *comm = procfile_lineword(ff, 0, 1);
1351 - // p->state = *(procfile_lineword(ff, 0, 2));
1393 + p->state = *(procfile_lineword(ff, 0, 2));
1394 p->ppid = (int32_t)str2pid_t(procfile_lineword(ff, 0, 3));
1395 // p->pgrp = (int32_t)str2pid_t(procfile_lineword(ff, 0, 4));
1396 // p->session = (int32_t)str2pid_t(procfile_lineword(ff, 0, 5));
@@ -1356,7 +1398,6 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
1398 // p->tpgid = (int32_t)str2pid_t(procfile_lineword(ff, 0, 7));
1399 // p->flags = str2uint64_t(procfile_lineword(ff, 0, 8));
1400 #endif
1359 -
1401 if(strcmp(p->comm, comm) != 0) {
1402 if(unlikely(debug_enabled)) {
1403 if(p->comm[0])
@@ -1454,7 +1495,7 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
1495 p->cstime = 0;
1496 p->cgtime = 0;
1497 }
1457 -
1498 + update_proc_state_count(p->state);
1499 return 1;
1500
1501 cleanup:
@@ -2534,6 +2575,8 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) {
2575 static int collect_data_for_all_processes(void) {
2576 struct pid_stat *p = NULL;
2577
2578 + // clear process state counter
2579 + memset(proc_state_count, 0, sizeof proc_state_count);
2580 #ifdef __FreeBSD__
2581 int i, procnum;
2582
@@ -2608,8 +2651,9 @@ static int collect_data_for_all_processes(void) {
2651 // we forward read all running processes
2652 // collect_data_for_pid() is smart enough,
2653 // not to read the same pid twice per iteration
2611 - for(slc = 0; slc < all_pids_count; slc++)
2654 + for(slc = 0; slc < all_pids_count; slc++) {
2655 collect_data_for_pid(all_pids_sortlist[slc], NULL);
2656 + }
2657 }
2658 #endif
2659 }
@@ -2666,7 +2710,6 @@ static int collect_data_for_all_processes(void) {
2710 // we do this by collecting the ownership of process
2711 // if we manage to get the ownership, the process still runs
2712 process_exited_processes();
2669 -
2713 return 1;
2714 }
2715
@@ -3640,7 +3683,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3683 debug_log_int("%s just added - regenerating charts.", w->name);
3684 }
3685 }
3643 -
3686 +
3687 // nothing more to show
3688 if(!newly_added && show_guest_time == show_guest_time_old) return;
3689
@@ -3806,6 +3849,29 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3849 }
3850 }
3851
3852 +static void send_proc_states_count(usec_t dt)
3853 +{
3854 + static bool chart_added = false;
3855 + // create chart for count of processes in different states
3856 + if (!chart_added) {
3857 + fprintf(
3858 + stdout,
3859 + "CHART system.processes_state '' 'System Processes State' 'processes' processes system.processes_state line %d %d\n",
3860 + NETDATA_CHART_PRIO_SYSTEM_PROCESS_STATES,
3861 + update_every);
3862 + for (proc_state i = PROC_STATUS_RUNNING; i < PROC_STATUS_END; i++) {
3863 + fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", proc_states[i]);
3864 + }
3865 + chart_added = true;
3866 + }
3867 +
3868 + // send process state count
3869 + send_BEGIN("system", "processes_state", dt);
3870 + for (proc_state i = PROC_STATUS_RUNNING; i < PROC_STATUS_END; i++) {
3871 + send_SET(proc_states[i], proc_state_count[i]);
3872 + }
3873 + send_END();
3874 +}
3875
3876 // ----------------------------------------------------------------------------
3877 // parse command line arguments
@@ -4181,10 +4247,10 @@ int main(int argc, char **argv) {
4247 normalize_utilization(apps_groups_root_target);
4248
4249 send_resource_usage_to_netdata(dt);
4250 + send_proc_states_count(dt);
4251
4252 // this is smart enough to show only newly added apps, when needed
4253 send_charts_updates_to_netdata(apps_groups_root_target, "apps", "Apps");
4187 -
4254 if(likely(enable_users_charts))
4255 send_charts_updates_to_netdata(users_root_target, "users", "Users");
4256
web/gui/dashboard_info.js
+13
@@ -1218,6 +1218,19 @@ netdataDashboard.context = {
1218 '<b>Blocked</b> - currently blocked, waiting for I/O to complete.</p>'
1219 },
1220
1221 + 'system.processes_state': {
1222 + info: '<p>The number of processes in different states. </p> '+
1223 + '<p><b>Running</b> - Process using the CPU at a particular moment. '+
1224 + '<b>Sleeping (uninterruptible)</b> - Process will wake when a waited-upon resource becomes available or after a time-out occurs during that wait. '+
1225 + 'Mostly used by device drivers waiting for disk or network I/O. '+
1226 + '<b>Sleeping (interruptible)</b> - Process is waiting either for a particular time slot or for a particular event to occur. '+
1227 + '<b>Zombie</b> - Process that has completed its execution, released the system resources, but its entry is not removed from the process table. '+
1228 + 'Usually occurs in child processes when the parent process still needs to read its child’s exit status. '+
1229 + 'A process that stays a zombie for a long time is generally an error and causes system PID space leak. '+
1230 + '<b>Stopped</b> - Process is suspended from proceeding further due to STOP or TSTP signals. ' +
1231 + 'In this state, a process will not do anything (not even terminate) until it receives a CONT signal.</p>'
1232 + },
1233 +
1234 'system.active_processes': {
1235 info: 'The total number of processes in the system.'
1236 },