ebpf_process.c 50 KB

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