eBPF Functions (enable/disable threads) (#15214)
thiagoftsm committed
Jul 12, 2023 at 16:49 UTC
929b19f485b7100d8caa322abb0987afd01b3883
69 files changed
+3726
-617
.gitignore
+1
@@ -196,6 +196,7 @@ tests/acls/acl.sh
196
tests/urls/request.sh
197
tests/alarm_repetition/alarm.sh
198
tests/template_dimension/template_dim.sh
199
+tests/ebpf/ebpf_thread_function.sh
200
aclk/legacy/tests/install-fake-charts.d.sh
201
202
# tests and temp files
CMakeLists.txt
+2
@@ -624,6 +624,8 @@ set(EBPF_PROCESS_PLUGIN_FILES
624
collectors/ebpf.plugin/ebpf_cgroup.h
625
collectors/ebpf.plugin/ebpf_unittest.c
626
collectors/ebpf.plugin/ebpf_unittest.h
627
+ collectors/ebpf.plugin/ebpf_functions.c
628
+ collectors/ebpf.plugin/ebpf_functions.h
629
)
630
631
set(PROC_PLUGIN_FILES
Makefile.am
+2
@@ -365,6 +365,8 @@ EBPF_PLUGIN_FILES = \
365
collectors/ebpf.plugin/ebpf_cgroup.h \
366
collectors/ebpf.plugin/ebpf_unittest.c \
367
collectors/ebpf.plugin/ebpf_unittest.h \
368
+ collectors/ebpf.plugin/ebpf_functions.c \
369
+ collectors/ebpf.plugin/ebpf_functions.h \
370
$(LIBNETDATA_FILES) \
371
$(NULL)
372
collectors/ebpf.plugin/README.md
+54
-7
@@ -235,13 +235,12 @@ Linux metrics:
235
236
The eBPF collector enables and runs the following eBPF programs by default:
237
238
+- `cachestat`: Netdata's eBPF data collector creates charts about the memory page cache. When the integration with
239
+ [`apps.plugin`](https://github.com/netdata/netdata/blob/master/collectors/apps.plugin/README.md) is enabled, this collector creates charts for the whole host _and_
240
+ for each application.
241
- `fd` : This eBPF program creates charts that show information about calls to open files.
242
- `mount`: This eBPF program creates charts that show calls to syscalls mount(2) and umount(2).
243
- `shm`: This eBPF program creates charts that show calls to syscalls shmget(2), shmat(2), shmdt(2) and shmctl(2).
241
-- `sync`: Monitor calls to syscalls sync(2), fsync(2), fdatasync(2), syncfs(2), msync(2), and sync_file_range(2).
242
-- `network viewer`: This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
243
- bandwidth consumed by each.
244
-- `vfs`: This eBPF program creates charts that show information about VFS (Virtual File System) functions.
244
- `process`: This eBPF program creates charts that show information about process life. When in `return` mode, it also
245
creates charts showing errors when these operations are executed.
246
- `hardirq`: This eBPF program creates charts that show information about time spent servicing individual hardware
@@ -254,9 +253,6 @@ The eBPF collector enables and runs the following eBPF programs by default:
253
254
You can also enable the following eBPF programs:
255
257
-- `cachestat`: Netdata's eBPF data collector creates charts about the memory page cache. When the integration with
258
- [`apps.plugin`](https://github.com/netdata/netdata/blob/master/collectors/apps.plugin/README.md) is enabled, this collector creates charts for the whole host _and_
259
- for each application.
256
- `dcstat` : This eBPF program creates charts that show information about file access using directory cache. It appends
257
`kprobes` for `lookup_fast()` and `d_lookup()` to identify if files are inside directory cache, outside and files are
258
not found.
@@ -264,7 +260,11 @@ You can also enable the following eBPF programs:
260
- `filesystem` : This eBPF program creates charts that show information about some filesystem latency.
261
- `swap` : This eBPF program creates charts that show information about swap access.
262
- `mdflush`: This eBPF program creates charts that show information about
263
+- `sync`: Monitor calls to syscalls sync(2), fsync(2), fdatasync(2), syncfs(2), msync(2), and sync_file_range(2).
264
+- `network viewer`: This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
265
+ bandwidth consumed by each.
266
multi-device software flushes.
267
+- `vfs`: This eBPF program creates charts that show information about VFS (Virtual File System) functions.
268
269
### Configuring eBPF threads
270
@@ -989,3 +989,50 @@ shows how the lockdown module impacts `ebpf.plugin` based on the selected option
989
990
If you or your distribution compiled the kernel with the last combination, your system cannot load shared libraries
991
required to run `ebpf.plugin`.
992
+
993
+## Function
994
+
995
+The eBPF plugin has a [function](https://github.com/netdata/netdata/blob/master/docs/cloud/netdata-functions.md) named
996
+`ebpf_thread` that controls its internal threads and helps to reduce the overhead on host. Using the function you
997
+can run the plugin with all threads disabled and enable them only when you want to take a look in specific areas.
998
+
999
+### List threads
1000
+
1001
+To list all threads status you can query directly the endpoint function:
1002
+
1003
+`http://localhost:19999/api/v1/function?function=ebpf_thread`
1004
+
1005
+It is also possible to query a specific thread adding keyword `thread` and thread name:
1006
+
1007
+`http://localhost:19999/api/v1/function?function=ebpf_thread%20thread:mount`
1008
+
1009
+### Enable thread
1010
+
1011
+It is possible to enable a specific thread using the keyword `enable`:
1012
+
1013
+`http://localhost:19999/api/v1/function?function=ebpf_thread%20enable:mount`
1014
+
1015
+this will run thread `mount` during 300 seconds (5 minutes). You can specify a specific period by appending the period
1016
+after the thread name:
1017
+
1018
+`http://localhost:19999/api/v1/function?function=ebpf_thread%20enable:mount:600`
1019
+
1020
+in this example thread `mount` will run during 600 seconds (10 minutes).
1021
+
1022
+### Disable thread
1023
+
1024
+It is also possible to stop any thread running using the keyword `disable`. For example, to disable `cachestat` you can
1025
+request:
1026
+
1027
+`http://localhost:19999/api/v1/function?function=ebpf_thread%20disable:cachestat`
1028
+
1029
+### Debugging threads
1030
+
1031
+You can verify the impact of threads on the host by running the
1032
+[ebpf_thread_function.sh](https://github.com/netdata/netdata/blob/master/tests/ebpf/ebpf_thread_function.sh)
1033
+script on your environment.
1034
+
1035
+You can check the results of having threads running on your environment in the Netdata monitoring section on your
1036
+dashboard
1037
+
1038
+<img src="https://github.com/netdata/netdata/assets/49162938/91823573-114c-4c16-b634-cc46f7bb1bcf" alt="Threads running." />
collectors/ebpf.plugin/ebpf.c
+500
-187
@@ -30,6 +30,8 @@ int ebpf_nprocs;
30
int isrh = 0;
31
int main_thread_id = 0;
32
int process_pid_fd = -1;
33
+static size_t global_iterations_counter = 1;
34
+bool publish_internal_metrics = true;
35
36
pthread_mutex_t lock;
37
pthread_mutex_t ebpf_exit_cleanup;
@@ -47,7 +49,8 @@ struct netdata_static_thread cgroup_integration_thread = {
49
};
50
51
ebpf_module_t ebpf_modules[] = {
50
- { .thread_name = "process", .config_name = "process", .enabled = 0, .start_routine = ebpf_process_thread,
52
+ { .thread_name = "process", .config_name = "process", .thread_description = NETDATA_EBPF_MODULE_PROCESS_DESC,
53
+ .enabled = 0, .start_routine = ebpf_process_thread,
54
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
55
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
56
.apps_routine = ebpf_process_create_apps_charts, .maps = NULL,
@@ -56,8 +59,9 @@ ebpf_module_t ebpf_modules[] = {
59
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10 |
60
NETDATA_V5_14,
61
.load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
59
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
60
- { .thread_name = "socket", .config_name = "socket", .enabled = 0, .start_routine = ebpf_socket_thread,
62
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0 },
63
+ { .thread_name = "socket", .config_name = "socket", .thread_description = NETDATA_EBPF_SOCKET_MODULE_DESC,
64
+ .enabled = 0, .start_routine = ebpf_socket_thread,
65
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
66
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
67
.apps_routine = ebpf_socket_create_apps_charts, .maps = NULL,
@@ -65,8 +69,9 @@ ebpf_module_t ebpf_modules[] = {
69
.config_file = NETDATA_NETWORK_CONFIG_FILE,
70
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
71
.load = EBPF_LOAD_LEGACY, .targets = socket_targets, .probe_links = NULL, .objects = NULL,
68
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
69
- { .thread_name = "cachestat", .config_name = "cachestat", .enabled = 0, .start_routine = ebpf_cachestat_thread,
72
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
73
+ { .thread_name = "cachestat", .config_name = "cachestat", .thread_description = NETDATA_EBPF_CACHESTAT_MODULE_DESC,
74
+ .enabled = 0, .start_routine = ebpf_cachestat_thread,
75
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
76
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
77
.apps_routine = ebpf_cachestat_create_apps_charts, .maps = cachestat_maps,
@@ -75,8 +80,9 @@ ebpf_module_t ebpf_modules[] = {
80
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18|
81
NETDATA_V5_4 | NETDATA_V5_14 | NETDATA_V5_15 | NETDATA_V5_16,
82
.load = EBPF_LOAD_LEGACY, .targets = cachestat_targets, .probe_links = NULL, .objects = NULL,
78
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
79
- { .thread_name = "sync", .config_name = "sync", .enabled = 0, .start_routine = ebpf_sync_thread,
83
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
84
+ { .thread_name = "sync", .config_name = "sync", .thread_description = NETDATA_EBPF_SYNC_MODULE_DESC,
85
+ .enabled = 0, .start_routine = ebpf_sync_thread,
86
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
87
.apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
88
.apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &sync_config,
@@ -84,8 +90,9 @@ ebpf_module_t ebpf_modules[] = {
90
// All syscalls have the same kernels
91
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
92
.load = EBPF_LOAD_LEGACY, .targets = sync_targets, .probe_links = NULL, .objects = NULL,
87
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
88
- { .thread_name = "dc", .config_name = "dc", .enabled = 0, .start_routine = ebpf_dcstat_thread,
93
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
94
+ { .thread_name = "dc", .config_name = "dc", .thread_description = NETDATA_EBPF_DC_MODULE_DESC,
95
+ .enabled = 0, .start_routine = ebpf_dcstat_thread,
96
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
97
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
98
.apps_routine = ebpf_dcstat_create_apps_charts, .maps = dcstat_maps,
@@ -93,8 +100,9 @@ ebpf_module_t ebpf_modules[] = {
100
.config_file = NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE,
101
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
102
.load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL,
96
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
97
- { .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
103
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
104
+ { .thread_name = "swap", .config_name = "swap", .thread_description = NETDATA_EBPF_SWAP_MODULE_DESC,
105
+ .enabled = 0, .start_routine = ebpf_swap_thread,
106
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
107
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
108
.apps_routine = ebpf_swap_create_apps_charts, .maps = NULL,
@@ -102,8 +110,9 @@ ebpf_module_t ebpf_modules[] = {
110
.config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE,
111
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
112
.load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL,
105
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
106
- { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
113
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
114
+ { .thread_name = "vfs", .config_name = "vfs", .thread_description = NETDATA_EBPF_VFS_MODULE_DESC,
115
+ .enabled = 0, .start_routine = ebpf_vfs_thread,
116
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
117
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
118
.apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL,
@@ -111,32 +120,36 @@ ebpf_module_t ebpf_modules[] = {
120
.config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE,
121
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
122
.load = EBPF_LOAD_LEGACY, .targets = vfs_targets, .probe_links = NULL, .objects = NULL,
114
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
115
- { .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread,
123
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
124
+ { .thread_name = "filesystem", .config_name = "filesystem", .thread_description = NETDATA_EBPF_FS_MODULE_DESC,
125
+ .enabled = 0, .start_routine = ebpf_filesystem_thread,
126
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
127
.apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
128
.apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config,
129
.config_file = NETDATA_FILESYSTEM_CONFIG_FILE,
130
//We are setting kernels as zero, because we load eBPF programs according the kernel running.
131
.kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
122
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES },
123
- { .thread_name = "disk", .config_name = "disk", .enabled = 0, .start_routine = ebpf_disk_thread,
132
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
133
+ { .thread_name = "disk", .config_name = "disk", .thread_description = NETDATA_EBPF_DISK_MODULE_DESC,
134
+ .enabled = 0, .start_routine = ebpf_disk_thread,
135
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
136
.apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
137
.apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config,
138
.config_file = NETDATA_DISK_CONFIG_FILE,
139
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
140
.load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
130
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
131
- { .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread,
141
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
142
+ { .thread_name = "mount", .config_name = "mount", .thread_description = NETDATA_EBPF_MOUNT_MODULE_DESC,
143
+ .enabled = 0, .start_routine = ebpf_mount_thread,
144
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
145
.apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
146
.apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config,
147
.config_file = NETDATA_MOUNT_CONFIG_FILE,
148
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
149
.load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL,
138
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
139
- { .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread,
150
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
151
+ { .thread_name = "fd", .config_name = "fd", .thread_description = NETDATA_EBPF_FD_MODULE_DESC,
152
+ .enabled = 0, .start_routine = ebpf_fd_thread,
153
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
154
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
155
.apps_routine = ebpf_fd_create_apps_charts, .maps = NULL,
@@ -145,24 +158,27 @@ ebpf_module_t ebpf_modules[] = {
158
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11 |
159
NETDATA_V5_14,
160
.load = EBPF_LOAD_LEGACY, .targets = fd_targets, .probe_links = NULL, .objects = NULL,
148
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
149
- { .thread_name = "hardirq", .config_name = "hardirq", .enabled = 0, .start_routine = ebpf_hardirq_thread,
161
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
162
+ { .thread_name = "hardirq", .config_name = "hardirq", .thread_description = NETDATA_EBPF_HARDIRQ_MODULE_DESC,
163
+ .enabled = 0, .start_routine = ebpf_hardirq_thread,
164
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
165
.apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
166
.apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &hardirq_config,
167
.config_file = NETDATA_HARDIRQ_CONFIG_FILE,
168
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
169
.load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
156
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
157
- { .thread_name = "softirq", .config_name = "softirq", .enabled = 0, .start_routine = ebpf_softirq_thread,
170
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
171
+ { .thread_name = "softirq", .config_name = "softirq", .thread_description = NETDATA_EBPF_SOFTIRQ_MODULE_DESC,
172
+ .enabled = 0, .start_routine = ebpf_softirq_thread,
173
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
174
.apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
175
.apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &softirq_config,
176
.config_file = NETDATA_SOFTIRQ_CONFIG_FILE,
177
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
178
.load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
164
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
165
- { .thread_name = "oomkill", .config_name = "oomkill", .enabled = 0, .start_routine = ebpf_oomkill_thread,
179
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
180
+ { .thread_name = "oomkill", .config_name = "oomkill", .thread_description = NETDATA_EBPF_OOMKILL_MODULE_DESC,
181
+ .enabled = 0, .start_routine = ebpf_oomkill_thread,
182
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
183
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
184
.apps_routine = ebpf_oomkill_create_apps_charts, .maps = NULL,
@@ -170,8 +186,9 @@ ebpf_module_t ebpf_modules[] = {
186
.config_file = NETDATA_OOMKILL_CONFIG_FILE,
187
.kernels = NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
188
.load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
173
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
174
- { .thread_name = "shm", .config_name = "shm", .enabled = 0, .start_routine = ebpf_shm_thread,
189
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
190
+ { .thread_name = "shm", .config_name = "shm", .thread_description = NETDATA_EBPF_SHM_MODULE_DESC,
191
+ .enabled = 0, .start_routine = ebpf_shm_thread,
192
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
193
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
194
.apps_routine = ebpf_shm_create_apps_charts, .maps = NULL,
@@ -179,15 +196,25 @@ ebpf_module_t ebpf_modules[] = {
196
.config_file = NETDATA_DIRECTORY_SHM_CONFIG_FILE,
197
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
198
.load = EBPF_LOAD_LEGACY, .targets = shm_targets, .probe_links = NULL, .objects = NULL,
182
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
183
- { .thread_name = "mdflush", .config_name = "mdflush", .enabled = 0, .start_routine = ebpf_mdflush_thread,
199
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
200
+ { .thread_name = "mdflush", .config_name = "mdflush", .thread_description = NETDATA_EBPF_MD_MODULE_DESC,
201
+ .enabled = 0, .start_routine = ebpf_mdflush_thread,
202
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
203
.apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
204
.apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mdflush_config,
205
.config_file = NETDATA_DIRECTORY_MDFLUSH_CONFIG_FILE,
206
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
207
.load = EBPF_LOAD_LEGACY, .targets = mdflush_targets, .probe_links = NULL, .objects = NULL,
190
- .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
208
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
209
+ { .thread_name = "functions", .config_name = "functions", .thread_description = NETDATA_EBPF_FUNCTIONS_MODULE_DESC,
210
+ .enabled = 1, .start_routine = ebpf_function_thread,
211
+ .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
212
+ .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
213
+ .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = NULL,
214
+ .config_file = NETDATA_DIRECTORY_FUNCTIONS_CONFIG_FILE,
215
+ .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
216
+ .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
217
+ .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0},
218
{ .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_every = EBPF_DEFAULT_UPDATE_EVERY,
219
.global_charts = 0, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, .apps_level = NETDATA_APPS_NOT_SET,
220
.cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
@@ -356,6 +383,16 @@ struct netdata_static_thread ebpf_threads[] = {
383
.init_routine = NULL,
384
.start_routine = NULL
385
},
386
+ {
387
+ .name = "EBPF FUNCTIONS",
388
+ .config_section = NULL,
389
+ .config_name = NULL,
390
+ .env_name = NULL,
391
+ .enabled = 1,
392
+ .thread = NULL,
393
+ .init_routine = NULL,
394
+ .start_routine = NULL
395
+ },
396
{
397
.name = NULL,
398
.config_section = NULL,
@@ -586,7 +623,7 @@ static inline void ebpf_check_before2go()
623
int j;
624
pthread_mutex_lock(&ebpf_exit_cleanup);
625
for (j = 0; ebpf_modules[j].thread_name != NULL; j++) {
589
- if (ebpf_modules[j].enabled == NETDATA_THREAD_EBPF_RUNNING)
626
+ if (ebpf_modules[j].enabled < NETDATA_THREAD_EBPF_STOPPING)
627
i++;
628
}
629
pthread_mutex_unlock(&ebpf_exit_cleanup);
@@ -665,7 +702,7 @@ static void ebpf_unload_unique_maps()
702
int i;
703
for (i = 0; ebpf_modules[i].thread_name; i++) {
704
// These threads are cleaned with other functions
668
- if (i > EBPF_MODULE_SOCKET_IDX)
705
+ if (i != EBPF_MODULE_SOCKET_IDX)
706
continue;
707
708
if (ebpf_modules[i].enabled != NETDATA_THREAD_EBPF_STOPPED) {
@@ -680,13 +717,10 @@ static void ebpf_unload_unique_maps()
717
continue;
718
}
719
683
- if (i == EBPF_MODULE_SOCKET_IDX) {
720
#ifdef LIBBPF_MAJOR_VERSION
685
- if (socket_bpf_obj)
686
- socket_bpf__destroy(socket_bpf_obj);
721
+ if (socket_bpf_obj)
722
+ socket_bpf__destroy(socket_bpf_obj);
723
#endif
688
- }
689
-
724
}
725
}
726
@@ -698,7 +732,7 @@ static void ebpf_unload_unique_maps()
732
static void ebpf_unload_filesystems()
733
{
734
if (ebpf_modules[EBPF_MODULE_FILESYSTEM_IDX].enabled == NETDATA_THREAD_EBPF_NOT_RUNNING ||
701
- ebpf_modules[EBPF_MODULE_FILESYSTEM_IDX].enabled == NETDATA_THREAD_EBPF_RUNNING ||
735
+ ebpf_modules[EBPF_MODULE_FILESYSTEM_IDX].enabled < NETDATA_THREAD_EBPF_STOPPING ||
736
ebpf_modules[EBPF_MODULE_FILESYSTEM_IDX].load != EBPF_LOAD_LEGACY)
737
return;
738
@@ -719,7 +753,7 @@ static void ebpf_unload_filesystems()
753
static void ebpf_unload_sync()
754
{
755
if (ebpf_modules[EBPF_MODULE_SYNC_IDX].enabled == NETDATA_THREAD_EBPF_NOT_RUNNING ||
722
- ebpf_modules[EBPF_MODULE_SYNC_IDX].enabled == NETDATA_THREAD_EBPF_RUNNING)
756
+ ebpf_modules[EBPF_MODULE_SYNC_IDX].enabled < NETDATA_THREAD_EBPF_STOPPING)
757
return;
758
759
int i;
@@ -757,7 +791,7 @@ static void ebpf_stop_threads(int sig)
791
only_one = 1;
792
int i;
793
for (i = 0; ebpf_modules[i].thread_name != NULL; i++) {
760
- if (ebpf_modules[i].enabled == NETDATA_THREAD_EBPF_RUNNING) {
794
+ if (ebpf_modules[i].enabled < NETDATA_THREAD_EBPF_STOPPING) {
795
netdata_thread_cancel(*ebpf_modules[i].thread->thread);
796
#ifdef NETDATA_DEV_MODE
797
netdata_log_info("Sending cancel for thread %s", ebpf_modules[i].thread_name);
@@ -792,6 +826,19 @@ static void ebpf_stop_threads(int sig)
826
*
827
*****************************************************************/
828
829
+/**
830
+ * Create apps for module
831
+ *
832
+ * Create apps chart that will be used with specific module
833
+ *
834
+ * @param em the module main structure.
835
+ * @param root a pointer for the targets.
836
+ */
837
+static inline void ebpf_create_apps_for_module(ebpf_module_t *em, struct ebpf_target *root) {
838
+ if (em->enabled < NETDATA_THREAD_EBPF_STOPPING && em->apps_charts && em->apps_routine)
839
+ em->apps_routine(em, root);
840
+}
841
+
842
/**
843
* Create apps charts
844
*
@@ -833,14 +880,21 @@ static void ebpf_create_apps_charts(struct ebpf_target *root)
880
}
881
}
882
836
- if (!newly_added)
883
+ int i;
884
+ if (!newly_added) {
885
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX ; i++) {
886
+ ebpf_module_t *current = &ebpf_modules[i];
887
+ if (current->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
888
+ continue;
889
+
890
+ ebpf_create_apps_for_module(current, root);
891
+ }
892
return;
893
+ }
894
839
- int counter;
840
- for (counter = 0; ebpf_modules[counter].thread_name; counter++) {
841
- ebpf_module_t *current = &ebpf_modules[counter];
842
- if (current->enabled == NETDATA_THREAD_EBPF_RUNNING && current->apps_charts && current->apps_routine)
843
- current->apps_routine(current, root);
895
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX ; i++) {
896
+ ebpf_module_t *current = &ebpf_modules[i];
897
+ ebpf_create_apps_for_module(current, root);
898
}
899
}
900
@@ -1169,7 +1223,7 @@ void write_histogram_chart(char *family, char *name, const netdata_idx_t *hist,
1223
* @param name the name used to create aral
1224
* @param em a pointer to the structure with the default values.
1225
*/
1172
-void ebpf_statistic_create_aral_chart(char *name, ebpf_module_t *em)
1226
+int ebpf_statistic_create_aral_chart(char *name, ebpf_module_t *em)
1227
{
1228
static int priority = 140100;
1229
char *mem = { NETDATA_EBPF_STAT_DIMENSION_MEMORY };
@@ -1207,6 +1261,40 @@ void ebpf_statistic_create_aral_chart(char *name, ebpf_module_t *em)
1261
ebpf_write_global_dimension(aral,
1262
aral,
1263
ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
1264
+
1265
+ return priority - 2;
1266
+}
1267
+
1268
+/**
1269
+ * ARAL Charts
1270
+ *
1271
+ * Add chart to monitor ARAL usage
1272
+ * Caller must call this function with mutex locked.
1273
+ *
1274
+ * @param em a pointer to the structure with the default values.
1275
+ * @param prio the initial priority used to disable charts.
1276
+ */
1277
+void ebpf_statistic_obsolete_aral_chart(ebpf_module_t *em, int prio)
1278
+{
1279
+ ebpf_write_chart_obsolete(NETDATA_MONITORING_FAMILY,
1280
+ em->memory_allocations,
1281
+ "Calls to allocate memory.",
1282
+ "calls",
1283
+ NETDATA_EBPF_FAMILY,
1284
+ NETDATA_EBPF_CHART_TYPE_STACKED,
1285
+ "netdata.ebpf_aral_stat_alloc",
1286
+ prio++,
1287
+ em->update_every);
1288
+
1289
+ ebpf_write_chart_obsolete(NETDATA_MONITORING_FAMILY,
1290
+ em->memory_allocations,
1291
+ "Calls to allocate memory.",
1292
+ "calls",
1293
+ NETDATA_EBPF_FAMILY,
1294
+ NETDATA_EBPF_CHART_TYPE_STACKED,
1295
+ "netdata.ebpf_aral_stat_alloc",
1296
+ prio++,
1297
+ em->update_every);
1298
}
1299
1300
/**
@@ -1280,7 +1368,7 @@ void ebpf_global_labels(netdata_syscall_stat_t *is, netdata_publish_syscall_t *p
1368
static inline void ebpf_set_thread_mode(netdata_run_mode_t lmode)
1369
{
1370
int i;
1283
- for (i = 0; ebpf_modules[i].thread_name; i++) {
1371
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
1372
ebpf_modules[i].mode = lmode;
1373
}
1374
}
@@ -1289,16 +1377,15 @@ static inline void ebpf_set_thread_mode(netdata_run_mode_t lmode)
1377
* Enable specific charts selected by user.
1378
*
1379
* @param em the structure that will be changed
1292
- * @param disable_apps the status about the apps charts.
1380
* @param disable_cgroup the status about the cgroups charts.
1381
*/
1295
-static inline void ebpf_enable_specific_chart(struct ebpf_module *em, int disable_apps, int disable_cgroup)
1382
+static inline void ebpf_enable_specific_chart(struct ebpf_module *em, int disable_cgroup)
1383
{
1384
em->enabled = CONFIG_BOOLEAN_YES;
1385
1386
// oomkill stores data inside apps submenu, so it always need to have apps_enabled for plugin to create
1387
// its chart, without this comparison eBPF.plugin will try to store invalid data when apps is disabled.
1301
- if (!disable_apps || !strcmp(em->thread_name, "oomkill")) {
1388
+ if (!strcmp(em->thread_name, "oomkill")) {
1389
em->apps_charts = NETDATA_EBPF_APPS_FLAG_YES;
1390
}
1391
@@ -1309,20 +1396,6 @@ static inline void ebpf_enable_specific_chart(struct ebpf_module *em, int disabl
1396
em->global_charts = CONFIG_BOOLEAN_YES;
1397
}
1398
1312
-/**
1313
- * Enable all charts
1314
- *
1315
- * @param apps what is the current status of apps
1316
- * @param cgroups what is the current status of cgroups
1317
- */
1318
-static inline void ebpf_enable_all_charts(int apps, int cgroups)
1319
-{
1320
- int i;
1321
- for (i = 0; ebpf_modules[i].thread_name; i++) {
1322
- ebpf_enable_specific_chart(&ebpf_modules[i], apps, cgroups);
1323
- }
1324
-}
1325
-
1399
/**
1400
* Disable all Global charts
1401
*
@@ -1337,37 +1410,22 @@ static inline void disable_all_global_charts()
1410
}
1411
}
1412
1340
-
1413
/**
1414
* Enable the specified chart group
1415
*
1416
* @param idx the index of ebpf_modules that I am enabling
1345
- * @param disable_apps should I keep apps charts?
1417
*/
1347
-static inline void ebpf_enable_chart(int idx, int disable_apps, int disable_cgroup)
1418
+static inline void ebpf_enable_chart(int idx, int disable_cgroup)
1419
{
1420
int i;
1421
for (i = 0; ebpf_modules[i].thread_name; i++) {
1422
if (i == idx) {
1352
- ebpf_enable_specific_chart(&ebpf_modules[i], disable_apps, disable_cgroup);
1423
+ ebpf_enable_specific_chart(&ebpf_modules[i], disable_cgroup);
1424
break;
1425
}
1426
}
1427
}
1428
1358
-/**
1359
- * Disable APPs
1360
- *
1361
- * Disable charts for apps loading only global charts.
1362
- */
1363
-static inline void ebpf_disable_apps()
1364
-{
1365
- int i;
1366
- for (i = 0; ebpf_modules[i].thread_name; i++) {
1367
- ebpf_modules[i].apps_charts = NETDATA_EBPF_APPS_FLAG_NO;
1368
- }
1369
-}
1370
-
1429
/**
1430
* Disable Cgroups
1431
*
@@ -1670,33 +1728,11 @@ void ebpf_start_pthread_variables()
1728
pthread_mutex_init(&mutex_cgroup_shm, NULL);
1729
}
1730
1673
-/**
1674
- * Am I collecting PIDs?
1675
- *
1676
- * Test if eBPF plugin needs to collect PID information.
1677
- *
1678
- * @return It returns 1 if at least one thread needs to collect the data, or zero otherwise.
1679
- */
1680
-static inline uint32_t ebpf_am_i_collect_pids()
1681
-{
1682
- uint32_t ret = 0;
1683
- int i;
1684
- for (i = 0; ebpf_modules[i].thread_name; i++) {
1685
- ret |= ebpf_modules[i].cgroup_charts | (ebpf_modules[i].apps_charts & NETDATA_EBPF_APPS_FLAG_YES);
1686
- }
1687
-
1688
- return ret;
1689
-}
1690
-
1731
/**
1732
* Allocate the vectors used for all threads.
1733
*/
1734
static void ebpf_allocate_common_vectors()
1735
{
1696
- if (unlikely(!ebpf_am_i_collect_pids())) {
1697
- return;
1698
- }
1699
-
1736
ebpf_all_pids = callocz((size_t)pid_max, sizeof(struct ebpf_pid_stat *));
1737
ebpf_aral_init();
1738
}
@@ -1706,7 +1742,7 @@ static void ebpf_allocate_common_vectors()
1742
*
1743
* @param ptr the option given by users
1744
*/
1709
-static inline void how_to_load(char *ptr)
1745
+static inline void ebpf_how_to_load(char *ptr)
1746
{
1747
if (!strcasecmp(ptr, EBPF_CFG_LOAD_MODE_RETURN))
1748
ebpf_set_thread_mode(MODE_RETURN);
@@ -1716,6 +1752,20 @@ static inline void how_to_load(char *ptr)
1752
netdata_log_error("the option %s for \"ebpf load mode\" is not a valid option.", ptr);
1753
}
1754
1755
+/**
1756
+ * Define whether we should have charts for apps
1757
+ *
1758
+ * @param lmode the mode that will be used for them.
1759
+ */
1760
+static inline void ebpf_set_apps_mode(netdata_apps_integration_flags_t value)
1761
+{
1762
+ int i;
1763
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
1764
+ ebpf_modules[i].apps_charts = value;
1765
+ }
1766
+}
1767
+
1768
+
1769
/**
1770
* Update interval
1771
*
@@ -1748,6 +1798,21 @@ static void ebpf_update_table_size()
1798
}
1799
}
1800
1801
+/**
1802
+ * Update lifetime
1803
+ *
1804
+ * Update the period of time that specific thread will run
1805
+ */
1806
+static void ebpf_update_lifetime()
1807
+{
1808
+ int i;
1809
+ uint32_t value = (uint32_t) appconfig_get_number(&collector_config, EBPF_GLOBAL_SECTION,
1810
+ EBPF_CFG_LIFETIME, EBPF_DEFAULT_LIFETIME);
1811
+ for (i = 0; ebpf_modules[i].thread_name; i++) {
1812
+ ebpf_modules[i].lifetime = value;
1813
+ }
1814
+}
1815
+
1816
/**
1817
* Set Load mode
1818
*
@@ -1793,12 +1858,11 @@ static void ebpf_update_map_per_core()
1858
/**
1859
* Read collector values
1860
*
1796
- * @param disable_apps variable to store information related to apps.
1861
* @param disable_cgroups variable to store information related to cgroups.
1862
* @param update_every value to overwrite the update frequency set by the server.
1863
* @param origin specify the configuration file loaded
1864
*/
1801
-static void read_collector_values(int *disable_apps, int *disable_cgroups,
1865
+static void read_collector_values(int *disable_cgroups,
1866
int update_every, netdata_ebpf_load_mode_t origin)
1867
{
1868
// Read global section
@@ -1810,7 +1874,7 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
1874
value = appconfig_get(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE,
1875
EBPF_CFG_LOAD_MODE_DEFAULT);
1876
1813
- how_to_load(value);
1877
+ ebpf_how_to_load(value);
1878
1879
btf_path = appconfig_get(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_PROGRAM_PATH,
1880
EBPF_DEFAULT_BTF_PATH);
@@ -1827,6 +1891,8 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
1891
1892
ebpf_update_table_size();
1893
1894
+ ebpf_update_lifetime();
1895
+
1896
// This is kept to keep compatibility
1897
uint32_t enabled = appconfig_get_boolean(&collector_config, EBPF_GLOBAL_SECTION, "disable apps",
1898
CONFIG_BOOLEAN_NO);
@@ -1836,7 +1902,8 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
1902
CONFIG_BOOLEAN_YES);
1903
enabled = (enabled == CONFIG_BOOLEAN_NO)?CONFIG_BOOLEAN_YES:CONFIG_BOOLEAN_NO;
1904
}
1839
- *disable_apps = (int)enabled;
1905
+
1906
+ ebpf_set_apps_mode(!enabled);
1907
1908
// Cgroup is a positive sentence, so we need to invert the values to disable apps.
1909
// We are using the same pattern for cgroup and apps
@@ -1848,10 +1915,8 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
1915
// Read ebpf programs section
1916
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION,
1917
ebpf_modules[EBPF_MODULE_PROCESS_IDX].config_name, CONFIG_BOOLEAN_YES);
1851
- int started = 0;
1918
if (enabled) {
1853
- ebpf_enable_chart(EBPF_MODULE_PROCESS_IDX, *disable_apps, *disable_cgroups);
1854
- started++;
1919
+ ebpf_enable_chart(EBPF_MODULE_PROCESS_IDX, *disable_cgroups);
1920
}
1921
1922
// This is kept to keep compatibility
@@ -1862,8 +1927,7 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
1927
ebpf_modules[EBPF_MODULE_SOCKET_IDX].config_name,
1928
CONFIG_BOOLEAN_NO);
1929
if (enabled) {
1865
- ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, *disable_apps, *disable_cgroups);
1866
- started++;
1930
+ ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, *disable_cgroups);
1931
}
1932
1933
// This is kept to keep compatibility
@@ -1875,123 +1939,98 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
1939
network_viewer_opt.enabled = enabled;
1940
if (enabled) {
1941
if (!ebpf_modules[EBPF_MODULE_SOCKET_IDX].enabled)
1878
- ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, *disable_apps, *disable_cgroups);
1942
+ ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, *disable_cgroups);
1943
1944
// Read network viewer section if network viewer is enabled
1945
// This is kept here to keep backward compatibility
1946
parse_network_viewer_section(&collector_config);
1947
parse_service_name_section(&collector_config);
1884
- started++;
1948
}
1949
1950
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "cachestat",
1951
CONFIG_BOOLEAN_NO);
1952
1953
if (enabled) {
1891
- ebpf_enable_chart(EBPF_MODULE_CACHESTAT_IDX, *disable_apps, *disable_cgroups);
1892
- started++;
1954
+ ebpf_enable_chart(EBPF_MODULE_CACHESTAT_IDX, *disable_cgroups);
1955
}
1956
1957
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "sync",
1958
CONFIG_BOOLEAN_YES);
1959
1960
if (enabled) {
1899
- ebpf_enable_chart(EBPF_MODULE_SYNC_IDX, *disable_apps, *disable_cgroups);
1900
- started++;
1961
+ ebpf_enable_chart(EBPF_MODULE_SYNC_IDX, *disable_cgroups);
1962
}
1963
1964
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "dcstat",
1965
CONFIG_BOOLEAN_NO);
1966
if (enabled) {
1906
- ebpf_enable_chart(EBPF_MODULE_DCSTAT_IDX, *disable_apps, *disable_cgroups);
1907
- started++;
1967
+ ebpf_enable_chart(EBPF_MODULE_DCSTAT_IDX, *disable_cgroups);
1968
}
1969
1970
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "swap",
1971
CONFIG_BOOLEAN_NO);
1972
if (enabled) {
1913
- ebpf_enable_chart(EBPF_MODULE_SWAP_IDX, *disable_apps, *disable_cgroups);
1914
- started++;
1973
+ ebpf_enable_chart(EBPF_MODULE_SWAP_IDX, *disable_cgroups);
1974
}
1975
1976
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "vfs",
1977
CONFIG_BOOLEAN_NO);
1978
if (enabled) {
1920
- ebpf_enable_chart(EBPF_MODULE_VFS_IDX, *disable_apps, *disable_cgroups);
1921
- started++;
1979
+ ebpf_enable_chart(EBPF_MODULE_VFS_IDX, *disable_cgroups);
1980
}
1981
1982
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "filesystem",
1983
CONFIG_BOOLEAN_NO);
1984
if (enabled) {
1927
- ebpf_enable_chart(EBPF_MODULE_FILESYSTEM_IDX, *disable_apps, *disable_cgroups);
1928
- started++;
1985
+ ebpf_enable_chart(EBPF_MODULE_FILESYSTEM_IDX, *disable_cgroups);
1986
}
1987
1988
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "disk",
1989
CONFIG_BOOLEAN_NO);
1990
if (enabled) {
1934
- ebpf_enable_chart(EBPF_MODULE_DISK_IDX, *disable_apps, *disable_cgroups);
1935
- started++;
1991
+ ebpf_enable_chart(EBPF_MODULE_DISK_IDX, *disable_cgroups);
1992
}
1993
1994
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "mount",
1995
CONFIG_BOOLEAN_YES);
1996
if (enabled) {
1941
- ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, *disable_apps, *disable_cgroups);
1942
- started++;
1997
+ ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, *disable_cgroups);
1998
}
1999
2000
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "fd",
2001
CONFIG_BOOLEAN_YES);
2002
if (enabled) {
1948
- ebpf_enable_chart(EBPF_MODULE_FD_IDX, *disable_apps, *disable_cgroups);
1949
- started++;
2003
+ ebpf_enable_chart(EBPF_MODULE_FD_IDX, *disable_cgroups);
2004
}
2005
2006
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "hardirq",
2007
CONFIG_BOOLEAN_YES);
2008
if (enabled) {
1955
- ebpf_enable_chart(EBPF_MODULE_HARDIRQ_IDX, *disable_apps, *disable_cgroups);
1956
- started++;
2009
+ ebpf_enable_chart(EBPF_MODULE_HARDIRQ_IDX, *disable_cgroups);
2010
}
2011
2012
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "softirq",
2013
CONFIG_BOOLEAN_YES);
2014
if (enabled) {
1962
- ebpf_enable_chart(EBPF_MODULE_SOFTIRQ_IDX, *disable_apps, *disable_cgroups);
1963
- started++;
2015
+ ebpf_enable_chart(EBPF_MODULE_SOFTIRQ_IDX, *disable_cgroups);
2016
}
2017
2018
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "oomkill",
2019
CONFIG_BOOLEAN_YES);
2020
if (enabled) {
1969
- ebpf_enable_chart(EBPF_MODULE_OOMKILL_IDX, *disable_apps, *disable_cgroups);
1970
- started++;
2021
+ ebpf_enable_chart(EBPF_MODULE_OOMKILL_IDX, *disable_cgroups);
2022
}
2023
2024
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "shm",
2025
CONFIG_BOOLEAN_YES);
2026
if (enabled) {
1976
- ebpf_enable_chart(EBPF_MODULE_SHM_IDX, *disable_apps, *disable_cgroups);
1977
- started++;
2027
+ ebpf_enable_chart(EBPF_MODULE_SHM_IDX, *disable_cgroups);
2028
}
2029
2030
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "mdflush",
2031
CONFIG_BOOLEAN_NO);
2032
if (enabled) {
1983
- ebpf_enable_chart(EBPF_MODULE_MDFLUSH_IDX, *disable_apps, *disable_cgroups);
1984
- started++;
1985
- }
1986
-
1987
- if (!started){
1988
- ebpf_enable_all_charts(*disable_apps, *disable_cgroups);
1989
- // Read network viewer section
1990
- // This is kept here to keep backward compatibility
1991
- if (network_viewer_opt.enabled) {
1992
- parse_network_viewer_section(&collector_config);
1993
- parse_service_name_section(&collector_config);
1994
- }
2033
+ ebpf_enable_chart(EBPF_MODULE_MDFLUSH_IDX, *disable_cgroups);
2034
}
2035
}
2036
@@ -1999,13 +2038,12 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
2038
* Load collector config
2039
*
2040
* @param path the path where the file ebpf.conf is stored.
2002
- * @param disable_apps variable to store the information about apps plugin status.
2041
* @param disable_cgroups variable to store the information about cgroups plugin status.
2042
* @param update_every value to overwrite the update frequency set by the server.
2043
*
2044
* @return 0 on success and -1 otherwise.
2045
*/
2008
-static int load_collector_config(char *path, int *disable_apps, int *disable_cgroups, int update_every)
2046
+static int ebpf_load_collector_config(char *path, int *disable_cgroups, int update_every)
2047
{
2048
char lpath[4096];
2049
netdata_ebpf_load_mode_t origin;
@@ -2020,7 +2058,7 @@ static int load_collector_config(char *path, int *disable_apps, int *disable_cgr
2058
} else
2059
origin = EBPF_LOADED_FROM_USER;
2060
2023
- read_collector_values(disable_apps, disable_cgroups, update_every, origin);
2061
+ read_collector_values(disable_cgroups, update_every, origin);
2062
2063
return 0;
2064
}
@@ -2064,7 +2102,7 @@ void set_global_variables()
2102
static inline void ebpf_load_thread_config()
2103
{
2104
int i;
2067
- for (i = 0; ebpf_modules[i].thread_name; i++) {
2105
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
2106
ebpf_update_module(&ebpf_modules[i], default_btf, running_on_kernel, isrh);
2107
}
2108
}
@@ -2119,7 +2157,6 @@ int ebpf_adjust_memory_limit()
2157
*/
2158
static void ebpf_parse_args(int argc, char **argv)
2159
{
2122
- int disable_apps = 0;
2160
int disable_cgroups = 1;
2161
int freq = 0;
2162
int option_index = 0;
@@ -2166,11 +2203,11 @@ static void ebpf_parse_args(int argc, char **argv)
2203
if (!freq)
2204
freq = EBPF_DEFAULT_UPDATE_EVERY;
2205
2169
- if (load_collector_config(ebpf_user_config_dir, &disable_apps, &disable_cgroups, freq)) {
2206
+ if (ebpf_load_collector_config(ebpf_user_config_dir, &disable_cgroups, freq)) {
2207
netdata_log_info(
2208
"Does not have a configuration file inside `%s/ebpf.d.conf. It will try to load stock file.",
2209
ebpf_user_config_dir);
2173
- if (load_collector_config(ebpf_stock_config_dir, &disable_apps, &disable_cgroups, freq)) {
2210
+ if (ebpf_load_collector_config(ebpf_stock_config_dir, &disable_cgroups, freq)) {
2211
netdata_log_info("Does not have a stock file. It is starting with default options.");
2212
}
2213
}
@@ -2296,7 +2333,7 @@ static void ebpf_parse_args(int argc, char **argv)
2333
break;
2334
}
2335
case EBPF_OPTION_ALL_CHARTS: {
2299
- disable_apps = 0;
2336
+ ebpf_set_apps_mode(NETDATA_EBPF_APPS_FLAG_YES);
2337
disable_cgroups = 0;
2338
#ifdef NETDATA_INTERNAL_CHECKS
2339
netdata_log_info("EBPF running with all chart groups, because it was started with the option \"[-]-all\".");
@@ -2312,7 +2349,6 @@ static void ebpf_parse_args(int argc, char **argv)
2349
exit(0);
2350
}
2351
case EBPF_OPTION_GLOBAL_CHART: {
2315
- disable_apps = 1;
2352
disable_cgroups = 1;
2353
#ifdef NETDATA_INTERNAL_CHECKS
2354
netdata_log_info("EBPF running with global chart group, because it was started with the option \"[-]-global\".");
@@ -2373,10 +2409,7 @@ unittest:
2409
}
2410
}
2411
2376
- if (disable_apps || disable_cgroups) {
2377
- if (disable_apps)
2378
- ebpf_disable_apps();
2379
-
2412
+ if (disable_cgroups) {
2413
if (disable_cgroups)
2414
ebpf_disable_cgroups();
2415
}
@@ -2386,7 +2419,7 @@ unittest:
2419
uint64_t idx;
2420
for (idx = 0; idx < EBPF_OPTION_ALL_CHARTS; idx++) {
2421
if (select_threads & 1<<idx)
2389
- ebpf_enable_specific_chart(&ebpf_modules[idx], disable_apps, disable_cgroups);
2422
+ ebpf_enable_specific_chart(&ebpf_modules[idx], disable_cgroups);
2423
}
2424
}
2425
@@ -2405,6 +2438,280 @@ unittest:
2438
netdata_log_info("Loaded config file '%s/apps_groups.conf'", ebpf_user_config_dir);
2439
}
2440
2441
+/*****************************************************************
2442
+ *
2443
+ * Collector charts
2444
+ *
2445
+ *****************************************************************/
2446
+
2447
+static char *load_event_stat[NETDATA_EBPF_LOAD_STAT_END] = {"legacy", "co-re"};
2448
+static char *memlock_stat = {"memory_locked"};
2449
+static char *hash_table_stat = {"hash_table"};
2450
+static char *hash_table_core[NETDATA_EBPF_LOAD_STAT_END] = {"per_core", "unique"};
2451
+
2452
+/**
2453
+ * Send Statistic Data
2454
+ *
2455
+ * Send statistic information to netdata.
2456
+ */
2457
+void ebpf_send_statistic_data()
2458
+{
2459
+ if (!publish_internal_metrics)
2460
+ return;
2461
+
2462
+ write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_THREADS);
2463
+ int i;
2464
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
2465
+ ebpf_module_t *wem = &ebpf_modules[i];
2466
+ write_chart_dimension((char *)wem->thread_name, (wem->enabled < NETDATA_THREAD_EBPF_STOPPING) ? 1 : 0);
2467
+ }
2468
+ write_end_chart();
2469
+
2470
+ write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_LIFE_TIME);
2471
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX ; i++) {
2472
+ ebpf_module_t *wem = &ebpf_modules[i];
2473
+ // Threads like VFS is slow to load and this can create an invalid number, this is the motive
2474
+ // we are also testing wem->lifetime value.
2475
+ write_chart_dimension((char *)wem->thread_name,
2476
+ (wem->lifetime && wem->enabled < NETDATA_THREAD_EBPF_STOPPING) ?
2477
+ (long long) (wem->lifetime - wem->running_time):
2478
+ 0) ;
2479
+ }
2480
+ write_end_chart();
2481
+
2482
+ write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_LOAD_METHOD);
2483
+ write_chart_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_LEGACY], (long long)plugin_statistics.legacy);
2484
+ write_chart_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_CORE], (long long)plugin_statistics.core);
2485
+ write_end_chart();
2486
+
2487
+ write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_KERNEL_MEMORY);
2488
+ write_chart_dimension(memlock_stat, (long long)plugin_statistics.memlock_kern);
2489
+ write_end_chart();
2490
+
2491
+ write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_HASH_TABLES_LOADED);
2492
+ write_chart_dimension(hash_table_stat, (long long)plugin_statistics.hash_tables);
2493
+ write_end_chart();
2494
+
2495
+ write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_HASH_TABLES_PER_CORE);
2496
+ write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_PER_CORE], (long long)plugin_statistics.hash_percpu);
2497
+ write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_UNIQUE], (long long)plugin_statistics.hash_unique);
2498
+ write_end_chart();
2499
+}
2500
+
2501
+/**
2502
+ * Update Internal Metric variable
2503
+ *
2504
+ * By default eBPF.plugin sends internal metrics for netdata, but user can
2505
+ * disable this.
2506
+ *
2507
+ * The function updates the variable used to send charts.
2508
+ */
2509
+static void update_internal_metric_variable()
2510
+{
2511
+ const char *s = getenv("NETDATA_INTERNALS_MONITORING");
2512
+ if (s && *s && strcmp(s, "NO") == 0)
2513
+ publish_internal_metrics = false;
2514
+}
2515
+
2516
+/**
2517
+ * Create chart for Statistic Thread
2518
+ *
2519
+ * Write to standard output current values for threads.
2520
+ *
2521
+ * @param update_every time used to update charts
2522
+ */
2523
+static inline void ebpf_create_statistic_thread_chart(int update_every)
2524
+{
2525
+ ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
2526
+ NETDATA_EBPF_THREADS,
2527
+ "Threads running.",
2528
+ "boolean",
2529
+ NETDATA_EBPF_FAMILY,
2530
+ NETDATA_EBPF_CHART_TYPE_LINE,
2531
+ NULL,
2532
+ NETDATA_EBPF_ORDER_STAT_THREADS,
2533
+ update_every,
2534
+ NETDATA_EBPF_MODULE_NAME_PROCESS);
2535
+
2536
+ int i;
2537
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
2538
+ ebpf_write_global_dimension((char *)ebpf_modules[i].thread_name,
2539
+ (char *)ebpf_modules[i].thread_name,
2540
+ ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2541
+ }
2542
+}
2543
+
2544
+/**
2545
+ * Create lifetime Thread Chart
2546
+ *
2547
+ * Write to standard output current values for threads lifetime.
2548
+ *
2549
+ * @param update_every time used to update charts
2550
+ */
2551
+static inline void ebpf_create_lifetime_thread_chart(int update_every)
2552
+{
2553
+ ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
2554
+ NETDATA_EBPF_LIFE_TIME,
2555
+ "Threads running.",
2556
+ "seconds",
2557
+ NETDATA_EBPF_FAMILY,
2558
+ NETDATA_EBPF_CHART_TYPE_LINE,
2559
+ NULL,
2560
+ NETDATA_EBPF_ORDER_STAT_LIFE_TIME,
2561
+ update_every,
2562
+ NETDATA_EBPF_MODULE_NAME_PROCESS);
2563
+
2564
+ int i;
2565
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
2566
+ ebpf_write_global_dimension((char *)ebpf_modules[i].thread_name,
2567
+ (char *)ebpf_modules[i].thread_name,
2568
+ ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2569
+ }
2570
+}
2571
+
2572
+/**
2573
+ * Create chart for Load Thread
2574
+ *
2575
+ * Write to standard output current values for load mode.
2576
+ *
2577
+ * @param update_every time used to update charts
2578
+ */
2579
+static inline void ebpf_create_statistic_load_chart(int update_every)
2580
+{
2581
+ ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
2582
+ NETDATA_EBPF_LOAD_METHOD,
2583
+ "Load info.",
2584
+ "methods",
2585
+ NETDATA_EBPF_FAMILY,
2586
+ NETDATA_EBPF_CHART_TYPE_LINE,
2587
+ NULL,
2588
+ NETDATA_EBPF_ORDER_STAT_LOAD_METHOD,
2589
+ update_every,
2590
+ NETDATA_EBPF_MODULE_NAME_PROCESS);
2591
+
2592
+ ebpf_write_global_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_LEGACY],
2593
+ load_event_stat[NETDATA_EBPF_LOAD_STAT_LEGACY],
2594
+ ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2595
+
2596
+ ebpf_write_global_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_CORE],
2597
+ load_event_stat[NETDATA_EBPF_LOAD_STAT_CORE],
2598
+ ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2599
+}
2600
+
2601
+/**
2602
+ * Create chart for Kernel Memory
2603
+ *
2604
+ * Write to standard output current values for allocated memory.
2605
+ *
2606
+ * @param update_every time used to update charts
2607
+ */
2608
+static inline void ebpf_create_statistic_kernel_memory(int update_every)
2609
+{
2610
+ ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
2611
+ NETDATA_EBPF_KERNEL_MEMORY,
2612
+ "Memory allocated for hash tables.",
2613
+ "bytes",
2614
+ NETDATA_EBPF_FAMILY,
2615
+ NETDATA_EBPF_CHART_TYPE_LINE,
2616
+ NULL,
2617
+ NETDATA_EBPF_ORDER_STAT_KERNEL_MEMORY,
2618
+ update_every,
2619
+ NETDATA_EBPF_MODULE_NAME_PROCESS);
2620
+
2621
+ ebpf_write_global_dimension(memlock_stat,
2622
+ memlock_stat,
2623
+ ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2624
+}
2625
+
2626
+/**
2627
+ * Create chart Hash Table
2628
+ *
2629
+ * Write to standard output number of hash tables used with this software.
2630
+ *
2631
+ * @param update_every time used to update charts
2632
+ */
2633
+static inline void ebpf_create_statistic_hash_tables(int update_every)
2634
+{
2635
+ ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
2636
+ NETDATA_EBPF_HASH_TABLES_LOADED,
2637
+ "Number of hash tables loaded.",
2638
+ "hash tables",
2639
+ NETDATA_EBPF_FAMILY,
2640
+ NETDATA_EBPF_CHART_TYPE_LINE,
2641
+ NULL,
2642
+ NETDATA_EBPF_ORDER_STAT_HASH_TABLES,
2643
+ update_every,
2644
+ NETDATA_EBPF_MODULE_NAME_PROCESS);
2645
+
2646
+ ebpf_write_global_dimension(hash_table_stat,
2647
+ hash_table_stat,
2648
+ ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2649
+}
2650
+
2651
+/**
2652
+ * Create chart for percpu stats
2653
+ *
2654
+ * Write to standard output current values for threads.
2655
+ *
2656
+ * @param update_every time used to update charts
2657
+ */
2658
+static inline void ebpf_create_statistic_hash_per_core(int update_every)
2659
+{
2660
+ ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
2661
+ NETDATA_EBPF_HASH_TABLES_PER_CORE,
2662
+ "How threads are loading hash/array tables.",
2663
+ "threads",
2664
+ NETDATA_EBPF_FAMILY,
2665
+ NETDATA_EBPF_CHART_TYPE_LINE,
2666
+ NULL,
2667
+ NETDATA_EBPF_ORDER_STAT_HASH_CORE,
2668
+ update_every,
2669
+ NETDATA_EBPF_MODULE_NAME_PROCESS);
2670
+
2671
+ ebpf_write_global_dimension(hash_table_core[NETDATA_EBPF_THREAD_PER_CORE],
2672
+ hash_table_core[NETDATA_EBPF_THREAD_PER_CORE],
2673
+ ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2674
+
2675
+ ebpf_write_global_dimension(hash_table_core[NETDATA_EBPF_THREAD_UNIQUE],
2676
+ hash_table_core[NETDATA_EBPF_THREAD_UNIQUE],
2677
+ ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2678
+}
2679
+
2680
+
2681
+/**
2682
+ * Create Statistics Charts
2683
+ *
2684
+ * Create charts that will show statistics related to eBPF plugin.
2685
+ *
2686
+ * @param update_every time used to update charts
2687
+ */
2688
+static void ebpf_create_statistic_charts(int update_every)
2689
+{
2690
+ static char create_charts = 1;
2691
+ update_internal_metric_variable();
2692
+ if (!publish_internal_metrics)
2693
+ return;
2694
+
2695
+ if (!create_charts)
2696
+ return;
2697
+
2698
+ create_charts = 0;
2699
+
2700
+ ebpf_create_statistic_thread_chart(update_every);
2701
+ EBPF_PLUGIN_FUNCTIONS(EBPF_FUNCTION_THREAD, EBPF_PLUGIN_THREAD_FUNCTION_DESCRIPTION);
2702
+
2703
+ ebpf_create_lifetime_thread_chart(update_every);
2704
+ EBPF_PLUGIN_FUNCTIONS(EBPF_FUNCTION_THREAD, EBPF_PLUGIN_THREAD_FUNCTION_DESCRIPTION);
2705
+
2706
+ ebpf_create_statistic_load_chart(update_every);
2707
+
2708
+ ebpf_create_statistic_kernel_memory(update_every);
2709
+
2710
+ ebpf_create_statistic_hash_tables(update_every);
2711
+
2712
+ ebpf_create_statistic_hash_per_core(update_every);
2713
+}
2714
+
2715
/*****************************************************************
2716
*
2717
* COLLECTOR ENTRY POINT
@@ -2637,11 +2944,11 @@ int main(int argc, char **argv)
2944
2945
ebpf_module_t *em = &ebpf_modules[i];
2946
em->thread = st;
2640
- // We always initialize process, because it is responsible to take care of apps integration
2641
- if (em->enabled || !i) {
2947
+ em->thread_id = i;
2948
+ if (em->enabled) {
2949
st->thread = mallocz(sizeof(netdata_thread_t));
2643
- em->thread_id = i;
2950
em->enabled = NETDATA_THREAD_EBPF_RUNNING;
2951
+ em->lifetime = EBPF_NON_FUNCTION_LIFE_TIME;
2952
netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, em);
2953
} else {
2954
em->enabled = NETDATA_THREAD_EBPF_NOT_RUNNING;
@@ -2655,23 +2962,30 @@ int main(int argc, char **argv)
2962
int update_apps_list = update_apps_every - 1;
2963
int process_maps_per_core = ebpf_modules[EBPF_MODULE_PROCESS_IDX].maps_per_core;
2964
//Plugin will be killed when it receives a signal
2658
- while (!ebpf_exit_plugin) {
2965
+ for ( ; !ebpf_exit_plugin ; global_iterations_counter++) {
2966
(void)heartbeat_next(&hb, step);
2967
2968
+ if (global_iterations_counter % EBPF_DEFAULT_UPDATE_EVERY == 0) {
2969
+ pthread_mutex_lock(&lock);
2970
+ ebpf_create_statistic_charts(EBPF_DEFAULT_UPDATE_EVERY);
2971
+
2972
+ ebpf_send_statistic_data();
2973
+ pthread_mutex_unlock(&lock);
2974
+ fflush(stdout);
2975
+ }
2976
+
2977
pthread_mutex_lock(&ebpf_exit_cleanup);
2662
- if (process_pid_fd != -1) {
2663
- pthread_mutex_lock(&collect_data_mutex);
2664
- if (++update_apps_list == update_apps_every) {
2665
- update_apps_list = 0;
2666
- cleanup_exited_pids();
2667
- collect_data_for_all_processes(process_pid_fd, process_maps_per_core);
2668
-
2669
- pthread_mutex_lock(&lock);
2670
- ebpf_create_apps_charts(apps_groups_root_target);
2671
- pthread_mutex_unlock(&lock);
2672
- }
2673
- pthread_mutex_unlock(&collect_data_mutex);
2978
+ pthread_mutex_lock(&collect_data_mutex);
2979
+ if (++update_apps_list == update_apps_every) {
2980
+ update_apps_list = 0;
2981
+ cleanup_exited_pids();
2982
+ collect_data_for_all_processes(process_pid_fd, process_maps_per_core);
2983
+
2984
+ pthread_mutex_lock(&lock);
2985
+ ebpf_create_apps_charts(apps_groups_root_target);
2986
+ pthread_mutex_unlock(&lock);
2987
}
2988
+ pthread_mutex_unlock(&collect_data_mutex);
2989
pthread_mutex_unlock(&ebpf_exit_cleanup);
2990
}
2991
@@ -2679,4 +2993,3 @@ int main(int argc, char **argv)
2993
2994
return 0;
2995
}
2682
-
collectors/ebpf.plugin/ebpf.d.conf
+3
@@ -19,6 +19,8 @@
19
#
20
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.15.
21
#
22
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
23
+#
24
[global]
25
ebpf load mode = entry
26
apps = no
@@ -27,6 +29,7 @@
29
pid table size = 32768
30
btf path = /sys/kernel/btf/
31
maps per core = yes
32
+ lifetime = 300
33
34
#
35
# eBPF Programs
collectors/ebpf.plugin/ebpf.d/cachestat.conf
+3
@@ -26,6 +26,8 @@
26
#
27
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
28
#
29
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
30
+#
31
# Uncomment lines to define specific options for thread.
32
[global]
33
# ebpf load mode = entry
@@ -37,3 +39,4 @@
39
ebpf co-re tracing = trampoline
40
collect pid = real parent
41
# maps per core = yes
42
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/dcstat.conf
+3
@@ -24,6 +24,8 @@
24
#
25
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
26
#
27
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
28
+#
29
# Uncomment lines to define specific options for thread.
30
[global]
31
# ebpf load mode = entry
@@ -35,3 +37,4 @@
37
ebpf co-re tracing = trampoline
38
collect pid = real parent
39
# maps per core = yes
40
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/disk.conf
+4
-1
@@ -3,7 +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
-#[global]
6
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
7
+#
8
+[global]
9
# ebpf load mode = entry
10
# update every = 10
11
+ lifetime = 300
12
collectors/ebpf.plugin/ebpf.d/fd.conf
+3
@@ -12,6 +12,8 @@
12
#
13
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
14
#
15
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
16
+#
17
# Uncomment lines to define specific options for thread.
18
[global]
19
# ebpf load mode = entry
@@ -22,3 +24,4 @@
24
ebpf type format = auto
25
ebpf co-re tracing = trampoline
26
# maps per core = yes
27
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/filesystem.conf
+4
-1
@@ -3,13 +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 `lifetime` defines the time length a thread will run when it is enabled by a function.
7
+#
8
# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
9
# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
10
# 'no'.
11
#
10
-#[global]
12
+[global]
13
# ebpf load mode = entry
14
# update every = 10
15
+ lifetime = 300
16
17
# All filesystems are named as 'NAMEdist' where NAME is the filesystem name while 'dist' is a reference for distribution.
18
[filesystem]
collectors/ebpf.plugin/ebpf.d/functions.conf
new
+3
@@ -0,0 +1,3 @@
1
+#[global]
2
+# update every = 5
3
+
collectors/ebpf.plugin/ebpf.d/hardirq.conf
+4
-1
@@ -3,6 +3,9 @@
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
-#[global]
6
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
7
+#
8
+[global]
9
# ebpf load mode = entry
10
# update every = 10
11
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/mdflush.conf
+5
-1
@@ -2,6 +2,10 @@
2
# `entry` : The eBPF collector only monitors calls for the functions, and does not show charts related to errors.
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
-#[global]
5
+#
6
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
7
+#
8
+[global]
9
# ebpf load mode = entry
10
# update every = 1
11
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/mount.conf
+4
@@ -12,8 +12,12 @@
12
# `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host.
13
# `tracepoint`: When available, the eBPF collector will use kernel tracepoint to monitor syscall.
14
# `probe` : This is the same as legacy code.
15
+#
16
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
17
+#
18
[global]
19
# ebpf load mode = entry
20
# update every = 1
21
ebpf type format = auto
22
ebpf co-re tracing = trampoline
23
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/network.conf
+3
@@ -26,6 +26,8 @@
26
#
27
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
28
#
29
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
30
+#
31
# Uncomment lines to define specific options for thread.
32
[global]
33
# ebpf load mode = entry
@@ -39,6 +41,7 @@
41
ebpf type format = auto
42
ebpf co-re tracing = trampoline
43
maps per core = no
44
+ lifetime = 300
45
46
#
47
# Network Connection
collectors/ebpf.plugin/ebpf.d/oomkill.conf
+5
-1
@@ -2,6 +2,10 @@
2
# `entry` : The eBPF collector only monitors calls for the functions, and does not show charts related to errors.
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
-#[global]
5
+#
6
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
7
+#
8
+[global]
9
# ebpf load mode = entry
10
# update every = 1
11
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/process.conf
+3
@@ -17,6 +17,8 @@
17
#
18
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
19
#
20
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
21
+#
22
# Uncomment lines to define specific options for thread.
23
[global]
24
# ebpf load mode = entry
@@ -26,3 +28,4 @@
28
# pid table size = 32768
29
collect pid = real parent
30
# maps per core = yes
31
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/shm.conf
+3
@@ -20,6 +20,8 @@
20
#
21
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
22
#
23
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
24
+#
25
# Uncomment lines to define specific options for thread.
26
[global]
27
# ebpf load mode = entry
@@ -30,6 +32,7 @@
32
ebpf type format = auto
33
ebpf co-re tracing = trampoline
34
# maps per core = yes
35
+ lifetime = 300
36
37
# List of monitored syscalls
38
[syscalls]
collectors/ebpf.plugin/ebpf.d/softirq.conf
+4
-1
@@ -3,6 +3,9 @@
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
-#[global]
6
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
7
+#
8
+[global]
9
# ebpf load mode = entry
10
# update every = 10
11
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/swap.conf
+3
@@ -19,6 +19,8 @@
19
#
20
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
21
#
22
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
23
+#
24
# Uncomment lines to define specific options for thread.
25
[global]
26
# ebpf load mode = entry
@@ -29,3 +31,4 @@
31
ebpf type format = auto
32
ebpf co-re tracing = trampoline
33
# maps per core = yes
34
+ lifetime = 300
collectors/ebpf.plugin/ebpf.d/sync.conf
+3
@@ -19,6 +19,8 @@
19
# `probe` : This is the same as legacy code.
20
#
21
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
22
+#
23
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
24
#
25
# Uncomment lines to define specific options for thread.
26
[global]
@@ -29,6 +31,7 @@
31
ebpf type format = auto
32
ebpf co-re tracing = trampoline
33
# maps per core = yes
34
+ lifetime = 300
35
36
# List of monitored syscalls
37
[syscalls]
collectors/ebpf.plugin/ebpf.d/vfs.conf
+3
@@ -20,6 +20,8 @@
20
#
21
# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
22
#
23
+# The `lifetime` defines the time length a thread will run when it is enabled by a function.
24
+#
25
# Uncomment lines to define specific options for thread.
26
[global]
27
# ebpf load mode = entry
@@ -30,3 +32,4 @@
32
ebpf type format = auto
33
ebpf co-re tracing = trampoline
34
# maps per core = yes
35
+ lifetime = 300
collectors/ebpf.plugin/ebpf.h
+2
@@ -118,6 +118,7 @@ enum ebpf_main_index {
118
EBPF_MODULE_OOMKILL_IDX,
119
EBPF_MODULE_SHM_IDX,
120
EBPF_MODULE_MDFLUSH_IDX,
121
+ EBPF_MODULE_FUNCTION_IDX,
122
/* THREADS MUST BE INCLUDED BEFORE THIS COMMENT */
123
EBPF_OPTION_ALL_CHARTS,
124
EBPF_OPTION_VERSION,
@@ -163,6 +164,7 @@ typedef struct ebpf_tracepoint {
164
165
// Statistics charts
166
#define NETDATA_EBPF_THREADS "ebpf_threads"
167
+#define NETDATA_EBPF_LIFE_TIME "ebpf_life_time"
168
#define NETDATA_EBPF_LOAD_METHOD "ebpf_load_methods"
169
#define NETDATA_EBPF_KERNEL_MEMORY "ebpf_kernel_memory"
170
#define NETDATA_EBPF_HASH_TABLES_LOADED "ebpf_hash_tables_count"
collectors/ebpf.plugin/ebpf_apps.c
+30
-24
@@ -1338,8 +1338,10 @@ void cleanup_exited_pids()
1338
p = p->next;
1339
1340
// Clean process structure
1341
- ebpf_process_stat_release(global_process_stats[r]);
1342
- global_process_stats[r] = NULL;
1341
+ if (global_process_stats) {
1342
+ ebpf_process_stat_release(global_process_stats[r]);
1343
+ global_process_stats[r] = NULL;
1344
+ }
1345
1346
cleanup_variables_from_other_threads(r);
1347
@@ -1471,36 +1473,40 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd, int maps_per_core)
1473
uint32_t key;
1474
pids = ebpf_root_of_pids; // global list of all processes running
1475
// while (bpf_map_get_next_key(tbl_pid_stats_fd, &key, &next_key) == 0) {
1474
- size_t length = sizeof(ebpf_process_stat_t);
1475
- if (maps_per_core)
1476
- length *= ebpf_nprocs;
1476
1478
- while (pids) {
1479
- key = pids->pid;
1480
- ebpf_process_stat_t *w = global_process_stats[key];
1481
- if (!w) {
1482
- w = ebpf_process_stat_get();
1483
- global_process_stats[key] = w;
1484
- }
1477
+ if (tbl_pid_stats_fd != -1) {
1478
+ size_t length = sizeof(ebpf_process_stat_t);
1479
+ if (maps_per_core)
1480
+ length *= ebpf_nprocs;
1481
1486
- if (bpf_map_lookup_elem(tbl_pid_stats_fd, &key, process_stat_vector)) {
1487
- // Clean Process structures
1488
- ebpf_process_stat_release(w);
1489
- global_process_stats[key] = NULL;
1482
+ while (pids) {
1483
+ key = pids->pid;
1484
1491
- cleanup_variables_from_other_threads(key);
1485
+ ebpf_process_stat_t *w = global_process_stats[key];
1486
+ if (!w) {
1487
+ w = ebpf_process_stat_get();
1488
+ global_process_stats[key] = w;
1489
+ }
1490
1493
- pids = pids->next;
1494
- continue;
1495
- }
1491
+ if (bpf_map_lookup_elem(tbl_pid_stats_fd, &key, process_stat_vector)) {
1492
+ // Clean Process structures
1493
+ ebpf_process_stat_release(w);
1494
+ global_process_stats[key] = NULL;
1495
1497
- ebpf_process_apps_accumulator(process_stat_vector, maps_per_core);
1496
+ cleanup_variables_from_other_threads(key);
1497
1499
- memcpy(w, process_stat_vector, sizeof(ebpf_process_stat_t));
1498
+ pids = pids->next;
1499
+ continue;
1500
+ }
1501
1501
- memset(process_stat_vector, 0, length);
1502
+ ebpf_process_apps_accumulator(process_stat_vector, maps_per_core);
1503
1503
- pids = pids->next;
1504
+ memcpy(w, process_stat_vector, sizeof(ebpf_process_stat_t));
1505
+
1506
+ memset(process_stat_vector, 0, length);
1507
+
1508
+ pids = pids->next;
1509
+ }
1510
}
1511
1512
link_all_processes_to_their_parents();
collectors/ebpf.plugin/ebpf_apps.h
+1
@@ -21,6 +21,7 @@
21
#include "ebpf_disk.h"
22
#include "ebpf_fd.h"
23
#include "ebpf_filesystem.h"
24
+#include "ebpf_functions.h"
25
#include "ebpf_hardirq.h"
26
#include "ebpf_cachestat.h"
27
#include "ebpf_mdflush.h"
collectors/ebpf.plugin/ebpf_cachestat.c
+222
-4
@@ -58,6 +58,10 @@ netdata_ebpf_targets_t cachestat_targets[] = { {.name = "add_to_page_cache_lru",
58
static char *account_page[NETDATA_CACHESTAT_ACCOUNT_DIRTY_END] ={ "account_page_dirtied",
59
"__set_page_dirty", "__folio_mark_dirty" };
60
61
+#ifdef NETDATA_DEV_MODE
62
+int cachestat_disable_priority;
63
+#endif
64
+
65
#ifdef LIBBPF_MAJOR_VERSION
66
/**
67
* Disable probe
@@ -336,6 +340,179 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf
340
*
341
*****************************************************************/
342
343
+static void ebpf_obsolete_specific_cachestat_charts(char *type, int update_every);
344
+
345
+/**
346
+ * Obsolete services
347
+ *
348
+ * Obsolete all service charts created
349
+ *
350
+ * @param em a pointer to `struct ebpf_module`
351
+ */
352
+static void ebpf_obsolete_services(ebpf_module_t *em)
353
+{
354
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
355
+ NETDATA_CACHESTAT_HIT_RATIO_CHART,
356
+ "Hit ratio",
357
+ EBPF_COMMON_DIMENSION_PERCENTAGE,
358
+ NETDATA_CACHESTAT_SUBMENU,
359
+ NETDATA_EBPF_CHART_TYPE_LINE,
360
+ NETDATA_SYSTEMD_CACHESTAT_HIT_RATIO_CONTEXT,
361
+ 21100,
362
+ em->update_every);
363
+
364
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
365
+ NETDATA_CACHESTAT_DIRTY_CHART,
366
+ "Number of dirty pages",
367
+ EBPF_CACHESTAT_DIMENSION_PAGE,
368
+ NETDATA_CACHESTAT_SUBMENU,
369
+ NETDATA_EBPF_CHART_TYPE_LINE,
370
+ NETDATA_SYSTEMD_CACHESTAT_MODIFIED_CACHE_CONTEXT,
371
+ 21101,
372
+ em->update_every);
373
+
374
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
375
+ NETDATA_CACHESTAT_HIT_CHART,
376
+ "Number of accessed files",
377
+ EBPF_CACHESTAT_DIMENSION_HITS,
378
+ NETDATA_CACHESTAT_SUBMENU,
379
+ NETDATA_EBPF_CHART_TYPE_LINE,
380
+ NETDATA_SYSTEMD_CACHESTAT_HIT_FILE_CONTEXT,
381
+ 21102,
382
+ em->update_every);
383
+
384
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
385
+ NETDATA_CACHESTAT_MISSES_CHART,
386
+ "Files out of page cache",
387
+ EBPF_CACHESTAT_DIMENSION_MISSES,
388
+ NETDATA_CACHESTAT_SUBMENU,
389
+ NETDATA_EBPF_CHART_TYPE_LINE,
390
+ NETDATA_SYSTEMD_CACHESTAT_MISS_FILES_CONTEXT,
391
+ 21103,
392
+ em->update_every);
393
+}
394
+
395
+/**
396
+ * Obsolete cgroup chart
397
+ *
398
+ * Send obsolete for all charts created before to close.
399
+ *
400
+ * @param em a pointer to `struct ebpf_module`
401
+ */
402
+static inline void ebpf_obsolete_cachestat_cgroup_charts(ebpf_module_t *em) {
403
+ pthread_mutex_lock(&mutex_cgroup_shm);
404
+
405
+ ebpf_obsolete_services(em);
406
+
407
+ ebpf_cgroup_target_t *ect;
408
+ for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
409
+ if (ect->systemd)
410
+ continue;
411
+
412
+ ebpf_obsolete_specific_cachestat_charts(ect->name, em->update_every);
413
+ }
414
+ pthread_mutex_unlock(&mutex_cgroup_shm);
415
+}
416
+
417
+/**
418
+ * Obsolete global
419
+ *
420
+ * Obsolete global charts created by thread.
421
+ *
422
+ * @param em a pointer to `struct ebpf_module`
423
+ */
424
+static void ebpf_obsolete_cachestat_global(ebpf_module_t *em)
425
+{
426
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MEMORY_GROUP,
427
+ NETDATA_CACHESTAT_HIT_RATIO_CHART,
428
+ "Hit ratio",
429
+ EBPF_COMMON_DIMENSION_PERCENTAGE,
430
+ NETDATA_CACHESTAT_SUBMENU,
431
+ NETDATA_EBPF_CHART_TYPE_LINE,
432
+ NULL,
433
+ 21100,
434
+ em->update_every);
435
+
436
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MEMORY_GROUP,
437
+ NETDATA_CACHESTAT_DIRTY_CHART,
438
+ "Number of dirty pages",
439
+ EBPF_CACHESTAT_DIMENSION_PAGE,
440
+ NETDATA_CACHESTAT_SUBMENU,
441
+ NETDATA_EBPF_CHART_TYPE_LINE,
442
+ NULL,
443
+ 21101,
444
+ em->update_every);
445
+
446
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MEMORY_GROUP,
447
+ NETDATA_CACHESTAT_HIT_CHART,
448
+ "Number of accessed files",
449
+ EBPF_CACHESTAT_DIMENSION_HITS,
450
+ NETDATA_CACHESTAT_SUBMENU,
451
+ NETDATA_EBPF_CHART_TYPE_LINE,
452
+ NULL,
453
+ 21102,
454
+ em->update_every);
455
+
456
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MEMORY_GROUP,
457
+ NETDATA_CACHESTAT_MISSES_CHART,
458
+ "Files out of page cache",
459
+ EBPF_CACHESTAT_DIMENSION_MISSES,
460
+ NETDATA_CACHESTAT_SUBMENU,
461
+ NETDATA_EBPF_CHART_TYPE_LINE,
462
+ NULL,
463
+ 21103,
464
+ em->update_every);
465
+}
466
+
467
+/**
468
+ * Obsolette apps charts
469
+ *
470
+ * Obsolete apps charts.
471
+ *
472
+ * @param em a pointer to the structure with the default values.
473
+ */
474
+void ebpf_obsolete_cachestat_apps_charts(struct ebpf_module *em)
475
+{
476
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
477
+ NETDATA_CACHESTAT_HIT_RATIO_CHART,
478
+ "Hit ratio",
479
+ EBPF_COMMON_DIMENSION_PERCENTAGE,
480
+ NETDATA_CACHESTAT_SUBMENU,
481
+ NETDATA_EBPF_CHART_TYPE_LINE,
482
+ NULL,
483
+ 20090,
484
+ em->update_every);
485
+
486
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
487
+ NETDATA_CACHESTAT_DIRTY_CHART,
488
+ "Number of dirty pages",
489
+ EBPF_CACHESTAT_DIMENSION_PAGE,
490
+ NETDATA_CACHESTAT_SUBMENU,
491
+ NETDATA_EBPF_CHART_TYPE_STACKED,
492
+ NULL,
493
+ 20091,
494
+ em->update_every);
495
+
496
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY, NETDATA_CACHESTAT_HIT_CHART,
497
+ "Number of accessed files",
498
+ EBPF_CACHESTAT_DIMENSION_HITS,
499
+ NETDATA_CACHESTAT_SUBMENU,
500
+ NETDATA_EBPF_CHART_TYPE_STACKED,
501
+ NULL,
502
+ 20092,
503
+ em->update_every);
504
+
505
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
506
+ NETDATA_CACHESTAT_MISSES_CHART,
507
+ "Files out of page cache",
508
+ EBPF_CACHESTAT_DIMENSION_MISSES,
509
+ NETDATA_CACHESTAT_SUBMENU,
510
+ NETDATA_EBPF_CHART_TYPE_STACKED,
511
+ NULL,
512
+ 20093,
513
+ em->update_every);
514
+}
515
+
516
/**
517
* Cachestat exit.
518
*
@@ -347,17 +524,47 @@ static void ebpf_cachestat_exit(void *ptr)
524
{
525
ebpf_module_t *em = (ebpf_module_t *)ptr;
526
527
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
528
+ pthread_mutex_lock(&lock);
529
+ if (em->cgroup_charts) {
530
+ ebpf_obsolete_cachestat_cgroup_charts(em);
531
+ fflush(stdout);
532
+ }
533
+
534
+ if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
535
+ ebpf_obsolete_cachestat_apps_charts(em);
536
+ }
537
+
538
+ ebpf_obsolete_cachestat_global(em);
539
+
540
+#ifdef NETDATA_DEV_MODE
541
+ if (ebpf_aral_cachestat_pid)
542
+ ebpf_statistic_obsolete_aral_chart(em, cachestat_disable_priority);
543
+#endif
544
+
545
+
546
+ fflush(stdout);
547
+ pthread_mutex_unlock(&lock);
548
+ }
549
+
550
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
551
+
552
#ifdef LIBBPF_MAJOR_VERSION
351
- if (cachestat_bpf_obj)
553
+ if (cachestat_bpf_obj) {
554
cachestat_bpf__destroy(cachestat_bpf_obj);
555
+ cachestat_bpf_obj = NULL;
556
+ }
557
#endif
558
559
if (em->objects) {
560
ebpf_unload_legacy_code(em->objects, em->probe_links);
561
+ em->objects = NULL;
562
+ em->probe_links = NULL;
563
}
564
565
pthread_mutex_lock(&ebpf_exit_cleanup);
566
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
567
+ ebpf_update_stats(&plugin_statistics, em);
568
pthread_mutex_unlock(&ebpf_exit_cleanup);
569
}
570
@@ -1079,7 +1286,9 @@ static void cachestat_collector(ebpf_module_t *em)
1286
heartbeat_init(&hb);
1287
int counter = update_every - 1;
1288
//This will be cancelled by its parent
1082
- while (!ebpf_exit_plugin) {
1289
+ uint32_t running_time = 0;
1290
+ uint32_t lifetime = em->lifetime;
1291
+ while (!ebpf_exit_plugin && running_time < lifetime) {
1292
(void)heartbeat_next(&hb, USEC_PER_SEC);
1293
1294
if (ebpf_exit_plugin || ++counter != update_every)
@@ -1112,6 +1321,15 @@ static void cachestat_collector(ebpf_module_t *em)
1321
1322
pthread_mutex_unlock(&lock);
1323
pthread_mutex_unlock(&collect_data_mutex);
1324
+
1325
+ pthread_mutex_lock(&ebpf_exit_cleanup);
1326
+ if (running_time && !em->running_time)
1327
+ running_time = update_every;
1328
+ else
1329
+ running_time += update_every;
1330
+
1331
+ em->running_time = running_time;
1332
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
1333
}
1334
}
1335
@@ -1307,11 +1525,11 @@ void *ebpf_cachestat_thread(void *ptr)
1525
1526
pthread_mutex_lock(&lock);
1527
ebpf_update_stats(&plugin_statistics, em);
1310
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
1528
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
1529
ebpf_create_memory_charts(em);
1530
#ifdef NETDATA_DEV_MODE
1531
if (ebpf_aral_cachestat_pid)
1314
- ebpf_statistic_create_aral_chart(NETDATA_EBPF_CACHESTAT_ARAL_NAME, em);
1532
+ cachestat_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_CACHESTAT_ARAL_NAME, em);
1533
#endif
1534
1535
pthread_mutex_unlock(&lock);
collectors/ebpf.plugin/ebpf_cachestat.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_CACHESTAT_H
4
#define NETDATA_EBPF_CACHESTAT_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_CACHESTAT "cachestat"
8
+#define NETDATA_EBPF_CACHESTAT_MODULE_DESC "Monitor Linux page cache internal functions. This thread is integrated with apps and cgroup."
9
10
// charts
11
#define NETDATA_CACHESTAT_HIT_RATIO_CHART "cachestat_ratio"
collectors/ebpf.plugin/ebpf_dcstat.c
+206
-7
@@ -59,6 +59,10 @@ netdata_ebpf_targets_t dc_targets[] = { {.name = "lookup_fast", .mode = EBPF_LOA
59
{.name = "d_lookup", .mode = EBPF_LOAD_TRAMPOLINE},
60
{.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
61
62
+#ifdef NETDATA_DEV_MODE
63
+int dcstat_disable_priority;
64
+#endif
65
+
66
#ifdef LIBBPF_MAJOR_VERSION
67
/**
68
* Disable probe
@@ -285,6 +289,160 @@ void dcstat_update_publish(netdata_publish_dcstat_t *out, uint64_t cache_access,
289
*
290
*****************************************************************/
291
292
+static void ebpf_obsolete_specific_dc_charts(char *type, int update_every);
293
+
294
+/**
295
+ * Obsolete services
296
+ *
297
+ * Obsolete all service charts created
298
+ *
299
+ * @param em a pointer to `struct ebpf_module`
300
+ */
301
+static void ebpf_obsolete_dc_services(ebpf_module_t *em)
302
+{
303
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
304
+ NETDATA_DC_HIT_CHART,
305
+ "Percentage of files inside directory cache",
306
+ EBPF_COMMON_DIMENSION_PERCENTAGE,
307
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
308
+ NETDATA_EBPF_CHART_TYPE_LINE,
309
+ NETDATA_SYSTEMD_DC_HIT_RATIO_CONTEXT,
310
+ 21200,
311
+ em->update_every);
312
+
313
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
314
+ NETDATA_DC_REFERENCE_CHART,
315
+ "Count file access",
316
+ EBPF_COMMON_DIMENSION_FILES,
317
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
318
+ NETDATA_EBPF_CHART_TYPE_LINE,
319
+ NETDATA_SYSTEMD_DC_REFERENCE_CONTEXT,
320
+ 21201,
321
+ em->update_every);
322
+
323
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
324
+ NETDATA_DC_REQUEST_NOT_CACHE_CHART,
325
+ "Files not present inside directory cache",
326
+ EBPF_COMMON_DIMENSION_FILES,
327
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
328
+ NETDATA_EBPF_CHART_TYPE_LINE,
329
+ NETDATA_SYSTEMD_DC_NOT_CACHE_CONTEXT,
330
+ 21202,
331
+ em->update_every);
332
+
333
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
334
+ NETDATA_DC_REQUEST_NOT_FOUND_CHART,
335
+ "Files not found",
336
+ EBPF_COMMON_DIMENSION_FILES,
337
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
338
+ NETDATA_EBPF_CHART_TYPE_LINE,
339
+ NETDATA_SYSTEMD_DC_NOT_FOUND_CONTEXT,
340
+ 21202,
341
+ em->update_every);
342
+}
343
+
344
+/**
345
+ * Obsolete cgroup chart
346
+ *
347
+ * Send obsolete for all charts created before to close.
348
+ *
349
+ * @param em a pointer to `struct ebpf_module`
350
+ */
351
+static inline void ebpf_obsolete_dc_cgroup_charts(ebpf_module_t *em) {
352
+ pthread_mutex_lock(&mutex_cgroup_shm);
353
+
354
+ ebpf_obsolete_dc_services(em);
355
+
356
+ ebpf_cgroup_target_t *ect;
357
+ for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
358
+ if (ect->systemd)
359
+ continue;
360
+
361
+ ebpf_obsolete_specific_dc_charts(ect->name, em->update_every);
362
+ }
363
+ pthread_mutex_unlock(&mutex_cgroup_shm);
364
+}
365
+
366
+/**
367
+ * Obsolette apps charts
368
+ *
369
+ * Obsolete apps charts.
370
+ *
371
+ * @param em a pointer to the structure with the default values.
372
+ */
373
+void ebpf_obsolete_dc_apps_charts(struct ebpf_module *em)
374
+{
375
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
376
+ NETDATA_DC_HIT_CHART,
377
+ "Percentage of files inside directory cache",
378
+ EBPF_COMMON_DIMENSION_PERCENTAGE,
379
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
380
+ NETDATA_EBPF_CHART_TYPE_LINE,
381
+ NULL,
382
+ 20100,
383
+ em->update_every);
384
+
385
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
386
+ NETDATA_DC_REFERENCE_CHART,
387
+ "Count file access",
388
+ EBPF_COMMON_DIMENSION_FILES,
389
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
390
+ NETDATA_EBPF_CHART_TYPE_STACKED,
391
+ NULL,
392
+ 20101,
393
+ em->update_every);
394
+
395
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
396
+ NETDATA_DC_REQUEST_NOT_CACHE_CHART,
397
+ "Files not present inside directory cache",
398
+ EBPF_COMMON_DIMENSION_FILES,
399
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
400
+ NETDATA_EBPF_CHART_TYPE_STACKED,
401
+ NULL,
402
+ 20102,
403
+ em->update_every);
404
+
405
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
406
+ NETDATA_DC_REQUEST_NOT_FOUND_CHART,
407
+ "Files not found",
408
+ EBPF_COMMON_DIMENSION_FILES,
409
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
410
+ NETDATA_EBPF_CHART_TYPE_STACKED,
411
+ NULL,
412
+ 20103,
413
+ em->update_every);
414
+}
415
+
416
+/**
417
+ * Obsolete global
418
+ *
419
+ * Obsolete global charts created by thread.
420
+ *
421
+ * @param em a pointer to `struct ebpf_module`
422
+ */
423
+static void ebpf_obsolete_dc_global(ebpf_module_t *em)
424
+{
425
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
426
+ NETDATA_DC_HIT_CHART,
427
+ "Percentage of files inside directory cache",
428
+ EBPF_COMMON_DIMENSION_PERCENTAGE,
429
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
430
+ NETDATA_EBPF_CHART_TYPE_LINE,
431
+ NULL,
432
+ 21200,
433
+ em->update_every);
434
+
435
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
436
+ NETDATA_DC_REFERENCE_CHART,
437
+ "Variables used to calculate hit ratio.",
438
+ EBPF_COMMON_DIMENSION_FILES,
439
+ NETDATA_DIRECTORY_CACHE_SUBMENU,
440
+ NETDATA_EBPF_CHART_TYPE_LINE,
441
+ NULL,
442
+ 21201,
443
+ em->update_every);
444
+}
445
+
446
/**
447
* DCstat exit
448
*
@@ -296,16 +454,46 @@ static void ebpf_dcstat_exit(void *ptr)
454
{
455
ebpf_module_t *em = (ebpf_module_t *)ptr;
456
457
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
458
+ pthread_mutex_lock(&lock);
459
+ if (em->cgroup_charts) {
460
+ ebpf_obsolete_dc_cgroup_charts(em);
461
+ fflush(stdout);
462
+ }
463
+
464
+ if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
465
+ ebpf_obsolete_dc_apps_charts(em);
466
+ }
467
+
468
+ ebpf_obsolete_dc_global(em);
469
+
470
+#ifdef NETDATA_DEV_MODE
471
+ if (ebpf_aral_dcstat_pid)
472
+ ebpf_statistic_obsolete_aral_chart(em, dcstat_disable_priority);
473
+#endif
474
+
475
+ fflush(stdout);
476
+ pthread_mutex_unlock(&lock);
477
+ }
478
+
479
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
480
+
481
#ifdef LIBBPF_MAJOR_VERSION
300
- if (dc_bpf_obj)
482
+ if (dc_bpf_obj) {
483
dc_bpf__destroy(dc_bpf_obj);
484
+ dc_bpf_obj = NULL;
485
+ }
486
#endif
487
304
- if (em->objects)
488
+ if (em->objects){
489
ebpf_unload_legacy_code(em->objects, em->probe_links);
490
+ em->objects = NULL;
491
+ em->probe_links = NULL;
492
+ }
493
494
pthread_mutex_lock(&ebpf_exit_cleanup);
495
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
496
+ ebpf_update_stats(&plugin_statistics, em);
497
pthread_mutex_unlock(&ebpf_exit_cleanup);
498
}
499
@@ -979,7 +1167,9 @@ static void dcstat_collector(ebpf_module_t *em)
1167
heartbeat_init(&hb);
1168
int counter = update_every - 1;
1169
int maps_per_core = em->maps_per_core;
982
- while (!ebpf_exit_plugin) {
1170
+ uint32_t running_time = 0;
1171
+ uint32_t lifetime = em->lifetime;
1172
+ while (!ebpf_exit_plugin && running_time < lifetime) {
1173
(void)heartbeat_next(&hb, USEC_PER_SEC);
1174
1175
if (ebpf_exit_plugin || ++counter != update_every)
@@ -1012,6 +1202,15 @@ static void dcstat_collector(ebpf_module_t *em)
1202
1203
pthread_mutex_unlock(&lock);
1204
pthread_mutex_unlock(&collect_data_mutex);
1205
+
1206
+ pthread_mutex_lock(&ebpf_exit_cleanup);
1207
+ if (running_time && !em->running_time)
1208
+ running_time = update_every;
1209
+ else
1210
+ running_time += update_every;
1211
+
1212
+ em->running_time = running_time;
1213
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
1214
}
1215
}
1216
@@ -1028,7 +1227,7 @@ static void dcstat_collector(ebpf_module_t *em)
1227
*
1228
* @param update_every value to overwrite the update frequency set by the server.
1229
*/
1031
-static void ebpf_create_filesystem_charts(int update_every)
1230
+static void ebpf_create_dc_global_charts(int update_every)
1231
{
1232
ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_HIT_CHART,
1233
"Percentage of files inside directory cache",
@@ -1156,12 +1355,12 @@ void *ebpf_dcstat_thread(void *ptr)
1355
algorithms, NETDATA_DCSTAT_IDX_END);
1356
1357
pthread_mutex_lock(&lock);
1159
- ebpf_create_filesystem_charts(em->update_every);
1358
+ ebpf_create_dc_global_charts(em->update_every);
1359
ebpf_update_stats(&plugin_statistics, em);
1161
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
1360
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
1361
#ifdef NETDATA_DEV_MODE
1362
if (ebpf_aral_dcstat_pid)
1164
- ebpf_statistic_create_aral_chart(NETDATA_EBPF_DCSTAT_ARAL_NAME, em);
1363
+ dcstat_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_DCSTAT_ARAL_NAME, em);
1364
#endif
1365
1366
pthread_mutex_unlock(&lock);
collectors/ebpf.plugin/ebpf_dcstat.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_DCSTAT_H
4
#define NETDATA_EBPF_DCSTAT_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_DCSTAT "dcstat"
8
+#define NETDATA_EBPF_DC_MODULE_DESC "Monitor file access using directory cache. This thread is integrated with apps and cgroup."
9
10
// charts
11
#define NETDATA_DC_HIT_CHART "dc_hit_ratio"
collectors/ebpf.plugin/ebpf_disk.c
+63
-4
@@ -448,6 +448,7 @@ static void ebpf_cleanup_plot_disks()
448
449
move = next;
450
}
451
+ plot_disks = NULL;
452
}
453
454
/**
@@ -465,6 +466,36 @@ static void ebpf_cleanup_disk_list()
466
467
move = next;
468
}
469
+ disk_list = NULL;
470
+}
471
+
472
+/**
473
+ * Obsolete global
474
+ *
475
+ * Obsolete global charts created by thread.
476
+ *
477
+ * @param em a pointer to `struct ebpf_module`
478
+ */
479
+static void ebpf_obsolete_disk_global(ebpf_module_t *em)
480
+{
481
+ ebpf_publish_disk_t *move = plot_disks;
482
+ while (move) {
483
+ netdata_ebpf_disks_t *ned = move->plot;
484
+ uint32_t flags = ned->flags;
485
+ if (flags & NETDATA_DISK_CHART_CREATED) {
486
+ ebpf_write_chart_obsolete(ned->histogram.name,
487
+ ned->family,
488
+ "Disk latency",
489
+ EBPF_COMMON_DIMENSION_CALL,
490
+ ned->family,
491
+ NETDATA_EBPF_CHART_TYPE_STACKED,
492
+ NULL,
493
+ ned->histogram.order,
494
+ em->update_every);
495
+ }
496
+
497
+ move = move->next;
498
+ }
499
}
500
501
/**
@@ -478,15 +509,29 @@ static void ebpf_disk_exit(void *ptr)
509
{
510
ebpf_module_t *em = (ebpf_module_t *)ptr;
511
481
- if (em->objects)
482
- ebpf_unload_legacy_code(em->objects, em->probe_links);
512
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
513
+ pthread_mutex_lock(&lock);
514
+
515
+ ebpf_obsolete_disk_global(em);
516
517
+ pthread_mutex_unlock(&lock);
518
+ fflush(stdout);
519
+ }
520
ebpf_disk_disable_tracepoints();
521
522
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, disk_maps, EBPF_ACTION_STAT_REMOVE);
523
+
524
+ if (em->objects) {
525
+ ebpf_unload_legacy_code(em->objects, em->probe_links);
526
+ em->objects = NULL;
527
+ em->probe_links = NULL;
528
+ }
529
+
530
if (dimensions)
531
ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
532
533
freez(disk_hash_values);
534
+ disk_hash_values = NULL;
535
pthread_mutex_destroy(&plot_mutex);
536
537
ebpf_cleanup_plot_disks();
@@ -494,6 +539,7 @@ static void ebpf_disk_exit(void *ptr)
539
540
pthread_mutex_lock(&ebpf_exit_cleanup);
541
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
542
+ ebpf_update_stats(&plugin_statistics, em);
543
pthread_mutex_unlock(&ebpf_exit_cleanup);
544
}
545
@@ -640,6 +686,8 @@ static void ebpf_create_hd_charts(netdata_ebpf_disks_t *w, int update_every)
686
order++;
687
688
w->flags |= NETDATA_DISK_CHART_CREATED;
689
+
690
+ fflush(stdout);
691
}
692
693
/**
@@ -728,7 +776,9 @@ static void disk_collector(ebpf_module_t *em)
776
heartbeat_init(&hb);
777
int counter = update_every - 1;
778
int maps_per_core = em->maps_per_core;
731
- while (!ebpf_exit_plugin) {
779
+ uint32_t running_time = 0;
780
+ uint32_t lifetime = em->lifetime;
781
+ while (!ebpf_exit_plugin && running_time < lifetime) {
782
(void)heartbeat_next(&hb, USEC_PER_SEC);
783
784
if (ebpf_exit_plugin || ++counter != update_every)
@@ -743,6 +793,15 @@ static void disk_collector(ebpf_module_t *em)
793
pthread_mutex_unlock(&lock);
794
795
ebpf_update_disks(em);
796
+
797
+ pthread_mutex_lock(&ebpf_exit_cleanup);
798
+ if (running_time && !em->running_time)
799
+ running_time = update_every;
800
+ else
801
+ running_time += update_every;
802
+
803
+ em->running_time = running_time;
804
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
805
}
806
}
807
@@ -866,7 +925,7 @@ void *ebpf_disk_thread(void *ptr)
925
926
pthread_mutex_lock(&lock);
927
ebpf_update_stats(&plugin_statistics, em);
869
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, disk_maps);
928
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, disk_maps, EBPF_ACTION_STAT_ADD);
929
pthread_mutex_unlock(&lock);
930
931
disk_collector(em);
collectors/ebpf.plugin/ebpf_disk.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_DISK_H
4
#define NETDATA_EBPF_DISK_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_DISK "disk"
8
+#define NETDATA_EBPF_DISK_MODULE_DESC "Monitor disk latency independent of filesystem."
9
10
#include "libnetdata/avl/avl.h"
11
#include "libnetdata/ebpf/ebpf.h"
collectors/ebpf.plugin/ebpf_fd.c
+217
-5
@@ -57,6 +57,10 @@ netdata_ebpf_targets_t fd_targets[] = { {.name = "open", .mode = EBPF_LOAD_TRAMP
57
{.name = "close", .mode = EBPF_LOAD_TRAMPOLINE},
58
{.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
59
60
+#ifdef NETDATA_DEV_MODE
61
+int fd_disable_priority;
62
+#endif
63
+
64
#ifdef LIBBPF_MAJOR_VERSION
65
/**
66
* Disable probe
@@ -369,6 +373,170 @@ static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
373
*
374
*****************************************************************/
375
376
+static void ebpf_obsolete_specific_fd_charts(char *type, ebpf_module_t *em);
377
+
378
+/**
379
+ * Obsolete services
380
+ *
381
+ * Obsolete all service charts created
382
+ *
383
+ * @param em a pointer to `struct ebpf_module`
384
+ */
385
+static void ebpf_obsolete_fd_services(ebpf_module_t *em)
386
+{
387
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
388
+ NETDATA_SYSCALL_APPS_FILE_OPEN,
389
+ "Number of open files",
390
+ EBPF_COMMON_DIMENSION_CALL,
391
+ NETDATA_APPS_FILE_CGROUP_GROUP,
392
+ NETDATA_EBPF_CHART_TYPE_STACKED,
393
+ NETDATA_CGROUP_FD_OPEN_CONTEXT,
394
+ 20061,
395
+ em->update_every);
396
+
397
+ if (em->mode < MODE_ENTRY) {
398
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
399
+ NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR,
400
+ "Fails to open files",
401
+ EBPF_COMMON_DIMENSION_CALL,
402
+ NETDATA_APPS_FILE_CGROUP_GROUP,
403
+ NETDATA_EBPF_CHART_TYPE_STACKED,
404
+ NETDATA_CGROUP_FD_OPEN_ERR_CONTEXT,
405
+ 20062,
406
+ em->update_every);
407
+ }
408
+
409
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
410
+ NETDATA_SYSCALL_APPS_FILE_CLOSED,
411
+ "Files closed",
412
+ EBPF_COMMON_DIMENSION_CALL,
413
+ NETDATA_APPS_FILE_CGROUP_GROUP,
414
+ NETDATA_EBPF_CHART_TYPE_STACKED,
415
+ NETDATA_CGROUP_FD_CLOSE_CONTEXT,
416
+ 20063,
417
+ em->update_every);
418
+
419
+ if (em->mode < MODE_ENTRY) {
420
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
421
+ NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR,
422
+ "Fails to close files",
423
+ EBPF_COMMON_DIMENSION_CALL,
424
+ NETDATA_APPS_FILE_CGROUP_GROUP,
425
+ NETDATA_EBPF_CHART_TYPE_STACKED,
426
+ NETDATA_CGROUP_FD_CLOSE_ERR_CONTEXT,
427
+ 20064,
428
+ em->update_every);
429
+ }
430
+}
431
+
432
+/**
433
+ * Obsolete cgroup chart
434
+ *
435
+ * Send obsolete for all charts created before to close.
436
+ *
437
+ * @param em a pointer to `struct ebpf_module`
438
+ */
439
+static inline void ebpf_obsolete_fd_cgroup_charts(ebpf_module_t *em) {
440
+ pthread_mutex_lock(&mutex_cgroup_shm);
441
+
442
+ ebpf_obsolete_fd_services(em);
443
+
444
+ ebpf_cgroup_target_t *ect;
445
+ for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
446
+ if (ect->systemd)
447
+ continue;
448
+
449
+ ebpf_obsolete_specific_fd_charts(ect->name, em);
450
+ }
451
+ pthread_mutex_unlock(&mutex_cgroup_shm);
452
+}
453
+
454
+/**
455
+ * Obsolette apps charts
456
+ *
457
+ * Obsolete apps charts.
458
+ *
459
+ * @param em a pointer to the structure with the default values.
460
+ */
461
+void ebpf_obsolete_fd_apps_charts(struct ebpf_module *em)
462
+{
463
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
464
+ NETDATA_SYSCALL_APPS_FILE_OPEN,
465
+ "Number of open files",
466
+ EBPF_COMMON_DIMENSION_CALL,
467
+ NETDATA_APPS_FILE_GROUP,
468
+ NETDATA_EBPF_CHART_TYPE_STACKED,
469
+ NULL,
470
+ 20061,
471
+ em->update_every);
472
+
473
+ if (em->mode < MODE_ENTRY) {
474
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
475
+ NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR,
476
+ "Fails to open files",
477
+ EBPF_COMMON_DIMENSION_CALL,
478
+ NETDATA_APPS_FILE_GROUP,
479
+ NETDATA_EBPF_CHART_TYPE_STACKED,
480
+ NULL,
481
+ 20062,
482
+ em->update_every);
483
+ }
484
+
485
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
486
+ NETDATA_SYSCALL_APPS_FILE_CLOSED,
487
+ "Files closed",
488
+ EBPF_COMMON_DIMENSION_CALL,
489
+ NETDATA_APPS_FILE_GROUP,
490
+ NETDATA_EBPF_CHART_TYPE_STACKED,
491
+ NULL,
492
+ 20063,
493
+ em->update_every);
494
+
495
+ if (em->mode < MODE_ENTRY) {
496
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
497
+ NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR,
498
+ "Fails to close files",
499
+ EBPF_COMMON_DIMENSION_CALL,
500
+ NETDATA_APPS_FILE_GROUP,
501
+ NETDATA_EBPF_CHART_TYPE_STACKED,
502
+ NULL,
503
+ 20064,
504
+ em->update_every);
505
+ }
506
+}
507
+
508
+/**
509
+ * Obsolete global
510
+ *
511
+ * Obsolete global charts created by thread.
512
+ *
513
+ * @param em a pointer to `struct ebpf_module`
514
+ */
515
+static void ebpf_obsolete_fd_global(ebpf_module_t *em)
516
+{
517
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
518
+ NETDATA_FILE_OPEN_CLOSE_COUNT,
519
+ "Open and close calls",
520
+ EBPF_COMMON_DIMENSION_CALL,
521
+ NETDATA_FILE_GROUP,
522
+ NETDATA_EBPF_CHART_TYPE_LINE,
523
+ NULL,
524
+ NETDATA_CHART_PRIO_EBPF_FD_CHARTS,
525
+ em->update_every);
526
+
527
+ if (em->mode < MODE_ENTRY) {
528
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
529
+ NETDATA_FILE_OPEN_ERR_COUNT,
530
+ "Open fails",
531
+ EBPF_COMMON_DIMENSION_CALL,
532
+ NETDATA_FILE_GROUP,
533
+ NETDATA_EBPF_CHART_TYPE_LINE,
534
+ NULL,
535
+ NETDATA_CHART_PRIO_EBPF_FD_CHARTS + 1,
536
+ em->update_every);
537
+ }
538
+}
539
+
540
/**
541
* FD Exit
542
*
@@ -380,15 +548,46 @@ static void ebpf_fd_exit(void *ptr)
548
{
549
ebpf_module_t *em = (ebpf_module_t *)ptr;
550
551
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
552
+ pthread_mutex_lock(&lock);
553
+ if (em->cgroup_charts) {
554
+ ebpf_obsolete_fd_cgroup_charts(em);
555
+ fflush(stdout);
556
+ }
557
+
558
+ if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
559
+ ebpf_obsolete_fd_apps_charts(em);
560
+ }
561
+
562
+ ebpf_obsolete_fd_global(em);
563
+
564
+#ifdef NETDATA_DEV_MODE
565
+ if (ebpf_aral_fd_pid)
566
+ ebpf_statistic_obsolete_aral_chart(em, fd_disable_priority);
567
+#endif
568
+
569
+
570
+ fflush(stdout);
571
+ pthread_mutex_unlock(&lock);
572
+ }
573
+
574
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
575
+
576
#ifdef LIBBPF_MAJOR_VERSION
384
- if (fd_bpf_obj)
577
+ if (fd_bpf_obj) {
578
fd_bpf__destroy(fd_bpf_obj);
579
+ fd_bpf_obj = NULL;
580
+ }
581
#endif
387
- if (em->objects)
582
+ if (em->objects) {
583
ebpf_unload_legacy_code(em->objects, em->probe_links);
584
+ em->objects = NULL;
585
+ em->probe_links = NULL;
586
+ }
587
588
pthread_mutex_lock(&ebpf_exit_cleanup);
589
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
590
+ ebpf_update_stats(&plugin_statistics, em);
591
pthread_mutex_unlock(&ebpf_exit_cleanup);
592
}
593
@@ -935,7 +1134,9 @@ static void fd_collector(ebpf_module_t *em)
1134
int update_every = em->update_every;
1135
int counter = update_every - 1;
1136
int maps_per_core = em->maps_per_core;
938
- while (!ebpf_exit_plugin) {
1137
+ uint32_t running_time = 0;
1138
+ uint32_t lifetime = em->lifetime;
1139
+ while (!ebpf_exit_plugin && running_time < lifetime) {
1140
(void)heartbeat_next(&hb, USEC_PER_SEC);
1141
1142
if (ebpf_exit_plugin || ++counter != update_every)
@@ -968,6 +1169,15 @@ static void fd_collector(ebpf_module_t *em)
1169
1170
pthread_mutex_unlock(&lock);
1171
pthread_mutex_unlock(&collect_data_mutex);
1172
+
1173
+ pthread_mutex_lock(&ebpf_exit_cleanup);
1174
+ if (running_time && !em->running_time)
1175
+ running_time = update_every;
1176
+ else
1177
+ running_time += update_every;
1178
+
1179
+ em->running_time = running_time;
1180
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
1181
}
1182
}
1183
@@ -1066,6 +1276,8 @@ static void ebpf_create_fd_global_charts(ebpf_module_t *em)
1276
NETDATA_FD_SYSCALL_END,
1277
em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
1278
}
1279
+
1280
+ fflush(stdout);
1281
}
1282
1283
/*****************************************************************
@@ -1165,10 +1377,10 @@ void *ebpf_fd_thread(void *ptr)
1377
pthread_mutex_lock(&lock);
1378
ebpf_create_fd_global_charts(em);
1379
ebpf_update_stats(&plugin_statistics, em);
1168
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
1380
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
1381
#ifdef NETDATA_DEV_MODE
1382
if (ebpf_aral_fd_pid)
1171
- ebpf_statistic_create_aral_chart(NETDATA_EBPF_FD_ARAL_NAME, em);
1383
+ fd_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_FD_ARAL_NAME, em);
1384
#endif
1385
1386
pthread_mutex_unlock(&lock);
collectors/ebpf.plugin/ebpf_fd.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_FD_H
4
#define NETDATA_EBPF_FD_H 1
5
6
-// Module name
6
+// Module name & File description
7
#define NETDATA_EBPF_MODULE_NAME_FD "filedescriptor"
8
+#define NETDATA_EBPF_FD_MODULE_DESC "Monitor when files are open and closed. This thread is integrated with apps and cgroup."
9
10
// Menu group
11
#define NETDATA_FILE_GROUP "file_access"
collectors/ebpf.plugin/ebpf_filesystem.c
+129
-30
@@ -395,13 +395,15 @@ static void ebpf_create_fs_charts(int update_every)
395
snprintfz(chart_name, 63, "%s_read_latency", efp->filesystem);
396
efp->hread.name = strdupz(chart_name);
397
efp->hread.title = strdupz(title);
398
+ efp->hread.ctx = NULL;
399
efp->hread.order = order;
400
efp->family_name = strdupz(family);
401
402
ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hread.name,
402
- title,
403
- EBPF_COMMON_DIMENSION_CALL, family,
404
- "filesystem.read_latency", NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
403
+ efp->hread.title,
404
+ EBPF_COMMON_DIMENSION_CALL, efp->family_name,
405
+ "filesystem.read_latency", NETDATA_EBPF_CHART_TYPE_STACKED, order,
406
+ ebpf_create_global_dimension,
407
filesystem_publish_aggregated, NETDATA_EBPF_HIST_MAX_BINS,
408
update_every, NETDATA_EBPF_MODULE_NAME_FILESYSTEM);
409
order++;
@@ -410,11 +412,13 @@ static void ebpf_create_fs_charts(int update_every)
412
snprintfz(chart_name, 63, "%s_write_latency", efp->filesystem);
413
efp->hwrite.name = strdupz(chart_name);
414
efp->hwrite.title = strdupz(title);
415
+ efp->hwrite.ctx = NULL;
416
efp->hwrite.order = order;
417
ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hwrite.name,
415
- title,
416
- EBPF_COMMON_DIMENSION_CALL, family,
417
- "filesystem.write_latency", NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
418
+ efp->hwrite.title,
419
+ EBPF_COMMON_DIMENSION_CALL, efp->family_name,
420
+ "filesystem.write_latency", NETDATA_EBPF_CHART_TYPE_STACKED, order,
421
+ ebpf_create_global_dimension,
422
filesystem_publish_aggregated, NETDATA_EBPF_HIST_MAX_BINS,
423
update_every, NETDATA_EBPF_MODULE_NAME_FILESYSTEM);
424
order++;
@@ -423,11 +427,13 @@ static void ebpf_create_fs_charts(int update_every)
427
snprintfz(chart_name, 63, "%s_open_latency", efp->filesystem);
428
efp->hopen.name = strdupz(chart_name);
429
efp->hopen.title = strdupz(title);
430
+ efp->hopen.ctx = NULL;
431
efp->hopen.order = order;
432
ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hopen.name,
428
- title,
429
- EBPF_COMMON_DIMENSION_CALL, family,
430
- "filesystem.open_latency", NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
433
+ efp->hopen.title,
434
+ EBPF_COMMON_DIMENSION_CALL, efp->family_name,
435
+ "filesystem.open_latency", NETDATA_EBPF_CHART_TYPE_STACKED, order,
436
+ ebpf_create_global_dimension,
437
filesystem_publish_aggregated, NETDATA_EBPF_HIST_MAX_BINS,
438
update_every, NETDATA_EBPF_MODULE_NAME_FILESYSTEM);
439
order++;
@@ -438,9 +444,10 @@ static void ebpf_create_fs_charts(int update_every)
444
snprintfz(ctx, 63, "filesystem.%s_latency", type);
445
efp->hadditional.name = strdupz(chart_name);
446
efp->hadditional.title = strdupz(title);
447
+ efp->hadditional.ctx = strdupz(ctx);
448
efp->hadditional.order = order;
442
- ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hadditional.name, title,
443
- EBPF_COMMON_DIMENSION_CALL, family,
449
+ ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hadditional.name, efp->hadditional.title,
450
+ EBPF_COMMON_DIMENSION_CALL, efp->family_name,
451
ctx, NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
452
filesystem_publish_aggregated, NETDATA_EBPF_HIST_MAX_BINS,
453
update_every, NETDATA_EBPF_MODULE_NAME_FILESYSTEM);
@@ -448,6 +455,8 @@ static void ebpf_create_fs_charts(int update_every)
455
efp->flags |= NETDATA_FILESYSTEM_FLAG_CHART_CREATED;
456
}
457
}
458
+
459
+ fflush(stdout);
460
}
461
462
/**
@@ -459,6 +468,7 @@ static void ebpf_create_fs_charts(int update_every)
468
*/
469
int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em)
470
{
471
+ pthread_mutex_lock(&lock);
472
int i;
473
const char *saved_name = em->thread_name;
474
uint64_t kernels = em->kernels;
@@ -476,6 +486,8 @@ int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em)
486
if (!efp->probe_links) {
487
em->thread_name = saved_name;
488
em->kernels = kernels;
489
+ em->maps = NULL;
490
+ pthread_mutex_unlock(&lock);
491
return -1;
492
}
493
}
@@ -494,9 +506,7 @@ int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em)
506
}
507
#endif
508
efp->flags |= NETDATA_FILESYSTEM_FLAG_HAS_PARTITION;
497
- pthread_mutex_lock(&lock);
509
ebpf_update_kernel_memory(&plugin_statistics, efp->fs_maps, EBPF_ACTION_STAT_ADD);
499
- pthread_mutex_unlock(&lock);
510
511
// Nedeed for filesystems like btrfs
512
if ((efp->flags & NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE) && (efp->addresses.function)) {
@@ -506,6 +516,7 @@ int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em)
516
efp->flags &= ~NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM;
517
}
518
em->thread_name = saved_name;
519
+ pthread_mutex_unlock(&lock);
520
em->kernels = kernels;
521
em->maps = NULL;
522
@@ -616,43 +627,88 @@ void ebpf_filesystem_cleanup_ebpf_data()
627
ebpf_filesystem_partitions_t *efp = &localfs[i];
628
if (efp->probe_links) {
629
freez(efp->family_name);
630
+ efp->family_name = NULL;
631
632
freez(efp->hread.name);
633
+ efp->hread.name = NULL;
634
freez(efp->hread.title);
635
+ efp->hread.title = NULL;
636
637
freez(efp->hwrite.name);
638
+ efp->hwrite.name = NULL;
639
freez(efp->hwrite.title);
640
+ efp->hwrite.title = NULL;
641
642
freez(efp->hopen.name);
643
+ efp->hopen.name = NULL;
644
freez(efp->hopen.title);
645
+ efp->hopen.title = NULL;
646
647
freez(efp->hadditional.name);
648
+ efp->hadditional.name = NULL;
649
freez(efp->hadditional.title);
650
+ efp->hadditional.title = NULL;
651
+ freez(efp->hadditional.ctx);
652
+ efp->hadditional.ctx = NULL;
653
}
654
}
655
}
656
657
/**
636
- * Filesystem Free
658
+ * Obsolete global
659
*
638
- * Cleanup variables after child threads to stop
660
+ * Obsolete global charts created by thread.
661
*
640
- * @param ptr thread data.
662
+ * @param em a pointer to `struct ebpf_module`
663
*/
642
-static void ebpf_filesystem_free(ebpf_module_t *em)
664
+static void ebpf_obsolete_filesystem_global(ebpf_module_t *em)
665
{
644
- pthread_mutex_lock(&ebpf_exit_cleanup);
645
- em->enabled = NETDATA_THREAD_EBPF_STOPPING;
646
- pthread_mutex_unlock(&ebpf_exit_cleanup);
647
-
648
- ebpf_filesystem_cleanup_ebpf_data();
649
- if (dimensions)
650
- ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
651
- freez(filesystem_hash_values);
666
+ int i;
667
+ for (i = 0; localfs[i].filesystem; i++) {
668
+ ebpf_filesystem_partitions_t *efp = &localfs[i];
669
+ if (!efp->objects)
670
+ continue;
671
653
- pthread_mutex_lock(&ebpf_exit_cleanup);
654
- em->enabled = NETDATA_THREAD_EBPF_STOPPED;
655
- pthread_mutex_unlock(&ebpf_exit_cleanup);
672
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
673
+ efp->hread.name,
674
+ efp->hread.title,
675
+ EBPF_COMMON_DIMENSION_CALL,
676
+ efp->family_name,
677
+ NETDATA_EBPF_CHART_TYPE_STACKED,
678
+ "filesystem.read_latency",
679
+ efp->hread.order,
680
+ em->update_every);
681
+
682
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
683
+ efp->hwrite.name,
684
+ efp->hwrite.title,
685
+ EBPF_COMMON_DIMENSION_CALL,
686
+ efp->family_name,
687
+ NETDATA_EBPF_CHART_TYPE_STACKED,
688
+ "filesystem.write_latency",
689
+ efp->hwrite.order,
690
+ em->update_every);
691
+
692
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
693
+ efp->hopen.name,
694
+ efp->hopen.title,
695
+ EBPF_COMMON_DIMENSION_CALL,
696
+ efp->family_name,
697
+ NETDATA_EBPF_CHART_TYPE_STACKED,
698
+ "filesystem.open_latency",
699
+ efp->hopen.order,
700
+ em->update_every);
701
+
702
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
703
+ efp->hadditional.name,
704
+ efp->hadditional.title,
705
+ EBPF_COMMON_DIMENSION_CALL,
706
+ efp->family_name,
707
+ NETDATA_EBPF_CHART_TYPE_STACKED,
708
+ efp->hadditional.ctx,
709
+ efp->hadditional.order,
710
+ em->update_every);
711
+ }
712
}
713
714
/**
@@ -665,7 +721,39 @@ static void ebpf_filesystem_free(ebpf_module_t *em)
721
static void ebpf_filesystem_exit(void *ptr)
722
{
723
ebpf_module_t *em = (ebpf_module_t *)ptr;
668
- ebpf_filesystem_free(em);
724
+
725
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
726
+ pthread_mutex_lock(&lock);
727
+ ebpf_obsolete_filesystem_global(em);
728
+
729
+ pthread_mutex_unlock(&lock);
730
+ fflush(stdout);
731
+ }
732
+
733
+ ebpf_filesystem_cleanup_ebpf_data();
734
+ if (dimensions) {
735
+ ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
736
+ dimensions = NULL;
737
+ }
738
+
739
+ freez(filesystem_hash_values);
740
+
741
+ int i;
742
+ for (i = 0; localfs[i].filesystem; i++) {
743
+ ebpf_filesystem_partitions_t *efp = &localfs[i];
744
+ if (!efp->probe_links)
745
+ continue;
746
+
747
+ ebpf_unload_legacy_code(efp->objects, efp->probe_links);
748
+ efp->objects = NULL;
749
+ efp->probe_links = NULL;
750
+ efp->flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION;
751
+ }
752
+
753
+ pthread_mutex_lock(&ebpf_exit_cleanup);
754
+ em->enabled = NETDATA_THREAD_EBPF_STOPPED;
755
+ ebpf_update_stats(&plugin_statistics, em);
756
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
757
}
758
759
/*****************************************************************
@@ -819,7 +907,9 @@ static void filesystem_collector(ebpf_module_t *em)
907
heartbeat_t hb;
908
heartbeat_init(&hb);
909
int counter = update_every - 1;
822
- while (!ebpf_exit_plugin) {
910
+ uint32_t running_time = 0;
911
+ uint32_t lifetime = em->lifetime;
912
+ while (!ebpf_exit_plugin && running_time < lifetime) {
913
(void)heartbeat_next(&hb, USEC_PER_SEC);
914
915
if (ebpf_exit_plugin || ++counter != update_every)
@@ -833,6 +923,15 @@ static void filesystem_collector(ebpf_module_t *em)
923
ebpf_histogram_send_data();
924
925
pthread_mutex_unlock(&lock);
926
+
927
+ pthread_mutex_lock(&ebpf_exit_cleanup);
928
+ if (running_time && !em->running_time)
929
+ running_time = update_every;
930
+ else
931
+ running_time += update_every;
932
+
933
+ em->running_time = running_time;
934
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
935
}
936
}
937
collectors/ebpf.plugin/ebpf_filesystem.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_FILESYSTEM_H
4
#define NETDATA_EBPF_FILESYSTEM_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_FILESYSTEM "filesystem"
8
+#define NETDATA_EBPF_FS_MODULE_DESC "Monitor filesystem latency for: btrfs, ext4, nfs, xfs and zfs."
9
10
#include "ebpf.h"
11
#ifdef LIBBPF_MAJOR_VERSION
collectors/ebpf.plugin/ebpf_functions.c
new
+419
@@ -0,0 +1,419 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "ebpf.h"
4
+#include "ebpf_functions.h"
5
+
6
+/*****************************************************************
7
+ * EBPF SELECT MODULE
8
+ *****************************************************************/
9
+
10
+/**
11
+ * Select Module
12
+ *
13
+ * @param thread_name name of the thread we are looking for.
14
+ *
15
+ * @return it returns a pointer for the module that has thread_name on success or NULL otherwise.
16
+ */
17
+ebpf_module_t *ebpf_functions_select_module(const char *thread_name) {
18
+ int i;
19
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
20
+ if (strcmp(ebpf_modules[i].thread_name, thread_name) == 0) {
21
+ return &ebpf_modules[i];
22
+ }
23
+ }
24
+
25
+ return NULL;
26
+}
27
+
28
+/*****************************************************************
29
+ * EBPF HELP FUNCTIONS
30
+ *****************************************************************/
31
+
32
+/**
33
+ * Thread Help
34
+ *
35
+ * Shows help with all options accepted by thread function.
36
+ *
37
+ * @param transaction the transaction id that Netdata sent for this function execution
38
+*/
39
+static void ebpf_function_thread_manipulation_help(const char *transaction) {
40
+ pthread_mutex_lock(&lock);
41
+ pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "text/plain", now_realtime_sec() + 3600);
42
+ fprintf(stdout, "%s",
43
+ "ebpf.plugin / thread\n"
44
+ "\n"
45
+ "Function `thread` allows user to control eBPF threads.\n"
46
+ "\n"
47
+ "The following filters are supported:\n"
48
+ "\n"
49
+ " thread:NAME\n"
50
+ " Shows information for the thread NAME. Names are listed inside `ebpf.d.conf`.\n"
51
+ "\n"
52
+ " enable:NAME:PERIOD\n"
53
+ " Enable a specific thread named `NAME` to run a specific PERIOD in seconds. When PERIOD is not\n"
54
+ " specified plugin will use the default 300 seconds\n"
55
+ "\n"
56
+ " disable:NAME\n"
57
+ " Disable a sp.\n"
58
+ "\n"
59
+ "Filters can be combined. Each filter can be given only one time.\n"
60
+ "Process thread is not controlled by functions until we finish the creation of functions per thread..\n"
61
+ );
62
+ pluginsd_function_result_end_to_stdout();
63
+ fflush(stdout);
64
+ pthread_mutex_unlock(&lock);
65
+}
66
+
67
+
68
+/*****************************************************************
69
+ * EBPF ERROR FUNCTIONS
70
+ *****************************************************************/
71
+
72
+/**
73
+ * Function error
74
+ *
75
+ * Show error when a wrong function is given
76
+ *
77
+ * @param transaction the transaction id that Netdata sent for this function execution
78
+ * @param code the error code to show with the message.
79
+ * @param msg the error message
80
+ */
81
+static void ebpf_function_error(const char *transaction, int code, const char *msg) {
82
+ char buffer[PLUGINSD_LINE_MAX + 1];
83
+ json_escape_string(buffer, msg, PLUGINSD_LINE_MAX);
84
+
85
+ pluginsd_function_result_begin_to_stdout(transaction, code, "application/json", now_realtime_sec());
86
+ fprintf(stdout, "{\"status\":%d,\"error_message\":\"%s\"}", code, buffer);
87
+ pluginsd_function_result_end_to_stdout();
88
+}
89
+
90
+/*****************************************************************
91
+ * EBPF THREAD FUNCTION
92
+ *****************************************************************/
93
+
94
+/**
95
+ * Function enable
96
+ *
97
+ * Enable a specific thread.
98
+ *
99
+ * @param transaction the transaction id that Netdata sent for this function execution
100
+ * @param function function name and arguments given to thread.
101
+ * @param line_buffer buffer used to parse args
102
+ * @param line_max Number of arguments given
103
+ * @param timeout The function timeout
104
+ * @param em The structure with thread information
105
+ */
106
+static void ebpf_function_thread_manipulation(const char *transaction,
107
+ char *function __maybe_unused,
108
+ char *line_buffer __maybe_unused,
109
+ int line_max __maybe_unused,
110
+ int timeout __maybe_unused,
111
+ ebpf_module_t *em)
112
+{
113
+ char *words[PLUGINSD_MAX_WORDS] = { NULL };
114
+ char message[512];
115
+ uint32_t show_specific_thread = 0;
116
+ size_t num_words = quoted_strings_splitter_pluginsd(function, words, PLUGINSD_MAX_WORDS);
117
+ for(int i = 1; i < PLUGINSD_MAX_WORDS ;i++) {
118
+ const char *keyword = get_word(words, num_words, i);
119
+ if (!keyword)
120
+ break;
121
+
122
+ ebpf_module_t *lem;
123
+ if(strncmp(keyword, EBPF_THREADS_ENABLE_CATEGORY, sizeof(EBPF_THREADS_ENABLE_CATEGORY) -1) == 0) {
124
+ char thread_name[128];
125
+ int period = -1;
126
+ const char *name = &keyword[sizeof(EBPF_THREADS_ENABLE_CATEGORY) - 1];
127
+ char *separator = strchr(name, ':');
128
+ if (separator) {
129
+ strncpyz(thread_name, name, separator - name);
130
+ period = str2i(++separator);
131
+ } else {
132
+ strncpyz(thread_name, name, strlen(name));
133
+ }
134
+
135
+ lem = ebpf_functions_select_module(thread_name);
136
+ if (!lem) {
137
+ snprintfz(message, 511, "%s%s", EBPF_PLUGIN_THREAD_FUNCTION_ERROR_THREAD_NOT_FOUND, name);
138
+ ebpf_function_error(transaction, HTTP_RESP_NOT_FOUND, message);
139
+ return;
140
+ }
141
+
142
+ pthread_mutex_lock(&ebpf_exit_cleanup);
143
+ if (lem->enabled > NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
144
+ struct netdata_static_thread *st = lem->thread;
145
+ // Load configuration again
146
+ ebpf_update_module(lem, default_btf, running_on_kernel, isrh);
147
+
148
+ // another request for thread that already ran, cleanup and restart
149
+ if (st->thread)
150
+ freez(st->thread);
151
+
152
+ if (period <= 0)
153
+ period = EBPF_DEFAULT_LIFETIME;
154
+
155
+ st->thread = mallocz(sizeof(netdata_thread_t));
156
+ lem->enabled = NETDATA_THREAD_EBPF_FUNCTION_RUNNING;
157
+ lem->lifetime = period;
158
+
159
+#ifdef NETDATA_INTERNAL_CHECKS
160
+ netdata_log_info("Starting thread %s with lifetime = %d", thread_name, period);
161
+#endif
162
+
163
+ netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT,
164
+ st->start_routine, lem);
165
+ } else {
166
+ lem->running_time = 0;
167
+ if (period > 0) // user is modifying period to run
168
+ lem->lifetime = period;
169
+#ifdef NETDATA_INTERNAL_CHECKS
170
+ netdata_log_info("Thread %s had lifetime updated for %d", thread_name, period);
171
+#endif
172
+ }
173
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
174
+ } else if(strncmp(keyword, EBPF_THREADS_DISABLE_CATEGORY, sizeof(EBPF_THREADS_DISABLE_CATEGORY) -1) == 0) {
175
+ const char *name = &keyword[sizeof(EBPF_THREADS_DISABLE_CATEGORY) - 1];
176
+ lem = ebpf_functions_select_module(name);
177
+ if (!lem) {
178
+ snprintfz(message, 511, "%s%s", EBPF_PLUGIN_THREAD_FUNCTION_ERROR_THREAD_NOT_FOUND, name);
179
+ ebpf_function_error(transaction, HTTP_RESP_NOT_FOUND, message);
180
+ return;
181
+ }
182
+
183
+ pthread_mutex_lock(&ebpf_exit_cleanup);
184
+ if (lem->enabled < NETDATA_THREAD_EBPF_STOPPING && lem->thread->thread) {
185
+ lem->lifetime = 0;
186
+ lem->running_time = lem->update_every;
187
+ netdata_thread_cancel(*lem->thread->thread);
188
+ }
189
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
190
+ } else if(strncmp(keyword, EBPF_THREADS_SELECT_THREAD, sizeof(EBPF_THREADS_SELECT_THREAD) -1) == 0) {
191
+ const char *name = &keyword[sizeof(EBPF_THREADS_SELECT_THREAD) - 1];
192
+ lem = ebpf_functions_select_module(name);
193
+ if (!lem) {
194
+ snprintfz(message, 511, "%s%s", EBPF_PLUGIN_THREAD_FUNCTION_ERROR_THREAD_NOT_FOUND, name);
195
+ ebpf_function_error(transaction, HTTP_RESP_NOT_FOUND, message);
196
+ return;
197
+ }
198
+
199
+ show_specific_thread |= 1<<lem->thread_id;
200
+ } else if(strncmp(keyword, "help", 4) == 0) {
201
+ ebpf_function_thread_manipulation_help(transaction);
202
+ return;
203
+ }
204
+ }
205
+
206
+ time_t expires = now_realtime_sec() + em->update_every;
207
+
208
+ BUFFER *wb = buffer_create(PLUGINSD_LINE_MAX, NULL);
209
+ buffer_json_initialize(wb, "\"", "\"", 0, true, false);
210
+ buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
211
+ buffer_json_member_add_string(wb, "type", "table");
212
+ buffer_json_member_add_time_t(wb, "update_every", em->update_every);
213
+ buffer_json_member_add_string(wb, "help", EBPF_PLUGIN_THREAD_FUNCTION_DESCRIPTION);
214
+
215
+ // Collect data
216
+ buffer_json_member_add_array(wb, "data");
217
+ int i;
218
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
219
+ if (show_specific_thread && !(show_specific_thread & 1<<i))
220
+ continue;
221
+
222
+ ebpf_module_t *wem = &ebpf_modules[i];
223
+ buffer_json_add_array_item_array(wb);
224
+
225
+ // IMPORTANT!
226
+ // THE ORDER SHOULD BE THE SAME WITH THE FIELDS!
227
+
228
+ // thread name
229
+ buffer_json_add_array_item_string(wb, wem->thread_name);
230
+
231
+ // description
232
+ buffer_json_add_array_item_string(wb, wem->thread_description);
233
+ // Either it is not running or received a disabled signal and it is stopping.
234
+ if (wem->enabled > NETDATA_THREAD_EBPF_FUNCTION_RUNNING ||
235
+ (!wem->lifetime && (int)wem->running_time == wem->update_every)) {
236
+ // status
237
+ buffer_json_add_array_item_string(wb, EBPF_THREAD_STATUS_STOPPED);
238
+
239
+ // Time remaining
240
+ buffer_json_add_array_item_uint64(wb, 0);
241
+
242
+ // action
243
+ buffer_json_add_array_item_string(wb, "NULL");
244
+ } else {
245
+ // status
246
+ buffer_json_add_array_item_string(wb, EBPF_THREAD_STATUS_RUNNING);
247
+
248
+ // Time remaining
249
+ buffer_json_add_array_item_uint64(wb, (wem->lifetime) ? (wem->lifetime - wem->running_time) : 0);
250
+
251
+ // action
252
+ buffer_json_add_array_item_string(wb, "Enabled/Disabled");
253
+ }
254
+
255
+ buffer_json_array_close(wb);
256
+ }
257
+
258
+ buffer_json_array_close(wb); // data
259
+
260
+ buffer_json_member_add_object(wb, "columns");
261
+ {
262
+ int fields_id = 0;
263
+
264
+ // IMPORTANT!
265
+ // THE ORDER SHOULD BE THE SAME WITH THE VALUES!
266
+ buffer_rrdf_table_add_field(wb, fields_id++, "Thread", "Thread Name", RRDF_FIELD_TYPE_STRING,
267
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
268
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
269
+ RRDF_FIELD_FILTER_MULTISELECT,
270
+ RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
271
+
272
+ buffer_rrdf_table_add_field(wb, fields_id++, "Description", "Thread Desc", RRDF_FIELD_TYPE_STRING,
273
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
274
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
275
+ RRDF_FIELD_FILTER_MULTISELECT,
276
+ RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
277
+
278
+ buffer_rrdf_table_add_field(wb, fields_id++, "Status", "Thread Status", RRDF_FIELD_TYPE_STRING,
279
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
280
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
281
+ RRDF_FIELD_FILTER_MULTISELECT,
282
+ RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
283
+
284
+ buffer_rrdf_table_add_field(wb, fields_id++, "Time", "Time Remaining", RRDF_FIELD_TYPE_INTEGER,
285
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL,
286
+ NAN, RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
287
+ RRDF_FIELD_FILTER_MULTISELECT,
288
+ RRDF_FIELD_OPTS_NONE, NULL);
289
+
290
+ buffer_rrdf_table_add_field(wb, fields_id++, "Action", "Thread Action", RRDF_FIELD_TYPE_STRING,
291
+ RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
292
+ RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
293
+ RRDF_FIELD_FILTER_MULTISELECT,
294
+ RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
295
+ }
296
+ buffer_json_object_close(wb); // columns
297
+
298
+ buffer_json_member_add_string(wb, "default_sort_column", "Thread");
299
+
300
+ buffer_json_member_add_object(wb, "charts");
301
+ {
302
+ // Threads
303
+ buffer_json_member_add_object(wb, "eBPFThreads");
304
+ {
305
+ buffer_json_member_add_string(wb, "name", "Threads");
306
+ buffer_json_member_add_string(wb, "type", "line");
307
+ buffer_json_member_add_array(wb, "columns");
308
+ {
309
+ buffer_json_add_array_item_string(wb, "Threads");
310
+ }
311
+ buffer_json_array_close(wb);
312
+ }
313
+ buffer_json_object_close(wb);
314
+
315
+ // Life Time
316
+ buffer_json_member_add_object(wb, "eBPFLifeTime");
317
+ {
318
+ buffer_json_member_add_string(wb, "name", "LifeTime");
319
+ buffer_json_member_add_string(wb, "type", "line");
320
+ buffer_json_member_add_array(wb, "columns");
321
+ {
322
+ buffer_json_add_array_item_string(wb, "Threads");
323
+ buffer_json_add_array_item_string(wb, "Time");
324
+ }
325
+ buffer_json_array_close(wb);
326
+ }
327
+ buffer_json_object_close(wb);
328
+ }
329
+ buffer_json_object_close(wb); // charts
330
+
331
+ // Do we use only on fields that can be groupped?
332
+ buffer_json_member_add_object(wb, "group_by");
333
+ {
334
+ // group by Status
335
+ buffer_json_member_add_object(wb, "Status");
336
+ {
337
+ buffer_json_member_add_string(wb, "name", "Thread status");
338
+ buffer_json_member_add_array(wb, "columns");
339
+ {
340
+ buffer_json_add_array_item_string(wb, "Status");
341
+ }
342
+ buffer_json_array_close(wb);
343
+ }
344
+ buffer_json_object_close(wb);
345
+ }
346
+ buffer_json_object_close(wb); // group_by
347
+
348
+ buffer_json_member_add_time_t(wb, "expires", expires);
349
+ buffer_json_finalize(wb);
350
+
351
+ // Lock necessary to avoid race condition
352
+ pthread_mutex_lock(&lock);
353
+ pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "application/json", expires);
354
+
355
+ fwrite(buffer_tostring(wb), buffer_strlen(wb), 1, stdout);
356
+
357
+ pluginsd_function_result_end_to_stdout();
358
+ fflush(stdout);
359
+ pthread_mutex_unlock(&lock);
360
+
361
+ buffer_free(wb);
362
+}
363
+
364
+
365
+/*****************************************************************
366
+ * EBPF FUNCTION THREAD
367
+ *****************************************************************/
368
+
369
+/**
370
+ * FUNCTION thread.
371
+ *
372
+ * @param ptr a `ebpf_module_t *`.
373
+ *
374
+ * @return always NULL.
375
+ */
376
+void *ebpf_function_thread(void *ptr)
377
+{
378
+ ebpf_module_t *em = (ebpf_module_t *)ptr;
379
+ char buffer[PLUGINSD_LINE_MAX + 1];
380
+
381
+ char *s = NULL;
382
+ while(!ebpf_exit_plugin && (s = fgets(buffer, PLUGINSD_LINE_MAX, stdin))) {
383
+ char *words[PLUGINSD_MAX_WORDS] = { NULL };
384
+ size_t num_words = quoted_strings_splitter_pluginsd(buffer, words, PLUGINSD_MAX_WORDS);
385
+
386
+ const char *keyword = get_word(words, num_words, 0);
387
+
388
+ if(keyword && strcmp(keyword, PLUGINSD_KEYWORD_FUNCTION) == 0) {
389
+ char *transaction = get_word(words, num_words, 1);
390
+ char *timeout_s = get_word(words, num_words, 2);
391
+ char *function = get_word(words, num_words, 3);
392
+
393
+ if(!transaction || !*transaction || !timeout_s || !*timeout_s || !function || !*function) {
394
+ netdata_log_error("Received incomplete %s (transaction = '%s', timeout = '%s', function = '%s'). Ignoring it.",
395
+ keyword,
396
+ transaction?transaction:"(unset)",
397
+ timeout_s?timeout_s:"(unset)",
398
+ function?function:"(unset)");
399
+ }
400
+ else {
401
+ int timeout = str2i(timeout_s);
402
+ if (!strncmp(function, EBPF_FUNCTION_THREAD, sizeof(EBPF_FUNCTION_THREAD) - 1))
403
+ ebpf_function_thread_manipulation(transaction,
404
+ function,
405
+ buffer,
406
+ PLUGINSD_LINE_MAX + 1,
407
+ timeout,
408
+ em);
409
+ else
410
+ ebpf_function_error(transaction,
411
+ HTTP_RESP_NOT_FOUND,
412
+ "No function with this name found in ebpf.plugin.");
413
+ }
414
+ }
415
+ else
416
+ netdata_log_error("Received unknown command: %s", keyword ? keyword : "(unset)");
417
+ }
418
+ return NULL;
419
+}
collectors/ebpf.plugin/ebpf_functions.h
new
+29
@@ -0,0 +1,29 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_EBPF_FUNCTIONS_H
4
+#define NETDATA_EBPF_FUNCTIONS_H 1
5
+
6
+// configuration file & description
7
+#define NETDATA_DIRECTORY_FUNCTIONS_CONFIG_FILE "functions.conf"
8
+#define NETDATA_EBPF_FUNCTIONS_MODULE_DESC "Show information about current function status."
9
+
10
+// function list
11
+#define EBPF_FUNCTION_THREAD "ebpf_thread"
12
+
13
+#define EBPF_PLUGIN_THREAD_FUNCTION_DESCRIPTION "Detailed information about eBPF threads."
14
+#define EBPF_PLUGIN_THREAD_FUNCTION_ERROR_THREAD_NOT_FOUND "ebpf.plugin does not have thread named "
15
+
16
+#define EBPF_PLUGIN_FUNCTIONS(NAME, DESC) do { \
17
+ fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " \"" NAME "\" 10 \"%s\"\n", DESC); \
18
+} while(0)
19
+
20
+#define EBPF_THREADS_SELECT_THREAD "thread:"
21
+#define EBPF_THREADS_ENABLE_CATEGORY "enable:"
22
+#define EBPF_THREADS_DISABLE_CATEGORY "disable:"
23
+
24
+#define EBPF_THREAD_STATUS_RUNNING "running"
25
+#define EBPF_THREAD_STATUS_STOPPED "stopped"
26
+
27
+void *ebpf_function_thread(void *ptr);
28
+
29
+#endif
collectors/ebpf.plugin/ebpf_hardirq.c
+50
-3
@@ -215,6 +215,27 @@ void ebpf_hardirq_release(hardirq_val_t *stat)
215
*
216
*****************************************************************/
217
218
+/**
219
+ * Obsolete global
220
+ *
221
+ * Obsolete global charts created by thread.
222
+ *
223
+ * @param em a pointer to `struct ebpf_module`
224
+ */
225
+static void ebpf_obsolete_hardirq_global(ebpf_module_t *em)
226
+{
227
+ ebpf_write_chart_obsolete(NETDATA_EBPF_SYSTEM_GROUP,
228
+ "hardirq_latency",
229
+ "Hardware IRQ latency",
230
+ EBPF_COMMON_DIMENSION_MILLISECONDS,
231
+ "interrupts",
232
+ NETDATA_EBPF_CHART_TYPE_STACKED,
233
+ NULL,
234
+ NETDATA_CHART_PRIO_HARDIRQ_LATENCY,
235
+ em->update_every
236
+ );
237
+}
238
+
239
/**
240
* Hardirq Exit
241
*
@@ -226,8 +247,22 @@ static void hardirq_exit(void *ptr)
247
{
248
ebpf_module_t *em = (ebpf_module_t *)ptr;
249
229
- if (em->objects)
250
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
251
+ pthread_mutex_lock(&lock);
252
+
253
+ ebpf_obsolete_hardirq_global(em);
254
+
255
+ pthread_mutex_unlock(&lock);
256
+ fflush(stdout);
257
+ }
258
+
259
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
260
+
261
+ if (em->objects) {
262
ebpf_unload_legacy_code(em->objects, em->probe_links);
263
+ em->objects = NULL;
264
+ em->probe_links = NULL;
265
+ }
266
267
for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) {
268
ebpf_disable_tracepoint(&hardirq_tracepoints[i]);
@@ -235,6 +270,7 @@ static void hardirq_exit(void *ptr)
270
271
pthread_mutex_lock(&ebpf_exit_cleanup);
272
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
273
+ ebpf_update_stats(&plugin_statistics, em);
274
pthread_mutex_unlock(&ebpf_exit_cleanup);
275
}
276
@@ -533,7 +569,7 @@ static void hardirq_collector(ebpf_module_t *em)
569
hardirq_create_charts(em->update_every);
570
hardirq_create_static_dims();
571
ebpf_update_stats(&plugin_statistics, em);
536
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
572
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
573
pthread_mutex_unlock(&lock);
574
575
// loop and read from published data until ebpf plugin is closed.
@@ -542,7 +578,9 @@ static void hardirq_collector(ebpf_module_t *em)
578
int update_every = em->update_every;
579
int counter = update_every - 1;
580
//This will be cancelled by its parent
545
- while (!ebpf_exit_plugin) {
581
+ uint32_t running_time = 0;
582
+ uint32_t lifetime = em->lifetime;
583
+ while (!ebpf_exit_plugin && running_time < lifetime) {
584
(void)heartbeat_next(&hb, USEC_PER_SEC);
585
586
if (ebpf_exit_plugin || ++counter != update_every)
@@ -561,6 +599,15 @@ static void hardirq_collector(ebpf_module_t *em)
599
write_end_chart();
600
601
pthread_mutex_unlock(&lock);
602
+
603
+ pthread_mutex_lock(&ebpf_exit_cleanup);
604
+ if (running_time && !em->running_time)
605
+ running_time = update_every;
606
+ else
607
+ running_time += update_every;
608
+
609
+ em->running_time = running_time;
610
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
611
}
612
}
613
collectors/ebpf.plugin/ebpf_hardirq.h
+3
@@ -3,6 +3,9 @@
3
#ifndef NETDATA_EBPF_HARDIRQ_H
4
#define NETDATA_EBPF_HARDIRQ_H 1
5
6
+// Module description
7
+#define NETDATA_EBPF_HARDIRQ_MODULE_DESC "Show time spent servicing individual hardware interrupt requests (hard IRQs)."
8
+
9
#include <stdint.h>
10
#include "libnetdata/avl/avl.h"
11
collectors/ebpf.plugin/ebpf_mdflush.c
+49
-3
@@ -129,6 +129,26 @@ static inline int ebpf_mdflush_load_and_attach(struct mdflush_bpf *obj, ebpf_mod
129
130
#endif
131
132
+/**
133
+ * Obsolete global
134
+ *
135
+ * Obsolete global charts created by thread.
136
+ *
137
+ * @param em a pointer to `struct ebpf_module`
138
+ */
139
+static void ebpf_obsolete_mdflush_global(ebpf_module_t *em)
140
+{
141
+ ebpf_write_chart_obsolete("mdstat",
142
+ "mdstat_flush",
143
+ "MD flushes",
144
+ "flushes",
145
+ "flush (eBPF)",
146
+ NETDATA_EBPF_CHART_TYPE_STACKED,
147
+ NULL,
148
+ NETDATA_CHART_PRIO_MDSTAT_FLUSH,
149
+ em->update_every);
150
+}
151
+
152
/**
153
* MDflush exit
154
*
@@ -140,11 +160,26 @@ static void mdflush_exit(void *ptr)
160
{
161
ebpf_module_t *em = (ebpf_module_t *)ptr;
162
143
- if (em->objects)
163
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
164
+ pthread_mutex_lock(&lock);
165
+
166
+ ebpf_obsolete_mdflush_global(em);
167
+
168
+ pthread_mutex_unlock(&lock);
169
+ fflush(stdout);
170
+ }
171
+
172
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
173
+
174
+ if (em->objects) {
175
ebpf_unload_legacy_code(em->objects, em->probe_links);
176
+ em->objects = NULL;
177
+ em->probe_links = NULL;
178
+ }
179
180
pthread_mutex_lock(&ebpf_exit_cleanup);
181
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
182
+ ebpf_update_stats(&plugin_statistics, em);
183
pthread_mutex_unlock(&ebpf_exit_cleanup);
184
}
185
@@ -300,7 +335,7 @@ static void mdflush_collector(ebpf_module_t *em)
335
pthread_mutex_lock(&lock);
336
mdflush_create_charts(update_every);
337
ebpf_update_stats(&plugin_statistics, em);
303
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
338
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
339
pthread_mutex_unlock(&lock);
340
341
// loop and read from published data until ebpf plugin is closed.
@@ -308,7 +343,9 @@ static void mdflush_collector(ebpf_module_t *em)
343
heartbeat_init(&hb);
344
int counter = update_every - 1;
345
int maps_per_core = em->maps_per_core;
311
- while (!ebpf_exit_plugin) {
346
+ uint32_t running_time = 0;
347
+ uint32_t lifetime = em->lifetime;
348
+ while (!ebpf_exit_plugin && running_time < lifetime) {
349
(void)heartbeat_next(&hb, USEC_PER_SEC);
350
351
if (ebpf_exit_plugin || ++counter != update_every)
@@ -323,6 +360,15 @@ static void mdflush_collector(ebpf_module_t *em)
360
write_end_chart();
361
362
pthread_mutex_unlock(&lock);
363
+
364
+ pthread_mutex_lock(&ebpf_exit_cleanup);
365
+ if (running_time && !em->running_time)
366
+ running_time = update_every;
367
+ else
368
+ running_time += update_every;
369
+
370
+ em->running_time = running_time;
371
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
372
}
373
}
374
collectors/ebpf.plugin/ebpf_mdflush.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_MDFLUSH_H
4
#define NETDATA_EBPF_MDFLUSH_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_MDFLUSH "mdflush"
8
+#define NETDATA_EBPF_MD_MODULE_DESC "Show information about multi-device software flushes."
9
10
// charts
11
#define NETDATA_MDFLUSH_GLOBAL_CHART "mdflush"
collectors/ebpf.plugin/ebpf_mount.c
+62
-4
@@ -222,6 +222,36 @@ static inline int ebpf_mount_load_and_attach(struct mount_bpf *obj, ebpf_module_
222
*
223
*****************************************************************/
224
225
+/**
226
+ * Obsolete global
227
+ *
228
+ * Obsolete global charts created by thread.
229
+ *
230
+ * @param em a pointer to `struct ebpf_module`
231
+ */
232
+static void ebpf_obsolete_mount_global(ebpf_module_t *em)
233
+{
234
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MOUNT_GLOBAL_FAMILY,
235
+ NETDATA_EBPF_MOUNT_CALLS,
236
+ "Calls to mount and umount syscalls",
237
+ EBPF_COMMON_DIMENSION_CALL,
238
+ NETDATA_EBPF_MOUNT_FAMILY,
239
+ NETDATA_EBPF_CHART_TYPE_LINE,
240
+ NULL,
241
+ NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS,
242
+ em->update_every);
243
+
244
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MOUNT_GLOBAL_FAMILY,
245
+ NETDATA_EBPF_MOUNT_ERRORS,
246
+ "Errors to mount and umount file systems",
247
+ EBPF_COMMON_DIMENSION_CALL,
248
+ NETDATA_EBPF_MOUNT_FAMILY,
249
+ NETDATA_EBPF_CHART_TYPE_LINE,
250
+ NULL,
251
+ NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS + 1,
252
+ em->update_every);
253
+}
254
+
255
/**
256
* Mount Exit
257
*
@@ -233,15 +263,32 @@ static void ebpf_mount_exit(void *ptr)
263
{
264
ebpf_module_t *em = (ebpf_module_t *)ptr;
265
266
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
267
+ pthread_mutex_lock(&lock);
268
+
269
+ ebpf_obsolete_mount_global(em);
270
+
271
+ fflush(stdout);
272
+ pthread_mutex_unlock(&lock);
273
+ }
274
+
275
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
276
+
277
#ifdef LIBBPF_MAJOR_VERSION
237
- if (mount_bpf_obj)
278
+ if (mount_bpf_obj) {
279
mount_bpf__destroy(mount_bpf_obj);
280
+ mount_bpf_obj = NULL;
281
+ }
282
#endif
240
- if (em->objects)
283
+ if (em->objects) {
284
ebpf_unload_legacy_code(em->objects, em->probe_links);
285
+ em->objects = NULL;
286
+ em->probe_links = NULL;
287
+ }
288
289
pthread_mutex_lock(&ebpf_exit_cleanup);
290
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
291
+ ebpf_update_stats(&plugin_statistics, em);
292
pthread_mutex_unlock(&ebpf_exit_cleanup);
293
}
294
@@ -318,7 +365,9 @@ static void mount_collector(ebpf_module_t *em)
365
int update_every = em->update_every;
366
int counter = update_every - 1;
367
int maps_per_core = em->maps_per_core;
321
- while (!ebpf_exit_plugin) {
368
+ uint32_t running_time = 0;
369
+ uint32_t lifetime = em->lifetime;
370
+ while (!ebpf_exit_plugin && running_time < lifetime) {
371
(void)heartbeat_next(&hb, USEC_PER_SEC);
372
if (ebpf_exit_plugin || ++counter != update_every)
373
continue;
@@ -330,6 +379,15 @@ static void mount_collector(ebpf_module_t *em)
379
ebpf_mount_send_data();
380
381
pthread_mutex_unlock(&lock);
382
+
383
+ pthread_mutex_lock(&ebpf_exit_cleanup);
384
+ if (running_time && !em->running_time)
385
+ running_time = update_every;
386
+ else
387
+ running_time += update_every;
388
+
389
+ em->running_time = running_time;
390
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
391
}
392
}
393
@@ -444,7 +502,7 @@ void *ebpf_mount_thread(void *ptr)
502
pthread_mutex_lock(&lock);
503
ebpf_create_mount_charts(em->update_every);
504
ebpf_update_stats(&plugin_statistics, em);
447
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
505
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
506
pthread_mutex_unlock(&lock);
507
508
mount_collector(em);
collectors/ebpf.plugin/ebpf_mount.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_MOUNT_H
4
#define NETDATA_EBPF_MOUNT_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_MOUNT "mount"
8
+#define NETDATA_EBPF_MOUNT_MODULE_DESC "Show calls to syscalls mount(2) and umount(2)."
9
10
#define NETDATA_EBPF_MOUNT_SYSCALL 2
11
collectors/ebpf.plugin/ebpf_oomkill.c
+118
-4
@@ -44,6 +44,71 @@ static netdata_publish_syscall_t oomkill_publish_aggregated = {.name = "oomkill"
44
.algorithm = "absolute",
45
.next = NULL};
46
47
+static void ebpf_create_specific_oomkill_charts(char *type, int update_every);
48
+
49
+/**
50
+ * Obsolete services
51
+ *
52
+ * Obsolete all service charts created
53
+ *
54
+ * @param em a pointer to `struct ebpf_module`
55
+ */
56
+static void ebpf_obsolete_oomkill_services(ebpf_module_t *em)
57
+{
58
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
59
+ NETDATA_OOMKILL_CHART,
60
+ "OOM kills. This chart is provided by eBPF plugin.",
61
+ EBPF_COMMON_DIMENSION_KILLS,
62
+ NETDATA_EBPF_MEMORY_GROUP,
63
+ NETDATA_EBPF_CHART_TYPE_LINE,
64
+ NULL,
65
+ 20191,
66
+ em->update_every);
67
+}
68
+
69
+/**
70
+ * Obsolete cgroup chart
71
+ *
72
+ * Send obsolete for all charts created before to close.
73
+ *
74
+ * @param em a pointer to `struct ebpf_module`
75
+ */
76
+static inline void ebpf_obsolete_oomkill_cgroup_charts(ebpf_module_t *em)
77
+{
78
+ pthread_mutex_lock(&mutex_cgroup_shm);
79
+
80
+ ebpf_obsolete_oomkill_services(em);
81
+
82
+ ebpf_cgroup_target_t *ect;
83
+ for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
84
+ if (ect->systemd)
85
+ continue;
86
+
87
+ ebpf_create_specific_oomkill_charts(ect->name, em->update_every);
88
+ }
89
+ pthread_mutex_unlock(&mutex_cgroup_shm);
90
+}
91
+
92
+/**
93
+ * Obsolete global
94
+ *
95
+ * Obsolete global charts created by thread.
96
+ *
97
+ * @param em a pointer to `struct ebpf_module`
98
+ */
99
+static void ebpf_obsolete_oomkill_apps(ebpf_module_t *em)
100
+{
101
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
102
+ NETDATA_OOMKILL_CHART,
103
+ "OOM kills",
104
+ EBPF_COMMON_DIMENSION_KILLS,
105
+ "mem",
106
+ NETDATA_EBPF_CHART_TYPE_STACKED,
107
+ NULL,
108
+ 20020,
109
+ em->update_every);
110
+}
111
+
112
/**
113
* Clean up the main thread.
114
*
@@ -53,11 +118,30 @@ static void oomkill_cleanup(void *ptr)
118
{
119
ebpf_module_t *em = (ebpf_module_t *)ptr;
120
56
- if (em->objects)
121
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
122
+ pthread_mutex_lock(&lock);
123
+
124
+ if (em->cgroup_charts) {
125
+ ebpf_obsolete_oomkill_cgroup_charts(em);
126
+ }
127
+
128
+ ebpf_obsolete_oomkill_apps(em);
129
+
130
+ fflush(stdout);
131
+ pthread_mutex_unlock(&lock);
132
+ }
133
+
134
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
135
+
136
+ if (em->objects) {
137
ebpf_unload_legacy_code(em->objects, em->probe_links);
138
+ em->objects = NULL;
139
+ em->probe_links = NULL;
140
+ }
141
142
pthread_mutex_lock(&ebpf_exit_cleanup);
143
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
144
+ ebpf_update_stats(&plugin_statistics, em);
145
pthread_mutex_unlock(&ebpf_exit_cleanup);
146
}
147
@@ -293,6 +377,30 @@ static void ebpf_update_oomkill_cgroup(int32_t *keys, uint32_t total)
377
}
378
}
379
380
+/**
381
+ * Update OOMkill period
382
+ *
383
+ * Update oomkill period according function arguments.
384
+ *
385
+ * @param running_time current value of running_value.
386
+ * @param em the thread main structure.
387
+ *
388
+ * @return It returns new running_time value.
389
+ */
390
+static int ebpf_update_oomkill_period(int running_time, ebpf_module_t *em)
391
+{
392
+ pthread_mutex_lock(&ebpf_exit_cleanup);
393
+ if (running_time && !em->running_time)
394
+ running_time = em->update_every;
395
+ else
396
+ running_time += em->update_every;
397
+
398
+ em->running_time = running_time;
399
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
400
+
401
+ return running_time;
402
+}
403
+
404
/**
405
* Main loop for this collector.
406
*
@@ -309,7 +417,9 @@ static void oomkill_collector(ebpf_module_t *em)
417
heartbeat_t hb;
418
heartbeat_init(&hb);
419
int counter = update_every - 1;
312
- while (!ebpf_exit_plugin) {
420
+ uint32_t running_time = 0;
421
+ uint32_t lifetime = em->lifetime;
422
+ while (!ebpf_exit_plugin && running_time < lifetime) {
423
(void)heartbeat_next(&hb, USEC_PER_SEC);
424
if (ebpf_exit_plugin || ++counter != update_every)
425
continue;
@@ -317,8 +427,10 @@ static void oomkill_collector(ebpf_module_t *em)
427
counter = 0;
428
429
uint32_t count = oomkill_read_data(keys);
320
- if (!count)
430
+ if (!count) {
431
+ running_time = ebpf_update_oomkill_period(running_time, em);
432
continue;
433
+ }
434
435
pthread_mutex_lock(&collect_data_mutex);
436
pthread_mutex_lock(&lock);
@@ -335,6 +447,8 @@ static void oomkill_collector(ebpf_module_t *em)
447
}
448
pthread_mutex_unlock(&lock);
449
pthread_mutex_unlock(&collect_data_mutex);
450
+
451
+ running_time = ebpf_update_oomkill_period(running_time, em);
452
}
453
}
454
@@ -406,7 +520,7 @@ void *ebpf_oomkill_thread(void *ptr)
520
521
pthread_mutex_lock(&lock);
522
ebpf_update_stats(&plugin_statistics, em);
409
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
523
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
524
pthread_mutex_unlock(&lock);
525
526
oomkill_collector(em);
collectors/ebpf.plugin/ebpf_oomkill.h
+3
@@ -3,6 +3,9 @@
3
#ifndef NETDATA_EBPF_OOMKILL_H
4
#define NETDATA_EBPF_OOMKILL_H 1
5
6
+// Module description
7
+#define NETDATA_EBPF_OOMKILL_MODULE_DESC "Show OOM kills for all applications recognized via the apps.plugin."
8
+
9
/*****************************************************************
10
* copied from kernel-collectors repo, with modifications needed
11
* for inclusion here.
collectors/ebpf.plugin/ebpf_process.c
+269
-248
@@ -59,20 +59,15 @@ ebpf_process_stat_t *process_stat_vector = NULL;
59
static netdata_syscall_stat_t process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_END];
60
static netdata_publish_syscall_t process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_END];
61
62
-int process_enabled = 0;
63
-bool publish_internal_metrics = true;
64
-
62
struct config process_config = { .first_section = NULL,
63
.last_section = NULL,
64
.mutex = NETDATA_MUTEX_INITIALIZER,
65
.index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
66
.rwlock = AVL_LOCK_INITIALIZER } };
67
71
-static char *threads_stat[NETDATA_EBPF_THREAD_STAT_END] = {"total", "running"};
72
-static char *load_event_stat[NETDATA_EBPF_LOAD_STAT_END] = {"legacy", "co-re"};
73
-static char *memlock_stat = {"memory_locked"};
74
-static char *hash_table_stat = {"hash_table"};
75
-static char *hash_table_core[NETDATA_EBPF_LOAD_STAT_END] = {"per_core", "unique"};
68
+#ifdef NETDATA_DEV_MODE
69
+int process_disable_priority;
70
+#endif
71
72
/*****************************************************************
73
*
@@ -427,182 +422,8 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
422
&process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK],
423
2, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
424
}
430
-}
431
-
432
-/**
433
- * Create chart for Statistic Thread
434
- *
435
- * Write to standard output current values for threads.
436
- *
437
- * @param em a pointer to the structure with the default values.
438
- */
439
-static inline void ebpf_create_statistic_thread_chart(ebpf_module_t *em)
440
-{
441
- ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
442
- NETDATA_EBPF_THREADS,
443
- "Threads info.",
444
- "threads",
445
- NETDATA_EBPF_FAMILY,
446
- NETDATA_EBPF_CHART_TYPE_LINE,
447
- NULL,
448
- 140000,
449
- em->update_every,
450
- NETDATA_EBPF_MODULE_NAME_PROCESS);
451
-
452
- ebpf_write_global_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_TOTAL],
453
- threads_stat[NETDATA_EBPF_THREAD_STAT_TOTAL],
454
- ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
455
-
456
- ebpf_write_global_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_RUNNING],
457
- threads_stat[NETDATA_EBPF_THREAD_STAT_RUNNING],
458
- ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
459
-}
460
-
461
-/**
462
- * Create chart for Load Thread
463
- *
464
- * Write to standard output current values for load mode.
465
- *
466
- * @param em a pointer to the structure with the default values.
467
- */
468
-static inline void ebpf_create_statistic_load_chart(ebpf_module_t *em)
469
-{
470
- ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
471
- NETDATA_EBPF_LOAD_METHOD,
472
- "Load info.",
473
- "methods",
474
- NETDATA_EBPF_FAMILY,
475
- NETDATA_EBPF_CHART_TYPE_LINE,
476
- NULL,
477
- 140001,
478
- em->update_every,
479
- NETDATA_EBPF_MODULE_NAME_PROCESS);
480
-
481
- ebpf_write_global_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_LEGACY],
482
- load_event_stat[NETDATA_EBPF_LOAD_STAT_LEGACY],
483
- ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
484
-
485
- ebpf_write_global_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_CORE],
486
- load_event_stat[NETDATA_EBPF_LOAD_STAT_CORE],
487
- ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
488
-}
489
-
490
-/**
491
- * Create chart for Kernel Memory
492
- *
493
- * Write to standard output current values for allocated memory.
494
- *
495
- * @param em a pointer to the structure with the default values.
496
- */
497
-static inline void ebpf_create_statistic_kernel_memory(ebpf_module_t *em)
498
-{
499
- ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
500
- NETDATA_EBPF_KERNEL_MEMORY,
501
- "Memory allocated for hash tables.",
502
- "bytes",
503
- NETDATA_EBPF_FAMILY,
504
- NETDATA_EBPF_CHART_TYPE_LINE,
505
- NULL,
506
- 140002,
507
- em->update_every,
508
- NETDATA_EBPF_MODULE_NAME_PROCESS);
509
-
510
- ebpf_write_global_dimension(memlock_stat,
511
- memlock_stat,
512
- ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
513
-}
514
-
515
-/**
516
- * Create chart Hash Table
517
- *
518
- * Write to standard output number of hash tables used with this software.
519
- *
520
- * @param em a pointer to the structure with the default values.
521
- */
522
-static inline void ebpf_create_statistic_hash_tables(ebpf_module_t *em)
523
-{
524
- ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
525
- NETDATA_EBPF_HASH_TABLES_LOADED,
526
- "Number of hash tables loaded.",
527
- "hash tables",
528
- NETDATA_EBPF_FAMILY,
529
- NETDATA_EBPF_CHART_TYPE_LINE,
530
- NULL,
531
- 140003,
532
- em->update_every,
533
- NETDATA_EBPF_MODULE_NAME_PROCESS);
534
-
535
- ebpf_write_global_dimension(hash_table_stat,
536
- hash_table_stat,
537
- ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
538
-}
539
-
540
-/**
541
- * Create chart for percpu stats
542
- *
543
- * Write to standard output current values for threads.
544
- *
545
- * @param em a pointer to the structure with the default values.
546
- */
547
-static inline void ebpf_create_statistic_hash_per_core(ebpf_module_t *em)
548
-{
549
- ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
550
- NETDATA_EBPF_HASH_TABLES_PER_CORE,
551
- "How threads are loading hash/array tables.",
552
- "threads",
553
- NETDATA_EBPF_FAMILY,
554
- NETDATA_EBPF_CHART_TYPE_LINE,
555
- NULL,
556
- 140004,
557
- em->update_every,
558
- NETDATA_EBPF_MODULE_NAME_PROCESS);
559
-
560
- ebpf_write_global_dimension(hash_table_core[NETDATA_EBPF_THREAD_PER_CORE],
561
- hash_table_core[NETDATA_EBPF_THREAD_PER_CORE],
562
- ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
563
-
564
- ebpf_write_global_dimension(hash_table_core[NETDATA_EBPF_THREAD_UNIQUE],
565
- hash_table_core[NETDATA_EBPF_THREAD_UNIQUE],
566
- ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
567
-}
568
-
569
-/**
570
- * Update Internal Metric variable
571
- *
572
- * By default eBPF.plugin sends internal metrics for netdata, but user can
573
- * disable this.
574
- *
575
- * The function updates the variable used to send charts.
576
- */
577
-static void update_internal_metric_variable()
578
-{
579
- const char *s = getenv("NETDATA_INTERNALS_MONITORING");
580
- if (s && *s && strcmp(s, "NO") == 0)
581
- publish_internal_metrics = false;
582
-}
583
-
584
-/**
585
- * Create Statistics Charts
586
- *
587
- * Create charts that will show statistics related to eBPF plugin.
588
- *
589
- * @param em a pointer to the structure with the default values.
590
- */
591
-static void ebpf_create_statistic_charts(ebpf_module_t *em)
592
-{
593
- update_internal_metric_variable();
594
- if (!publish_internal_metrics)
595
- return;
425
597
- ebpf_create_statistic_thread_chart(em);
598
-
599
- ebpf_create_statistic_load_chart(em);
600
-
601
- ebpf_create_statistic_kernel_memory(em);
602
-
603
- ebpf_create_statistic_hash_tables(em);
604
-
605
- ebpf_create_statistic_hash_per_core(em);
426
+ fflush(stdout);
427
}
428
429
/**
@@ -673,6 +494,206 @@ void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
494
*
495
*****************************************************************/
496
497
+static void ebpf_obsolete_specific_process_charts(char *type, ebpf_module_t *em);
498
+
499
+/**
500
+ * Obsolete services
501
+ *
502
+ * Obsolete all service charts created
503
+ *
504
+ * @param em a pointer to `struct ebpf_module`
505
+ */
506
+static void ebpf_obsolete_process_services(ebpf_module_t *em)
507
+{
508
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
509
+ NETDATA_SYSCALL_APPS_TASK_PROCESS,
510
+ "Process started",
511
+ EBPF_COMMON_DIMENSION_CALL,
512
+ NETDATA_APPS_PROCESS_GROUP,
513
+ NETDATA_EBPF_CHART_TYPE_STACKED,
514
+ NULL,
515
+ 20065,
516
+ em->update_every);
517
+
518
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
519
+ NETDATA_SYSCALL_APPS_TASK_THREAD,
520
+ "Threads started",
521
+ EBPF_COMMON_DIMENSION_CALL,
522
+ NETDATA_APPS_PROCESS_GROUP,
523
+ NETDATA_EBPF_CHART_TYPE_STACKED,
524
+ NULL,
525
+ 20066,
526
+ em->update_every);
527
+
528
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
529
+ NETDATA_SYSCALL_APPS_TASK_CLOSE,
530
+ "Tasks starts exit process.",
531
+ EBPF_COMMON_DIMENSION_CALL,
532
+ NETDATA_APPS_PROCESS_GROUP,
533
+ NETDATA_EBPF_CHART_TYPE_STACKED,
534
+ NULL,
535
+ 20067,
536
+ em->update_every);
537
+
538
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
539
+ NETDATA_SYSCALL_APPS_TASK_EXIT,
540
+ "Tasks closed",
541
+ EBPF_COMMON_DIMENSION_CALL,
542
+ NETDATA_APPS_PROCESS_GROUP,
543
+ NETDATA_EBPF_CHART_TYPE_STACKED,
544
+ NULL,
545
+ 20068,
546
+ em->update_every);
547
+
548
+ if (em->mode < MODE_ENTRY) {
549
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
550
+ NETDATA_SYSCALL_APPS_TASK_ERROR,
551
+ "Errors to create process or threads.",
552
+ EBPF_COMMON_DIMENSION_CALL,
553
+ NETDATA_APPS_PROCESS_GROUP,
554
+ NETDATA_EBPF_CHART_TYPE_STACKED,
555
+ NULL,
556
+ 20069,
557
+ em->update_every);
558
+ }
559
+}
560
+
561
+/**
562
+ * Obsolete cgroup chart
563
+ *
564
+ * Send obsolete for all charts created before to close.
565
+ *
566
+ * @param em a pointer to `struct ebpf_module`
567
+ */
568
+static inline void ebpf_obsolete_process_cgroup_charts(ebpf_module_t *em) {
569
+ pthread_mutex_lock(&mutex_cgroup_shm);
570
+
571
+ ebpf_obsolete_process_services(em);
572
+
573
+ ebpf_cgroup_target_t *ect;
574
+ for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
575
+ if (ect->systemd)
576
+ continue;
577
+
578
+ ebpf_obsolete_specific_process_charts(ect->name, em);
579
+ }
580
+ pthread_mutex_unlock(&mutex_cgroup_shm);
581
+}
582
+
583
+/**
584
+ * Obsolette apps charts
585
+ *
586
+ * Obsolete apps charts.
587
+ *
588
+ * @param em a pointer to the structure with the default values.
589
+ */
590
+void ebpf_obsolete_process_apps_charts(struct ebpf_module *em)
591
+{
592
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
593
+ NETDATA_SYSCALL_APPS_TASK_PROCESS,
594
+ "Process started",
595
+ EBPF_COMMON_DIMENSION_CALL,
596
+ NETDATA_PROCESS_GROUP,
597
+ NETDATA_EBPF_CHART_TYPE_STACKED,
598
+ NULL,
599
+ 20065,
600
+ em->update_every);
601
+
602
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
603
+ NETDATA_SYSCALL_APPS_TASK_THREAD,
604
+ "Threads started",
605
+ EBPF_COMMON_DIMENSION_CALL,
606
+ NETDATA_PROCESS_GROUP,
607
+ NETDATA_EBPF_CHART_TYPE_STACKED,
608
+ NULL,
609
+ 20066,
610
+ em->update_every);
611
+
612
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
613
+ NETDATA_SYSCALL_APPS_TASK_EXIT,
614
+ "Tasks starts exit process.",
615
+ EBPF_COMMON_DIMENSION_CALL,
616
+ NETDATA_PROCESS_GROUP,
617
+ NETDATA_EBPF_CHART_TYPE_STACKED,
618
+ NULL,
619
+ 20067,
620
+ em->update_every);
621
+
622
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
623
+ NETDATA_SYSCALL_APPS_TASK_CLOSE,
624
+ "Tasks closed",
625
+ EBPF_COMMON_DIMENSION_CALL,
626
+ NETDATA_PROCESS_GROUP,
627
+ NETDATA_EBPF_CHART_TYPE_STACKED,
628
+ NULL,
629
+ 20068,
630
+ em->update_every);
631
+
632
+ if (em->mode < MODE_ENTRY) {
633
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
634
+ NETDATA_SYSCALL_APPS_TASK_ERROR,
635
+ "Errors to create process or threads.",
636
+ EBPF_COMMON_DIMENSION_CALL,
637
+ NETDATA_PROCESS_GROUP,
638
+ NETDATA_EBPF_CHART_TYPE_STACKED,
639
+ NULL,
640
+ 20069,
641
+ em->update_every);
642
+ }
643
+}
644
+
645
+/**
646
+ * Obsolete global
647
+ *
648
+ * Obsolete global charts created by thread.
649
+ *
650
+ * @param em a pointer to `struct ebpf_module`
651
+ */
652
+static void ebpf_obsolete_process_global(ebpf_module_t *em)
653
+{
654
+ ebpf_write_chart_obsolete(NETDATA_EBPF_SYSTEM_GROUP,
655
+ NETDATA_PROCESS_SYSCALL,
656
+ "Start process",
657
+ EBPF_COMMON_DIMENSION_CALL,
658
+ NETDATA_PROCESS_GROUP,
659
+ NETDATA_EBPF_CHART_TYPE_LINE,
660
+ NULL,
661
+ 21002,
662
+ em->update_every);
663
+
664
+ ebpf_write_chart_obsolete(NETDATA_EBPF_SYSTEM_GROUP,
665
+ NETDATA_EXIT_SYSCALL,
666
+ "Exit process",
667
+ EBPF_COMMON_DIMENSION_CALL,
668
+ NETDATA_PROCESS_GROUP,
669
+ NETDATA_EBPF_CHART_TYPE_LINE,
670
+ NULL,
671
+ 21003,
672
+ em->update_every);
673
+
674
+ ebpf_write_chart_obsolete(NETDATA_EBPF_SYSTEM_GROUP,
675
+ NETDATA_PROCESS_STATUS_NAME,
676
+ "Process not closed",
677
+ EBPF_COMMON_DIMENSION_DIFFERENCE,
678
+ NETDATA_PROCESS_GROUP,
679
+ NETDATA_EBPF_CHART_TYPE_LINE,
680
+ NULL,
681
+ 21004,
682
+ em->update_every);
683
+
684
+ if (em->mode < MODE_ENTRY) {
685
+ ebpf_write_chart_obsolete(NETDATA_EBPF_SYSTEM_GROUP,
686
+ NETDATA_PROCESS_ERROR_NAME,
687
+ "Fails to create process",
688
+ EBPF_COMMON_DIMENSION_CALL,
689
+ NETDATA_PROCESS_GROUP,
690
+ NETDATA_EBPF_CHART_TYPE_LINE,
691
+ NULL,
692
+ 21005,
693
+ em->update_every);
694
+ }
695
+}
696
+
697
/**
698
* Process disable tracepoints
699
*
@@ -708,6 +729,37 @@ static void ebpf_process_exit(void *ptr)
729
{
730
ebpf_module_t *em = (ebpf_module_t *)ptr;
731
732
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
733
+ pthread_mutex_lock(&lock);
734
+ if (em->cgroup_charts) {
735
+ ebpf_obsolete_process_cgroup_charts(em);
736
+ fflush(stdout);
737
+ }
738
+
739
+ if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
740
+ ebpf_obsolete_process_apps_charts(em);
741
+ }
742
+
743
+ ebpf_obsolete_process_global(em);
744
+
745
+#ifdef NETDATA_DEV_MODE
746
+ if (ebpf_aral_process_stat)
747
+ ebpf_statistic_obsolete_aral_chart(em, process_disable_priority);
748
+#endif
749
+
750
+
751
+ fflush(stdout);
752
+ pthread_mutex_unlock(&lock);
753
+ }
754
+
755
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
756
+
757
+ if (em->objects) {
758
+ ebpf_unload_legacy_code(em->objects, em->probe_links);
759
+ em->objects = NULL;
760
+ em->probe_links = NULL;
761
+ }
762
+
763
freez(process_hash_values);
764
freez(process_stat_vector);
765
@@ -716,6 +768,7 @@ static void ebpf_process_exit(void *ptr)
768
pthread_mutex_lock(&ebpf_exit_cleanup);
769
process_pid_fd = -1;
770
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
771
+ ebpf_update_stats(&plugin_statistics, em);
772
pthread_mutex_unlock(&ebpf_exit_cleanup);
773
}
774
@@ -740,14 +793,14 @@ static void ebpf_process_sum_cgroup_pids(ebpf_process_stat_t *ps, struct pid_on_
793
memset(&accumulator, 0, sizeof(accumulator));
794
795
while (pids) {
743
- ebpf_process_stat_t *ps = &pids->ps;
796
+ ebpf_process_stat_t *pps = &pids->ps;
797
745
- accumulator.exit_call += ps->exit_call;
746
- accumulator.release_call += ps->release_call;
747
- accumulator.create_process += ps->create_process;
748
- accumulator.create_thread += ps->create_thread;
798
+ accumulator.exit_call += pps->exit_call;
799
+ accumulator.release_call += pps->release_call;
800
+ accumulator.create_process += pps->create_process;
801
+ accumulator.create_thread += pps->create_thread;
802
750
- accumulator.task_err += ps->task_err;
803
+ accumulator.task_err += pps->task_err;
804
805
pids = pids->next;
806
}
@@ -1046,40 +1099,6 @@ void ebpf_process_update_cgroup_algorithm()
1099
}
1100
}
1101
1049
-/**
1050
- * Send Statistic Data
1051
- *
1052
- * Send statistic information to netdata.
1053
- */
1054
-void ebpf_send_statistic_data()
1055
-{
1056
- if (!publish_internal_metrics)
1057
- return;
1058
-
1059
- write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_THREADS);
1060
- write_chart_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_TOTAL], (long long)plugin_statistics.threads);
1061
- write_chart_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_RUNNING], (long long)plugin_statistics.running);
1062
- write_end_chart();
1063
-
1064
- write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_LOAD_METHOD);
1065
- write_chart_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_LEGACY], (long long)plugin_statistics.legacy);
1066
- write_chart_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_CORE], (long long)plugin_statistics.core);
1067
- write_end_chart();
1068
-
1069
- write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_KERNEL_MEMORY);
1070
- write_chart_dimension(memlock_stat, (long long)plugin_statistics.memlock_kern);
1071
- write_end_chart();
1072
-
1073
- write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_HASH_TABLES_LOADED);
1074
- write_chart_dimension(hash_table_stat, (long long)plugin_statistics.hash_tables);
1075
- write_end_chart();
1076
-
1077
- write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_HASH_TABLES_PER_CORE);
1078
- write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_PER_CORE], (long long)plugin_statistics.hash_percpu);
1079
- write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_UNIQUE], (long long)plugin_statistics.hash_unique);
1080
- write_end_chart();
1081
-}
1082
-
1102
/**
1103
* Main loop for this collector.
1104
*
@@ -1092,7 +1111,6 @@ static void process_collector(ebpf_module_t *em)
1111
int publish_global = em->global_charts;
1112
int cgroups = em->cgroup_charts;
1113
pthread_mutex_lock(&ebpf_exit_cleanup);
1095
- int thread_enabled = em->enabled;
1114
process_pid_fd = process_maps[NETDATA_PROCESS_PID_TABLE].map_fd;
1115
pthread_mutex_unlock(&ebpf_exit_cleanup);
1116
if (cgroups)
@@ -1101,7 +1119,9 @@ static void process_collector(ebpf_module_t *em)
1119
int update_every = em->update_every;
1120
int counter = update_every - 1;
1121
int maps_per_core = em->maps_per_core;
1104
- while (!ebpf_exit_plugin) {
1122
+ uint32_t running_time = 0;
1123
+ uint32_t lifetime = em->lifetime;
1124
+ while (!ebpf_exit_plugin && running_time < lifetime) {
1125
usec_t dt = heartbeat_next(&hb, USEC_PER_SEC);
1126
(void)dt;
1127
if (ebpf_exit_plugin)
@@ -1122,28 +1142,35 @@ static void process_collector(ebpf_module_t *em)
1142
}
1143
1144
pthread_mutex_lock(&lock);
1125
- ebpf_send_statistic_data();
1145
1127
- if (thread_enabled == NETDATA_THREAD_EBPF_RUNNING) {
1128
- if (publish_global) {
1129
- ebpf_process_send_data(em);
1130
- }
1146
+ if (publish_global) {
1147
+ ebpf_process_send_data(em);
1148
+ }
1149
1132
- if (apps_enabled & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
1133
- ebpf_process_send_apps_data(apps_groups_root_target, em);
1134
- }
1150
+ if (apps_enabled & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
1151
+ ebpf_process_send_apps_data(apps_groups_root_target, em);
1152
+ }
1153
1154
#ifdef NETDATA_DEV_MODE
1137
- if (ebpf_aral_process_stat)
1138
- ebpf_send_data_aral_chart(ebpf_aral_process_stat, em);
1155
+ if (ebpf_aral_process_stat)
1156
+ ebpf_send_data_aral_chart(ebpf_aral_process_stat, em);
1157
#endif
1158
1141
- if (cgroups && shm_ebpf_cgroup.header) {
1142
- ebpf_process_send_cgroup_data(em);
1143
- }
1159
+ if (cgroups && shm_ebpf_cgroup.header) {
1160
+ ebpf_process_send_cgroup_data(em);
1161
}
1162
+
1163
pthread_mutex_unlock(&lock);
1164
pthread_mutex_unlock(&collect_data_mutex);
1165
+
1166
+ pthread_mutex_lock(&ebpf_exit_cleanup);
1167
+ if (running_time && !em->running_time)
1168
+ running_time = update_every;
1169
+ else
1170
+ running_time += update_every;
1171
+
1172
+ em->running_time = running_time;
1173
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
1174
}
1175
1176
fflush(stdout);
@@ -1254,7 +1281,6 @@ void *ebpf_process_thread(void *ptr)
1281
if (ebpf_process_enable_tracepoints()) {
1282
em->enabled = em->global_charts = em->apps_charts = em->cgroup_charts = NETDATA_THREAD_EBPF_STOPPING;
1283
}
1257
- process_enabled = em->enabled;
1284
pthread_mutex_unlock(&ebpf_exit_cleanup);
1285
1286
pthread_mutex_lock(&lock);
@@ -1276,27 +1302,22 @@ void *ebpf_process_thread(void *ptr)
1302
process_aggregated_data, process_publish_aggregated, process_dimension_names, process_id_names,
1303
algorithms, NETDATA_KEY_PUBLISH_PROCESS_END);
1304
1279
- if (process_enabled == NETDATA_THREAD_EBPF_RUNNING) {
1280
- ebpf_create_global_charts(em);
1281
- }
1305
+ ebpf_create_global_charts(em);
1306
1307
ebpf_update_stats(&plugin_statistics, em);
1284
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
1308
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
1309
1310
#ifdef NETDATA_DEV_MODE
1311
if (ebpf_aral_process_stat)
1288
- ebpf_statistic_create_aral_chart(NETDATA_EBPF_PROC_ARAL_NAME, em);
1312
+ process_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_PROC_ARAL_NAME, em);
1313
#endif
1314
1291
- ebpf_create_statistic_charts(em);
1292
-
1315
pthread_mutex_unlock(&lock);
1316
1317
process_collector(em);
1318
1319
pthread_mutex_lock(&ebpf_exit_cleanup);
1298
- if (em->enabled == NETDATA_THREAD_EBPF_RUNNING)
1299
- ebpf_update_disabled_plugin_stats(em);
1320
+ ebpf_update_disabled_plugin_stats(em);
1321
pthread_mutex_unlock(&ebpf_exit_cleanup);
1322
1323
netdata_thread_cleanup_pop(1);
collectors/ebpf.plugin/ebpf_process.h
+9
-7
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_PROCESS_H
4
#define NETDATA_EBPF_PROCESS_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_PROCESS "process"
8
+#define NETDATA_EBPF_MODULE_PROCESS_DESC "Monitor information about process life. This thread is integrated with apps and cgroup."
9
10
// Groups used on Dashboard
11
#define NETDATA_PROCESS_GROUP "processes"
@@ -41,12 +42,13 @@
42
43
#define NETDATA_EBPF_CGROUP_UPDATE 30
44
44
-// Statistical information
45
-enum netdata_ebpf_thread_stats{
46
- NETDATA_EBPF_THREAD_STAT_TOTAL,
47
- NETDATA_EBPF_THREAD_STAT_RUNNING,
48
-
49
- NETDATA_EBPF_THREAD_STAT_END
45
+enum netdata_ebpf_stats_order {
46
+ NETDATA_EBPF_ORDER_STAT_THREADS = 140000,
47
+ NETDATA_EBPF_ORDER_STAT_LIFE_TIME,
48
+ NETDATA_EBPF_ORDER_STAT_LOAD_METHOD,
49
+ NETDATA_EBPF_ORDER_STAT_KERNEL_MEMORY,
50
+ NETDATA_EBPF_ORDER_STAT_HASH_TABLES,
51
+ NETDATA_EBPF_ORDER_STAT_HASH_CORE
52
};
53
54
enum netdata_ebpf_load_mode_stats{
collectors/ebpf.plugin/ebpf_shm.c
+194
-5
@@ -50,6 +50,10 @@ netdata_ebpf_targets_t shm_targets[] = { {.name = "shmget", .mode = EBPF_LOAD_TR
50
{.name = "shmctl", .mode = EBPF_LOAD_TRAMPOLINE},
51
{.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
52
53
+#ifdef NETDATA_DEV_MODE
54
+int shm_disable_priority;
55
+#endif
56
+
57
#ifdef LIBBPF_MAJOR_VERSION
58
/*****************************************************************
59
*
@@ -288,6 +292,150 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e
292
* FUNCTIONS TO CLOSE THE THREAD
293
*****************************************************************/
294
295
+static void ebpf_obsolete_specific_shm_charts(char *type, int update_every);
296
+
297
+/**
298
+ * Obsolete services
299
+ *
300
+ * Obsolete all service charts created
301
+ *
302
+ * @param em a pointer to `struct ebpf_module`
303
+ */
304
+static void ebpf_obsolete_shm_services(ebpf_module_t *em)
305
+{
306
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
307
+ NETDATA_SHMGET_CHART,
308
+ "Calls to syscall <code>shmget(2)</code>.",
309
+ EBPF_COMMON_DIMENSION_CALL,
310
+ NETDATA_APPS_IPC_SHM_GROUP,
311
+ NETDATA_EBPF_CHART_TYPE_STACKED,
312
+ NULL,
313
+ 20191,
314
+ em->update_every);
315
+
316
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
317
+ NETDATA_SHMAT_CHART,
318
+ "Calls to syscall <code>shmat(2)</code>.",
319
+ EBPF_COMMON_DIMENSION_CALL,
320
+ NETDATA_APPS_IPC_SHM_GROUP,
321
+ NETDATA_EBPF_CHART_TYPE_STACKED,
322
+ NULL,
323
+ 20192,
324
+ em->update_every);
325
+
326
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
327
+ NETDATA_SHMDT_CHART,
328
+ "Calls to syscall <code>shmdt(2)</code>.",
329
+ EBPF_COMMON_DIMENSION_CALL,
330
+ NETDATA_APPS_IPC_SHM_GROUP,
331
+ NETDATA_EBPF_CHART_TYPE_STACKED,
332
+ NULL,
333
+ 20193,
334
+ em->update_every);
335
+
336
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
337
+ NETDATA_SHMCTL_CHART,
338
+ "Calls to syscall <code>shmctl(2)</code>.",
339
+ EBPF_COMMON_DIMENSION_CALL,
340
+ NETDATA_APPS_IPC_SHM_GROUP,
341
+ NETDATA_EBPF_CHART_TYPE_STACKED,
342
+ NULL,
343
+ 20193,
344
+ em->update_every);
345
+}
346
+
347
+/**
348
+ * Obsolete cgroup chart
349
+ *
350
+ * Send obsolete for all charts created before to close.
351
+ *
352
+ * @param em a pointer to `struct ebpf_module`
353
+ */
354
+static inline void ebpf_obsolete_shm_cgroup_charts(ebpf_module_t *em) {
355
+ pthread_mutex_lock(&mutex_cgroup_shm);
356
+
357
+ ebpf_obsolete_shm_services(em);
358
+
359
+ ebpf_cgroup_target_t *ect;
360
+ for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
361
+ if (ect->systemd)
362
+ continue;
363
+
364
+ ebpf_obsolete_specific_shm_charts(ect->name, em->update_every);
365
+ }
366
+ pthread_mutex_unlock(&mutex_cgroup_shm);
367
+}
368
+
369
+/**
370
+ * Obsolette apps charts
371
+ *
372
+ * Obsolete apps charts.
373
+ *
374
+ * @param em a pointer to the structure with the default values.
375
+ */
376
+void ebpf_obsolete_shm_apps_charts(struct ebpf_module *em)
377
+{
378
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
379
+ NETDATA_SHMGET_CHART,
380
+ "Calls to syscall <code>shmget(2)</code>.",
381
+ EBPF_COMMON_DIMENSION_CALL,
382
+ NETDATA_APPS_IPC_SHM_GROUP,
383
+ NETDATA_EBPF_CHART_TYPE_STACKED,
384
+ NULL,
385
+ 20191,
386
+ em->update_every);
387
+
388
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
389
+ NETDATA_SHMAT_CHART,
390
+ "Calls to syscall <code>shmat(2)</code>.",
391
+ EBPF_COMMON_DIMENSION_CALL,
392
+ NETDATA_APPS_IPC_SHM_GROUP,
393
+ NETDATA_EBPF_CHART_TYPE_STACKED,
394
+ NULL,
395
+ 20192,
396
+ em->update_every);
397
+
398
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
399
+ NETDATA_SHMDT_CHART,
400
+ "Calls to syscall <code>shmdt(2)</code>.",
401
+ EBPF_COMMON_DIMENSION_CALL,
402
+ NETDATA_APPS_IPC_SHM_GROUP,
403
+ NETDATA_EBPF_CHART_TYPE_STACKED,
404
+ NULL,
405
+ 20193,
406
+ em->update_every);
407
+
408
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
409
+ NETDATA_SHMCTL_CHART,
410
+ "Calls to syscall <code>shmctl(2)</code>.",
411
+ EBPF_COMMON_DIMENSION_CALL,
412
+ NETDATA_APPS_IPC_SHM_GROUP,
413
+ NETDATA_EBPF_CHART_TYPE_STACKED,
414
+ NULL,
415
+ 20194,
416
+ em->update_every);
417
+}
418
+
419
+/**
420
+ * Obsolete global
421
+ *
422
+ * Obsolete global charts created by thread.
423
+ *
424
+ * @param em a pointer to `struct ebpf_module`
425
+ */
426
+static void ebpf_obsolete_shm_global(ebpf_module_t *em)
427
+{
428
+ ebpf_write_chart_obsolete(NETDATA_EBPF_SYSTEM_GROUP,
429
+ NETDATA_SHM_GLOBAL_CHART,
430
+ "Calls to shared memory system calls",
431
+ EBPF_COMMON_DIMENSION_CALL,
432
+ NETDATA_SYSTEM_IPC_SHM_SUBMENU,
433
+ NETDATA_EBPF_CHART_TYPE_LINE,
434
+ NULL,
435
+ NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_CALLS,
436
+ em->update_every);
437
+}
438
+
439
/**
440
* SHM Exit
441
*
@@ -299,16 +447,46 @@ static void ebpf_shm_exit(void *ptr)
447
{
448
ebpf_module_t *em = (ebpf_module_t *)ptr;
449
450
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
451
+ pthread_mutex_lock(&lock);
452
+ if (em->cgroup_charts) {
453
+ ebpf_obsolete_shm_cgroup_charts(em);
454
+ fflush(stdout);
455
+ }
456
+
457
+ if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
458
+ ebpf_obsolete_shm_apps_charts(em);
459
+ }
460
+
461
+ ebpf_obsolete_shm_global(em);
462
+
463
+#ifdef NETDATA_DEV_MODE
464
+ if (ebpf_aral_shm_pid)
465
+ ebpf_statistic_obsolete_aral_chart(em, shm_disable_priority);
466
+#endif
467
+
468
+ fflush(stdout);
469
+ pthread_mutex_unlock(&lock);
470
+ }
471
+
472
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
473
+
474
#ifdef LIBBPF_MAJOR_VERSION
303
- if (shm_bpf_obj)
475
+ if (shm_bpf_obj) {
476
shm_bpf__destroy(shm_bpf_obj);
477
+ shm_bpf_obj = NULL;
478
+ }
479
#endif
480
307
- if (em->objects)
481
+ if (em->objects) {
482
ebpf_unload_legacy_code(em->objects, em->probe_links);
483
+ em->objects = NULL;
484
+ em->probe_links = NULL;
485
+ }
486
487
pthread_mutex_lock(&ebpf_exit_cleanup);
488
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
489
+ ebpf_update_stats(&plugin_statistics, em);
490
pthread_mutex_unlock(&ebpf_exit_cleanup);
491
}
492
@@ -859,7 +1037,9 @@ static void shm_collector(ebpf_module_t *em)
1037
heartbeat_init(&hb);
1038
int counter = update_every - 1;
1039
int maps_per_core = em->maps_per_core;
862
- while (!ebpf_exit_plugin) {
1040
+ uint32_t running_time = 0;
1041
+ uint32_t lifetime = em->lifetime;
1042
+ while (!ebpf_exit_plugin && running_time < lifetime) {
1043
(void)heartbeat_next(&hb, USEC_PER_SEC);
1044
if (ebpf_exit_plugin || ++counter != update_every)
1045
continue;
@@ -895,6 +1075,15 @@ static void shm_collector(ebpf_module_t *em)
1075
1076
pthread_mutex_unlock(&lock);
1077
pthread_mutex_unlock(&collect_data_mutex);
1078
+
1079
+ pthread_mutex_lock(&ebpf_exit_cleanup);
1080
+ if (running_time && !em->running_time)
1081
+ running_time = update_every;
1082
+ else
1083
+ running_time += update_every;
1084
+
1085
+ em->running_time = running_time;
1086
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
1087
}
1088
}
1089
@@ -1084,10 +1273,10 @@ void *ebpf_shm_thread(void *ptr)
1273
pthread_mutex_lock(&lock);
1274
ebpf_create_shm_charts(em->update_every);
1275
ebpf_update_stats(&plugin_statistics, em);
1087
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
1276
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
1277
#ifdef NETDATA_DEV_MODE
1278
if (ebpf_aral_shm_pid)
1090
- ebpf_statistic_create_aral_chart(NETDATA_EBPF_SHM_ARAL_NAME, em);
1279
+ shm_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_SHM_ARAL_NAME, em);
1280
#endif
1281
1282
pthread_mutex_unlock(&lock);
collectors/ebpf.plugin/ebpf_shm.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_SHM_H
4
#define NETDATA_EBPF_SHM_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_SHM "shm"
8
+#define NETDATA_EBPF_SHM_MODULE_DESC "Show calls to syscalls shmget(2), shmat(2), shmdt(2) and shmctl(2). This thread is integrated with apps and cgroup."
9
10
// charts
11
#define NETDATA_SHM_GLOBAL_CHART "shared_memory_calls"
collectors/ebpf.plugin/ebpf_socket.c
+25
-4
@@ -130,6 +130,10 @@ struct netdata_static_thread socket_threads = {
130
.start_routine = NULL
131
};
132
133
+#ifdef NETDATA_DEV_MODE
134
+int socket_disable_priority;
135
+#endif
136
+
137
#ifdef LIBBPF_MAJOR_VERSION
138
/**
139
* Disable Probe
@@ -646,6 +650,8 @@ static void ebpf_socket_free(ebpf_module_t *em )
650
651
pthread_mutex_lock(&ebpf_exit_cleanup);
652
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
653
+ ebpf_update_stats(&plugin_statistics, em);
654
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
655
pthread_mutex_unlock(&ebpf_exit_cleanup);
656
}
657
@@ -1217,6 +1223,8 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
1223
&socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
1224
2, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET);
1225
}
1226
+
1227
+ fflush(stdout);
1228
}
1229
1230
/**
@@ -2177,7 +2185,9 @@ void *ebpf_socket_read_hash(void *ptr)
2185
int fd_ipv6 = socket_maps[NETDATA_SOCKET_TABLE_IPV6].map_fd;
2186
int maps_per_core = em->maps_per_core;
2187
// This thread is cancelled from another thread
2180
- for (;;) {
2188
+ uint32_t running_time;
2189
+ uint32_t lifetime = em->lifetime;
2190
+ for (running_time = 0;!ebpf_exit_plugin && running_time < lifetime; running_time++) {
2191
(void)heartbeat_next(&hb, USEC_PER_SEC);
2192
if (ebpf_exit_plugin)
2193
break;
@@ -2918,7 +2928,9 @@ static void socket_collector(ebpf_module_t *em)
2928
int update_every = em->update_every;
2929
int maps_per_core = em->maps_per_core;
2930
int counter = update_every - 1;
2921
- while (!ebpf_exit_plugin) {
2931
+ uint32_t running_time = 0;
2932
+ uint32_t lifetime = em->lifetime;
2933
+ while (!ebpf_exit_plugin && running_time < lifetime) {
2934
(void)heartbeat_next(&hb, USEC_PER_SEC);
2935
if (ebpf_exit_plugin || ++counter != update_every)
2936
continue;
@@ -2973,6 +2985,15 @@ static void socket_collector(ebpf_module_t *em)
2985
}
2986
pthread_mutex_unlock(&lock);
2987
pthread_mutex_unlock(&collect_data_mutex);
2988
+
2989
+ pthread_mutex_lock(&ebpf_exit_cleanup);
2990
+ if (running_time && !em->running_time)
2991
+ running_time = update_every;
2992
+ else
2993
+ running_time += update_every;
2994
+
2995
+ em->running_time = running_time;
2996
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
2997
}
2998
}
2999
@@ -4015,11 +4036,11 @@ void *ebpf_socket_thread(void *ptr)
4036
ebpf_create_global_charts(em);
4037
4038
ebpf_update_stats(&plugin_statistics, em);
4018
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
4039
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
4040
4041
#ifdef NETDATA_DEV_MODE
4042
if (ebpf_aral_socket_pid)
4022
- ebpf_statistic_create_aral_chart(NETDATA_EBPF_SOCKET_ARAL_NAME, em);
4043
+ socket_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_SOCKET_ARAL_NAME, em);
4044
#endif
4045
4046
pthread_mutex_unlock(&lock);
collectors/ebpf.plugin/ebpf_socket.h
+2
-1
@@ -4,8 +4,9 @@
4
#include <stdint.h>
5
#include "libnetdata/avl/avl.h"
6
7
-// Module name
7
+// Module name & description
8
#define NETDATA_EBPF_MODULE_NAME_SOCKET "socket"
9
+#define NETDATA_EBPF_SOCKET_MODULE_DESC "Monitors TCP and UDP bandwidth. This thread is integrated with apps and cgroup."
10
11
// Vector indexes
12
#define NETDATA_UDP_START 3
collectors/ebpf.plugin/ebpf_softirq.c
+50
-3
@@ -60,6 +60,26 @@ static softirq_val_t softirq_vals[] = {
60
// tmp store for soft IRQ values we get from a per-CPU eBPF map.
61
static softirq_ebpf_val_t *softirq_ebpf_vals = NULL;
62
63
+/**
64
+ * Obsolete global
65
+ *
66
+ * Obsolete global charts created by thread.
67
+ *
68
+ * @param em a pointer to `struct ebpf_module`
69
+ */
70
+static void ebpf_obsolete_softirq_global(ebpf_module_t *em)
71
+{
72
+ ebpf_write_chart_obsolete(NETDATA_EBPF_SYSTEM_GROUP,
73
+ "softirq_latency",
74
+ "Software IRQ latency",
75
+ EBPF_COMMON_DIMENSION_MILLISECONDS,
76
+ "softirqs",
77
+ NETDATA_EBPF_CHART_TYPE_STACKED,
78
+ NULL,
79
+ NETDATA_CHART_PRIO_SYSTEM_SOFTIRQS+1,
80
+ em->update_every);
81
+}
82
+
83
/**
84
* Cleanup
85
*
@@ -71,16 +91,32 @@ static void softirq_cleanup(void *ptr)
91
{
92
ebpf_module_t *em = (ebpf_module_t *)ptr;
93
74
- if (em->objects)
94
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
95
+ pthread_mutex_lock(&lock);
96
+
97
+ ebpf_obsolete_softirq_global(em);
98
+
99
+ pthread_mutex_unlock(&lock);
100
+ fflush(stdout);
101
+ }
102
+
103
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
104
+
105
+ if (em->objects) {
106
ebpf_unload_legacy_code(em->objects, em->probe_links);
107
+ em->objects = NULL;
108
+ em->probe_links = NULL;
109
+ }
110
111
for (int i = 0; softirq_tracepoints[i].class != NULL; i++) {
112
ebpf_disable_tracepoint(&softirq_tracepoints[i]);
113
}
114
freez(softirq_ebpf_vals);
115
+ softirq_ebpf_vals = NULL;
116
117
pthread_mutex_lock(&ebpf_exit_cleanup);
118
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
119
+ ebpf_update_stats(&plugin_statistics, em);
120
pthread_mutex_unlock(&ebpf_exit_cleanup);
121
}
122
@@ -170,7 +206,7 @@ static void softirq_collector(ebpf_module_t *em)
206
softirq_create_charts(em->update_every);
207
softirq_create_dims();
208
ebpf_update_stats(&plugin_statistics, em);
173
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
209
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
210
pthread_mutex_unlock(&lock);
211
212
// loop and read from published data until ebpf plugin is closed.
@@ -180,7 +216,9 @@ static void softirq_collector(ebpf_module_t *em)
216
int counter = update_every - 1;
217
int maps_per_core = em->maps_per_core;
218
//This will be cancelled by its parent
183
- while (!ebpf_exit_plugin) {
219
+ uint32_t running_time = 0;
220
+ uint32_t lifetime = em->lifetime;
221
+ while (!ebpf_exit_plugin && running_time < lifetime) {
222
(void)heartbeat_next(&hb, USEC_PER_SEC);
223
if (ebpf_exit_plugin || ++counter != update_every)
224
continue;
@@ -195,6 +233,15 @@ static void softirq_collector(ebpf_module_t *em)
233
write_end_chart();
234
235
pthread_mutex_unlock(&lock);
236
+
237
+ pthread_mutex_lock(&ebpf_exit_cleanup);
238
+ if (running_time && !em->running_time)
239
+ running_time = update_every;
240
+ else
241
+ running_time += update_every;
242
+
243
+ em->running_time = running_time;
244
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
245
}
246
}
247
collectors/ebpf.plugin/ebpf_softirq.h
+3
@@ -3,6 +3,9 @@
3
#ifndef NETDATA_EBPF_SOFTIRQ_H
4
#define NETDATA_EBPF_SOFTIRQ_H 1
5
6
+// Module observation
7
+#define NETDATA_EBPF_SOFTIRQ_MODULE_DESC "Show time spent servicing individual software interrupt requests (soft IRQs)."
8
+
9
/*****************************************************************
10
* copied from kernel-collectors repo, with modifications needed
11
* for inclusion here.
collectors/ebpf.plugin/ebpf_swap.c
+145
-4
@@ -229,6 +229,109 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t
229
*
230
*****************************************************************/
231
232
+static void ebpf_obsolete_specific_swap_charts(char *type, int update_every);
233
+
234
+/**
235
+ * Obsolete services
236
+ *
237
+ * Obsolete all service charts created
238
+ *
239
+ * @param em a pointer to `struct ebpf_module`
240
+ */
241
+static void ebpf_obsolete_swap_services(ebpf_module_t *em)
242
+{
243
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
244
+ NETDATA_MEM_SWAP_READ_CHART,
245
+ "Calls to function <code>swap_readpage</code>.",
246
+ EBPF_COMMON_DIMENSION_CALL,
247
+ NETDATA_SYSTEM_CGROUP_SWAP_SUBMENU,
248
+ NETDATA_EBPF_CHART_TYPE_LINE,
249
+ NETDATA_CGROUP_SWAP_READ_CONTEXT,
250
+ NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5100,
251
+ em->update_every);
252
+
253
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
254
+ NETDATA_MEM_SWAP_WRITE_CHART,
255
+ "Calls to function <code>swap_writepage</code>.",
256
+ EBPF_COMMON_DIMENSION_CALL,
257
+ NETDATA_SYSTEM_CGROUP_SWAP_SUBMENU,
258
+ NETDATA_EBPF_CHART_TYPE_LINE,
259
+ NETDATA_CGROUP_SWAP_WRITE_CONTEXT,
260
+ NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5101,
261
+ em->update_every);
262
+}
263
+
264
+/**
265
+ * Obsolete cgroup chart
266
+ *
267
+ * Send obsolete for all charts created before to close.
268
+ *
269
+ * @param em a pointer to `struct ebpf_module`
270
+ */
271
+static inline void ebpf_obsolete_swap_cgroup_charts(ebpf_module_t *em) {
272
+ pthread_mutex_lock(&mutex_cgroup_shm);
273
+
274
+ ebpf_obsolete_swap_services(em);
275
+
276
+ ebpf_cgroup_target_t *ect;
277
+ for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
278
+ if (ect->systemd)
279
+ continue;
280
+
281
+ ebpf_obsolete_specific_swap_charts(ect->name, em->update_every);
282
+ }
283
+ pthread_mutex_unlock(&mutex_cgroup_shm);
284
+}
285
+
286
+/**
287
+ * Obsolette apps charts
288
+ *
289
+ * Obsolete apps charts.
290
+ *
291
+ * @param em a pointer to the structure with the default values.
292
+ */
293
+void ebpf_obsolete_swap_apps_charts(struct ebpf_module *em)
294
+{
295
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
296
+ NETDATA_MEM_SWAP_READ_CHART,
297
+ "Calls to function <code>swap_readpage</code>.",
298
+ EBPF_COMMON_DIMENSION_CALL,
299
+ NETDATA_SWAP_SUBMENU,
300
+ NETDATA_EBPF_CHART_TYPE_STACKED,
301
+ NULL,
302
+ 20191,
303
+ em->update_every);
304
+
305
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
306
+ NETDATA_MEM_SWAP_WRITE_CHART,
307
+ "Calls to function <code>swap_writepage</code>.",
308
+ EBPF_COMMON_DIMENSION_CALL,
309
+ NETDATA_SWAP_SUBMENU,
310
+ NETDATA_EBPF_CHART_TYPE_STACKED,
311
+ NULL,
312
+ 20192,
313
+ em->update_every);
314
+}
315
+
316
+/**
317
+ * Obsolete global
318
+ *
319
+ * Obsolete global charts created by thread.
320
+ *
321
+ * @param em a pointer to `struct ebpf_module`
322
+ */
323
+static void ebpf_obsolete_swap_global(ebpf_module_t *em)
324
+{
325
+ ebpf_write_chart_obsolete(NETDATA_EBPF_SYSTEM_GROUP,
326
+ NETDATA_MEM_SWAP_CHART,
327
+ "Calls to access swap memory",
328
+ EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
329
+ NETDATA_EBPF_CHART_TYPE_LINE,
330
+ NULL,
331
+ NETDATA_CHART_PRIO_SYSTEM_SWAP_CALLS,
332
+ em->update_every);
333
+}
334
+
335
/**
336
* Swap exit
337
*
@@ -240,15 +343,40 @@ static void ebpf_swap_exit(void *ptr)
343
{
344
ebpf_module_t *em = (ebpf_module_t *)ptr;
345
346
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
347
+ pthread_mutex_lock(&lock);
348
+ if (em->cgroup_charts) {
349
+ ebpf_obsolete_swap_cgroup_charts(em);
350
+ fflush(stdout);
351
+ }
352
+
353
+ if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
354
+ ebpf_obsolete_swap_apps_charts(em);
355
+ }
356
+
357
+ ebpf_obsolete_swap_global(em);
358
+
359
+ fflush(stdout);
360
+ pthread_mutex_unlock(&lock);
361
+ }
362
+
363
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
364
+
365
#ifdef LIBBPF_MAJOR_VERSION
244
- if (bpf_obj)
366
+ if (bpf_obj) {
367
swap_bpf__destroy(bpf_obj);
368
+ bpf_obj = NULL;
369
+ }
370
#endif
247
- if (em->objects)
371
+ if (em->objects) {
372
ebpf_unload_legacy_code(em->objects, em->probe_links);
373
+ em->objects = NULL;
374
+ em->probe_links = NULL;
375
+ }
376
377
pthread_mutex_lock(&ebpf_exit_cleanup);
378
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
379
+ ebpf_update_stats(&plugin_statistics, em);
380
pthread_mutex_unlock(&ebpf_exit_cleanup);
381
}
382
@@ -674,7 +802,9 @@ static void swap_collector(ebpf_module_t *em)
802
heartbeat_init(&hb);
803
int counter = update_every - 1;
804
int maps_per_core = em->maps_per_core;
677
- while (!ebpf_exit_plugin) {
805
+ uint32_t running_time = 0;
806
+ uint32_t lifetime = em->lifetime;
807
+ while (!ebpf_exit_plugin && running_time < lifetime) {
808
(void)heartbeat_next(&hb, USEC_PER_SEC);
809
if (ebpf_exit_plugin || ++counter != update_every)
810
continue;
@@ -701,6 +831,15 @@ static void swap_collector(ebpf_module_t *em)
831
832
pthread_mutex_unlock(&lock);
833
pthread_mutex_unlock(&collect_data_mutex);
834
+
835
+ pthread_mutex_lock(&ebpf_exit_cleanup);
836
+ if (running_time && !em->running_time)
837
+ running_time = update_every;
838
+ else
839
+ running_time += update_every;
840
+
841
+ em->running_time = running_time;
842
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
843
}
844
}
845
@@ -784,6 +923,8 @@ static void ebpf_create_swap_charts(int update_every)
923
ebpf_create_global_dimension,
924
swap_publish_aggregated, NETDATA_SWAP_END,
925
update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
926
+
927
+ fflush(stdout);
928
}
929
930
/*
@@ -857,7 +998,7 @@ void *ebpf_swap_thread(void *ptr)
998
pthread_mutex_lock(&lock);
999
ebpf_create_swap_charts(em->update_every);
1000
ebpf_update_stats(&plugin_statistics, em);
860
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
1001
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
1002
pthread_mutex_unlock(&lock);
1003
1004
swap_collector(em);
collectors/ebpf.plugin/ebpf_swap.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_SWAP_H
4
#define NETDATA_EBPF_SWAP_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_SWAP "swap"
8
+#define NETDATA_EBPF_SWAP_MODULE_DESC "Monitor swap space usage. This thread is integrated with apps and cgroup."
9
10
#define NETDATA_SWAP_SLEEP_MS 850000ULL
11
collectors/ebpf.plugin/ebpf_sync.c
+97
-15
@@ -248,7 +248,6 @@ static inline int ebpf_sync_load_and_attach(struct sync_bpf *obj, ebpf_module_t
248
*
249
*****************************************************************/
250
251
-#ifdef LIBBPF_MAJOR_VERSION
251
/**
252
* Cleanup Objects
253
*
@@ -259,28 +258,86 @@ void ebpf_sync_cleanup_objects()
258
int i;
259
for (i = 0; local_syscalls[i].syscall; i++) {
260
ebpf_sync_syscalls_t *w = &local_syscalls[i];
262
- if (w->sync_obj)
261
+#ifdef LIBBPF_MAJOR_VERSION
262
+ if (w->sync_obj) {
263
sync_bpf__destroy(w->sync_obj);
264
+ w->sync_obj = NULL;
265
+ }
266
+#endif
267
+ if (w->probe_links) {
268
+ ebpf_unload_legacy_code(w->objects, w->probe_links);
269
+ w->objects = NULL;
270
+ w->probe_links = NULL;
271
+ }
272
}
273
}
266
-#endif
274
+
275
+/*
276
+ static void ebpf_create_sync_chart(char *id,
277
+ char *title,
278
+ int order,
279
+ int idx,
280
+ int end,
281
+ int update_every)
282
+ {
283
+ ebpf_write_chart_cmd(NETDATA_EBPF_MEMORY_GROUP, id, title, EBPF_COMMON_DIMENSION_CALL,
284
+ NETDATA_EBPF_SYNC_SUBMENU, NETDATA_EBPF_CHART_TYPE_LINE, NULL, order,
285
+ update_every,
286
+ NETDATA_EBPF_MODULE_NAME_SYNC);
287
+ */
288
289
/**
269
- * Sync Free
290
+ * Obsolete global
291
*
271
- * Cleanup variables after child threads to stop
292
+ * Obsolete global charts created by thread.
293
*
273
- * @param ptr thread data.
294
+ * @param em a pointer to `struct ebpf_module`
295
*/
275
-static void ebpf_sync_free(ebpf_module_t *em)
296
+static void ebpf_obsolete_sync_global(ebpf_module_t *em)
297
{
277
-#ifdef LIBBPF_MAJOR_VERSION
278
- ebpf_sync_cleanup_objects();
279
-#endif
298
+ if (local_syscalls[NETDATA_SYNC_FSYNC_IDX].enabled && local_syscalls[NETDATA_SYNC_FDATASYNC_IDX].enabled)
299
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MEMORY_GROUP,
300
+ NETDATA_EBPF_FILE_SYNC_CHART,
301
+ "Monitor calls for <code>fsync(2)</code> and <code>fdatasync(2)</code>.",
302
+ EBPF_COMMON_DIMENSION_CALL,
303
+ NETDATA_EBPF_SYNC_SUBMENU,
304
+ NETDATA_EBPF_CHART_TYPE_LINE,
305
+ NULL,
306
+ 21300,
307
+ em->update_every);
308
281
- pthread_mutex_lock(&ebpf_exit_cleanup);
282
- em->enabled = NETDATA_THREAD_EBPF_STOPPED;
283
- pthread_mutex_unlock(&ebpf_exit_cleanup);
309
+ if (local_syscalls[NETDATA_SYNC_MSYNC_IDX].enabled)
310
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MEMORY_GROUP,
311
+ NETDATA_EBPF_MSYNC_CHART,
312
+ "Monitor calls for <code>msync(2)</code>.",
313
+ EBPF_COMMON_DIMENSION_CALL,
314
+ NETDATA_EBPF_SYNC_SUBMENU,
315
+ NETDATA_EBPF_CHART_TYPE_LINE,
316
+ NULL,
317
+ 21301,
318
+ em->update_every);
319
+
320
+ if (local_syscalls[NETDATA_SYNC_SYNC_IDX].enabled && local_syscalls[NETDATA_SYNC_SYNCFS_IDX].enabled)
321
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MEMORY_GROUP,
322
+ NETDATA_EBPF_SYNC_CHART,
323
+ "Monitor calls for <code>sync(2)</code> and <code>syncfs(2)</code>.",
324
+ EBPF_COMMON_DIMENSION_CALL,
325
+ NETDATA_EBPF_SYNC_SUBMENU,
326
+ NETDATA_EBPF_CHART_TYPE_LINE,
327
+ NULL,
328
+ 21302,
329
+ em->update_every);
330
+
331
+ if (local_syscalls[NETDATA_SYNC_SYNC_FILE_RANGE_IDX].enabled)
332
+ ebpf_write_chart_obsolete(NETDATA_EBPF_MEMORY_GROUP,
333
+ NETDATA_EBPF_FILE_SEGMENT_CHART,
334
+ "Monitor calls for <code>sync_file_range(2)</code>.",
335
+ EBPF_COMMON_DIMENSION_CALL,
336
+ NETDATA_EBPF_SYNC_SUBMENU,
337
+ NETDATA_EBPF_CHART_TYPE_LINE,
338
+ NULL,
339
+ 21303,
340
+ em->update_every);
341
}
342
343
/**
@@ -293,7 +350,19 @@ static void ebpf_sync_free(ebpf_module_t *em)
350
static void ebpf_sync_exit(void *ptr)
351
{
352
ebpf_module_t *em = (ebpf_module_t *)ptr;
296
- ebpf_sync_free(em);
353
+
354
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
355
+ pthread_mutex_lock(&lock);
356
+ ebpf_obsolete_sync_global(em);
357
+ pthread_mutex_unlock(&lock);
358
+ }
359
+
360
+ ebpf_sync_cleanup_objects();
361
+
362
+ pthread_mutex_lock(&ebpf_exit_cleanup);
363
+ em->enabled = NETDATA_THREAD_EBPF_STOPPED;
364
+ ebpf_update_stats(&plugin_statistics, em);
365
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
366
}
367
368
/*****************************************************************
@@ -489,7 +558,9 @@ static void sync_collector(ebpf_module_t *em)
558
int update_every = em->update_every;
559
int counter = update_every - 1;
560
int maps_per_core = em->maps_per_core;
492
- while (!ebpf_exit_plugin) {
561
+ uint32_t running_time = 0;
562
+ uint32_t lifetime = em->lifetime;
563
+ while (!ebpf_exit_plugin && running_time < lifetime) {
564
(void)heartbeat_next(&hb, USEC_PER_SEC);
565
if (ebpf_exit_plugin || ++counter != update_every)
566
continue;
@@ -501,6 +572,15 @@ static void sync_collector(ebpf_module_t *em)
572
sync_send_data();
573
574
pthread_mutex_unlock(&lock);
575
+
576
+ pthread_mutex_lock(&ebpf_exit_cleanup);
577
+ if (running_time && !em->running_time)
578
+ running_time = update_every;
579
+ else
580
+ running_time += update_every;
581
+
582
+ em->running_time = running_time;
583
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
584
}
585
}
586
@@ -574,6 +654,8 @@ static void ebpf_create_sync_charts(int update_every)
654
ebpf_create_sync_chart(NETDATA_EBPF_FILE_SEGMENT_CHART,
655
"Monitor calls for <code>sync_file_range(2)</code>.", 21303,
656
NETDATA_SYNC_SYNC_FILE_RANGE_IDX, NETDATA_SYNC_SYNC_FILE_RANGE_IDX, update_every);
657
+
658
+ fflush(stdout);
659
}
660
661
/**
collectors/ebpf.plugin/ebpf_sync.h
+2
-1
@@ -7,8 +7,9 @@
7
#include "includes/sync.skel.h"
8
#endif
9
10
-// Module name
10
+// Module name & description
11
#define NETDATA_EBPF_MODULE_NAME_SYNC "sync"
12
+#define NETDATA_EBPF_SYNC_MODULE_DESC "Monitor calls to syscalls sync(2), fsync(2), fdatasync(2), syncfs(2), msync(2), and sync_file_range(2)."
13
14
// charts
15
#define NETDATA_EBPF_SYNC_CHART "sync"
collectors/ebpf.plugin/ebpf_vfs.c
+493
-5
@@ -60,6 +60,10 @@ netdata_ebpf_targets_t vfs_targets[] = { {.name = "vfs_write", .mode = EBPF_LOAD
60
{.name = "release_task", .mode = EBPF_LOAD_TRAMPOLINE},
61
{.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
62
63
+#ifdef NETDATA_DEV_MODE
64
+int vfs_disable_priority;
65
+#endif
66
+
67
#ifdef LIBBPF_MAJOR_VERSION
68
/**
69
* Disable probe
@@ -403,6 +407,447 @@ static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *e
407
*
408
*****************************************************************/
409
410
+static void ebpf_obsolete_specific_vfs_charts(char *type, ebpf_module_t *em);
411
+
412
+/**
413
+ * Obsolete services
414
+ *
415
+ * Obsolete all service charts created
416
+ *
417
+ * @param em a pointer to `struct ebpf_module`
418
+ */
419
+static void ebpf_obsolete_vfs_services(ebpf_module_t *em)
420
+{
421
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
422
+ NETDATA_SYSCALL_APPS_FILE_DELETED,
423
+ "Files deleted",
424
+ EBPF_COMMON_DIMENSION_CALL,
425
+ NETDATA_VFS_CGROUP_GROUP,
426
+ NETDATA_EBPF_CHART_TYPE_STACKED,
427
+ NULL,
428
+ 20065,
429
+ em->update_every);
430
+
431
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
432
+ NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS,
433
+ "Write to disk",
434
+ EBPF_COMMON_DIMENSION_CALL,
435
+ NETDATA_VFS_CGROUP_GROUP,
436
+ NETDATA_EBPF_CHART_TYPE_STACKED,
437
+ NULL,
438
+ 20066,
439
+ em->update_every);
440
+
441
+ if (em->mode < MODE_ENTRY) {
442
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
443
+ NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR,
444
+ "Fails to write",
445
+ EBPF_COMMON_DIMENSION_CALL,
446
+ NETDATA_VFS_CGROUP_GROUP,
447
+ NETDATA_EBPF_CHART_TYPE_STACKED,
448
+ NULL,
449
+ 20067,
450
+ em->update_every);
451
+ }
452
+
453
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
454
+ NETDATA_SYSCALL_APPS_VFS_READ_CALLS,
455
+ "Read from disk",
456
+ EBPF_COMMON_DIMENSION_CALL,
457
+ NETDATA_VFS_CGROUP_GROUP,
458
+ NETDATA_EBPF_CHART_TYPE_STACKED,
459
+ NULL,
460
+ 20068,
461
+ em->update_every);
462
+
463
+ if (em->mode < MODE_ENTRY) {
464
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
465
+ NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR,
466
+ "Fails to read",
467
+ EBPF_COMMON_DIMENSION_CALL,
468
+ NETDATA_VFS_CGROUP_GROUP,
469
+ NETDATA_EBPF_CHART_TYPE_STACKED,
470
+ NULL,
471
+ 20069,
472
+ em->update_every);
473
+ }
474
+
475
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
476
+ NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES,
477
+ "Bytes written on disk",
478
+ EBPF_COMMON_DIMENSION_BYTES,
479
+ NETDATA_VFS_CGROUP_GROUP,
480
+ NETDATA_EBPF_CHART_TYPE_STACKED,
481
+ NULL,
482
+ 20070,
483
+ em->update_every);
484
+
485
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
486
+ NETDATA_SYSCALL_APPS_VFS_READ_BYTES,
487
+ "Bytes read from disk",
488
+ EBPF_COMMON_DIMENSION_BYTES,
489
+ NETDATA_VFS_CGROUP_GROUP,
490
+ NETDATA_EBPF_CHART_TYPE_STACKED,
491
+ NULL,
492
+ 20071,
493
+ em->update_every);
494
+
495
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
496
+ NETDATA_SYSCALL_APPS_VFS_FSYNC,
497
+ "Calls to <code>vfs_fsync</code>",
498
+ EBPF_COMMON_DIMENSION_CALL,
499
+ NETDATA_VFS_CGROUP_GROUP,
500
+ NETDATA_EBPF_CHART_TYPE_STACKED,
501
+ NULL,
502
+ 20072,
503
+ em->update_every);
504
+
505
+ if (em->mode < MODE_ENTRY) {
506
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
507
+ NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR,
508
+ "Sync error",
509
+ EBPF_COMMON_DIMENSION_CALL,
510
+ NETDATA_VFS_CGROUP_GROUP,
511
+ NETDATA_EBPF_CHART_TYPE_STACKED,
512
+ NULL,
513
+ 20073,
514
+ em->update_every);
515
+ }
516
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
517
+ NETDATA_SYSCALL_APPS_VFS_OPEN,
518
+ "Calls to <code>vfs_open</code>",
519
+ EBPF_COMMON_DIMENSION_CALL,
520
+ NETDATA_VFS_CGROUP_GROUP,
521
+ NETDATA_EBPF_CHART_TYPE_STACKED,
522
+ NULL,
523
+ 20074,
524
+ em->update_every);
525
+
526
+ if (em->mode < MODE_ENTRY) {
527
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
528
+ NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR,
529
+ "Open error",
530
+ EBPF_COMMON_DIMENSION_CALL,
531
+ NETDATA_VFS_CGROUP_GROUP,
532
+ NETDATA_EBPF_CHART_TYPE_STACKED,
533
+ NULL,
534
+ 20075,
535
+ em->update_every);
536
+ }
537
+
538
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
539
+ NETDATA_SYSCALL_APPS_VFS_CREATE,
540
+ "Calls to <code>vfs_create</code>",
541
+ EBPF_COMMON_DIMENSION_CALL,
542
+ NETDATA_VFS_CGROUP_GROUP,
543
+ NETDATA_EBPF_CHART_TYPE_STACKED,
544
+ NULL,
545
+ 20076,
546
+ em->update_every);
547
+
548
+ if (em->mode < MODE_ENTRY) {
549
+ ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
550
+ NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR,
551
+ "Create error",
552
+ EBPF_COMMON_DIMENSION_CALL,
553
+ NETDATA_VFS_CGROUP_GROUP,
554
+ NETDATA_EBPF_CHART_TYPE_STACKED,
555
+ NULL,
556
+ 20077,
557
+ em->update_every);
558
+ }
559
+}
560
+
561
+/**
562
+ * Obsolete cgroup chart
563
+ *
564
+ * Send obsolete for all charts created before to close.
565
+ *
566
+ * @param em a pointer to `struct ebpf_module`
567
+ */
568
+static inline void ebpf_obsolete_vfs_cgroup_charts(ebpf_module_t *em) {
569
+ pthread_mutex_lock(&mutex_cgroup_shm);
570
+
571
+ ebpf_obsolete_vfs_services(em);
572
+
573
+ ebpf_cgroup_target_t *ect;
574
+ for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
575
+ if (ect->systemd)
576
+ continue;
577
+
578
+ ebpf_obsolete_specific_vfs_charts(ect->name, em);
579
+ }
580
+ pthread_mutex_unlock(&mutex_cgroup_shm);
581
+}
582
+
583
+/**
584
+ * Obsolette apps charts
585
+ *
586
+ * Obsolete apps charts.
587
+ *
588
+ * @param em a pointer to the structure with the default values.
589
+ */
590
+void ebpf_obsolete_vfs_apps_charts(struct ebpf_module *em)
591
+{
592
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
593
+ NETDATA_SYSCALL_APPS_FILE_DELETED,
594
+ "Files deleted",
595
+ EBPF_COMMON_DIMENSION_CALL,
596
+ NETDATA_VFS_GROUP,
597
+ NETDATA_EBPF_CHART_TYPE_STACKED,
598
+ NULL,
599
+ 20065,
600
+ em->update_every);
601
+
602
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
603
+ NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS,
604
+ "Write to disk",
605
+ EBPF_COMMON_DIMENSION_CALL,
606
+ NETDATA_VFS_GROUP,
607
+ NETDATA_EBPF_CHART_TYPE_STACKED,
608
+ NULL,
609
+ 20066,
610
+ em->update_every);
611
+
612
+ if (em->mode < MODE_ENTRY) {
613
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
614
+ NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR,
615
+ "Fails to write",
616
+ EBPF_COMMON_DIMENSION_CALL,
617
+ NETDATA_VFS_GROUP,
618
+ NETDATA_EBPF_CHART_TYPE_STACKED,
619
+ NULL,
620
+ 20067,
621
+ em->update_every);
622
+ }
623
+
624
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
625
+ NETDATA_SYSCALL_APPS_VFS_READ_CALLS,
626
+ "Read from disk",
627
+ EBPF_COMMON_DIMENSION_CALL,
628
+ NETDATA_VFS_GROUP,
629
+ NETDATA_EBPF_CHART_TYPE_STACKED,
630
+ NULL,
631
+ 20068,
632
+ em->update_every);
633
+
634
+ if (em->mode < MODE_ENTRY) {
635
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
636
+ NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR,
637
+ "Fails to read",
638
+ EBPF_COMMON_DIMENSION_CALL,
639
+ NETDATA_VFS_GROUP,
640
+ NETDATA_EBPF_CHART_TYPE_STACKED,
641
+ NULL,
642
+ 20069,
643
+ em->update_every);
644
+ }
645
+
646
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
647
+ NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES,
648
+ "Bytes written on disk",
649
+ EBPF_COMMON_DIMENSION_BYTES,
650
+ NETDATA_VFS_GROUP,
651
+ NETDATA_EBPF_CHART_TYPE_STACKED,
652
+ NULL,
653
+ 20070,
654
+ em->update_every);
655
+
656
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
657
+ NETDATA_SYSCALL_APPS_VFS_READ_BYTES,
658
+ "Bytes read from disk",
659
+ EBPF_COMMON_DIMENSION_BYTES,
660
+ NETDATA_VFS_GROUP,
661
+ NETDATA_EBPF_CHART_TYPE_STACKED,
662
+ NULL,
663
+ 20071,
664
+ em->update_every);
665
+
666
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
667
+ NETDATA_SYSCALL_APPS_VFS_FSYNC,
668
+ "Calls for <code>vfs_fsync</code>",
669
+ EBPF_COMMON_DIMENSION_CALL,
670
+ NETDATA_VFS_GROUP,
671
+ NETDATA_EBPF_CHART_TYPE_STACKED,
672
+ NULL,
673
+ 20072,
674
+ em->update_every);
675
+
676
+ if (em->mode < MODE_ENTRY) {
677
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
678
+ NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR,
679
+ "Sync error",
680
+ EBPF_COMMON_DIMENSION_CALL,
681
+ NETDATA_VFS_GROUP,
682
+ NETDATA_EBPF_CHART_TYPE_STACKED,
683
+ NULL,
684
+ 20073,
685
+ em->update_every);
686
+ }
687
+
688
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
689
+ NETDATA_SYSCALL_APPS_VFS_OPEN,
690
+ "Calls for <code>vfs_open</code>",
691
+ EBPF_COMMON_DIMENSION_CALL,
692
+ NETDATA_VFS_GROUP,
693
+ NETDATA_EBPF_CHART_TYPE_STACKED,
694
+ NULL,
695
+ 20074,
696
+ em->update_every);
697
+
698
+ if (em->mode < MODE_ENTRY) {
699
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
700
+ NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR,
701
+ "Open error",
702
+ EBPF_COMMON_DIMENSION_CALL,
703
+ NETDATA_VFS_GROUP,
704
+ NETDATA_EBPF_CHART_TYPE_STACKED,
705
+ NULL,
706
+ 20075,
707
+ em->update_every);
708
+ }
709
+
710
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
711
+ NETDATA_SYSCALL_APPS_VFS_CREATE,
712
+ "Calls for <code>vfs_create</code>",
713
+ EBPF_COMMON_DIMENSION_CALL,
714
+ NETDATA_VFS_GROUP,
715
+ NETDATA_EBPF_CHART_TYPE_STACKED,
716
+ NULL,
717
+ 20076,
718
+ em->update_every);
719
+
720
+ if (em->mode < MODE_ENTRY) {
721
+ ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
722
+ NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR,
723
+ "Create error",
724
+ EBPF_COMMON_DIMENSION_CALL,
725
+ NETDATA_VFS_GROUP,
726
+ NETDATA_EBPF_CHART_TYPE_STACKED,
727
+ NULL,
728
+ 20077,
729
+ em->update_every);
730
+ }
731
+}
732
+
733
+/**
734
+ * Obsolete global
735
+ *
736
+ * Obsolete global charts created by thread.
737
+ *
738
+ * @param em a pointer to `struct ebpf_module`
739
+ */
740
+static void ebpf_obsolete_vfs_global(ebpf_module_t *em)
741
+{
742
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
743
+ NETDATA_VFS_FILE_CLEAN_COUNT,
744
+ "Remove files",
745
+ EBPF_COMMON_DIMENSION_CALL,
746
+ NETDATA_VFS_GROUP,
747
+ NETDATA_EBPF_CHART_TYPE_LINE,
748
+ NULL,
749
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_CLEAN,
750
+ em->update_every);
751
+
752
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
753
+ NETDATA_VFS_FILE_IO_COUNT,
754
+ "Calls to IO",
755
+ EBPF_COMMON_DIMENSION_CALL,
756
+ NETDATA_VFS_GROUP,
757
+ NETDATA_EBPF_CHART_TYPE_LINE,
758
+ NULL,
759
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_COUNT,
760
+ em->update_every);
761
+
762
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
763
+ NETDATA_VFS_IO_FILE_BYTES,
764
+ "Bytes written and read",
765
+ EBPF_COMMON_DIMENSION_BYTES,
766
+ NETDATA_VFS_GROUP,
767
+ NETDATA_EBPF_CHART_TYPE_LINE,
768
+ NULL,
769
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_BYTES,
770
+ em->update_every);
771
+
772
+ if (em->mode < MODE_ENTRY) {
773
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
774
+ NETDATA_VFS_FILE_ERR_COUNT,
775
+ "Fails to write or read",
776
+ EBPF_COMMON_DIMENSION_CALL,
777
+ NETDATA_VFS_GROUP,
778
+ NETDATA_EBPF_CHART_TYPE_LINE,
779
+ NULL,
780
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EBYTES,
781
+ em->update_every);
782
+ }
783
+
784
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
785
+ NETDATA_VFS_FSYNC,
786
+ "Calls for <code>vfs_fsync</code>",
787
+ EBPF_COMMON_DIMENSION_CALL,
788
+ NETDATA_VFS_GROUP,
789
+ NETDATA_EBPF_CHART_TYPE_LINE,
790
+ NULL,
791
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_FSYNC,
792
+ em->update_every);
793
+
794
+ if (em->mode < MODE_ENTRY) {
795
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
796
+ NETDATA_VFS_FSYNC_ERR,
797
+ "Fails to synchronize",
798
+ EBPF_COMMON_DIMENSION_CALL,
799
+ NETDATA_VFS_GROUP,
800
+ NETDATA_EBPF_CHART_TYPE_LINE,
801
+ NULL,
802
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EFSYNC,
803
+ em->update_every);
804
+ }
805
+
806
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
807
+ NETDATA_VFS_OPEN,
808
+ "Calls for <code>vfs_open</code>",
809
+ EBPF_COMMON_DIMENSION_CALL,
810
+ NETDATA_VFS_GROUP,
811
+ NETDATA_EBPF_CHART_TYPE_LINE,
812
+ NULL,
813
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_OPEN,
814
+ em->update_every);
815
+
816
+ if (em->mode < MODE_ENTRY) {
817
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
818
+ NETDATA_VFS_OPEN_ERR,
819
+ "Fails to open a file",
820
+ EBPF_COMMON_DIMENSION_CALL,
821
+ NETDATA_VFS_GROUP,
822
+ NETDATA_EBPF_CHART_TYPE_LINE,
823
+ NULL,
824
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EOPEN,
825
+ em->update_every);
826
+ }
827
+
828
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
829
+ NETDATA_VFS_CREATE,
830
+ "Calls for <code>vfs_create</code>",
831
+ EBPF_COMMON_DIMENSION_CALL,
832
+ NETDATA_VFS_GROUP,
833
+ NETDATA_EBPF_CHART_TYPE_LINE,
834
+ NULL,
835
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_CREATE,
836
+ em->update_every);
837
+
838
+ if (em->mode < MODE_ENTRY) {
839
+ ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY,
840
+ NETDATA_VFS_CREATE_ERR,
841
+ "Fails to create a file.",
842
+ EBPF_COMMON_DIMENSION_CALL,
843
+ NETDATA_VFS_GROUP,
844
+ NETDATA_EBPF_CHART_TYPE_LINE,
845
+ NULL,
846
+ NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_ECREATE,
847
+ em->update_every);
848
+ }
849
+}
850
+
851
/**
852
* Exit
853
*
@@ -414,15 +859,45 @@ static void ebpf_vfs_exit(void *ptr)
859
{
860
ebpf_module_t *em = (ebpf_module_t *)ptr;
861
862
+ if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
863
+ pthread_mutex_lock(&lock);
864
+ if (em->cgroup_charts) {
865
+ ebpf_obsolete_vfs_cgroup_charts(em);
866
+ fflush(stdout);
867
+ }
868
+
869
+ if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
870
+ ebpf_obsolete_vfs_apps_charts(em);
871
+ }
872
+
873
+ ebpf_obsolete_vfs_global(em);
874
+
875
+#ifdef NETDATA_DEV_MODE
876
+ if (ebpf_aral_vfs_pid)
877
+ ebpf_statistic_obsolete_aral_chart(em, vfs_disable_priority);
878
+#endif
879
+
880
+ fflush(stdout);
881
+ pthread_mutex_unlock(&lock);
882
+ }
883
+
884
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
885
+
886
#ifdef LIBBPF_MAJOR_VERSION
418
- if (vfs_bpf_obj)
887
+ if (vfs_bpf_obj) {
888
vfs_bpf__destroy(vfs_bpf_obj);
889
+ vfs_bpf_obj = NULL;
890
+ }
891
#endif
421
- if (em->objects)
892
+ if (em->objects) {
893
ebpf_unload_legacy_code(em->objects, em->probe_links);
894
+ em->objects = NULL;
895
+ em->probe_links = NULL;
896
+ }
897
898
pthread_mutex_lock(&ebpf_exit_cleanup);
899
em->enabled = NETDATA_THREAD_EBPF_STOPPED;
900
+ ebpf_update_stats(&plugin_statistics, em);
901
pthread_mutex_unlock(&ebpf_exit_cleanup);
902
}
903
@@ -1486,7 +1961,9 @@ static void vfs_collector(ebpf_module_t *em)
1961
int update_every = em->update_every;
1962
int counter = update_every - 1;
1963
int maps_per_core = em->maps_per_core;
1489
- while (!ebpf_exit_plugin) {
1964
+ uint32_t running_time = 0;
1965
+ uint32_t lifetime = em->lifetime;
1966
+ while (!ebpf_exit_plugin && running_time < lifetime) {
1967
(void)heartbeat_next(&hb, USEC_PER_SEC);
1968
if (ebpf_exit_plugin || ++counter != update_every)
1969
continue;
@@ -1519,6 +1996,15 @@ static void vfs_collector(ebpf_module_t *em)
1996
1997
pthread_mutex_unlock(&lock);
1998
pthread_mutex_unlock(&collect_data_mutex);
1999
+
2000
+ pthread_mutex_lock(&ebpf_exit_cleanup);
2001
+ if (running_time && !em->running_time)
2002
+ running_time = update_every;
2003
+ else
2004
+ running_time += update_every;
2005
+
2006
+ em->running_time = running_time;
2007
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
2008
}
2009
}
2010
@@ -1690,6 +2176,8 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
2176
&vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
2177
1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
2178
}
2179
+
2180
+ fflush(stdout);
2181
}
2182
2183
/**
@@ -1934,10 +2422,10 @@ void *ebpf_vfs_thread(void *ptr)
2422
pthread_mutex_lock(&lock);
2423
ebpf_create_global_charts(em);
2424
ebpf_update_stats(&plugin_statistics, em);
1937
- ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
2425
+ ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
2426
#ifdef NETDATA_DEV_MODE
2427
if (ebpf_aral_vfs_pid)
1940
- ebpf_statistic_create_aral_chart(NETDATA_EBPF_VFS_ARAL_NAME, em);
2428
+ vfs_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_VFS_ARAL_NAME, em);
2429
#endif
2430
2431
pthread_mutex_unlock(&lock);
collectors/ebpf.plugin/ebpf_vfs.h
+2
-1
@@ -3,8 +3,9 @@
3
#ifndef NETDATA_EBPF_VFS_H
4
#define NETDATA_EBPF_VFS_H 1
5
6
-// Module name
6
+// Module name & description
7
#define NETDATA_EBPF_MODULE_NAME_VFS "vfs"
8
+#define NETDATA_EBPF_VFS_MODULE_DESC "Monitor VFS (Virtual File System) functions. This thread is integrated with apps and cgroup."
9
10
#define NETDATA_DIRECTORY_VFS_CONFIG_FILE "vfs.conf"
11
docs/cloud/netdata-functions.md
+1
@@ -33,6 +33,7 @@ functions - [plugins.d](https://github.com/netdata/netdata/blob/master/collector
33
| Function | Description | plugin - module |
34
| :-- | :-- | :-- |
35
| processes | Detailed information on the currently running processes on the node. | [apps.plugin](https://github.com/netdata/netdata/blob/master/collectors/apps.plugin/README.md) |
36
+| ebpf_thread | Controller for eBPF threads. | [ebpf.plugin](https://github.com/netdata/netdata/blob/master/collectors/ebpf.plugin/README.md) |
37
38
If you have ideas or requests for other functions:
39
* open a [Feature request](https://github.com/netdata/netdata-cloud/issues/new?assignees=&labels=feature+request%2Cneeds+triage&template=FEAT_REQUEST.yml&title=%5BFeat%5D%3A+) on Netdata Cloud repo
libnetdata/ebpf/ebpf.c
+30
-19
@@ -391,9 +391,10 @@ static void ebpf_mount_name(char *out, size_t len, char *path, uint32_t kver, co
391
* Count the information from targets.
392
*
393
* @param report the output structure
394
- * @param targets vector with information about the eBPF plugin.
394
+ * @param targets vector with information about the eBPF plugin.
395
+ * @param value factor used to update calculation
396
*/
396
-static void ebpf_stats_targets(ebpf_plugin_stats_t *report, netdata_ebpf_targets_t *targets)
397
+static void ebpf_stats_targets(ebpf_plugin_stats_t *report, netdata_ebpf_targets_t *targets, int value)
398
{
399
if (!targets) {
400
report->probes = report->tracepoints = report->trampolines = 0;
@@ -404,19 +405,19 @@ static void ebpf_stats_targets(ebpf_plugin_stats_t *report, netdata_ebpf_targets
405
while (targets[i].name) {
406
switch (targets[i].mode) {
407
case EBPF_LOAD_PROBE: {
407
- report->probes++;
408
+ report->probes += value;
409
break;
410
}
411
case EBPF_LOAD_RETPROBE: {
411
- report->retprobes++;
412
+ report->retprobes += value;
413
break;
414
}
415
case EBPF_LOAD_TRACEPOINT: {
415
- report->tracepoints++;
416
+ report->tracepoints += value;
417
break;
418
}
419
case EBPF_LOAD_TRAMPOLINE: {
419
- report->trampolines++;
420
+ report->trampolines += value;
421
break;
422
}
423
}
@@ -437,27 +438,30 @@ static void ebpf_stats_targets(ebpf_plugin_stats_t *report, netdata_ebpf_targets
438
*/
439
void ebpf_update_stats(ebpf_plugin_stats_t *report, ebpf_module_t *em)
440
{
440
- report->threads++;
441
+ int value;
442
443
// It is not necessary to report more information.
443
- if (em->enabled != NETDATA_THREAD_EBPF_RUNNING)
444
- return;
444
+ if (em->enabled > NETDATA_THREAD_EBPF_FUNCTION_RUNNING)
445
+ value = -1;
446
+ else
447
+ value = 1;
448
446
- report->running++;
449
+ report->threads += value;
450
+ report->running += value;
451
452
// In theory the `else if` is useless, because when this function is called, the module should not stay in
453
// EBPF_LOAD_PLAY_DICE. We have this additional condition to detect errors from developers.
454
if (em->load & EBPF_LOAD_LEGACY)
451
- report->legacy++;
455
+ report->legacy += value;
456
else if (em->load & EBPF_LOAD_CORE)
453
- report->core++;
457
+ report->core += value;
458
459
if (em->maps_per_core)
456
- report->hash_percpu++;
460
+ report->hash_percpu += value;
461
else
458
- report->hash_unique++;
462
+ report->hash_unique += value;
463
460
- ebpf_stats_targets(report, em->targets);
464
+ ebpf_stats_targets(report, em->targets, value);
465
}
466
467
/**
@@ -528,8 +532,11 @@ void ebpf_update_kernel_memory(ebpf_plugin_stats_t *report, ebpf_local_maps_t *m
532
*
533
* @param report the output structure
534
* @param map pointer to a map. Last map must fish with name = NULL
535
+ * @param action should plugin add or remove values from amount.
536
*/
532
-void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_local_maps_t *maps)
537
+void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report,
538
+ ebpf_local_maps_t *maps,
539
+ ebpf_stats_action_t action)
540
{
541
if (!maps)
542
return;
@@ -541,7 +548,7 @@ void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_loc
548
if (fd == ND_EBPF_MAP_FD_NOT_INITIALIZED)
549
continue;
550
544
- ebpf_update_kernel_memory(report, map, EBPF_ACTION_STAT_ADD);
551
+ ebpf_update_kernel_memory(report, map, action);
552
}
553
}
554
@@ -1238,6 +1245,9 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
1245
modules->pid_map_size = (uint32_t)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE,
1246
modules->pid_map_size);
1247
1248
+ modules->lifetime = (uint32_t) appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION,
1249
+ EBPF_CFG_LIFETIME, EBPF_DEFAULT_LIFETIME);
1250
+
1251
char *value = ebpf_convert_load_mode_to_string(modules->load & NETDATA_EBPF_LOAD_METHODS);
1252
char *type_format = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, value);
1253
netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(type_format);
@@ -1258,7 +1268,7 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
1268
modules->maps_per_core = CONFIG_BOOLEAN_NO;
1269
1270
#ifdef NETDATA_DEV_MODE
1261
- netdata_log_info("The thread %s was configured with: mode = %s; update every = %d; apps = %s; cgroup = %s; ebpf type format = %s; ebpf co-re tracing = %s; collect pid = %s; maps per core = %s",
1271
+ netdata_log_info("The thread %s was configured with: mode = %s; update every = %d; apps = %s; cgroup = %s; ebpf type format = %s; ebpf co-re tracing = %s; collect pid = %s; maps per core = %s, lifetime=%u",
1272
modules->thread_name,
1273
load_mode,
1274
modules->update_every,
@@ -1267,7 +1277,8 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
1277
type_format,
1278
core_attach,
1279
collect_pid,
1270
- (modules->maps_per_core)?"enabled":"disabled"
1280
+ (modules->maps_per_core)?"enabled":"disabled",
1281
+ modules->lifetime
1282
);
1283
#endif
1284
}
libnetdata/ebpf/ebpf.h
+20
-6
@@ -43,6 +43,7 @@
43
#define EBPF_CFG_MAPS_PER_CORE "maps per core"
44
45
#define EBPF_CFG_UPDATE_EVERY "update every"
46
+#define EBPF_CFG_LIFETIME "lifetime"
47
#define EBPF_CFG_UPDATE_APPS_EVERY_DEFAULT 10
48
#define EBPF_CFG_PID_SIZE "pid table size"
49
#define EBPF_CFG_APPLICATION "apps"
@@ -270,15 +271,17 @@ typedef enum netdata_apps_integration_flags {
271
#define NETDATA_EBPF_STAT_DIMENSION_ARAL "aral"
272
273
enum ebpf_threads_status {
273
- NETDATA_THREAD_EBPF_RUNNING,
274
- NETDATA_THREAD_EBPF_STOPPING,
275
- NETDATA_THREAD_EBPF_STOPPED,
276
- NETDATA_THREAD_EBPF_NOT_RUNNING
274
+ NETDATA_THREAD_EBPF_RUNNING, // started by plugin
275
+ NETDATA_THREAD_EBPF_FUNCTION_RUNNING, // started by function
276
+ NETDATA_THREAD_EBPF_STOPPING, // stopping thread
277
+ NETDATA_THREAD_EBPF_STOPPED, // thread stopped
278
+ NETDATA_THREAD_EBPF_NOT_RUNNING // thread was never started
279
};
280
281
typedef struct ebpf_module {
282
const char *thread_name;
283
const char *config_name;
284
+ const char *thread_description;
285
enum ebpf_threads_status enabled;
286
void *(*start_routine)(void *);
287
int update_every;
@@ -306,8 +309,16 @@ typedef struct ebpf_module {
309
char memory_usage[NETDATA_EBPF_CHART_MEM_LENGTH];
310
char memory_allocations[NETDATA_EBPF_CHART_MEM_LENGTH];
311
int maps_per_core;
312
+
313
+ // period to run
314
+ uint32_t running_time; // internal usage, this is used to reset a value when a new request happens.
315
+ uint32_t lifetime;
316
} ebpf_module_t;
317
318
+#define EBPF_DEFAULT_LIFETIME 300
319
+// This will be present until all functions are merged
320
+#define EBPF_NON_FUNCTION_LIFE_TIME 86400
321
+
322
int ebpf_get_kernel_version();
323
int get_redhat_release();
324
int has_condition_to_run(int version);
@@ -336,6 +347,7 @@ void ebpf_update_map_size(struct bpf_map *map, ebpf_local_maps_t *lmap, ebpf_mod
347
typedef struct netdata_ebpf_histogram {
348
char *name;
349
char *title;
350
+ char *ctx;
351
int order;
352
uint64_t histogram[NETDATA_EBPF_HIST_MAX_BINS];
353
} netdata_ebpf_histogram_t;
@@ -425,9 +437,11 @@ void ebpf_update_map_type(struct bpf_map *map, ebpf_local_maps_t *w);
437
void ebpf_define_map_type(ebpf_local_maps_t *maps, int maps_per_core, int kver);
438
#endif
439
428
-void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_local_maps_t *maps);
440
+void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_local_maps_t *maps,
441
+ ebpf_stats_action_t action);
442
void ebpf_update_kernel_memory(ebpf_plugin_stats_t *report, ebpf_local_maps_t *map, ebpf_stats_action_t action);
430
-void ebpf_statistic_create_aral_chart(char *name, ebpf_module_t *em);
443
+int ebpf_statistic_create_aral_chart(char *name, ebpf_module_t *em);
444
+void ebpf_statistic_obsolete_aral_chart(ebpf_module_t *em, int prio);
445
void ebpf_send_data_aral_chart(ARAL *memory, ebpf_module_t *em);
446
447
#endif /* NETDATA_EBPF_H */
netdata.spec.in
+1
@@ -530,6 +530,7 @@ rm -rf "${RPM_BUILD_ROOT}"
530
%{_libexecdir}/%{name}/plugins.d/system-info.sh
531
%{_libexecdir}/%{name}/plugins.d/tc-qos-helper.sh
532
%{_libexecdir}/%{name}/plugins.d/template_dim.sh
533
+%{_libexecdir}/%{name}/plugins.d/ebpf_thread_function.sh
534
535
# cgroup-network detects the network interfaces of CGROUPs
536
# it must be able to use setns() and run cgroup-network-helper.sh as root
tests/Makefile.am
+3
@@ -9,6 +9,7 @@ CLEANFILES = \
9
$(srcdir)/urls/request.sh \
10
$(srcdir)/alarm_repetition/alarm.sh \
11
$(srcdir)/template_dimension/template_dim.sh \
12
+ $(srcdir)/ebpf/ebpf_thread_function.sh \
13
$(NULL)
14
15
include $(top_srcdir)/build/subst.inc
@@ -20,6 +21,7 @@ dist_noinst_DATA = \
21
$(srcdir)/urls/request.sh.in \
22
$(srcdir)/alarm_repetition/alarm.sh.in \
23
$(srcdir)/template_dimension/template_dim.sh.in \
24
+ $(srcdir)/ebpf/ebpf_thread_function.sh.in \
25
$(NULL)
26
27
dist_plugins_SCRIPTS = \
@@ -28,6 +30,7 @@ dist_plugins_SCRIPTS = \
30
$(srcdir)/urls/request.sh \
31
$(srcdir)/alarm_repetition/alarm.sh \
32
$(srcdir)/template_dimension/template_dim.sh \
33
+ $(srcdir)/ebpf/ebpf_thread_function.sh \
34
$(NULL)
35
36
dist_noinst_SCRIPTS = \
tests/ebpf/ebpf.d.conf
new
+28
@@ -0,0 +1,28 @@
1
+[global]
2
+ ebpf load mode = entry
3
+ apps = yes
4
+ cgroups = no
5
+ update every = 5
6
+ pid table size = 32768
7
+ btf path = /sys/kernel/btf/
8
+ maps per core = yes
9
+ life time = 300
10
+
11
+[ebpf programs]
12
+ cachestat = no
13
+ dcstat = no
14
+ disk = no
15
+ fd = no
16
+ filesystem = no
17
+ hardirq = no
18
+ mdflush = no
19
+ mount = no
20
+ oomkill = no
21
+ process = no
22
+ shm = no
23
+ socket = no
24
+ softirq = no
25
+ sync = no
26
+ swap = no
27
+ vfs = no
28
+ network connections = no
tests/ebpf/ebpf_thread_function.sh
new
+52
@@ -0,0 +1,52 @@
1
+#!/bin/bash
2
+
3
+netdata_ebpf_test_functions() {
4
+ echo "QUERYING: ${1}"
5
+ curl -k -o /tmp/ebpf_netdata_test_functions.txt "${1}"
6
+ TEST=$?
7
+ if [ $TEST -ne 0 ]; then
8
+ echo "Cannot request run a for ${1}. See '/tmp/ebpf_netdata_test_functions.txt' for more details."
9
+ exit 1
10
+ fi
11
+
12
+ grep "${2}" /tmp/ebpf_netdata_test_functions.txt >/dev/null
13
+ TEST=$?
14
+ if [ $TEST -ne 0 ]; then
15
+ echo "Cannot find ${2} in the output. See '/tmp/ebpf_netdata_test_functions.txt' for more details.."
16
+ exit 1
17
+ fi
18
+
19
+ rm /tmp/ebpf_netdata_test_functions.txt
20
+}
21
+
22
+MURL="http://127.0.0.1:19999"
23
+INTERVAL=60
24
+
25
+if [ -n "$1" ]; then
26
+ MURL="$1"
27
+fi
28
+
29
+# Check function loaded
30
+netdata_ebpf_test_functions "${MURL}/api/v1/functions" "ebpf_thread"
31
+
32
+# Check function help
33
+netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20help" "allows user to control eBPF threads"
34
+
35
+#Test default request
36
+netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread" "columns"
37
+
38
+#Test thread requests . The mdflush is not enabled, because it is not present in all distributions by default.
39
+#Socket is not in the list, because it will have a complete refactory with next PR
40
+for THREAD in "cachestat" "dc" "disk" "fd" "filesystem" "hardirq" "mount" "oomkill" "process" "shm" "softirq" "sync" "swap" "vfs" ;
41
+do
42
+ echo "TESTING ${THREAD}"
43
+ netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20enable:${THREAD}:${INTERVAL}%20thread:${THREAD}"
44
+ sleep 17
45
+ netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20thread:${THREAD}" "running"
46
+ sleep 17
47
+ netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20disable:${THREAD}"
48
+ sleep 6
49
+ netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20thread:${THREAD}" "stopped"
50
+ sleep 6
51
+done
52
+
tests/ebpf/ebpf_thread_function.sh.in
new
+52
@@ -0,0 +1,52 @@
1
+#!/bin/bash
2
+
3
+netdata_ebpf_test_functions() {
4
+ echo "QUERYING: ${1}"
5
+ curl -k -o /tmp/ebpf_netdata_test_functions.txt "${1}"
6
+ TEST=$?
7
+ if [ $TEST -ne 0 ]; then
8
+ echo "Cannot request run a for ${1}. See '/tmp/ebpf_netdata_test_functions.txt' for more details."
9
+ exit 1
10
+ fi
11
+
12
+ grep "${2}" /tmp/ebpf_netdata_test_functions.txt >/dev/null
13
+ TEST=$?
14
+ if [ $TEST -ne 0 ]; then
15
+ echo "Cannot find ${2} in the output. See '/tmp/ebpf_netdata_test_functions.txt' for more details.."
16
+ exit 1
17
+ fi
18
+
19
+ rm /tmp/ebpf_netdata_test_functions.txt
20
+}
21
+
22
+MURL="http://127.0.0.1:19999"
23
+INTERVAL=60
24
+
25
+if [ -n "$1" ]; then
26
+ MURL="$1"
27
+fi
28
+
29
+# Check function loaded
30
+netdata_ebpf_test_functions "${MURL}/api/v1/functions" "ebpf_thread"
31
+
32
+# Check function help
33
+netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20help" "allows user to control eBPF threads"
34
+
35
+#Test default request
36
+netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread" "columns"
37
+
38
+#Test thread requests . The mdflush is not enabled, because it is not present in all distributions by default.
39
+#Socket is not in the list, because it will have a complete refactory with next PR
40
+for THREAD in "cachestat" "dc" "disk" "fd" "filesystem" "hardirq" "mount" "oomkill" "process" "shm" "softirq" "sync" "swap" "vfs" ;
41
+do
42
+ echo "TESTING ${THREAD}"
43
+ netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20enable:${THREAD}:${INTERVAL}%20thread:${THREAD}"
44
+ sleep 17
45
+ netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20thread:${THREAD}" "running"
46
+ sleep 17
47
+ netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20disable:${THREAD}"
48
+ sleep 6
49
+ netdata_ebpf_test_functions "${MURL}/api/v1/function?function=ebpf_thread%20thread:${THREAD}" "stopped"
50
+ sleep 6
51
+done
52
+
web/gui/dashboard_info.js
+5
-1
@@ -4935,7 +4935,11 @@ netdataDashboard.context = {
4935
},
4936
4937
'netdata.ebpf_threads': {
4938
- info: 'Show total number of threads and number of active threads. For more details about the threads, see the <a href="https://learn.netdata.cloud/docs/agent/collectors/ebpf.plugin#ebpf-programs-configuration-options" target="_blank">official documentation</a>.'
4938
+ info: 'Show thread status. Threads running have value 1 an stopped value 0. For more details about the threads, see the <a href="https://learn.netdata.cloud/docs/agent/collectors/ebpf.plugin#ebpf-programs-configuration-options" target="_blank">official documentation</a>.'
4939
+ },
4940
+
4941
+ 'netdata.ebpf_life_time': {
4942
+ info: 'Time remaining for thread shutdown itself.'
4943
},
4944
4945
'netdata.ebpf_load_methods': {