ebpf_process.c 46 KB

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