6
* Released under GPL v3+
7
*/
8
9
+#include "collectors/all.h"
10
#include "libnetdata/libnetdata.h"
11
#include "libnetdata/required_dummies.h"
12
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)
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;
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;
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);
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
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));
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])
1495
p->cstime = 0;
1496
p->cgtime = 0;
1497
}
1457
-
1498
+ update_proc_state_count(p->state);
1499
return 1;
1500
1501
cleanup:
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
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
}
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
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
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
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