ebpf_process.c 53 KB

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