ebpf_process.c 45 KB

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