@cryptotaxi247 / netdata-1 / commits / 9c4e17dd0

Integrate eBPF and cgroup (consumer side) (#11573)

thiagoftsm committed Oct 1, 2021 at 10:45 UTC 9c4e17dd00de645d7943f358c89dac8dccf2b785
23 files changed +874 -135
CMakeLists.txt
+2
@@ -518,6 +518,8 @@ set(EBPF_PROCESS_PLUGIN_FILES
518 collectors/ebpf.plugin/ebpf_vfs.h
519 collectors/ebpf.plugin/ebpf_apps.c
520 collectors/ebpf.plugin/ebpf_apps.h
521 + collectors/ebpf.plugin/ebpf_cgroup.c
522 + collectors/ebpf.plugin/ebpf_cgroup.h
523 )
524
525 set(PROC_PLUGIN_FILES
Makefile.am
+2
@@ -323,6 +323,8 @@ EBPF_PLUGIN_FILES = \
323 collectors/ebpf.plugin/ebpf.h \
324 collectors/ebpf.plugin/ebpf_apps.c \
325 collectors/ebpf.plugin/ebpf_apps.h \
326 + collectors/ebpf.plugin/ebpf_cgroup.c \
327 + collectors/ebpf.plugin/ebpf_cgroup.h \
328 $(LIBNETDATA_FILES) \
329 $(NULL)
330
collectors/cgroups.plugin/sys_fs_cgroup.c
-2
@@ -4143,7 +4143,6 @@ static void cgroup_main_cleanup(void *ptr) {
4143
4144 if (shm_mutex_cgroup_ebpf != SEM_FAILED) {
4145 sem_close(shm_mutex_cgroup_ebpf);
4146 - sem_unlink(NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME);
4146 }
4147
4148 if (shm_cgroup_ebpf.header) {
@@ -4152,7 +4151,6 @@ static void cgroup_main_cleanup(void *ptr) {
4151
4152 if (shm_fd_cgroup_ebpf > 0) {
4153 close(shm_fd_cgroup_ebpf);
4155 - shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME);
4154 }
4155
4156 static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
collectors/ebpf.plugin/ebpf.c
+113 -88
@@ -76,89 +76,95 @@ pthread_cond_t collect_data_cond_var;
76
77 ebpf_module_t ebpf_modules[] = {
78 { .thread_name = "process", .config_name = "process", .enabled = 0, .start_routine = ebpf_process_thread,
79 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
80 - .optional = 0, .apps_routine = ebpf_process_create_apps_charts, .maps = NULL,
79 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
80 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_process_create_apps_charts, .maps = NULL,
81 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &process_config,
82 .config_file = NETDATA_PROCESS_CONFIG_FILE},
83 { .thread_name = "socket", .config_name = "socket", .enabled = 0, .start_routine = ebpf_socket_thread,
84 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
85 - .optional = 0, .apps_routine = ebpf_socket_create_apps_charts, .maps = NULL,
84 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
85 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_socket_create_apps_charts, .maps = NULL,
86 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &socket_config,
87 .config_file = NETDATA_NETWORK_CONFIG_FILE},
88 { .thread_name = "cachestat", .config_name = "cachestat", .enabled = 0, .start_routine = ebpf_cachestat_thread,
89 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
90 - .optional = 0, .apps_routine = ebpf_cachestat_create_apps_charts, .maps = NULL,
89 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
90 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_cachestat_create_apps_charts, .maps = NULL,
91 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &cachestat_config,
92 .config_file = NETDATA_CACHESTAT_CONFIG_FILE},
93 { .thread_name = "sync", .config_name = "sync", .enabled = 0, .start_routine = ebpf_sync_thread,
94 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
95 - .optional = 0, .apps_routine = NULL, .maps = NULL,
94 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
95 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
96 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &sync_config,
97 .config_file = NETDATA_SYNC_CONFIG_FILE},
98 { .thread_name = "dc", .config_name = "dc", .enabled = 0, .start_routine = ebpf_dcstat_thread,
99 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
100 - .optional = 0, .apps_routine = ebpf_dcstat_create_apps_charts, .maps = NULL,
99 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
100 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_dcstat_create_apps_charts, .maps = NULL,
101 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &dcstat_config,
102 .config_file = NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE},
103 { .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
104 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
105 - .optional = 0, .apps_routine = ebpf_swap_create_apps_charts, .maps = NULL,
104 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
105 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_swap_create_apps_charts, .maps = NULL,
106 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
107 .config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE},
108 { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
109 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
110 - .optional = 0, .apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL,
109 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
110 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL,
111 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config,
112 .config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE },
113 { .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread,
114 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
115 - .optional = 0, .apps_routine = NULL, .maps = NULL,
114 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
115 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
116 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config,
117 .config_file = NETDATA_FILESYSTEM_CONFIG_FILE},
118 { .thread_name = "disk", .config_name = "disk", .enabled = 0, .start_routine = ebpf_disk_thread,
119 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
120 - .optional = 0, .apps_routine = NULL, .maps = NULL,
119 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
120 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
121 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config,
122 .config_file = NETDATA_DISK_CONFIG_FILE},
123 { .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread,
124 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
125 - .optional = 0, .apps_routine = NULL, .maps = NULL,
124 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
125 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
126 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config,
127 .config_file = NETDATA_MOUNT_CONFIG_FILE},
128 { .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread,
129 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
130 - .optional = 0, .apps_routine = ebpf_fd_create_apps_charts, .maps = NULL,
129 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
130 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_fd_create_apps_charts, .maps = NULL,
131 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fd_config,
132 .config_file = NETDATA_FD_CONFIG_FILE},
133 { .thread_name = "hardirq", .config_name = "hardirq", .enabled = 0, .start_routine = ebpf_hardirq_thread,
134 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
135 - .optional = 0, .apps_routine = NULL, .maps = NULL,
134 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
135 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
136 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &hardirq_config,
137 .config_file = NETDATA_HARDIRQ_CONFIG_FILE},
138 { .thread_name = "softirq", .config_name = "softirq", .enabled = 0, .start_routine = ebpf_softirq_thread,
139 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
140 - .optional = 0, .apps_routine = NULL, .maps = NULL,
139 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
140 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
141 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &softirq_config,
142 .config_file = NETDATA_SOFTIRQ_CONFIG_FILE},
143 { .thread_name = "oomkill", .config_name = "oomkill", .enabled = 0, .start_routine = ebpf_oomkill_thread,
144 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
145 - .optional = 0, .apps_routine = ebpf_oomkill_create_apps_charts, .maps = NULL,
144 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
145 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_oomkill_create_apps_charts, .maps = NULL,
146 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &oomkill_config,
147 .config_file = NETDATA_OOMKILL_CONFIG_FILE},
148 { .thread_name = "shm", .config_name = "shm", .enabled = 0, .start_routine = ebpf_shm_thread,
149 - .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
150 - .optional = 0, .apps_routine = ebpf_shm_create_apps_charts, .maps = NULL,
149 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
150 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = ebpf_shm_create_apps_charts, .maps = NULL,
151 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &shm_config,
152 .config_file = NETDATA_DIRECTORY_SHM_CONFIG_FILE},
153 { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_time = 1,
154 - .global_charts = 0, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
155 - .optional = 0, .apps_routine = NULL, .maps = NULL, .pid_map_size = 0, .names = NULL,
154 + .global_charts = 0, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO,
155 + .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL, .pid_map_size = 0, .names = NULL,
156 .cfg = NULL, .config_name = NULL},
157 };
158
159 // Link with apps.plugin
160 ebpf_process_stat_t *global_process_stat = NULL;
161
162 +// Link with cgroup.plugin
163 +netdata_ebpf_cgroup_shm_t shm_ebpf_cgroup = {NULL, NULL};
164 +int shm_fd_ebpf_cgroup = -1;
165 +sem_t *shm_sem_ebpf_cgroup = SEM_FAILED;
166 +pthread_mutex_t mutex_cgroup_shm;
167 +
168 //Network viewer
169 ebpf_network_viewer_options_t network_viewer_opt;
170
@@ -236,6 +242,9 @@ static void ebpf_exit(int sig)
242 freez(shm_pid);
243 }
244
245 + ebpf_close_cgroup_shm();
246 +
247 + ebpf_clean_cgroup_pids();
248 /*
249 int ret = fork();
250 if (ret < 0) // error
@@ -642,28 +651,36 @@ static inline void ebpf_set_thread_mode(netdata_run_mode_t lmode)
651 /**
652 * Enable specific charts selected by user.
653 *
645 - * @param em the structure that will be changed
646 - * @param enable the status about the apps charts.
654 + * @param em the structure that will be changed
655 + * @param disable_apps the status about the apps charts.
656 + * @param disable_cgroup the status about the cgroups charts.
657 */
648 -static inline void ebpf_enable_specific_chart(struct ebpf_module *em, int enable)
658 +static inline void ebpf_enable_specific_chart(struct ebpf_module *em, int disable_apps, int disable_cgroup)
659 {
650 - em->enabled = 1;
651 - if (!enable) {
652 - em->apps_charts = 1;
660 + em->enabled = CONFIG_BOOLEAN_YES;
661 +
662 + if (!disable_apps) {
663 + em->apps_charts = CONFIG_BOOLEAN_YES;
664 }
654 - em->global_charts = 1;
665 +
666 + if (!disable_cgroup) {
667 + em->cgroup_charts = CONFIG_BOOLEAN_YES;
668 + }
669 +
670 + em->global_charts = CONFIG_BOOLEAN_YES;
671 }
672
673 /**
674 * Enable all charts
675 *
660 - * @param apps what is the current status of apps
676 + * @param apps what is the current status of apps
677 + * @param cgroups what is the current status of cgroups
678 */
662 -static inline void ebpf_enable_all_charts(int apps)
679 +static inline void ebpf_enable_all_charts(int apps, int cgroups)
680 {
681 int i;
682 for (i = 0; ebpf_modules[i].thread_name; i++) {
666 - ebpf_enable_specific_chart(&ebpf_modules[i], apps);
683 + ebpf_enable_specific_chart(&ebpf_modules[i], apps, cgroups);
684 }
685 }
686
@@ -673,12 +690,12 @@ static inline void ebpf_enable_all_charts(int apps)
690 * @param idx the index of ebpf_modules that I am enabling
691 * @param disable_apps should I keep apps charts?
692 */
676 -static inline void ebpf_enable_chart(int idx, int disable_apps)
693 +static inline void ebpf_enable_chart(int idx, int disable_apps, int disable_cgroup)
694 {
695 int i;
696 for (i = 0; ebpf_modules[i].thread_name; i++) {
697 if (i == idx) {
681 - ebpf_enable_specific_chart(&ebpf_modules[i], disable_apps);
698 + ebpf_enable_specific_chart(&ebpf_modules[i], disable_apps, disable_cgroup);
699 break;
700 }
701 }
@@ -728,9 +745,9 @@ void ebpf_print_help()
745 "\n"
746 " --version or -v Show software version.\n"
747 "\n"
731 - " --global or -g Disable charts per application.\n"
748 + " --global or -g Disable charts per application and cgroup.\n"
749 "\n"
733 - " --all or -a Enable all chart groups (global and apps), unless -g is also given.\n"
750 + " --all or -a Enable all chart groups (global, apps, and cgroup), unless -g is also given.\n"
751 "\n"
752 " --cachestat or -c Enable charts related to process run time.\n"
753 "\n"
@@ -1031,9 +1048,10 @@ static void ebpf_update_table_size()
1048 /**
1049 * Read collector values
1050 *
1034 - * @param disable_apps variable to store information related to apps.
1051 + * @param disable_apps variable to store information related to apps.
1052 + * @param disable_cgroups variable to store information related to cgroups.
1053 */
1036 -static void read_collector_values(int *disable_apps)
1054 +static void read_collector_values(int *disable_apps, int *disable_cgroups)
1055 {
1056 // Read global section
1057 char *value;
@@ -1061,12 +1079,17 @@ static void read_collector_values(int *disable_apps)
1079 }
1080 *disable_apps = (int)enabled;
1081
1082 + // Cgroup is a positive sentence, so we need to invert the values to disable apps.
1083 + // We are using the same pattern for cgroup and apps
1084 + enabled = appconfig_get_boolean(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_CGROUP, CONFIG_BOOLEAN_NO);
1085 + *disable_cgroups = (enabled == CONFIG_BOOLEAN_NO)?CONFIG_BOOLEAN_YES:CONFIG_BOOLEAN_NO;
1086 +
1087 // Read ebpf programs section
1088 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION,
1089 ebpf_modules[EBPF_MODULE_PROCESS_IDX].config_name, CONFIG_BOOLEAN_YES);
1090 int started = 0;
1091 if (enabled) {
1069 - ebpf_enable_chart(EBPF_MODULE_PROCESS_IDX, *disable_apps);
1092 + ebpf_enable_chart(EBPF_MODULE_PROCESS_IDX, *disable_apps, *disable_cgroups);
1093 started++;
1094 }
1095
@@ -1079,7 +1102,7 @@ static void read_collector_values(int *disable_apps)
1102 CONFIG_BOOLEAN_NO);
1103
1104 if (enabled) {
1082 - ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, *disable_apps);
1105 + ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, *disable_apps, *disable_cgroups);
1106 // Read network viewer section if network viewer is enabled
1107 // This is kept here to keep backward compatibility
1108 parse_network_viewer_section(&collector_config);
@@ -1093,13 +1116,13 @@ static void read_collector_values(int *disable_apps)
1116 if (!enabled)
1117 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "network connections",
1118 CONFIG_BOOLEAN_NO);
1096 - ebpf_modules[EBPF_MODULE_SOCKET_IDX].optional = enabled;
1119 + ebpf_modules[EBPF_MODULE_SOCKET_IDX].optional = (int)enabled;
1120
1121 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "cachestat",
1122 CONFIG_BOOLEAN_NO);
1123
1124 if (enabled) {
1102 - ebpf_enable_chart(EBPF_MODULE_CACHESTAT_IDX, *disable_apps);
1125 + ebpf_enable_chart(EBPF_MODULE_CACHESTAT_IDX, *disable_apps, *disable_cgroups);
1126 started++;
1127 }
1128
@@ -1107,89 +1130,89 @@ static void read_collector_values(int *disable_apps)
1130 CONFIG_BOOLEAN_YES);
1131
1132 if (enabled) {
1110 - ebpf_enable_chart(EBPF_MODULE_SYNC_IDX, *disable_apps);
1133 + ebpf_enable_chart(EBPF_MODULE_SYNC_IDX, *disable_apps, *disable_cgroups);
1134 started++;
1135 }
1136
1137 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "dcstat",
1138 CONFIG_BOOLEAN_NO);
1139 if (enabled) {
1117 - ebpf_enable_chart(EBPF_MODULE_DCSTAT_IDX, *disable_apps);
1140 + ebpf_enable_chart(EBPF_MODULE_DCSTAT_IDX, *disable_apps, *disable_cgroups);
1141 started++;
1142 }
1143
1144 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "swap",
1145 CONFIG_BOOLEAN_NO);
1146 if (enabled) {
1124 - ebpf_enable_chart(EBPF_MODULE_SWAP_IDX, *disable_apps);
1147 + ebpf_enable_chart(EBPF_MODULE_SWAP_IDX, *disable_apps, *disable_cgroups);
1148 started++;
1149 }
1150
1151 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "vfs",
1152 CONFIG_BOOLEAN_NO);
1153 if (enabled) {
1131 - ebpf_enable_chart(EBPF_MODULE_VFS_IDX, *disable_apps);
1154 + ebpf_enable_chart(EBPF_MODULE_VFS_IDX, *disable_apps, *disable_cgroups);
1155 started++;
1156 }
1157
1158 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "filesystem",
1159 CONFIG_BOOLEAN_NO);
1160 if (enabled) {
1138 - ebpf_enable_chart(EBPF_MODULE_FILESYSTEM_IDX, *disable_apps);
1161 + ebpf_enable_chart(EBPF_MODULE_FILESYSTEM_IDX, *disable_apps, *disable_cgroups);
1162 started++;
1163 }
1164
1165 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "disk",
1166 CONFIG_BOOLEAN_NO);
1167 if (enabled) {
1145 - ebpf_enable_chart(EBPF_MODULE_DISK_IDX, *disable_apps);
1168 + ebpf_enable_chart(EBPF_MODULE_DISK_IDX, *disable_apps, *disable_cgroups);
1169 started++;
1170 }
1171
1172 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "mount",
1173 CONFIG_BOOLEAN_YES);
1174 if (enabled) {
1152 - ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, *disable_apps);
1175 + ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, *disable_apps, *disable_cgroups);
1176 started++;
1177 }
1178
1179 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "fd",
1180 CONFIG_BOOLEAN_YES);
1181 if (enabled) {
1159 - ebpf_enable_chart(EBPF_MODULE_FD_IDX, *disable_apps);
1182 + ebpf_enable_chart(EBPF_MODULE_FD_IDX, *disable_apps, *disable_cgroups);
1183 started++;
1184 }
1185
1186 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "hardirq",
1187 CONFIG_BOOLEAN_YES);
1188 if (enabled) {
1166 - ebpf_enable_chart(EBPF_MODULE_HARDIRQ_IDX, *disable_apps);
1189 + ebpf_enable_chart(EBPF_MODULE_HARDIRQ_IDX, *disable_apps, *disable_cgroups);
1190 started++;
1191 }
1192
1193 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "softirq",
1194 CONFIG_BOOLEAN_YES);
1195 if (enabled) {
1173 - ebpf_enable_chart(EBPF_MODULE_SOFTIRQ_IDX, *disable_apps);
1196 + ebpf_enable_chart(EBPF_MODULE_SOFTIRQ_IDX, *disable_apps, *disable_cgroups);
1197 started++;
1198 }
1199
1200 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "oomkill",
1201 CONFIG_BOOLEAN_YES);
1202 if (enabled) {
1180 - ebpf_enable_chart(EBPF_MODULE_OOMKILL_IDX, *disable_apps);
1203 + ebpf_enable_chart(EBPF_MODULE_OOMKILL_IDX, *disable_apps, *disable_cgroups);
1204 started++;
1205 }
1206
1207 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "shm",
1208 CONFIG_BOOLEAN_YES);
1209 if (enabled) {
1187 - ebpf_enable_chart(EBPF_MODULE_SHM_IDX, *disable_apps);
1210 + ebpf_enable_chart(EBPF_MODULE_SHM_IDX, *disable_apps, *disable_cgroups);
1211 started++;
1212 }
1213
1214 if (!started){
1192 - ebpf_enable_all_charts(*disable_apps);
1215 + ebpf_enable_all_charts(*disable_apps, *disable_cgroups);
1216 // Read network viewer section
1217 // This is kept here to keep backward compatibility
1218 parse_network_viewer_section(&collector_config);
@@ -1200,12 +1223,13 @@ static void read_collector_values(int *disable_apps)
1223 /**
1224 * Load collector config
1225 *
1203 - * @param path the path where the file ebpf.conf is stored.
1204 - * @param disable_apps variable to store the information about apps plugin status.
1226 + * @param path the path where the file ebpf.conf is stored.
1227 + * @param disable_apps variable to store the information about apps plugin status.
1228 + * @param disable_cgroups variable to store the information about cgroups plugin status.
1229 *
1230 * @return 0 on success and -1 otherwise.
1231 */
1208 -static int load_collector_config(char *path, int *disable_apps)
1232 +static int load_collector_config(char *path, int *disable_apps, int *disable_cgroups)
1233 {
1234 char lpath[4096];
1235
@@ -1217,7 +1241,7 @@ static int load_collector_config(char *path, int *disable_apps)
1241 }
1242 }
1243
1220 - read_collector_values(disable_apps);
1244 + read_collector_values(disable_apps, disable_cgroups);
1245
1246 return 0;
1247 }
@@ -1265,6 +1289,7 @@ static void parse_args(int argc, char **argv)
1289 {
1290 int enabled = 0;
1291 int disable_apps = 0;
1292 + int disable_cgroups = 0;
1293 int freq = 0;
1294 int option_index = 0;
1295 static struct option long_options[] = {
@@ -1325,7 +1350,7 @@ static void parse_args(int argc, char **argv)
1350 break;
1351 }
1352 case 'a': {
1328 - ebpf_enable_all_charts(disable_apps);
1353 + ebpf_enable_all_charts(disable_apps, disable_cgroups);
1354 #ifdef NETDATA_INTERNAL_CHECKS
1355 info("EBPF running with all chart groups, because it was started with the option \"--all\" or \"-a\".");
1356 #endif
@@ -1333,7 +1358,7 @@ static void parse_args(int argc, char **argv)
1358 }
1359 case 'c': {
1360 enabled = 1;
1336 - ebpf_enable_chart(EBPF_MODULE_CACHESTAT_IDX, disable_apps);
1361 + ebpf_enable_chart(EBPF_MODULE_CACHESTAT_IDX, disable_apps, disable_cgroups);
1362 #ifdef NETDATA_INTERNAL_CHECKS
1363 info(
1364 "EBPF enabling \"CACHESTAT\" charts, because it was started with the option \"--cachestat\" or \"-c\".");
@@ -1342,7 +1367,7 @@ static void parse_args(int argc, char **argv)
1367 }
1368 case 'd': {
1369 enabled = 1;
1345 - ebpf_enable_chart(EBPF_MODULE_DCSTAT_IDX, disable_apps);
1370 + ebpf_enable_chart(EBPF_MODULE_DCSTAT_IDX, disable_apps, disable_cgroups);
1371 #ifdef NETDATA_INTERNAL_CHECKS
1372 info(
1373 "EBPF enabling \"DCSTAT\" charts, because it was started with the option \"--dcstat\" or \"-d\".");
@@ -1351,7 +1376,7 @@ static void parse_args(int argc, char **argv)
1376 }
1377 case 'i': {
1378 enabled = 1;
1354 - ebpf_enable_chart(EBPF_MODULE_FILESYSTEM_IDX, disable_apps);
1379 + ebpf_enable_chart(EBPF_MODULE_FILESYSTEM_IDX, disable_apps, disable_cgroups);
1380 #ifdef NETDATA_INTERNAL_CHECKS
1381 info("EBPF enabling \"filesystem\" chart, because it was started with the option \"--filesystem\" or \"-i\".");
1382 #endif
@@ -1359,7 +1384,7 @@ static void parse_args(int argc, char **argv)
1384 }
1385 case 'q': {
1386 enabled = 1;
1362 - ebpf_enable_chart(EBPF_MODULE_HARDIRQ_IDX, disable_apps);
1387 + ebpf_enable_chart(EBPF_MODULE_HARDIRQ_IDX, disable_apps, disable_cgroups);
1388 #ifdef NETDATA_INTERNAL_CHECKS
1389 info("EBPF enabling \"hardirq\" chart, because it was started with the option \"--hardirq\" or \"-q\".");
1390 #endif
@@ -1367,7 +1392,7 @@ static void parse_args(int argc, char **argv)
1392 }
1393 case 'k': {
1394 enabled = 1;
1370 - ebpf_enable_chart(EBPF_MODULE_DISK_IDX, disable_apps);
1395 + ebpf_enable_chart(EBPF_MODULE_DISK_IDX, disable_apps, disable_cgroups);
1396 #ifdef NETDATA_INTERNAL_CHECKS
1397 info("EBPF enabling \"disk\" chart, because it was started with the option \"--disk\" or \"-k\".");
1398 #endif
@@ -1375,7 +1400,7 @@ static void parse_args(int argc, char **argv)
1400 }
1401 case 'm': {
1402 enabled = 1;
1378 - ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, disable_apps);
1403 + ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, disable_apps, disable_cgroups);
1404 #ifdef NETDATA_INTERNAL_CHECKS
1405 info("EBPF enabling \"mount\" chart, because it was started with the option \"--mount\" or \"-m\".");
1406 #endif
@@ -1383,7 +1408,7 @@ static void parse_args(int argc, char **argv)
1408 }
1409 case 'e': {
1410 enabled = 1;
1386 - ebpf_enable_chart(EBPF_MODULE_FD_IDX, disable_apps);
1411 + ebpf_enable_chart(EBPF_MODULE_FD_IDX, disable_apps, disable_cgroups);
1412 #ifdef NETDATA_INTERNAL_CHECKS
1413 info("EBPF enabling \"filedescriptor\" chart, because it was started with the option \"--filedescriptor\" or \"-e\".");
1414 #endif
@@ -1391,7 +1416,7 @@ static void parse_args(int argc, char **argv)
1416 }
1417 case 'n': {
1418 enabled = 1;
1394 - ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, disable_apps);
1419 + ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, disable_apps, disable_cgroups);
1420 #ifdef NETDATA_INTERNAL_CHECKS
1421 info("EBPF enabling \"NET\" charts, because it was started with the option \"--net\" or \"-n\".");
1422 #endif
@@ -1399,7 +1424,7 @@ static void parse_args(int argc, char **argv)
1424 }
1425 case 'o': {
1426 enabled = 1;
1402 - ebpf_enable_chart(EBPF_MODULE_OOMKILL_IDX, disable_apps);
1427 + ebpf_enable_chart(EBPF_MODULE_OOMKILL_IDX, disable_apps, disable_cgroups);
1428 #ifdef NETDATA_INTERNAL_CHECKS
1429 info("EBPF enabling \"oomkill\" chart, because it was started with the option \"--oomkill\" or \"-o\".");
1430 #endif
@@ -1407,7 +1432,7 @@ static void parse_args(int argc, char **argv)
1432 }
1433 case 'p': {
1434 enabled = 1;
1410 - ebpf_enable_chart(EBPF_MODULE_PROCESS_IDX, disable_apps);
1435 + ebpf_enable_chart(EBPF_MODULE_PROCESS_IDX, disable_apps, disable_cgroups);
1436 #ifdef NETDATA_INTERNAL_CHECKS
1437 info(
1438 "EBPF enabling \"PROCESS\" charts, because it was started with the option \"--process\" or \"-p\".");
@@ -1423,7 +1448,7 @@ static void parse_args(int argc, char **argv)
1448 }
1449 case 'b': {
1450 enabled = 1;
1426 - ebpf_enable_chart(EBPF_MODULE_SHM_IDX, disable_apps);
1451 + ebpf_enable_chart(EBPF_MODULE_SHM_IDX, disable_apps, disable_cgroups);
1452 #ifdef NETDATA_INTERNAL_CHECKS
1453 info("EBPF enabling \"shm\" chart, because it was started with the option \"--shm\" or \"-b\".");
1454 #endif
@@ -1431,7 +1456,7 @@ static void parse_args(int argc, char **argv)
1456 }
1457 case 't': {
1458 enabled = 1;
1434 - ebpf_enable_chart(EBPF_MODULE_SOFTIRQ_IDX, disable_apps);
1459 + ebpf_enable_chart(EBPF_MODULE_SOFTIRQ_IDX, disable_apps, disable_cgroups);
1460 #ifdef NETDATA_INTERNAL_CHECKS
1461 info("EBPF enabling \"softirq\" chart, because it was started with the option \"--softirq\" or \"-t\".");
1462 #endif
@@ -1439,7 +1464,7 @@ static void parse_args(int argc, char **argv)
1464 }
1465 case 's': {
1466 enabled = 1;
1442 - ebpf_enable_chart(EBPF_MODULE_SYNC_IDX, disable_apps);
1467 + ebpf_enable_chart(EBPF_MODULE_SYNC_IDX, disable_apps, disable_cgroups);
1468 #ifdef NETDATA_INTERNAL_CHECKS
1469 info("EBPF enabling \"sync\" chart, because it was started with the option \"--sync\" or \"-s\".");
1470 #endif
@@ -1447,7 +1472,7 @@ static void parse_args(int argc, char **argv)
1472 }
1473 case 'w': {
1474 enabled = 1;
1450 - ebpf_enable_chart(EBPF_MODULE_SWAP_IDX, disable_apps);
1475 + ebpf_enable_chart(EBPF_MODULE_SWAP_IDX, disable_apps, disable_cgroups);
1476 #ifdef NETDATA_INTERNAL_CHECKS
1477 info("EBPF enabling \"swap\" chart, because it was started with the option \"--swap\" or \"-w\".");
1478 #endif
@@ -1455,7 +1480,7 @@ static void parse_args(int argc, char **argv)
1480 }
1481 case 'f': {
1482 enabled = 1;
1458 - ebpf_enable_chart(EBPF_MODULE_VFS_IDX, disable_apps);
1483 + ebpf_enable_chart(EBPF_MODULE_VFS_IDX, disable_apps, disable_cgroups);
1484 #ifdef NETDATA_INTERNAL_CHECKS
1485 info("EBPF enabling \"vfs\" chart, because it was started with the option \"--vfs\" or \"-f\".");
1486 #endif
@@ -1471,11 +1496,11 @@ static void parse_args(int argc, char **argv)
1496 update_every = freq;
1497 }
1498
1474 - if (load_collector_config(ebpf_user_config_dir, &disable_apps)) {
1499 + if (load_collector_config(ebpf_user_config_dir, &disable_apps, &disable_cgroups)) {
1500 info(
1501 "Does not have a configuration file inside `%s/ebpf.d.conf. It will try to load stock file.",
1502 ebpf_user_config_dir);
1478 - if (load_collector_config(ebpf_stock_config_dir, &disable_apps)) {
1503 + if (load_collector_config(ebpf_stock_config_dir, &disable_apps, &disable_cgroups)) {
1504 info("Does not have a stock file. It is starting with default options.");
1505 } else {
1506 enabled = 1;
@@ -1485,7 +1510,7 @@ static void parse_args(int argc, char **argv)
1510 }
1511
1512 if (!enabled) {
1488 - ebpf_enable_all_charts(disable_apps);
1513 + ebpf_enable_all_charts(disable_apps, disable_cgroups);
1514 #ifdef NETDATA_INTERNAL_CHECKS
1515 info("EBPF running with all charts, because neither \"-n\" or \"-p\" was given.");
1516 #endif
collectors/ebpf.plugin/ebpf.d.conf
+5 -3
@@ -6,9 +6,10 @@
6 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
7 # new charts for the return of these functions, such as errors.
8 #
9 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
10 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
11 -# 'no'.
9 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
10 +# or `cgroups.plugin`.
11 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change the setting
12 +# `apps` and `cgroups` to 'no'.
13 #
14 # The `update every` option defines the number of seconds used to read data from kernel and send to netdata
15 #
@@ -17,6 +18,7 @@
18 [global]
19 ebpf load mode = entry
20 apps = yes
21 + cgroups = no
22 update every = 1
23 pid table size = 32768
24
collectors/ebpf.plugin/ebpf.d/cachestat.conf
+5 -3
@@ -3,9 +3,10 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
7 +# or `cgroups.plugin`.
8 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 +# the setting `apps` and `cgroups` to 'no'.
10 #
11 # The `pid table size` defines the maximum number of PIDs stored inside the application hash table.
12 #
@@ -13,5 +14,6 @@
14 [global]
15 # ebpf load mode = entry
16 # apps = yes
17 +# cgroups = no
18 update every = 2
19 # pid table size = 32768
collectors/ebpf.plugin/ebpf.d/dcstat.conf
+5 -3
@@ -3,13 +3,15 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
7 +# or `cgroups.plugin`.
8 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 +# the setting `apps` and `cgroups` to 'no'.
10 #
11 # Uncomment lines to define specific options for thread.
12 [global]
13 # ebpf load mode = entry
14 # apps = yes
15 +# cgroups = no
16 update every = 2
17 # pid table size = 32768
collectors/ebpf.plugin/ebpf.d/disk.conf
-4
@@ -3,10 +3,6 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
9 -#
6 [global]
7 ebpf load mode = entry
8 update every = 2
collectors/ebpf.plugin/ebpf.d/fd.conf
+5 -3
@@ -3,9 +3,10 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
7 +# or `cgroups.plugin`.
8 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 +# the setting `apps` and `cgroups` to 'no'.
10 #
11 # The `pid table size` defines the maximum number of PIDs stored inside the hash table.
12 #
@@ -13,5 +14,6 @@
14 [global]
15 # ebpf load mode = entry
16 # apps = yes
17 +# cgroups = no
18 update every = 1
19 # pid table size = 32768
collectors/ebpf.plugin/ebpf.d/network.conf
+7 -5
@@ -3,9 +3,10 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
7 +# or `cgroups.plugin`.
8 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 +# the setting `apps` and `cgroups` to 'no'.
10 #
11 # The following options change the hash table size:
12 # `bandwidth table size`: Maximum number of connections monitored
@@ -14,8 +15,9 @@
15 # `udp connection table size`: Maximum number of UDP connections monitored
16 #
17 [global]
17 - ebpf load mode = entry
18 - apps = yes
18 +# ebpf load mode = entry
19 +# apps = yes
20 +# cgroups = no
21 update every = 1
22 bandwidth table size = 16384
23 ipv4 connection table size = 16384
collectors/ebpf.plugin/ebpf.d/process.conf
+5 -3
@@ -3,9 +3,10 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
7 +# or `cgroups.plugin`.
8 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 +# the setting `apps` and `cgroups` to 'no'.
10 #
11 # The `pid table size` defines the maximum number of PIDs stored inside the hash table.
12 #
@@ -13,5 +14,6 @@
14 [global]
15 # ebpf load mode = entry
16 # apps = yes
17 +# cgroups = no
18 update every = 1
19 # pid table size = 32768
collectors/ebpf.plugin/ebpf.d/shm.conf
+5 -3
@@ -3,14 +3,16 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
7 +# or `cgroups.plugin`.
8 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 +# the setting `apps` and `cgroups` to 'no'.
10 #
11 # Uncomment lines to define specific options for thread.
12 [global]
13 # ebpf load mode = entry
14 # apps = yes
15 +# cgroups = no
16 update every = 2
17 # pid table size = 32768
18
collectors/ebpf.plugin/ebpf.d/swap.conf
+5 -3
@@ -3,13 +3,15 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
7 +# or `cgroups.plugin`.
8 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 +# the setting `apps` and `cgroups` to 'no'.
10 #
11 # Uncomment lines to define specific options for thread.
12 [global]
13 # ebpf load mode = entry
14 # apps = yes
15 +# cgroups = no
16 update every = 2
17 # pid table size = 32768
collectors/ebpf.plugin/ebpf.d/sync.conf
+7 -5
@@ -3,14 +3,16 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
7 +# or `cgroups.plugin`.
8 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 +# the setting `apps` and `cgroups` to 'no'.
10 #
11 #
12 [global]
12 - ebpf load mode = entry
13 - apps = yes
13 +# ebpf load mode = entry
14 +# apps = yes
15 +# cgroups = no
16 update every = 2
17
18 # List of monitored syscalls
collectors/ebpf.plugin/ebpf.d/vfs.conf
+5 -3
@@ -3,13 +3,15 @@
3 # `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 # new charts for the return of these functions, such as errors.
5 #
6 -# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 -# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 -# 'no'.
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps.plugin`
7 +# or `cgroups.plugin`.
8 +# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 +# the setting `apps` and `cgroups` to 'no'.
10 #
11 # Uncomment lines to define specific options for thread.
12 [global]
13 # ebpf load mode = entry
14 # apps = yes
15 +# cgroups = no
16 update every = 1
17 # pid table size = 32768
collectors/ebpf.plugin/ebpf.h
+6 -1
@@ -30,6 +30,7 @@
30 #include "daemon/main.h"
31
32 #include "ebpf_apps.h"
33 +#include "ebpf_cgroup.h"
34
35 #define NETDATA_EBPF_OLD_CONFIG_FILE "ebpf.conf"
36 #define NETDATA_EBPF_CONFIG_FILE "ebpf.d.conf"
@@ -232,10 +233,14 @@ extern uint32_t ebpf_enable_tracepoints(ebpf_tracepoint_t *tps);
233 // Common variables
234 extern int debug_enabled;
235 extern struct pid_stat *root_of_pids;
236 +extern ebpf_cgroup_target_t *ebpf_cgroup_pids;
237 extern char *ebpf_algorithms[];
238 extern struct config collector_config;
237 -extern struct pid_stat *root_of_pids;
239 extern ebpf_process_stat_t *global_process_stat;
240 +extern netdata_ebpf_cgroup_shm_t shm_ebpf_cgroup;
241 +extern int shm_fd_ebpf_cgroup;
242 +extern sem_t *shm_sem_ebpf_cgroup;
243 +extern pthread_mutex_t mutex_cgroup_shm;
244 extern size_t all_pids_count;
245 extern int update_every;
246 extern uint32_t finalized_threads;
collectors/ebpf.plugin/ebpf_cgroup.c new
+345
@@ -0,0 +1,345 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include <sys/resource.h>
4 +
5 +#include "ebpf.h"
6 +#include "ebpf_cgroup.h"
7 +
8 +ebpf_cgroup_target_t *ebpf_cgroup_pids = NULL;
9 +
10 +// --------------------------------------------------------------------------------------------------------------------
11 +// Map shared memory
12 +
13 +/**
14 + * Map Shared Memory locally
15 + *
16 + * Map the shared memory for current process
17 + *
18 + * @param fd file descriptor returned after shm_open was called.
19 + * @param length length of the shared memory
20 + *
21 + * @return It returns a pointer to the region mapped.
22 + */
23 +static inline void *ebpf_cgroup_map_shm_locally(int fd, size_t length)
24 +{
25 + void *value;
26 +
27 + value = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
28 + if (!value) {
29 + error("Cannot map shared memory used between eBPF and cgroup, integration between processes won't happen");
30 + close(shm_fd_ebpf_cgroup);
31 + shm_fd_ebpf_cgroup = -1;
32 + shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME);
33 + }
34 +
35 + return value;
36 +}
37 +
38 +/**
39 + * Map cgroup shared memory
40 + *
41 + * Map cgroup shared memory from cgroup to plugin
42 + */
43 +void ebpf_map_cgroup_shared_memory()
44 +{
45 + static int limit_try = 0;
46 + static time_t next_try = 0;
47 +
48 + if (shm_ebpf_cgroup.header || limit_try > NETDATA_EBPF_CGROUP_MAX_TRIES)
49 + return;
50 +
51 + time_t curr_time = time(NULL);
52 + if (curr_time < next_try)
53 + return;
54 +
55 + limit_try++;
56 + next_try = curr_time + NETDATA_EBPF_CGROUP_NEXT_TRY_SEC;
57 +
58 + shm_fd_ebpf_cgroup = shm_open(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME, O_RDWR, 0660);
59 + if (shm_fd_ebpf_cgroup < 0) {
60 + if (limit_try == NETDATA_EBPF_CGROUP_MAX_TRIES)
61 + error("Shared memory was not initialized, integration between processes won't happen.");
62 +
63 + return;
64 + }
65 +
66 + // Map only header
67 + shm_ebpf_cgroup.header = (netdata_ebpf_cgroup_shm_header_t *) ebpf_cgroup_map_shm_locally(shm_fd_ebpf_cgroup,
68 + sizeof(netdata_ebpf_cgroup_shm_header_t));
69 + if (!shm_ebpf_cgroup.header) {
70 + limit_try = NETDATA_EBPF_CGROUP_MAX_TRIES + 1;
71 + return;
72 + }
73 +
74 + size_t length = shm_ebpf_cgroup.header->body_length;
75 +
76 + munmap(shm_ebpf_cgroup.header, sizeof(netdata_ebpf_cgroup_shm_header_t));
77 +
78 + shm_ebpf_cgroup.header = (netdata_ebpf_cgroup_shm_header_t *)ebpf_cgroup_map_shm_locally(shm_fd_ebpf_cgroup, length);
79 + if (!shm_ebpf_cgroup.header) {
80 + limit_try = NETDATA_EBPF_CGROUP_MAX_TRIES + 1;
81 + return;
82 + }
83 + shm_ebpf_cgroup.body = (netdata_ebpf_cgroup_shm_body_t *) ((char *)shm_ebpf_cgroup.header +
84 + sizeof(netdata_ebpf_cgroup_shm_header_t));
85 +
86 + shm_sem_ebpf_cgroup = sem_open(NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME, O_CREAT, 0660, 1);
87 +
88 + if (shm_sem_ebpf_cgroup == SEM_FAILED) {
89 + error("Cannot create semaphore, integration between eBPF and cgroup won't happen");
90 + munmap(shm_ebpf_cgroup.header, length);
91 + shm_ebpf_cgroup.header = NULL;
92 + close(shm_fd_ebpf_cgroup);
93 + shm_fd_ebpf_cgroup = -1;
94 + shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME);
95 + }
96 +}
97 +
98 +// --------------------------------------------------------------------------------------------------------------------
99 +// Close and Cleanup
100 +
101 +/**
102 + * Close shared memory
103 + */
104 +void ebpf_close_cgroup_shm()
105 +{
106 + if (shm_sem_ebpf_cgroup != SEM_FAILED) {
107 + sem_close(shm_sem_ebpf_cgroup);
108 + sem_unlink(NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME);
109 + shm_sem_ebpf_cgroup = SEM_FAILED;
110 + }
111 +
112 + if (shm_fd_ebpf_cgroup > 0) {
113 + close(shm_fd_ebpf_cgroup);
114 + shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME);
115 + shm_fd_ebpf_cgroup = -1;
116 + }
117 +}
118 +
119 +/**
120 + * Clean Specific cgroup pid
121 + *
122 + * Clean all PIDs associated with cgroup.
123 + *
124 + * @param pt structure pid on target that will have your PRs removed
125 + */
126 +static inline void ebpf_clean_specific_cgroup_pids(struct pid_on_target2 *pt)
127 +{
128 + while (pt) {
129 + struct pid_on_target2 *next_pid = pt->next;
130 +
131 + freez(pt);
132 + pt = next_pid;
133 + }
134 +}
135 +
136 +/**
137 + * Cleanup link list
138 + */
139 +void ebpf_clean_cgroup_pids()
140 +{
141 + if (!ebpf_cgroup_pids)
142 + return;
143 +
144 + ebpf_cgroup_target_t *ect = ebpf_cgroup_pids;
145 + while (ect) {
146 + ebpf_cgroup_target_t *next_cgroup = ect->next;
147 +
148 + ebpf_clean_specific_cgroup_pids(ect->pids);
149 + freez(ect);
150 +
151 + ect = next_cgroup;
152 + }
153 + ebpf_cgroup_pids = NULL;
154 +}
155 +
156 +/**
157 + * Remove Cgroup Update Target Update List
158 + *
159 + * Remove from cgroup target and update the link list
160 + */
161 +static void ebpf_remove_cgroup_target_update_list()
162 +{
163 + ebpf_cgroup_target_t *next, *ect = ebpf_cgroup_pids;
164 + ebpf_cgroup_target_t *prev = ebpf_cgroup_pids;
165 + while (ect) {
166 + next = ect->next;
167 + if (!ect->updated) {
168 + if (ect == ebpf_cgroup_pids) {
169 + ebpf_cgroup_pids = next;
170 + prev = next;
171 + } else {
172 + prev->next = next;
173 + }
174 +
175 + ebpf_clean_specific_cgroup_pids(ect->pids);
176 + freez(ect);
177 + } else {
178 + prev = ect;
179 + }
180 +
181 + ect = next;
182 + }
183 +}
184 +
185 +// --------------------------------------------------------------------------------------------------------------------
186 +// Fill variables
187 +
188 +/**
189 + * Set Target Data
190 + *
191 + * Set local variable values according shared memory information.
192 + *
193 + * @param out local output variable.
194 + * @param ptr input from shared memory.
195 + */
196 +static inline void ebpf_cgroup_set_target_data(ebpf_cgroup_target_t *out, netdata_ebpf_cgroup_shm_body_t *ptr)
197 +{
198 + out->hash = ptr->hash;
199 + snprintfz(out->name, 255, "%s", ptr->name);
200 + out->systemd = ptr->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE;
201 + out->updated = 1;
202 +}
203 +
204 +/**
205 + * Find or create
206 + *
207 + * Find the structure inside the link list or allocate and link when it is not present.
208 + *
209 + * @param ptr Input from shared memory.
210 + *
211 + * @return It returns a pointer for the structure associated with the input.
212 + */
213 +static ebpf_cgroup_target_t * ebpf_cgroup_find_or_create(netdata_ebpf_cgroup_shm_body_t *ptr)
214 +{
215 + ebpf_cgroup_target_t *ect, *prev;
216 + for (ect = ebpf_cgroup_pids, prev = ebpf_cgroup_pids; ect; prev = ect, ect = ect->next) {
217 + if (ect->hash == ptr->hash && !strcmp(ect->name, ptr->name)) {
218 + ect->updated = 1;
219 + return ect;
220 + }
221 + }
222 +
223 + ebpf_cgroup_target_t *new_ect = callocz(1, sizeof(ebpf_cgroup_target_t));
224 +
225 + ebpf_cgroup_set_target_data(new_ect, ptr);
226 + if (!ebpf_cgroup_pids) {
227 + ebpf_cgroup_pids = new_ect;
228 + } else {
229 + prev->next = new_ect;
230 + }
231 +
232 + return new_ect;
233 +}
234 +
235 +/**
236 + * Update pid link list
237 + *
238 + * Update PIDs list associated with specific cgroup.
239 + *
240 + * @param ect cgroup structure where pids will be stored
241 + * @param path file with PIDs associated to cgroup.
242 + */
243 +static void ebpf_update_pid_link_list(ebpf_cgroup_target_t *ect, char *path)
244 +{
245 + procfile *ff = procfile_open(path, " \t:", PROCFILE_FLAG_DEFAULT);
246 + if (!ff)
247 + return;
248 +
249 + ff = procfile_readall(ff);
250 + if (!ff)
251 + return;
252 +
253 + size_t lines = procfile_lines(ff), l;
254 + for (l = 0; l < lines ;l++) {
255 + int pid = (int)str2l(procfile_lineword(ff, l, 0));
256 + if (pid) {
257 + struct pid_on_target2 *pt, *prev;
258 + for (pt = ect->pids, prev = ect->pids; pt; prev = pt, pt = pt->next) {
259 + if (pt->pid == pid)
260 + break;
261 + }
262 +
263 + if (!pt) {
264 + struct pid_on_target2 *w = callocz(1, sizeof(struct pid_on_target2));
265 + w->pid = pid;
266 + if (!ect->pids)
267 + ect->pids = w;
268 + else
269 + prev->next = w;
270 + }
271 + }
272 + }
273 +
274 + procfile_close(ff);
275 +}
276 +
277 +/**
278 + * Set remove var
279 + *
280 + * Set variable remove. If this variable is not reset, the structure will be removed from link list.
281 + */
282 + void ebpf_reset_updated_var()
283 + {
284 + ebpf_cgroup_target_t *ect;
285 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
286 + ect->updated = 0;
287 + }
288 + }
289 +
290 +/**
291 + * Parse cgroup shared memory
292 + *
293 + * This function is responsible to copy necessary data from shared memory to local memory.
294 + */
295 +void ebpf_parse_cgroup_shm_data()
296 +{
297 + if (shm_ebpf_cgroup.header) {
298 + sem_wait(shm_sem_ebpf_cgroup);
299 + int i, end = shm_ebpf_cgroup.header->cgroup_root_count;
300 +
301 + pthread_mutex_lock(&mutex_cgroup_shm);
302 +
303 + ebpf_remove_cgroup_target_update_list();
304 +
305 + ebpf_reset_updated_var();
306 +
307 + for (i = 0; i < end; i++) {
308 + netdata_ebpf_cgroup_shm_body_t *ptr = &shm_ebpf_cgroup.body[i];
309 + if (ptr->enabled) {
310 + ebpf_cgroup_target_t *ect = ebpf_cgroup_find_or_create(ptr);
311 + ebpf_update_pid_link_list(ect, ptr->path);
312 + }
313 + }
314 + pthread_mutex_unlock(&mutex_cgroup_shm);
315 +
316 + sem_post(shm_sem_ebpf_cgroup);
317 + }
318 +}
319 +
320 +// --------------------------------------------------------------------------------------------------------------------
321 +// Create charts
322 +
323 +/**
324 + * Create charts on systemd submenu
325 + *
326 + * @param id the chart id
327 + * @param title the value displayed on vertical axis.
328 + * @param units the value displayed on vertical axis.
329 + * @param family Submenu that the chart will be attached on dashboard.
330 + * @param charttype chart type
331 + * @param order the chart order
332 + * @param algorithm the algorithm used by dimension
333 + * @param module chart module name, this is the eBPF thread.
334 + */
335 +void ebpf_create_charts_on_systemd(char *id, char *title, char *units, char *family, char *charttype, int order,
336 + char *algorithm, char *module)
337 +{
338 + ebpf_cgroup_target_t *w;
339 + ebpf_write_chart_cmd(NETDATA_SERVICE_FAMILY, id, title, units, family, charttype, NULL, order, module);
340 +
341 + for (w = ebpf_cgroup_pids; w; w = w->next) {
342 + if (unlikely(w->systemd) && unlikely(w->updated))
343 + fprintf(stdout, "DIMENSION %s '' %s 1 1\n", w->name, algorithm);
344 + }
345 +}
collectors/ebpf.plugin/ebpf_cgroup.h new
+55
@@ -0,0 +1,55 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_EBPF_CGROUP_H
4 +#define NETDATA_EBPF_CGROUP_H 1
5 +
6 +#define NETDATA_EBPF_CGROUP_MAX_TRIES 3
7 +#define NETDATA_EBPF_CGROUP_NEXT_TRY_SEC 30
8 +
9 +#include "ebpf.h"
10 +#include "ebpf_apps.h"
11 +
12 +#define NETDATA_SERVICE_FAMILY "services"
13 +
14 +struct pid_on_target2 {
15 + int32_t pid;
16 + int updated;
17 +
18 + netdata_publish_swap_t swap;
19 +
20 + struct pid_on_target2 *next;
21 +};
22 +
23 +enum ebpf_cgroup_flags {
24 + NETDATA_EBPF_CGROUP_HAS_PROCESS_CHART = 1,
25 + NETDATA_EBPF_CGROUP_HAS_SWAP_CHART = 1<<2,
26 + NETDATA_EBPF_CGROUP_HAS_SOCKET_CHART = 1<<3,
27 + NETDATA_EBPF_CGROUP_HAS_FD_CHART = 1<<4,
28 + NETDATA_EBPF_CGROUP_HAS_VFS_CHART = 1<<5,
29 + NETDATA_EBPF_CGROUP_HAS_OOMKILL_CHART = 1<<6,
30 + NETDATA_EBPF_CGROUP_HAS_CACHESTAT_CHART = 1<<7,
31 + NETDATA_EBPF_CGROUP_HAS_DC_CHART = 1<<8,
32 + NETDATA_EBPF_CGROUP_HAS_SHM_CHART = 1<<9
33 +};
34 +
35 +typedef struct ebpf_cgroup_target {
36 + char name[256]; // title
37 + uint32_t hash;
38 + uint32_t flags;
39 + uint32_t systemd;
40 + uint32_t updated;
41 +
42 + netdata_publish_swap_t publish_systemd_swap;
43 +
44 + struct pid_on_target2 *pids;
45 + struct ebpf_cgroup_target *next;
46 +} ebpf_cgroup_target_t;
47 +
48 +extern void ebpf_map_cgroup_shared_memory();
49 +extern void ebpf_parse_cgroup_shm_data();
50 +extern void ebpf_close_cgroup_shm();
51 +extern void ebpf_clean_cgroup_pids();
52 +extern void ebpf_create_charts_on_systemd(char *id, char *title, char *units, char *family, char *charttype, int order,
53 + char *algorithm, char *module);
54 +
55 +#endif /* NETDATA_EBPF_CGROUP_H */
collectors/ebpf.plugin/ebpf_disk.c
+2
@@ -656,6 +656,8 @@ static void ebpf_remove_pointer_from_plot_disk(ebpf_module_t *em)
656
657 if (!(flags & NETDATA_DISK_IS_HERE) && ((current_time - ned->last_update) > limit)) {
658 ebpf_obsolete_hd_charts(ned);
659 + avl_t *ret = (avl_t *)avl_remove_lock(&disk_tree, (avl_t *)ned);
660 + UNUSED(ret);
661 if (move == plot_disks) {
662 freez(move);
663 plot_disks = NULL;
collectors/ebpf.plugin/ebpf_process.c
+40
@@ -48,6 +48,8 @@ struct config process_config = { .first_section = NULL,
48 .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
49 .rwlock = AVL_LOCK_INITIALIZER } };
50
51 +static struct netdata_static_thread cgroup_thread = {"EBPF CGROUP", NULL, NULL,
52 + 1, NULL, NULL, NULL};
53 /*****************************************************************
54 *
55 * PROCESS DATA AND SEND TO NETDATA
@@ -467,6 +469,36 @@ static void ebpf_create_apps_charts(struct target *root)
469 *
470 *****************************************************************/
471
472 +/**
473 + * Cgroup update shm
474 + *
475 + * This is the thread callback.
476 + * This thread is necessary, because we cannot freeze the whole plugin to read the data from shared memory.
477 + *
478 + * @param ptr It is a NULL value for this thread.
479 + *
480 + * @return It always returns NULL.
481 + */
482 +void *ebpf_cgroup_update_shm(void *ptr)
483 +{
484 + UNUSED(ptr);
485 + heartbeat_t hb;
486 + heartbeat_init(&hb);
487 +
488 + usec_t step = 30 * USEC_PER_SEC;
489 + while (!close_ebpf_plugin) {
490 + usec_t dt = heartbeat_next(&hb, step);
491 + (void)dt;
492 +
493 + if (!shm_ebpf_cgroup.header)
494 + ebpf_map_cgroup_shared_memory();
495 +
496 + ebpf_parse_cgroup_shm_data();
497 + }
498 +
499 + return NULL;
500 +}
501 +
502 /**
503 * Main loop for this collector.
504 *
@@ -475,6 +507,12 @@ static void ebpf_create_apps_charts(struct target *root)
507 */
508 static void process_collector(usec_t step, ebpf_module_t *em)
509 {
510 + cgroup_thread.thread = mallocz(sizeof(netdata_thread_t));
511 + cgroup_thread.start_routine = ebpf_cgroup_update_shm;
512 +
513 + netdata_thread_create(cgroup_thread.thread, cgroup_thread.name, NETDATA_THREAD_OPTION_JOINABLE,
514 + ebpf_cgroup_update_shm, em);
515 +
516 heartbeat_t hb;
517 heartbeat_init(&hb);
518 int publish_global = em->global_charts;
@@ -568,6 +606,8 @@ static void ebpf_process_cleanup(void *ptr)
606 }
607 bpf_object__close(objects);
608 }
609 +
610 + freez(cgroup_thread.thread);
611 }
612
613 /*****************************************************************
collectors/ebpf.plugin/ebpf_swap.c
+242 -6
@@ -137,6 +137,40 @@ static void swap_fill_pid(uint32_t current_pid, netdata_publish_swap_t *publish)
137 memcpy(curr, publish, sizeof(netdata_publish_swap_t));
138 }
139
140 +/**
141 + * Update cgroup
142 + *
143 + * Update cgroup data based in
144 + */
145 +static void ebpf_update_swap_cgroup()
146 +{
147 + ebpf_cgroup_target_t *ect ;
148 + netdata_publish_swap_t *cv = swap_vector;
149 + int fd = swap_maps[NETDATA_PID_SWAP_TABLE].map_fd;
150 + size_t length = sizeof(netdata_publish_swap_t)*ebpf_nprocs;
151 + pthread_mutex_lock(&mutex_cgroup_shm);
152 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
153 + struct pid_on_target2 *pids;
154 + for (pids = ect->pids; pids; pids = pids->next) {
155 + int pid = pids->pid;
156 + netdata_publish_swap_t *out = &pids->swap;
157 + if (swap_pid[pid]) {
158 + netdata_publish_swap_t *in = swap_pid[pid];
159 +
160 + memcpy(out, in, sizeof(netdata_publish_swap_t));
161 + } else {
162 + memset(cv, 0, length);
163 + if (!bpf_map_lookup_elem(fd, &pid, cv)) {
164 + swap_apps_accumulator(cv);
165 +
166 + memcpy(out, cv, sizeof(netdata_publish_swap_t));
167 + }
168 + }
169 + }
170 + }
171 + pthread_mutex_unlock(&mutex_cgroup_shm);
172 +}
173 +
174 /**
175 * Read APPS table
176 *
@@ -185,7 +219,7 @@ static void swap_send_global()
219 /**
220 * Read global counter
221 *
188 - * Read the table with number of calls for all functions
222 + * Read the table with number of calls to all functions
223 */
224 static void read_global_table()
225 {
@@ -208,10 +242,9 @@ static void read_global_table()
242 }
243
244 /**
211 - * Socket read hash
245 + * Swap read hash
246 *
247 * This is the thread callback.
214 - * This thread is necessary, because we cannot freeze the whole plugin to read the data on very busy socket.
248 *
249 * @param ptr It is a NULL value for this thread.
250 *
@@ -296,6 +329,202 @@ void ebpf_swap_send_apps_data(struct target *root)
329 write_end_chart();
330 }
331
332 +/**
333 + * Sum PIDs
334 + *
335 + * Sum values for all targets.
336 + *
337 + * @param swap
338 + * @param root
339 + */
340 +static void ebpf_swap_sum_cgroup_pids(netdata_publish_swap_t *swap, struct pid_on_target2 *pids)
341 +{
342 + uint64_t local_read = 0;
343 + uint64_t local_write = 0;
344 +
345 + while (pids) {
346 + netdata_publish_swap_t *w = &pids->swap;
347 + local_write += w->write;
348 + local_read += w->read;
349 +
350 + pids = pids->next;
351 + }
352 +
353 + // These conditions were added, because we are using incremental algorithm
354 + swap->write = (local_write >= swap->write) ? local_write : swap->write;
355 + swap->read = (local_read >= swap->read) ? local_read : swap->read;
356 +}
357 +
358 +/**
359 + * Send Systemd charts
360 + *
361 + * Send collected data to Netdata.
362 + *
363 + * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
364 + * otherwise function returns 1 to avoid chart recreation
365 + */
366 +static int ebpf_send_systemd_swap_charts()
367 +{
368 + int ret = 1;
369 + ebpf_cgroup_target_t *ect;
370 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_MEM_SWAP_READ_CHART);
371 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
372 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
373 + write_chart_dimension(ect->name, (long long) ect->publish_systemd_swap.read);
374 + } else
375 + ret = 0;
376 + }
377 + write_end_chart();
378 +
379 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_MEM_SWAP_WRITE_CHART);
380 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
381 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
382 + write_chart_dimension(ect->name, (long long) ect->publish_systemd_swap.write);
383 + }
384 + }
385 + write_end_chart();
386 +
387 + return ret;
388 +}
389 +
390 +/**
391 + * Create specific swap charts
392 + *
393 + * Create charts for cgroup/application.
394 + *
395 + * @param type the chart type.
396 + */
397 +static void ebpf_create_specific_swap_charts(char *type)
398 +{
399 + ebpf_create_chart(type, NETDATA_MEM_SWAP_READ_CHART,
400 + "Calls to function <code>swap_readpage</code>.",
401 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
402 + NULL,
403 + NETDATA_EBPF_CHART_TYPE_LINE,
404 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5100,
405 + ebpf_create_global_dimension,
406 + swap_publish_aggregated, 1, NETDATA_EBPF_MODULE_NAME_SWAP);
407 +
408 + ebpf_create_chart(type, NETDATA_MEM_SWAP_WRITE_CHART,
409 + "Calls to function <code>swap_writepage</code>.",
410 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
411 + NULL,
412 + NETDATA_EBPF_CHART_TYPE_LINE,
413 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5101,
414 + ebpf_create_global_dimension,
415 + &swap_publish_aggregated[NETDATA_KEY_SWAP_WRITEPAGE_CALL], 1, NETDATA_EBPF_MODULE_NAME_SWAP);
416 +}
417 +
418 +/**
419 + * Create specific swap charts
420 + *
421 + * Create charts for cgroup/application.
422 + *
423 + * @param type the chart type.
424 + */
425 +static void ebpf_obsolete_specific_swap_charts(char *type)
426 +{
427 + ebpf_write_chart_obsolete(type, NETDATA_MEM_SWAP_READ_CHART,"Calls to function <code>swap_readpage</code>.",
428 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
429 + NETDATA_EBPF_CHART_TYPE_LINE, NULL,
430 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5100);
431 +
432 + ebpf_write_chart_obsolete(type, NETDATA_MEM_SWAP_WRITE_CHART, "Calls to function <code>swap_writepage</code>.",
433 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
434 + NETDATA_EBPF_CHART_TYPE_LINE,NULL,
435 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5101);
436 +}
437 +
438 +/*
439 + * Send Specific Swap data
440 + *
441 + * Send data for specific cgroup/apps.
442 + *
443 + * @param type chart type
444 + * @param values structure with values that will be sent to netdata
445 + */
446 +static void ebpf_send_specific_swap_data(char *type, netdata_publish_swap_t *values)
447 +{
448 + write_begin_chart(type, NETDATA_MEM_SWAP_READ_CHART);
449 + write_chart_dimension(swap_publish_aggregated[NETDATA_KEY_SWAP_READPAGE_CALL].name, (long long) values->read);
450 + write_end_chart();
451 +
452 + write_begin_chart(type, NETDATA_MEM_SWAP_WRITE_CHART);
453 + write_chart_dimension(swap_publish_aggregated[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name, (long long) values->write);
454 + write_end_chart();
455 +}
456 +
457 +/**
458 + * Create Systemd Swap Charts
459 + *
460 + * Create charts when systemd is enabled
461 + **/
462 +static void ebpf_create_systemd_swap_charts()
463 +{
464 + ebpf_create_charts_on_systemd(NETDATA_MEM_SWAP_READ_CHART,
465 + "Calls to <code>swap_readpage</code>.",
466 + EBPF_COMMON_DIMENSION_CALL,
467 + NETDATA_SWAP_SUBMENU,
468 + NETDATA_EBPF_CHART_TYPE_STACKED,
469 + 20191,
470 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
471 + NETDATA_EBPF_MODULE_NAME_SWAP);
472 +
473 + ebpf_create_charts_on_systemd(NETDATA_MEM_SWAP_WRITE_CHART,
474 + "Calls to function <code>swap_writepage</code>.",
475 + EBPF_COMMON_DIMENSION_CALL,
476 + NETDATA_SWAP_SUBMENU,
477 + NETDATA_EBPF_CHART_TYPE_STACKED,
478 + 20192,
479 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
480 + NETDATA_EBPF_MODULE_NAME_SWAP);
481 +}
482 +
483 +/**
484 + * Send data to Netdata calling auxiliar functions.
485 +*/
486 +void ebpf_swap_send_cgroup_data()
487 +{
488 + static int systemd_charts = 0;
489 +
490 + if (!ebpf_cgroup_pids)
491 + return;
492 +
493 + pthread_mutex_lock(&mutex_cgroup_shm);
494 + ebpf_cgroup_target_t *ect;
495 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
496 + ebpf_swap_sum_cgroup_pids(&ect->publish_systemd_swap, ect->pids);
497 + if (!ect->systemd && !(ect->flags & NETDATA_EBPF_CGROUP_HAS_SWAP_CHART)) {
498 + ebpf_create_specific_swap_charts(ect->name);
499 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_SWAP_CHART;
500 + }
501 + }
502 +
503 + int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
504 +
505 + if (!systemd_charts) {
506 + if (has_systemd) {
507 + ebpf_create_systemd_swap_charts();
508 + }
509 + systemd_charts = 1;
510 + }
511 +
512 + if (has_systemd) {
513 + systemd_charts = ebpf_send_systemd_swap_charts();
514 + }
515 +
516 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
517 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_SWAP_CHART && ect->updated) {
518 + ebpf_send_specific_swap_data(ect->name, &ect->publish_systemd_swap);
519 + } else {
520 + ebpf_obsolete_specific_swap_charts(ect->name);
521 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_SWAP_CHART;
522 + }
523 + }
524 +
525 + pthread_mutex_unlock(&mutex_cgroup_shm);
526 +}
527 +
528 /**
529 * Main loop for this collector.
530 */
@@ -308,6 +537,7 @@ static void swap_collector(ebpf_module_t *em)
537 ebpf_swap_read_hash, em);
538
539 int apps = em->apps_charts;
540 + int cgroup = em->cgroup_charts;
541 while (!close_ebpf_plugin) {
542 pthread_mutex_lock(&collect_data_mutex);
543 pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
@@ -315,6 +545,9 @@ static void swap_collector(ebpf_module_t *em)
545 if (apps)
546 read_apps_table();
547
548 + if (cgroup)
549 + ebpf_update_swap_cgroup();
550 +
551 pthread_mutex_lock(&lock);
552
553 swap_send_global();
@@ -322,6 +555,9 @@ static void swap_collector(ebpf_module_t *em)
555 if (apps)
556 ebpf_swap_send_apps_data(apps_groups_root_target);
557
558 + if (cgroup)
559 + ebpf_swap_send_cgroup_data();
560 +
561 pthread_mutex_unlock(&lock);
562 pthread_mutex_unlock(&collect_data_mutex);
563 }
@@ -346,7 +582,7 @@ void ebpf_swap_create_apps_charts(struct ebpf_module *em, void *ptr)
582
583 struct target *root = ptr;
584 ebpf_create_charts_on_apps(NETDATA_MEM_SWAP_READ_CHART,
349 - "Calls for function <code>swap_readpage</code>.",
585 + "Calls to function <code>swap_readpage</code>.",
586 EBPF_COMMON_DIMENSION_CALL,
587 NETDATA_SWAP_SUBMENU,
588 NETDATA_EBPF_CHART_TYPE_STACKED,
@@ -355,7 +591,7 @@ void ebpf_swap_create_apps_charts(struct ebpf_module *em, void *ptr)
591 root, NETDATA_EBPF_MODULE_NAME_SWAP);
592
593 ebpf_create_charts_on_apps(NETDATA_MEM_SWAP_WRITE_CHART,
358 - "Calls for function <code>swap_writepage</code>.",
594 + "Calls to function <code>swap_writepage</code>.",
595 EBPF_COMMON_DIMENSION_CALL,
596 NETDATA_SWAP_SUBMENU,
597 NETDATA_EBPF_CHART_TYPE_STACKED,
@@ -396,7 +632,7 @@ static void ebpf_swap_allocate_global_vectors()
632 static void ebpf_create_swap_charts()
633 {
634 ebpf_create_chart(NETDATA_EBPF_SYSTEM_GROUP, NETDATA_MEM_SWAP_CHART,
399 - "Calls for internal functions used to access swap.",
635 + "Calls to internal functions used to access swap.",
636 EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
637 NULL,
638 NETDATA_EBPF_CHART_TYPE_LINE,
libnetdata/ebpf/ebpf.h
+2
@@ -20,6 +20,7 @@
20 #define EBPF_CFG_UPDATE_EVERY "update every"
21 #define EBPF_CFG_PID_SIZE "pid table size"
22 #define EBPF_CFG_APPLICATION "apps"
23 +#define EBPF_CFG_CGROUP "cgroups"
24
25 /**
26 * The next magic number is got doing the following math:
@@ -155,6 +156,7 @@ typedef struct ebpf_module {
156 int update_time;
157 int global_charts;
158 int apps_charts;
159 + int cgroup_charts;
160 netdata_run_mode_t mode;
161 uint32_t thread_id;
162 int optional;
web/gui/dashboard_info.js
+11
@@ -4658,6 +4658,17 @@ netdataDashboard.context = {
4658 info: 'Number of times the syscall <code>shmctl</code> is called.'
4659 },
4660
4661 + // ------------------------------------------------------------------------
4662 + // Services units
4663 +
4664 + 'services.swap_read_call': {
4665 + info: 'The function <code>swap_readpage</code> is called when the kernel reads a page from swap memory. This chart is provided by eBPF plugin.'
4666 + },
4667 +
4668 + 'services.swap_write_call': {
4669 + info: 'The function <code>swap_writepage</code> is called when the kernel writes a page to swap memory. This chart is provided by eBPF plugin.'
4670 + },
4671 +
4672 // ------------------------------------------------------------------------
4673 // ACLK Internal Stats
4674 'netdata.aclk_status': {