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': {