ebpf_process.c 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include <sys/resource.h>
  3. #include "ebpf.h"
  4. #include "ebpf_process.h"
  5. /*****************************************************************
  6. *
  7. * GLOBAL VARIABLES
  8. *
  9. *****************************************************************/
  10. static char *process_dimension_names[NETDATA_KEY_PUBLISH_PROCESS_END] = { "process", "task", "process", "thread" };
  11. static char *process_id_names[NETDATA_KEY_PUBLISH_PROCESS_END] = { "do_exit", "release_task", "_do_fork", "sys_clone" };
  12. static char *status[] = { "process", "zombie" };
  13. static ebpf_local_maps_t process_maps[] = {{.name = "tbl_pid_stats", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
  14. .user_input = 0,
  15. .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
  16. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
  17. #ifdef LIBBPF_MAJOR_VERSION
  18. .map_type = BPF_MAP_TYPE_PERCPU_HASH
  19. #endif
  20. },
  21. {.name = "tbl_total_stats", .internal_input = NETDATA_KEY_END_VECTOR,
  22. .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
  23. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
  24. #ifdef LIBBPF_MAJOR_VERSION
  25. .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
  26. #endif
  27. },
  28. {.name = "process_ctrl", .internal_input = NETDATA_CONTROLLER_END,
  29. .user_input = 0,
  30. .type = NETDATA_EBPF_MAP_CONTROLLER,
  31. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
  32. #ifdef LIBBPF_MAJOR_VERSION
  33. .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
  34. #endif
  35. },
  36. {.name = NULL, .internal_input = 0, .user_input = 0,
  37. .type = NETDATA_EBPF_MAP_CONTROLLER,
  38. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
  39. #ifdef LIBBPF_MAJOR_VERSION
  40. .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
  41. #endif
  42. }};
  43. char *tracepoint_sched_type = { "sched" } ;
  44. char *tracepoint_sched_process_exit = { "sched_process_exit" };
  45. char *tracepoint_sched_process_exec = { "sched_process_exec" };
  46. char *tracepoint_sched_process_fork = { "sched_process_fork" };
  47. static int was_sched_process_exit_enabled = 0;
  48. static int was_sched_process_exec_enabled = 0;
  49. static int was_sched_process_fork_enabled = 0;
  50. static netdata_idx_t *process_hash_values = NULL;
  51. ebpf_process_stat_t *process_stat_vector = NULL;
  52. static netdata_syscall_stat_t process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_END];
  53. static netdata_publish_syscall_t process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_END];
  54. int process_enabled = 0;
  55. bool publish_internal_metrics = true;
  56. struct config process_config = { .first_section = NULL,
  57. .last_section = NULL,
  58. .mutex = NETDATA_MUTEX_INITIALIZER,
  59. .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
  60. .rwlock = AVL_LOCK_INITIALIZER } };
  61. static char *threads_stat[NETDATA_EBPF_THREAD_STAT_END] = {"total", "running"};
  62. static char *load_event_stat[NETDATA_EBPF_LOAD_STAT_END] = {"legacy", "co-re"};
  63. static char *memlock_stat = {"memory_locked"};
  64. static char *hash_table_stat = {"hash_table"};
  65. static char *hash_table_core[NETDATA_EBPF_LOAD_STAT_END] = {"per_core", "unique"};
  66. /*****************************************************************
  67. *
  68. * PROCESS DATA AND SEND TO NETDATA
  69. *
  70. *****************************************************************/
  71. /**
  72. * Update publish structure before to send data to Netdata.
  73. *
  74. * @param publish the first output structure with independent dimensions
  75. * @param pvc the second output structure with correlated dimensions
  76. * @param input the structure with the input data.
  77. */
  78. static void ebpf_update_global_publish(netdata_publish_syscall_t *publish, netdata_publish_vfs_common_t *pvc,
  79. netdata_syscall_stat_t *input)
  80. {
  81. netdata_publish_syscall_t *move = publish;
  82. int selector = NETDATA_KEY_PUBLISH_PROCESS_EXIT;
  83. while (move) {
  84. move->ncall = (input->call > move->pcall) ? input->call - move->pcall : move->pcall - input->call;
  85. move->nbyte = (input->bytes > move->pbyte) ? input->bytes - move->pbyte : move->pbyte - input->bytes;
  86. move->nerr = (input->ecall > move->nerr) ? input->ecall - move->perr : move->perr - input->ecall;
  87. move->pcall = input->call;
  88. move->pbyte = input->bytes;
  89. move->perr = input->ecall;
  90. input = input->next;
  91. move = move->next;
  92. selector++;
  93. }
  94. pvc->running = (long)publish[NETDATA_KEY_PUBLISH_PROCESS_FORK].ncall -
  95. (long)publish[NETDATA_KEY_PUBLISH_PROCESS_CLONE].ncall;
  96. publish[NETDATA_KEY_PUBLISH_PROCESS_RELEASE_TASK].ncall = -publish[NETDATA_KEY_PUBLISH_PROCESS_RELEASE_TASK].ncall;
  97. pvc->zombie = (long)publish[NETDATA_KEY_PUBLISH_PROCESS_EXIT].ncall +
  98. (long)publish[NETDATA_KEY_PUBLISH_PROCESS_RELEASE_TASK].ncall;
  99. }
  100. /**
  101. * Call the necessary functions to create a chart.
  102. *
  103. * @param family the chart family
  104. * @param move the pointer with the values that will be published
  105. */
  106. static void write_status_chart(char *family, netdata_publish_vfs_common_t *pvc)
  107. {
  108. write_begin_chart(family, NETDATA_PROCESS_STATUS_NAME);
  109. write_chart_dimension(status[0], (long long)pvc->running);
  110. write_chart_dimension(status[1], (long long)pvc->zombie);
  111. write_end_chart();
  112. }
  113. /**
  114. * Send data to Netdata calling auxiliary functions.
  115. *
  116. * @param em the structure with thread information
  117. */
  118. static void ebpf_process_send_data(ebpf_module_t *em)
  119. {
  120. netdata_publish_vfs_common_t pvc;
  121. ebpf_update_global_publish(process_publish_aggregated, &pvc, process_aggregated_data);
  122. write_count_chart(NETDATA_EXIT_SYSCALL, NETDATA_EBPF_SYSTEM_GROUP,
  123. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_EXIT], 2);
  124. write_count_chart(NETDATA_PROCESS_SYSCALL, NETDATA_EBPF_SYSTEM_GROUP,
  125. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK], 2);
  126. write_status_chart(NETDATA_EBPF_SYSTEM_GROUP, &pvc);
  127. if (em->mode < MODE_ENTRY) {
  128. write_err_chart(NETDATA_PROCESS_ERROR_NAME, NETDATA_EBPF_SYSTEM_GROUP,
  129. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK], 2);
  130. }
  131. }
  132. /**
  133. * Sum values for pid
  134. *
  135. * @param root the structure with all available PIDs
  136. * @param offset the address that we are reading
  137. *
  138. * @return it returns the sum of all PIDs
  139. */
  140. long long ebpf_process_sum_values_for_pids(struct ebpf_pid_on_target *root, size_t offset)
  141. {
  142. long long ret = 0;
  143. while (root) {
  144. int32_t pid = root->pid;
  145. ebpf_process_stat_t *w = global_process_stats[pid];
  146. if (w) {
  147. uint32_t *value = (uint32_t *)((char *)w + offset);
  148. ret += *value;
  149. }
  150. root = root->next;
  151. }
  152. return ret;
  153. }
  154. /**
  155. * Remove process pid
  156. *
  157. * Remove from PID task table when task_release was called.
  158. */
  159. void ebpf_process_remove_pids()
  160. {
  161. struct ebpf_pid_stat *pids = ebpf_root_of_pids;
  162. int pid_fd = process_maps[NETDATA_PROCESS_PID_TABLE].map_fd;
  163. while (pids) {
  164. uint32_t pid = pids->pid;
  165. ebpf_process_stat_t *w = global_process_stats[pid];
  166. if (w) {
  167. ebpf_process_stat_release(w);
  168. global_process_stats[pid] = NULL;
  169. bpf_map_delete_elem(pid_fd, &pid);
  170. }
  171. pids = pids->next;
  172. }
  173. }
  174. /**
  175. * Send data to Netdata calling auxiliary functions.
  176. *
  177. * @param root the target list.
  178. */
  179. void ebpf_process_send_apps_data(struct ebpf_target *root, ebpf_module_t *em)
  180. {
  181. struct ebpf_target *w;
  182. collected_number value;
  183. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_PROCESS);
  184. for (w = root; w; w = w->next) {
  185. if (unlikely(w->exposed && w->processes)) {
  186. value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t, create_process));
  187. write_chart_dimension(w->name, value);
  188. }
  189. }
  190. write_end_chart();
  191. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_THREAD);
  192. for (w = root; w; w = w->next) {
  193. if (unlikely(w->exposed && w->processes)) {
  194. value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t, create_thread));
  195. write_chart_dimension(w->name, value);
  196. }
  197. }
  198. write_end_chart();
  199. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_EXIT);
  200. for (w = root; w; w = w->next) {
  201. if (unlikely(w->exposed && w->processes)) {
  202. value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t,
  203. exit_call));
  204. write_chart_dimension(w->name, value);
  205. }
  206. }
  207. write_end_chart();
  208. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_CLOSE);
  209. for (w = root; w; w = w->next) {
  210. if (unlikely(w->exposed && w->processes)) {
  211. value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t,
  212. release_call));
  213. write_chart_dimension(w->name, value);
  214. }
  215. }
  216. write_end_chart();
  217. if (em->mode < MODE_ENTRY) {
  218. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_ERROR);
  219. for (w = root; w; w = w->next) {
  220. if (unlikely(w->exposed && w->processes)) {
  221. value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_stat_t,
  222. task_err));
  223. write_chart_dimension(w->name, value);
  224. }
  225. }
  226. write_end_chart();
  227. }
  228. ebpf_process_remove_pids();
  229. }
  230. /*****************************************************************
  231. *
  232. * READ INFORMATION FROM KERNEL RING
  233. *
  234. *****************************************************************/
  235. /**
  236. * Read the hash table and store data to allocated vectors.
  237. *
  238. * @param maps_per_core do I need to read all cores?
  239. */
  240. static void ebpf_read_process_hash_global_tables(int maps_per_core)
  241. {
  242. uint64_t idx;
  243. netdata_idx_t res[NETDATA_KEY_END_VECTOR];
  244. netdata_idx_t *val = process_hash_values;
  245. int fd = process_maps[NETDATA_PROCESS_GLOBAL_TABLE].map_fd;
  246. for (idx = 0; idx < NETDATA_KEY_END_VECTOR; idx++) {
  247. if (!bpf_map_lookup_elem(fd, &idx, val)) {
  248. uint64_t total = 0;
  249. int i;
  250. int end = (maps_per_core) ? ebpf_nprocs : 1;
  251. for (i = 0; i < end; i++)
  252. total += val[i];
  253. res[idx] = total;
  254. } else {
  255. res[idx] = 0;
  256. }
  257. }
  258. process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_EXIT].call = res[NETDATA_KEY_CALLS_DO_EXIT];
  259. process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_RELEASE_TASK].call = res[NETDATA_KEY_CALLS_RELEASE_TASK];
  260. process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_FORK].call = res[NETDATA_KEY_CALLS_DO_FORK];
  261. process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_CLONE].call = res[NETDATA_KEY_CALLS_SYS_CLONE];
  262. process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_FORK].ecall = res[NETDATA_KEY_ERROR_DO_FORK];
  263. process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_CLONE].ecall = res[NETDATA_KEY_ERROR_SYS_CLONE];
  264. }
  265. /**
  266. * Update cgroup
  267. *
  268. * Update cgroup data based in PID running.
  269. *
  270. * @param maps_per_core do I need to read all cores?
  271. */
  272. static void ebpf_update_process_cgroup(int maps_per_core)
  273. {
  274. ebpf_cgroup_target_t *ect ;
  275. int pid_fd = process_maps[NETDATA_PROCESS_PID_TABLE].map_fd;
  276. size_t length = sizeof(ebpf_process_stat_t);
  277. if (maps_per_core)
  278. length *= ebpf_nprocs;
  279. pthread_mutex_lock(&mutex_cgroup_shm);
  280. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  281. struct pid_on_target2 *pids;
  282. for (pids = ect->pids; pids; pids = pids->next) {
  283. int pid = pids->pid;
  284. ebpf_process_stat_t *out = &pids->ps;
  285. if (global_process_stats[pid]) {
  286. ebpf_process_stat_t *in = global_process_stats[pid];
  287. memcpy(out, in, sizeof(ebpf_process_stat_t));
  288. } else {
  289. if (bpf_map_lookup_elem(pid_fd, &pid, process_stat_vector)) {
  290. memset(out, 0, sizeof(ebpf_process_stat_t));
  291. }
  292. ebpf_process_apps_accumulator(process_stat_vector, maps_per_core);
  293. memcpy(out, process_stat_vector, sizeof(ebpf_process_stat_t));
  294. memset(process_stat_vector, 0, length);
  295. }
  296. }
  297. }
  298. pthread_mutex_unlock(&mutex_cgroup_shm);
  299. }
  300. /*****************************************************************
  301. *
  302. * FUNCTIONS TO CREATE CHARTS
  303. *
  304. *****************************************************************/
  305. /**
  306. * Create process status chart
  307. *
  308. * @param family the chart family
  309. * @param name the chart name
  310. * @param axis the axis label
  311. * @param web the group name used to attach the chart on dashboard
  312. * @param order the order number of the specified chart
  313. * @param update_every value to overwrite the update frequency set by the server.
  314. */
  315. static void ebpf_process_status_chart(char *family, char *name, char *axis,
  316. char *web, char *algorithm, int order, int update_every)
  317. {
  318. printf("CHART %s.%s '' 'Process not closed' '%s' '%s' '' line %d %d '' 'ebpf.plugin' 'process'\n",
  319. family,
  320. name,
  321. axis,
  322. web,
  323. order,
  324. update_every);
  325. printf("DIMENSION %s '' %s 1 1\n", status[0], algorithm);
  326. printf("DIMENSION %s '' %s 1 1\n", status[1], algorithm);
  327. }
  328. /**
  329. * Create global charts
  330. *
  331. * Call ebpf_create_chart to create the charts for the collector.
  332. *
  333. * @param em a pointer to the structure with the default values.
  334. */
  335. static void ebpf_create_global_charts(ebpf_module_t *em)
  336. {
  337. ebpf_create_chart(NETDATA_EBPF_SYSTEM_GROUP,
  338. NETDATA_PROCESS_SYSCALL,
  339. "Start process",
  340. EBPF_COMMON_DIMENSION_CALL,
  341. NETDATA_PROCESS_GROUP,
  342. NULL,
  343. NETDATA_EBPF_CHART_TYPE_LINE,
  344. 21002,
  345. ebpf_create_global_dimension,
  346. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK],
  347. 2, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  348. ebpf_create_chart(NETDATA_EBPF_SYSTEM_GROUP,
  349. NETDATA_EXIT_SYSCALL,
  350. "Exit process",
  351. EBPF_COMMON_DIMENSION_CALL,
  352. NETDATA_PROCESS_GROUP,
  353. NULL,
  354. NETDATA_EBPF_CHART_TYPE_LINE,
  355. 21003,
  356. ebpf_create_global_dimension,
  357. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_EXIT],
  358. 2, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  359. ebpf_process_status_chart(NETDATA_EBPF_SYSTEM_GROUP,
  360. NETDATA_PROCESS_STATUS_NAME,
  361. EBPF_COMMON_DIMENSION_DIFFERENCE,
  362. NETDATA_PROCESS_GROUP,
  363. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  364. 21004, em->update_every);
  365. if (em->mode < MODE_ENTRY) {
  366. ebpf_create_chart(NETDATA_EBPF_SYSTEM_GROUP,
  367. NETDATA_PROCESS_ERROR_NAME,
  368. "Fails to create process",
  369. EBPF_COMMON_DIMENSION_CALL,
  370. NETDATA_PROCESS_GROUP,
  371. NULL,
  372. NETDATA_EBPF_CHART_TYPE_LINE,
  373. 21005,
  374. ebpf_create_global_dimension,
  375. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK],
  376. 2, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  377. }
  378. }
  379. /**
  380. * Create chart for Statistic Thread
  381. *
  382. * Write to standard output current values for threads.
  383. *
  384. * @param em a pointer to the structure with the default values.
  385. */
  386. static inline void ebpf_create_statistic_thread_chart(ebpf_module_t *em)
  387. {
  388. ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
  389. NETDATA_EBPF_THREADS,
  390. "Threads info.",
  391. "threads",
  392. NETDATA_EBPF_FAMILY,
  393. NETDATA_EBPF_CHART_TYPE_LINE,
  394. NULL,
  395. 140000,
  396. em->update_every,
  397. NETDATA_EBPF_MODULE_NAME_PROCESS);
  398. ebpf_write_global_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_TOTAL],
  399. threads_stat[NETDATA_EBPF_THREAD_STAT_TOTAL],
  400. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  401. ebpf_write_global_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_RUNNING],
  402. threads_stat[NETDATA_EBPF_THREAD_STAT_RUNNING],
  403. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  404. }
  405. /**
  406. * Create chart for Load Thread
  407. *
  408. * Write to standard output current values for load mode.
  409. *
  410. * @param em a pointer to the structure with the default values.
  411. */
  412. static inline void ebpf_create_statistic_load_chart(ebpf_module_t *em)
  413. {
  414. ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
  415. NETDATA_EBPF_LOAD_METHOD,
  416. "Load info.",
  417. "methods",
  418. NETDATA_EBPF_FAMILY,
  419. NETDATA_EBPF_CHART_TYPE_LINE,
  420. NULL,
  421. 140001,
  422. em->update_every,
  423. NETDATA_EBPF_MODULE_NAME_PROCESS);
  424. ebpf_write_global_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_LEGACY],
  425. load_event_stat[NETDATA_EBPF_LOAD_STAT_LEGACY],
  426. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  427. ebpf_write_global_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_CORE],
  428. load_event_stat[NETDATA_EBPF_LOAD_STAT_CORE],
  429. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  430. }
  431. /**
  432. * Create chart for Kernel Memory
  433. *
  434. * Write to standard output current values for allocated memory.
  435. *
  436. * @param em a pointer to the structure with the default values.
  437. */
  438. static inline void ebpf_create_statistic_kernel_memory(ebpf_module_t *em)
  439. {
  440. ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
  441. NETDATA_EBPF_KERNEL_MEMORY,
  442. "Memory allocated for hash tables.",
  443. "bytes",
  444. NETDATA_EBPF_FAMILY,
  445. NETDATA_EBPF_CHART_TYPE_LINE,
  446. NULL,
  447. 140002,
  448. em->update_every,
  449. NETDATA_EBPF_MODULE_NAME_PROCESS);
  450. ebpf_write_global_dimension(memlock_stat,
  451. memlock_stat,
  452. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  453. }
  454. /**
  455. * Create chart Hash Table
  456. *
  457. * Write to standard output number of hash tables used with this software.
  458. *
  459. * @param em a pointer to the structure with the default values.
  460. */
  461. static inline void ebpf_create_statistic_hash_tables(ebpf_module_t *em)
  462. {
  463. ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
  464. NETDATA_EBPF_HASH_TABLES_LOADED,
  465. "Number of hash tables loaded.",
  466. "hash tables",
  467. NETDATA_EBPF_FAMILY,
  468. NETDATA_EBPF_CHART_TYPE_LINE,
  469. NULL,
  470. 140003,
  471. em->update_every,
  472. NETDATA_EBPF_MODULE_NAME_PROCESS);
  473. ebpf_write_global_dimension(hash_table_stat,
  474. hash_table_stat,
  475. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  476. }
  477. /**
  478. * Create chart for percpu stats
  479. *
  480. * Write to standard output current values for threads.
  481. *
  482. * @param em a pointer to the structure with the default values.
  483. */
  484. static inline void ebpf_create_statistic_hash_per_core(ebpf_module_t *em)
  485. {
  486. ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
  487. NETDATA_EBPF_HASH_TABLES_PER_CORE,
  488. "How threads are loading hash/array tables.",
  489. "threads",
  490. NETDATA_EBPF_FAMILY,
  491. NETDATA_EBPF_CHART_TYPE_LINE,
  492. NULL,
  493. 140004,
  494. em->update_every,
  495. NETDATA_EBPF_MODULE_NAME_PROCESS);
  496. ebpf_write_global_dimension(hash_table_core[NETDATA_EBPF_THREAD_PER_CORE],
  497. hash_table_core[NETDATA_EBPF_THREAD_PER_CORE],
  498. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  499. ebpf_write_global_dimension(hash_table_core[NETDATA_EBPF_THREAD_UNIQUE],
  500. hash_table_core[NETDATA_EBPF_THREAD_UNIQUE],
  501. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
  502. }
  503. /**
  504. * Update Internal Metric variable
  505. *
  506. * By default eBPF.plugin sends internal metrics for netdata, but user can
  507. * disable this.
  508. *
  509. * The function updates the variable used to send charts.
  510. */
  511. static void update_internal_metric_variable()
  512. {
  513. const char *s = getenv("NETDATA_INTERNALS_MONITORING");
  514. if (s && *s && strcmp(s, "NO") == 0)
  515. publish_internal_metrics = false;
  516. }
  517. /**
  518. * Create Statistics Charts
  519. *
  520. * Create charts that will show statistics related to eBPF plugin.
  521. *
  522. * @param em a pointer to the structure with the default values.
  523. */
  524. static void ebpf_create_statistic_charts(ebpf_module_t *em)
  525. {
  526. update_internal_metric_variable();
  527. if (!publish_internal_metrics)
  528. return;
  529. ebpf_create_statistic_thread_chart(em);
  530. ebpf_create_statistic_load_chart(em);
  531. ebpf_create_statistic_kernel_memory(em);
  532. ebpf_create_statistic_hash_tables(em);
  533. ebpf_create_statistic_hash_per_core(em);
  534. }
  535. /**
  536. * Create process apps charts
  537. *
  538. * Call ebpf_create_chart to create the charts on apps submenu.
  539. *
  540. * @param em a pointer to the structure with the default values.
  541. * @param ptr a pointer for the targets.
  542. */
  543. void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
  544. {
  545. struct ebpf_target *root = ptr;
  546. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_TASK_PROCESS,
  547. "Process started",
  548. EBPF_COMMON_DIMENSION_CALL,
  549. NETDATA_PROCESS_GROUP,
  550. NETDATA_EBPF_CHART_TYPE_STACKED,
  551. 20065,
  552. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  553. root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  554. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_TASK_THREAD,
  555. "Threads started",
  556. EBPF_COMMON_DIMENSION_CALL,
  557. NETDATA_PROCESS_GROUP,
  558. NETDATA_EBPF_CHART_TYPE_STACKED,
  559. 20066,
  560. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  561. root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  562. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_TASK_EXIT,
  563. "Tasks starts exit process.",
  564. EBPF_COMMON_DIMENSION_CALL,
  565. NETDATA_PROCESS_GROUP,
  566. NETDATA_EBPF_CHART_TYPE_STACKED,
  567. 20067,
  568. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  569. root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  570. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_TASK_CLOSE,
  571. "Tasks closed",
  572. EBPF_COMMON_DIMENSION_CALL,
  573. NETDATA_PROCESS_GROUP,
  574. NETDATA_EBPF_CHART_TYPE_STACKED,
  575. 20068,
  576. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  577. root, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  578. if (em->mode < MODE_ENTRY) {
  579. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_TASK_ERROR,
  580. "Errors to create process or threads.",
  581. EBPF_COMMON_DIMENSION_CALL,
  582. NETDATA_PROCESS_GROUP,
  583. NETDATA_EBPF_CHART_TYPE_STACKED,
  584. 20069,
  585. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  586. root,
  587. em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  588. }
  589. em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
  590. }
  591. /*****************************************************************
  592. *
  593. * FUNCTIONS TO CLOSE THE THREAD
  594. *
  595. *****************************************************************/
  596. /**
  597. * Process disable tracepoints
  598. *
  599. * Disable tracepoints when the plugin was responsible to enable it.
  600. */
  601. static void ebpf_process_disable_tracepoints()
  602. {
  603. char *default_message = { "Cannot disable the tracepoint" };
  604. if (!was_sched_process_exit_enabled) {
  605. if (ebpf_disable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_exit))
  606. error("%s %s/%s.", default_message, tracepoint_sched_type, tracepoint_sched_process_exit);
  607. }
  608. if (!was_sched_process_exec_enabled) {
  609. if (ebpf_disable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_exec))
  610. error("%s %s/%s.", default_message, tracepoint_sched_type, tracepoint_sched_process_exec);
  611. }
  612. if (!was_sched_process_fork_enabled) {
  613. if (ebpf_disable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_fork))
  614. error("%s %s/%s.", default_message, tracepoint_sched_type, tracepoint_sched_process_fork);
  615. }
  616. }
  617. /**
  618. * Process Exit
  619. *
  620. * Cancel child thread.
  621. *
  622. * @param ptr thread data.
  623. */
  624. static void ebpf_process_exit(void *ptr)
  625. {
  626. ebpf_module_t *em = (ebpf_module_t *)ptr;
  627. freez(process_hash_values);
  628. freez(process_stat_vector);
  629. ebpf_process_disable_tracepoints();
  630. pthread_mutex_lock(&ebpf_exit_cleanup);
  631. process_pid_fd = -1;
  632. em->enabled = NETDATA_THREAD_EBPF_STOPPED;
  633. pthread_mutex_unlock(&ebpf_exit_cleanup);
  634. }
  635. /*****************************************************************
  636. *
  637. * FUNCTIONS WITH THE MAIN LOOP
  638. *
  639. *****************************************************************/
  640. /**
  641. * Sum PIDs
  642. *
  643. * Sum values for all targets.
  644. *
  645. * @param ps structure used to store data
  646. * @param pids input data
  647. */
  648. static void ebpf_process_sum_cgroup_pids(ebpf_process_stat_t *ps, struct pid_on_target2 *pids)
  649. {
  650. ebpf_process_stat_t accumulator;
  651. memset(&accumulator, 0, sizeof(accumulator));
  652. while (pids) {
  653. ebpf_process_stat_t *ps = &pids->ps;
  654. accumulator.exit_call += ps->exit_call;
  655. accumulator.release_call += ps->release_call;
  656. accumulator.create_process += ps->create_process;
  657. accumulator.create_thread += ps->create_thread;
  658. accumulator.task_err += ps->task_err;
  659. pids = pids->next;
  660. }
  661. ps->exit_call = (accumulator.exit_call >= ps->exit_call) ? accumulator.exit_call : ps->exit_call;
  662. ps->release_call = (accumulator.release_call >= ps->release_call) ? accumulator.release_call : ps->release_call;
  663. ps->create_process = (accumulator.create_process >= ps->create_process) ? accumulator.create_process : ps->create_process;
  664. ps->create_thread = (accumulator.create_thread >= ps->create_thread) ? accumulator.create_thread : ps->create_thread;
  665. ps->task_err = (accumulator.task_err >= ps->task_err) ? accumulator.task_err : ps->task_err;
  666. }
  667. /*
  668. * Send Specific Process data
  669. *
  670. * Send data for specific cgroup/apps.
  671. *
  672. * @param type chart type
  673. * @param values structure with values that will be sent to netdata
  674. * @param em the structure with thread information
  675. */
  676. static void ebpf_send_specific_process_data(char *type, ebpf_process_stat_t *values, ebpf_module_t *em)
  677. {
  678. write_begin_chart(type, NETDATA_SYSCALL_APPS_TASK_PROCESS);
  679. write_chart_dimension(process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK].name,
  680. (long long) values->create_process);
  681. write_end_chart();
  682. write_begin_chart(type, NETDATA_SYSCALL_APPS_TASK_THREAD);
  683. write_chart_dimension(process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_CLONE].name,
  684. (long long) values->create_thread);
  685. write_end_chart();
  686. write_begin_chart(type, NETDATA_SYSCALL_APPS_TASK_EXIT);
  687. write_chart_dimension(process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_EXIT].name,
  688. (long long) values->release_call);
  689. write_end_chart();
  690. write_begin_chart(type, NETDATA_SYSCALL_APPS_TASK_CLOSE);
  691. write_chart_dimension(process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_RELEASE_TASK].name,
  692. (long long) values->release_call);
  693. write_end_chart();
  694. if (em->mode < MODE_ENTRY) {
  695. write_begin_chart(type, NETDATA_SYSCALL_APPS_TASK_ERROR);
  696. write_chart_dimension(process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_EXIT].name,
  697. (long long) values->task_err);
  698. write_end_chart();
  699. }
  700. }
  701. /**
  702. * Create specific process charts
  703. *
  704. * Create charts for cgroup/application
  705. *
  706. * @param type the chart type.
  707. * @param em the structure with thread information
  708. */
  709. static void ebpf_create_specific_process_charts(char *type, ebpf_module_t *em)
  710. {
  711. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_TASK_PROCESS, "Process started",
  712. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_CGROUP_GROUP,
  713. NETDATA_CGROUP_PROCESS_CREATE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  714. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5000,
  715. ebpf_create_global_dimension, &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK],
  716. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  717. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_TASK_THREAD, "Threads started",
  718. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_CGROUP_GROUP,
  719. NETDATA_CGROUP_THREAD_CREATE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  720. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5001,
  721. ebpf_create_global_dimension,
  722. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_CLONE],
  723. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  724. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_TASK_EXIT, "Tasks starts exit process.",
  725. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_CGROUP_GROUP,
  726. NETDATA_CGROUP_PROCESS_EXIT_CONTEXT,
  727. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5002,
  728. ebpf_create_global_dimension,
  729. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_EXIT],
  730. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  731. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_TASK_CLOSE, "Tasks closed",
  732. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_CGROUP_GROUP,
  733. NETDATA_CGROUP_PROCESS_CLOSE_CONTEXT,
  734. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5003,
  735. ebpf_create_global_dimension,
  736. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_RELEASE_TASK],
  737. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  738. if (em->mode < MODE_ENTRY) {
  739. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_TASK_ERROR, "Errors to create process or threads.",
  740. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_CGROUP_GROUP,
  741. NETDATA_CGROUP_PROCESS_ERROR_CONTEXT,
  742. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5004,
  743. ebpf_create_global_dimension,
  744. &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_EXIT],
  745. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_PROCESS);
  746. }
  747. }
  748. /**
  749. * Obsolete specific process charts
  750. *
  751. * Obsolete charts for cgroup/application
  752. *
  753. * @param type the chart type.
  754. * @param em the structure with thread information
  755. */
  756. static void ebpf_obsolete_specific_process_charts(char *type, ebpf_module_t *em)
  757. {
  758. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_TASK_PROCESS, "Process started",
  759. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_GROUP, NETDATA_EBPF_CHART_TYPE_LINE,
  760. NETDATA_CGROUP_PROCESS_CREATE_CONTEXT, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5000,
  761. em->update_every);
  762. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_TASK_THREAD, "Threads started",
  763. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_GROUP, NETDATA_EBPF_CHART_TYPE_LINE,
  764. NETDATA_CGROUP_THREAD_CREATE_CONTEXT, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5001,
  765. em->update_every);
  766. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_TASK_EXIT,"Tasks starts exit process.",
  767. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_GROUP, NETDATA_EBPF_CHART_TYPE_LINE,
  768. NETDATA_CGROUP_PROCESS_EXIT_CONTEXT, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5002,
  769. em->update_every);
  770. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_TASK_CLOSE,"Tasks closed",
  771. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_GROUP, NETDATA_EBPF_CHART_TYPE_LINE,
  772. NETDATA_CGROUP_PROCESS_CLOSE_CONTEXT, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5003,
  773. em->update_every);
  774. if (em->mode < MODE_ENTRY) {
  775. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_TASK_ERROR,"Errors to create process or threads.",
  776. EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_GROUP, NETDATA_EBPF_CHART_TYPE_LINE,
  777. NETDATA_CGROUP_PROCESS_ERROR_CONTEXT, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5004,
  778. em->update_every);
  779. }
  780. }
  781. /**
  782. * Create Systemd process Charts
  783. *
  784. * Create charts when systemd is enabled
  785. *
  786. * @param em the structure with thread information
  787. **/
  788. static void ebpf_create_systemd_process_charts(ebpf_module_t *em)
  789. {
  790. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_TASK_PROCESS, "Process started",
  791. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_PROCESS_GROUP,
  792. NETDATA_EBPF_CHART_TYPE_STACKED, 20065,
  793. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_PROCESS_CREATE_CONTEXT,
  794. NETDATA_EBPF_MODULE_NAME_PROCESS, em->update_every);
  795. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_TASK_THREAD, "Threads started",
  796. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_PROCESS_GROUP,
  797. NETDATA_EBPF_CHART_TYPE_STACKED, 20066,
  798. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_THREAD_CREATE_CONTEXT,
  799. NETDATA_EBPF_MODULE_NAME_PROCESS, em->update_every);
  800. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_TASK_CLOSE, "Tasks starts exit process.",
  801. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_PROCESS_GROUP,
  802. NETDATA_EBPF_CHART_TYPE_STACKED, 20067,
  803. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_PROCESS_EXIT_CONTEXT,
  804. NETDATA_EBPF_MODULE_NAME_PROCESS, em->update_every);
  805. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_TASK_EXIT, "Tasks closed",
  806. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_PROCESS_GROUP,
  807. NETDATA_EBPF_CHART_TYPE_STACKED, 20068,
  808. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_PROCESS_CLOSE_CONTEXT,
  809. NETDATA_EBPF_MODULE_NAME_PROCESS, em->update_every);
  810. if (em->mode < MODE_ENTRY) {
  811. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_TASK_ERROR, "Errors to create process or threads.",
  812. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_PROCESS_GROUP,
  813. NETDATA_EBPF_CHART_TYPE_STACKED, 20069,
  814. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_PROCESS_ERROR_CONTEXT,
  815. NETDATA_EBPF_MODULE_NAME_PROCESS, em->update_every);
  816. }
  817. }
  818. /**
  819. * Send Systemd charts
  820. *
  821. * Send collected data to Netdata.
  822. *
  823. * @param em the structure with thread information
  824. */
  825. static void ebpf_send_systemd_process_charts(ebpf_module_t *em)
  826. {
  827. ebpf_cgroup_target_t *ect;
  828. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_TASK_PROCESS);
  829. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  830. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  831. write_chart_dimension(ect->name, ect->publish_systemd_ps.create_process);
  832. }
  833. }
  834. write_end_chart();
  835. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_TASK_THREAD);
  836. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  837. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  838. write_chart_dimension(ect->name, ect->publish_systemd_ps.create_thread);
  839. }
  840. }
  841. write_end_chart();
  842. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_TASK_EXIT);
  843. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  844. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  845. write_chart_dimension(ect->name, ect->publish_systemd_ps.exit_call);
  846. }
  847. }
  848. write_end_chart();
  849. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_TASK_CLOSE);
  850. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  851. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  852. write_chart_dimension(ect->name, ect->publish_systemd_ps.release_call);
  853. }
  854. }
  855. write_end_chart();
  856. if (em->mode < MODE_ENTRY) {
  857. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_TASK_ERROR);
  858. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  859. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  860. write_chart_dimension(ect->name, ect->publish_systemd_ps.task_err);
  861. }
  862. }
  863. write_end_chart();
  864. }
  865. }
  866. /**
  867. * Send data to Netdata calling auxiliary functions.
  868. *
  869. * @param em the structure with thread information
  870. */
  871. static void ebpf_process_send_cgroup_data(ebpf_module_t *em)
  872. {
  873. if (!ebpf_cgroup_pids)
  874. return;
  875. pthread_mutex_lock(&mutex_cgroup_shm);
  876. ebpf_cgroup_target_t *ect;
  877. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  878. ebpf_process_sum_cgroup_pids(&ect->publish_systemd_ps, ect->pids);
  879. }
  880. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  881. if (has_systemd) {
  882. if (send_cgroup_chart) {
  883. ebpf_create_systemd_process_charts(em);
  884. }
  885. ebpf_send_systemd_process_charts(em);
  886. }
  887. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  888. if (ect->systemd)
  889. continue;
  890. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_PROCESS_CHART) && ect->updated) {
  891. ebpf_create_specific_process_charts(ect->name, em);
  892. ect->flags |= NETDATA_EBPF_CGROUP_HAS_PROCESS_CHART;
  893. }
  894. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_PROCESS_CHART) {
  895. if (ect->updated) {
  896. ebpf_send_specific_process_data(ect->name, &ect->publish_systemd_ps, em);
  897. } else {
  898. ebpf_obsolete_specific_process_charts(ect->name, em);
  899. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_PROCESS_CHART;
  900. }
  901. }
  902. }
  903. pthread_mutex_unlock(&mutex_cgroup_shm);
  904. }
  905. /**
  906. * Update Cgroup algorithm
  907. *
  908. * Change algorithm from absolute to incremental
  909. */
  910. void ebpf_process_update_cgroup_algorithm()
  911. {
  912. int i;
  913. for (i = 0; i < NETDATA_KEY_PUBLISH_PROCESS_END; i++) {
  914. netdata_publish_syscall_t *ptr = &process_publish_aggregated[i];
  915. ptr->algorithm = ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX];
  916. }
  917. }
  918. /**
  919. * Send Statistic Data
  920. *
  921. * Send statistic information to netdata.
  922. */
  923. void ebpf_send_statistic_data()
  924. {
  925. if (!publish_internal_metrics)
  926. return;
  927. write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_THREADS);
  928. write_chart_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_TOTAL], (long long)plugin_statistics.threads);
  929. write_chart_dimension(threads_stat[NETDATA_EBPF_THREAD_STAT_RUNNING], (long long)plugin_statistics.running);
  930. write_end_chart();
  931. write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_LOAD_METHOD);
  932. write_chart_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_LEGACY], (long long)plugin_statistics.legacy);
  933. write_chart_dimension(load_event_stat[NETDATA_EBPF_LOAD_STAT_CORE], (long long)plugin_statistics.core);
  934. write_end_chart();
  935. write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_KERNEL_MEMORY);
  936. write_chart_dimension(memlock_stat, (long long)plugin_statistics.memlock_kern);
  937. write_end_chart();
  938. write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_HASH_TABLES_LOADED);
  939. write_chart_dimension(hash_table_stat, (long long)plugin_statistics.hash_tables);
  940. write_end_chart();
  941. write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_HASH_TABLES_PER_CORE);
  942. write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_PER_CORE], (long long)plugin_statistics.hash_percpu);
  943. write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_UNIQUE], (long long)plugin_statistics.hash_unique);
  944. write_end_chart();
  945. }
  946. /**
  947. * Main loop for this collector.
  948. *
  949. * @param em the structure with thread information
  950. */
  951. static void process_collector(ebpf_module_t *em)
  952. {
  953. heartbeat_t hb;
  954. heartbeat_init(&hb);
  955. int publish_global = em->global_charts;
  956. int cgroups = em->cgroup_charts;
  957. pthread_mutex_lock(&ebpf_exit_cleanup);
  958. int thread_enabled = em->enabled;
  959. process_pid_fd = process_maps[NETDATA_PROCESS_PID_TABLE].map_fd;
  960. pthread_mutex_unlock(&ebpf_exit_cleanup);
  961. if (cgroups)
  962. ebpf_process_update_cgroup_algorithm();
  963. int update_every = em->update_every;
  964. int counter = update_every - 1;
  965. int maps_per_core = em->maps_per_core;
  966. while (!ebpf_exit_plugin) {
  967. usec_t dt = heartbeat_next(&hb, USEC_PER_SEC);
  968. (void)dt;
  969. if (ebpf_exit_plugin)
  970. break;
  971. if (++counter == update_every) {
  972. counter = 0;
  973. ebpf_read_process_hash_global_tables(maps_per_core);
  974. netdata_apps_integration_flags_t apps_enabled = em->apps_charts;
  975. pthread_mutex_lock(&collect_data_mutex);
  976. if (ebpf_all_pids_count > 0) {
  977. if (cgroups && shm_ebpf_cgroup.header) {
  978. ebpf_update_process_cgroup(maps_per_core);
  979. }
  980. }
  981. pthread_mutex_lock(&lock);
  982. ebpf_send_statistic_data();
  983. if (thread_enabled == NETDATA_THREAD_EBPF_RUNNING) {
  984. if (publish_global) {
  985. ebpf_process_send_data(em);
  986. }
  987. if (apps_enabled & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
  988. ebpf_process_send_apps_data(apps_groups_root_target, em);
  989. }
  990. #ifdef NETDATA_DEV_MODE
  991. if (ebpf_aral_process_stat)
  992. ebpf_send_data_aral_chart(ebpf_aral_process_stat, em);
  993. #endif
  994. if (cgroups && shm_ebpf_cgroup.header) {
  995. ebpf_process_send_cgroup_data(em);
  996. }
  997. }
  998. pthread_mutex_unlock(&lock);
  999. pthread_mutex_unlock(&collect_data_mutex);
  1000. }
  1001. fflush(stdout);
  1002. }
  1003. }
  1004. /*****************************************************************
  1005. *
  1006. * FUNCTIONS TO START THREAD
  1007. *
  1008. *****************************************************************/
  1009. /**
  1010. * Allocate vectors used with this thread.
  1011. * We are not testing the return, because callocz does this and shutdown the software
  1012. * case it was not possible to allocate.
  1013. *
  1014. * @param length is the length for the vectors used inside the collector.
  1015. */
  1016. static void ebpf_process_allocate_global_vectors(size_t length)
  1017. {
  1018. memset(process_aggregated_data, 0, length * sizeof(netdata_syscall_stat_t));
  1019. memset(process_publish_aggregated, 0, length * sizeof(netdata_publish_syscall_t));
  1020. process_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
  1021. process_stat_vector = callocz(ebpf_nprocs, sizeof(ebpf_process_stat_t));
  1022. global_process_stats = callocz((size_t)pid_max, sizeof(ebpf_process_stat_t *));
  1023. }
  1024. static void change_syscalls()
  1025. {
  1026. static char *lfork = { "do_fork" };
  1027. process_id_names[NETDATA_KEY_PUBLISH_PROCESS_FORK] = lfork;
  1028. }
  1029. /**
  1030. * Set local variables
  1031. *
  1032. */
  1033. static void set_local_pointers()
  1034. {
  1035. if (isrh >= NETDATA_MINIMUM_RH_VERSION && isrh < NETDATA_RH_8)
  1036. change_syscalls();
  1037. }
  1038. /*****************************************************************
  1039. *
  1040. * EBPF PROCESS THREAD
  1041. *
  1042. *****************************************************************/
  1043. /**
  1044. * Enable tracepoints
  1045. *
  1046. * Enable necessary tracepoints for thread.
  1047. *
  1048. * @return It returns 0 on success and -1 otherwise
  1049. */
  1050. static int ebpf_process_enable_tracepoints()
  1051. {
  1052. int test = ebpf_is_tracepoint_enabled(tracepoint_sched_type, tracepoint_sched_process_exit);
  1053. if (test == -1)
  1054. return -1;
  1055. else if (!test) {
  1056. if (ebpf_enable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_exit))
  1057. return -1;
  1058. }
  1059. was_sched_process_exit_enabled = test;
  1060. test = ebpf_is_tracepoint_enabled(tracepoint_sched_type, tracepoint_sched_process_exec);
  1061. if (test == -1)
  1062. return -1;
  1063. else if (!test) {
  1064. if (ebpf_enable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_exec))
  1065. return -1;
  1066. }
  1067. was_sched_process_exec_enabled = test;
  1068. test = ebpf_is_tracepoint_enabled(tracepoint_sched_type, tracepoint_sched_process_fork);
  1069. if (test == -1)
  1070. return -1;
  1071. else if (!test) {
  1072. if (ebpf_enable_tracing_values(tracepoint_sched_type, tracepoint_sched_process_fork))
  1073. return -1;
  1074. }
  1075. was_sched_process_fork_enabled = test;
  1076. return 0;
  1077. }
  1078. /**
  1079. * Process thread
  1080. *
  1081. * Thread used to generate process charts.
  1082. *
  1083. * @param ptr a pointer to `struct ebpf_module`
  1084. *
  1085. * @return It always return NULL
  1086. */
  1087. void *ebpf_process_thread(void *ptr)
  1088. {
  1089. netdata_thread_cleanup_push(ebpf_process_exit, ptr);
  1090. ebpf_module_t *em = (ebpf_module_t *)ptr;
  1091. em->maps = process_maps;
  1092. pthread_mutex_lock(&ebpf_exit_cleanup);
  1093. if (ebpf_process_enable_tracepoints()) {
  1094. em->enabled = em->global_charts = em->apps_charts = em->cgroup_charts = NETDATA_THREAD_EBPF_STOPPING;
  1095. }
  1096. process_enabled = em->enabled;
  1097. pthread_mutex_unlock(&ebpf_exit_cleanup);
  1098. pthread_mutex_lock(&lock);
  1099. ebpf_process_allocate_global_vectors(NETDATA_KEY_PUBLISH_PROCESS_END);
  1100. ebpf_update_pid_table(&process_maps[0], em);
  1101. set_local_pointers();
  1102. em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
  1103. if (!em->probe_links) {
  1104. em->enabled = em->global_charts = em->apps_charts = em->cgroup_charts = NETDATA_THREAD_EBPF_STOPPING;
  1105. }
  1106. int algorithms[NETDATA_KEY_PUBLISH_PROCESS_END] = {
  1107. NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX
  1108. };
  1109. ebpf_global_labels(
  1110. process_aggregated_data, process_publish_aggregated, process_dimension_names, process_id_names,
  1111. algorithms, NETDATA_KEY_PUBLISH_PROCESS_END);
  1112. if (process_enabled == NETDATA_THREAD_EBPF_RUNNING) {
  1113. ebpf_create_global_charts(em);
  1114. }
  1115. ebpf_update_stats(&plugin_statistics, em);
  1116. ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
  1117. #ifdef NETDATA_DEV_MODE
  1118. if (ebpf_aral_process_stat)
  1119. ebpf_statistic_create_aral_chart(NETDATA_EBPF_PROC_ARAL_NAME, em);
  1120. #endif
  1121. ebpf_create_statistic_charts(em);
  1122. pthread_mutex_unlock(&lock);
  1123. process_collector(em);
  1124. pthread_mutex_lock(&ebpf_exit_cleanup);
  1125. if (em->enabled == NETDATA_THREAD_EBPF_RUNNING)
  1126. ebpf_update_disabled_plugin_stats(em);
  1127. pthread_mutex_unlock(&ebpf_exit_cleanup);
  1128. netdata_thread_cleanup_pop(1);
  1129. return NULL;
  1130. }