@cryptotaxi247 / netdata-1 / commits / 13b8b1114

feat(apps.plugin): collect context switches (#15002)

Ilya Mashchenko committed May 4, 2023 at 17:52 UTC 13b8b1114ec66044d4a3d9f01b5c34cdad8f1999
2 files changed +95
collectors/apps.plugin/apps_plugin.c
+89
@@ -251,6 +251,8 @@ struct target {
251 kernel_uint_t status_rssfile;
252 kernel_uint_t status_rssshmem;
253 kernel_uint_t status_vmswap;
254 + kernel_uint_t status_voluntary_ctxt_switches;
255 + kernel_uint_t status_nonvoluntary_ctxt_switches;
256
257 kernel_uint_t io_logical_bytes_read;
258 kernel_uint_t io_logical_bytes_written;
@@ -381,12 +383,17 @@ struct pid_stat {
383 uid_t uid;
384 gid_t gid;
385
386 + kernel_uint_t status_voluntary_ctxt_switches_raw;
387 + kernel_uint_t status_nonvoluntary_ctxt_switches_raw;
388 +
389 kernel_uint_t status_vmsize;
390 kernel_uint_t status_vmrss;
391 kernel_uint_t status_vmshared;
392 kernel_uint_t status_rssfile;
393 kernel_uint_t status_rssshmem;
394 kernel_uint_t status_vmswap;
395 + kernel_uint_t status_voluntary_ctxt_switches;
396 + kernel_uint_t status_nonvoluntary_ctxt_switches;
397 #ifndef __FreeBSD__
398 ARL_BASE *status_arl;
399 #endif
@@ -1263,6 +1270,26 @@ void arl_callback_status_rssshmem(const char *name, uint32_t hash, const char *v
1270 aptr->p->status_rssshmem = str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1));
1271 }
1272
1273 +void arl_callback_status_voluntary_ctxt_switches(const char *name, uint32_t hash, const char *value, void *dst) {
1274 + (void)name; (void)hash; (void)value;
1275 + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
1276 + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 2)) return;
1277 +
1278 + struct pid_stat *p = aptr->p;
1279 + pid_incremental_rate(
1280 + stat, p->status_voluntary_ctxt_switches, str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)));
1281 +}
1282 +
1283 +void arl_callback_status_nonvoluntary_ctxt_switches(const char *name, uint32_t hash, const char *value, void *dst) {
1284 + (void)name; (void)hash; (void)value;
1285 + struct arl_callback_ptr *aptr = (struct arl_callback_ptr *)dst;
1286 + if(unlikely(procfile_linewords(aptr->ff, aptr->line) < 2)) return;
1287 +
1288 + struct pid_stat *p = aptr->p;
1289 + pid_incremental_rate(
1290 + stat, p->status_nonvoluntary_ctxt_switches, str2kernel_uint_t(procfile_lineword(aptr->ff, aptr->line, 1)));
1291 +}
1292 +
1293 static void update_proc_state_count(char proc_state) {
1294 switch (proc_state) {
1295 case 'S':
@@ -1293,6 +1320,8 @@ static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) {
1320 p->status_rssfile = 0;
1321 p->status_rssshmem = 0;
1322 p->status_vmswap = 0;
1323 + p->status_voluntary_ctxt_switches = 0;
1324 + p->status_nonvoluntary_ctxt_switches = 0;
1325
1326 #ifdef __FreeBSD__
1327 struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
@@ -1318,6 +1347,8 @@ static inline int read_proc_pid_status(struct pid_stat *p, void *ptr) {
1347 arl_expect_custom(p->status_arl, "RssFile", arl_callback_status_rssfile, &arl_ptr);
1348 arl_expect_custom(p->status_arl, "RssShmem", arl_callback_status_rssshmem, &arl_ptr);
1349 arl_expect_custom(p->status_arl, "VmSwap", arl_callback_status_vmswap, &arl_ptr);
1350 + arl_expect_custom(p->status_arl, "voluntary_ctxt_switches", arl_callback_status_voluntary_ctxt_switches, &arl_ptr);
1351 + arl_expect_custom(p->status_arl, "nonvoluntary_ctxt_switches", arl_callback_status_nonvoluntary_ctxt_switches, &arl_ptr);
1352 }
1353
1354
@@ -2905,6 +2936,8 @@ static size_t zero_all_targets(struct target *root) {
2936 w->status_rssfile = 0;
2937 w->status_rssshmem = 0;
2938 w->status_vmswap = 0;
2939 + w->status_voluntary_ctxt_switches = 0;
2940 + w->status_nonvoluntary_ctxt_switches = 0;
2941
2942 w->io_logical_bytes_read = 0;
2943 w->io_logical_bytes_written = 0;
@@ -3095,6 +3128,8 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p,
3128 w->status_rssfile += p->status_rssfile;
3129 w->status_rssshmem += p->status_rssshmem;
3130 w->status_vmswap += p->status_vmswap;
3131 + w->status_voluntary_ctxt_switches += p->status_voluntary_ctxt_switches;
3132 + w->status_nonvoluntary_ctxt_switches += p->status_nonvoluntary_ctxt_switches;
3133
3134 w->io_logical_bytes_read += p->io_logical_bytes_read;
3135 w->io_logical_bytes_written += p->io_logical_bytes_written;
@@ -3540,6 +3575,22 @@ static void send_collected_data_to_netdata(struct target *root, const char *type
3575 send_END();
3576 }
3577
3578 +#ifndef __FreeBSD__
3579 + send_BEGIN(type, "voluntary_ctxt_switches", dt);
3580 + for (w = root; w ; w = w->next) {
3581 + if(unlikely(w->exposed && w->processes))
3582 + send_SET(w->name, w->status_voluntary_ctxt_switches);
3583 + }
3584 + send_END();
3585 +
3586 + send_BEGIN(type, "involuntary_ctxt_switches", dt);
3587 + for (w = root; w ; w = w->next) {
3588 + if(unlikely(w->exposed && w->processes))
3589 + send_SET(w->name, w->status_nonvoluntary_ctxt_switches);
3590 + }
3591 + send_END();
3592 +#endif
3593 +
3594 send_BEGIN(type, "threads", dt);
3595 for (w = root; w ; w = w->next) {
3596 if(unlikely(w->exposed))
@@ -3822,6 +3873,22 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3873 APPS_PLUGIN_FUNCTIONS();
3874 }
3875
3876 +#ifndef __FreeBSD__
3877 + fprintf(stdout, "CHART %s.voluntary_ctxt_switches '' '%s Voluntary Context Switches' 'switches/s' cpu %s.voluntary_ctxt_switches stacked 20023 %d\n", type, title, type, update_every);
3878 + for (w = root; w ; w = w->next) {
3879 + if(unlikely(w->exposed))
3880 + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
3881 + }
3882 + APPS_PLUGIN_FUNCTIONS();
3883 +
3884 + fprintf(stdout, "CHART %s.involuntary_ctxt_switches '' '%s Involuntary Context Switches' 'switches/s' cpu %s.involuntary_ctxt_switches stacked 20024 %d\n", type, title, type, update_every);
3885 + for (w = root; w ; w = w->next) {
3886 + if(unlikely(w->exposed))
3887 + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
3888 + }
3889 + APPS_PLUGIN_FUNCTIONS();
3890 +#endif
3891 +
3892 #ifndef __FreeBSD__
3893 fprintf(stdout, "CHART %s.swap '' '%s Swap Memory' 'MiB' swap %s.swap stacked 20011 %d\n", type, title, type, update_every);
3894 for (w = root; w ; w = w->next) {
@@ -4426,6 +4493,8 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
4493 unsigned long long
4494 Processes_max = 0
4495 , Threads_max = 0
4496 + , VoluntaryCtxtSwitches_max = 0
4497 + , NonVoluntaryCtxtSwitches_max = 0
4498 , Uptime_max = 0
4499 , MinFlt_max = 0
4500 , CMinFlt_max = 0
@@ -4527,6 +4596,9 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
4596 add_value_field_ndd_with_max(wb, CSysCPU, (NETDATA_DOUBLE)(p->cstime) / cpu_divisor);
4597 add_value_field_ndd_with_max(wb, CGuestCPU, (NETDATA_DOUBLE)(p->cgtime) / cpu_divisor);
4598
4599 + add_value_field_llu_with_max(wb, VoluntaryCtxtSwitches, p->status_voluntary_ctxt_switches / RATES_DETAIL);
4600 + add_value_field_llu_with_max(wb, NonVoluntaryCtxtSwitches, p->status_nonvoluntary_ctxt_switches / RATES_DETAIL);
4601 +
4602 // memory MiB
4603 if(MemTotal)
4604 add_value_field_ndd_with_max(wb, Memory, (NETDATA_DOUBLE)p->status_vmrss * 100.0 / (NETDATA_DOUBLE)MemTotal);
@@ -4610,6 +4682,10 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
4682 add_table_field(wb, "CSysCPU", "Children System CPU Time (100% = 1 core)", false, "bar-with-integer", "bar", "number", 2, "%", CSysCPU_max, "descending", true, false, false, NULL, "sum", true);
4683 add_table_field(wb, "CGuestCPU", "Children Guest CPU Time (100% = 1 core)", false, "bar-with-integer", "bar", "number", 2, "%", CGuestCPU_max, "descending", true, false, false, NULL, "sum", true);
4684
4685 + // CPU context switches
4686 + add_table_field(wb, "vCtxSwitch", "Voluntary Context Switches", false, "bar-with-integer", "bar", "number", 2, "switches/s", VoluntaryCtxtSwitches_max, "descending", true, false, false, NULL, "sum", true);
4687 + add_table_field(wb, "iCtxSwitch", "Involuntary Context Switches", false, "bar-with-integer", "bar", "number", 2, "switches/s", NonVoluntaryCtxtSwitches_max, "descending", true, false, false, NULL, "sum", true);
4688 +
4689 // memory
4690 if(MemTotal)
4691 add_table_field(wb, "Memory", "Memory Percentage", true, "bar-with-integer", "bar", "number", 2, "%", 100.0, "descending", true, false, false, NULL, "sum", true);
@@ -4684,6 +4760,19 @@ static void apps_plugin_function_processes(const char *transaction, char *functi
4760 }
4761 buffer_json_object_close(wb);
4762
4763 + buffer_json_member_add_object(wb, "CPUCtxSwitches");
4764 + {
4765 + buffer_json_member_add_string(wb, "name", "CPU Context Switches");
4766 + buffer_json_member_add_string(wb, "type", "stacked-bar");
4767 + buffer_json_member_add_array(wb, "columns");
4768 + {
4769 + buffer_json_add_array_item_string(wb, "vCtxSwitch");
4770 + buffer_json_add_array_item_string(wb, "iCtxSwitch");
4771 + }
4772 + buffer_json_array_close(wb);
4773 + }
4774 + buffer_json_object_close(wb);
4775 +
4776 // Memory chart
4777 buffer_json_member_add_object(wb, "Memory");
4778 {
collectors/apps.plugin/metrics.csv
+6
@@ -16,6 +16,8 @@ apps.lreads,,a dimension per app group,"KiB/s","Apps Disk Logical Reads",stacked
16 apps.lwrites,,a dimension per app group,"KiB/s","Apps I/O Logical Writes",stacked,,apps.plugin,
17 apps.threads,,a dimension per app group,threads,"Apps Threads",stacked,,apps.plugin,
18 apps.processes,,a dimension per app group,processes,"Apps Processes",stacked,,apps.plugin,
19 +apps.voluntary_ctxt_switches,,a dimension per app group,processes,"Apps Voluntary Context Switches",stacked,,apps.plugin,
20 +apps.involuntary_ctxt_switches,,a dimension per app group,processes,"Apps Involuntary Context Switches",stacked,,apps.plugin,
21 apps.uptime,,a dimension per app group,seconds,"Apps Carried Over Uptime",line,,apps.plugin,
22 apps.uptime_min,,a dimension per app group,seconds,"Apps Minimum Uptime",line,,apps.plugin,
23 apps.uptime_avg,,a dimension per app group,seconds,"Apps Average Uptime",line,,apps.plugin,
@@ -39,6 +41,8 @@ groups.lreads,,a dimension per user group,"KiB/s","User Groups Disk Logical Read
41 groups.lwrites,,a dimension per user group,"KiB/s","User Groups I/O Logical Writes",stacked,,apps.plugin,
42 groups.threads,,a dimension per user group,threads,"User Groups Threads",stacked,,apps.plugin,
43 groups.processes,,a dimension per user group,processes,"User Groups Processes",stacked,,apps.plugin,
44 +groups.voluntary_ctxt_switches,,a dimension per app group,processes,"User Groups Voluntary Context Switches",stacked,,apps.plugin,
45 +groups.involuntary_ctxt_switches,,a dimension per app group,processes,"User Groups Involuntary Context Switches",stacked,,apps.plugin,
46 groups.uptime,,a dimension per user group,seconds,"User Groups Carried Over Uptime",line,,apps.plugin,
47 groups.uptime_min,,a dimension per user group,seconds,"User Groups Minimum Uptime",line,,apps.plugin,
48 groups.uptime_avg,,a dimension per user group,seconds,"User Groups Average Uptime",line,,apps.plugin,
@@ -62,6 +66,8 @@ users.lreads,,a dimension per user,"KiB/s","Users Disk Logical Reads",stacked,,a
66 users.lwrites,,a dimension per user,"KiB/s","Users I/O Logical Writes",stacked,,apps.plugin,
67 users.threads,,a dimension per user,threads,"Users Threads",stacked,,apps.plugin,
68 users.processes,,a dimension per user,processes,"Users Processes",stacked,,apps.plugin,
69 +users.voluntary_ctxt_switches,,a dimension per app group,processes,"Users Voluntary Context Switches",stacked,,apps.plugin,
70 +users.involuntary_ctxt_switches,,a dimension per app group,processes,"Users Involuntary Context Switches",stacked,,apps.plugin,
71 users.uptime,,a dimension per user,seconds,"Users Carried Over Uptime",line,,apps.plugin,
72 users.uptime_min,,a dimension per user,seconds,"Users Minimum Uptime",line,,apps.plugin,
73 users.uptime_avg,,a dimension per user,seconds,"Users Average Uptime",line,,apps.plugin,