@cryptotaxi247 / netdata-1 / commits / dbc8fefd5

eBPF and cgroup (process, file descriptor, VFS, directory cache and OOMkill) (#11611)

thiagoftsm committed Oct 8, 2021 at 13:07 UTC dbc8fefd54ed9381537f2febbf714ce9ff121feb
17 files changed +2129 -88
collectors/ebpf.plugin/ebpf.h
+1
@@ -117,6 +117,7 @@ typedef struct ebpf_tracepoint {
117 #define NETDATA_EBPF_MEMORY_GROUP "mem"
118 #define NETDATA_EBPF_SYSTEM_GROUP "system"
119 #define NETDATA_SYSTEM_SWAP_SUBMENU "swap"
120 +#define NETDATA_SYSTEM_CGROUP_SWAP_SUBMENU "swap (eBPF)"
121 #define NETDATA_SYSTEM_IPC_SHM_SUBMENU "ipc shared memory"
122
123 // Log file
collectors/ebpf.plugin/ebpf_apps.h
+1 -4
@@ -12,6 +12,7 @@
12
13 #define NETDATA_APPS_FAMILY "apps"
14 #define NETDATA_APPS_FILE_GROUP "file_access"
15 +#define NETDATA_APPS_FILE_CGROUP_GROUP "file_access (eBPF)"
16 #define NETDATA_APPS_PROCESS_GROUP "process (eBPF)"
17 #define NETDATA_APPS_NET_GROUP "net"
18 #define NETDATA_APPS_IPC_SHM_GROUP "ipc shared memory"
@@ -353,18 +354,14 @@ typedef struct ebpf_process_stat {
354 uint32_t pid;
355
356 //Counter
356 - uint32_t open_call;
357 uint32_t exit_call;
358 uint32_t release_call;
359 uint32_t fork_call;
360 uint32_t clone_call;
361 - uint32_t close_call;
361
362 //Counter
364 - uint32_t open_err;
363 uint32_t fork_err;
364 uint32_t clone_err;
367 - uint32_t close_err;
365
366 uint8_t removeme;
367 } ebpf_process_stat_t;
collectors/ebpf.plugin/ebpf_cgroup.c
+3 -2
@@ -330,13 +330,14 @@ void ebpf_parse_cgroup_shm_data()
330 * @param charttype chart type
331 * @param order the chart order
332 * @param algorithm the algorithm used by dimension
333 + * @param context add context for chart
334 * @param module chart module name, this is the eBPF thread.
335 */
336 void ebpf_create_charts_on_systemd(char *id, char *title, char *units, char *family, char *charttype, int order,
336 - char *algorithm, char *module)
337 + char *algorithm, char *context, char *module)
338 {
339 ebpf_cgroup_target_t *w;
339 - ebpf_write_chart_cmd(NETDATA_SERVICE_FAMILY, id, title, units, family, charttype, NULL, order, module);
340 + ebpf_write_chart_cmd(NETDATA_SERVICE_FAMILY, id, title, units, family, charttype, context, order, module);
341
342 for (w = ebpf_cgroup_pids; w; w = w->next) {
343 if (unlikely(w->systemd) && unlikely(w->updated))
collectors/ebpf.plugin/ebpf_cgroup.h
+10 -1
@@ -16,6 +16,10 @@ struct pid_on_target2 {
16 int updated;
17
18 netdata_publish_swap_t swap;
19 + netdata_fd_stat_t fd;
20 + netdata_publish_vfs_t vfs;
21 + ebpf_process_stat_t ps;
22 + netdata_dcstat_pid_t dc;
23
24 struct pid_on_target2 *next;
25 };
@@ -40,6 +44,11 @@ typedef struct ebpf_cgroup_target {
44 uint32_t updated;
45
46 netdata_publish_swap_t publish_systemd_swap;
47 + netdata_fd_stat_t publish_systemd_fd;
48 + netdata_publish_vfs_t publish_systemd_vfs;
49 + ebpf_process_stat_t publish_systemd_ps;
50 + netdata_publish_dcstat_t publish_dc;
51 + int oomkill;
52
53 struct pid_on_target2 *pids;
54 struct ebpf_cgroup_target *next;
@@ -50,6 +59,6 @@ extern void ebpf_parse_cgroup_shm_data();
59 extern void ebpf_close_cgroup_shm();
60 extern void ebpf_clean_cgroup_pids();
61 extern void ebpf_create_charts_on_systemd(char *id, char *title, char *units, char *family, char *charttype, int order,
53 - char *algorithm, char *module);
62 + char *algorithm, char *context, char *module);
63
64 #endif /* NETDATA_EBPF_CGROUP_H */
collectors/ebpf.plugin/ebpf_dcstat.c
+355
@@ -285,6 +285,43 @@ static void read_apps_table()
285 }
286 }
287
288 +/**
289 + * Update cgroup
290 + *
291 + * Update cgroup data based in
292 + */
293 +static void ebpf_update_dc_cgroup()
294 +{
295 + netdata_dcstat_pid_t *cv = dcstat_vector;
296 + int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
297 + size_t length = sizeof(netdata_dcstat_pid_t)*ebpf_nprocs;
298 +
299 + ebpf_cgroup_target_t *ect;
300 + pthread_mutex_lock(&mutex_cgroup_shm);
301 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
302 + struct pid_on_target2 *pids;
303 + for (pids = ect->pids; pids; pids = pids->next) {
304 + int pid = pids->pid;
305 + netdata_dcstat_pid_t *out = &pids->dc;
306 + if (dcstat_pid[pid]) {
307 + netdata_publish_dcstat_t *in = dcstat_pid[pid];
308 +
309 + memcpy(out, &in->curr, sizeof(netdata_dcstat_pid_t));
310 + } else {
311 + memset(cv, 0, length);
312 + if (bpf_map_lookup_elem(fd, &pid, cv)) {
313 + continue;
314 + }
315 +
316 + dcstat_apps_accumulator(cv);
317 +
318 + memcpy(out, cv, sizeof(netdata_dcstat_pid_t));
319 + }
320 + }
321 + }
322 + pthread_mutex_unlock(&mutex_cgroup_shm);
323 +}
324 +
325 /**
326 * Read global table
327 *
@@ -474,6 +511,317 @@ static void dcstat_send_global(netdata_publish_dcstat_t *publish)
511 &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 3);
512 }
513
514 +/**
515 + * Create specific directory cache charts
516 + *
517 + * Create charts for cgroup/application.
518 + *
519 + * @param type the chart type.
520 + */
521 +static void ebpf_create_specific_dc_charts(char *type)
522 +{
523 + ebpf_create_chart(type, NETDATA_DC_HIT_CHART, "Percentage of files listed inside directory cache.",
524 + EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
525 + NETDATA_CGROUP_DC_HIT_RATIO_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
526 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5700,
527 + ebpf_create_global_dimension,
528 + dcstat_counter_publish_aggregated, 1, NETDATA_EBPF_MODULE_NAME_DCSTAT);
529 +
530 + ebpf_create_chart(type, NETDATA_DC_REFERENCE_CHART, "Count file access.",
531 + EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
532 + NETDATA_CGROUP_DC_REFERENCE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
533 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5701,
534 + ebpf_create_global_dimension,
535 + &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 1,
536 + NETDATA_EBPF_MODULE_NAME_DCSTAT);
537 +
538 + ebpf_create_chart(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART,
539 + "Access to files that were not present inside directory cache.",
540 + EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
541 + NETDATA_CGROUP_DC_NOT_CACHE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
542 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5702,
543 + ebpf_create_global_dimension,
544 + &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_SLOW], 1,
545 + NETDATA_EBPF_MODULE_NAME_DCSTAT);
546 +
547 + ebpf_create_chart(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART,
548 + "Number of requests for files that were not found on filesystem.",
549 + EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
550 + NETDATA_CGROUP_DC_NOT_FOUND_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
551 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5703,
552 + ebpf_create_global_dimension,
553 + &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_MISS], 1,
554 + NETDATA_EBPF_MODULE_NAME_DCSTAT);
555 +}
556 +
557 +/**
558 + * Obsolete specific directory cache charts
559 + *
560 + * Obsolete charts for cgroup/application.
561 + *
562 + * @param type the chart type.
563 + */
564 +static void ebpf_obsolete_specific_dc_charts(char *type)
565 +{
566 + ebpf_write_chart_obsolete(type, NETDATA_DC_HIT_CHART,
567 + "Percentage of files listed inside directory cache.",
568 + EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
569 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_HIT_RATIO_CONTEXT,
570 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5700);
571 +
572 + ebpf_write_chart_obsolete(type, NETDATA_DC_REFERENCE_CHART,
573 + "Count file access.",
574 + EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
575 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_REFERENCE_CONTEXT,
576 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5701);
577 +
578 + ebpf_write_chart_obsolete(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART,
579 + "Access to files that were not present inside directory cache.",
580 + EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
581 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_NOT_CACHE_CONTEXT,
582 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5702);
583 +
584 + ebpf_write_chart_obsolete(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART,
585 + "Number of requests for files that were not found on filesystem.",
586 + EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
587 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_NOT_FOUND_CONTEXT,
588 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5703);
589 +}
590 +
591 +/**
592 + * Cachestat sum PIDs
593 + *
594 + * Sum values for all PIDs associated to a group
595 + *
596 + * @param publish output structure.
597 + * @param root structure with listed IPs
598 + */
599 +void ebpf_dc_sum_cgroup_pids(netdata_publish_dcstat_t *publish, struct pid_on_target2 *root)
600 +{
601 + memset(&publish->curr, 0, sizeof(netdata_dcstat_pid_t));
602 + netdata_dcstat_pid_t *dst = &publish->curr;
603 + while (root) {
604 + int32_t pid = root->pid;
605 + netdata_publish_dcstat_t *w = dcstat_pid[pid];
606 + if (w) {
607 + netdata_dcstat_pid_t *src = &w->curr;
608 + dst->cache_access += src->cache_access;
609 + dst->file_system += src->file_system;
610 + dst->not_found += src->not_found;
611 + }
612 +
613 + root = root->next;
614 + }
615 +}
616 +
617 +/**
618 + * Calc chart values
619 + *
620 + * Do necessary math to plot charts.
621 + */
622 +void ebpf_dc_calc_chart_values()
623 +{
624 + ebpf_cgroup_target_t *ect;
625 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
626 + ebpf_dc_sum_cgroup_pids(&ect->publish_dc, ect->pids);
627 + uint64_t cache = ect->publish_dc.curr.cache_access;
628 + uint64_t not_found = ect->publish_dc.curr.not_found;
629 +
630 + dcstat_update_publish(&ect->publish_dc, cache, not_found);
631 +
632 + ect->publish_dc.cache_access = (long long)ect->publish_dc.curr.cache_access -
633 + (long long)ect->publish_dc.prev.cache_access;
634 + ect->publish_dc.prev.cache_access = ect->publish_dc.curr.cache_access;
635 +
636 + if (ect->publish_dc.curr.not_found < ect->publish_dc.prev.not_found) {
637 + ect->publish_dc.prev.not_found = 0;
638 + }
639 + }
640 +}
641 +
642 +/**
643 + * Create Systemd directory cache Charts
644 + *
645 + * Create charts when systemd is enabled
646 + **/
647 +static void ebpf_create_systemd_dc_charts()
648 +{
649 + ebpf_create_charts_on_systemd(NETDATA_DC_HIT_CHART,
650 + "Percentage of files listed inside directory cache.",
651 + EBPF_COMMON_DIMENSION_PERCENTAGE,
652 + NETDATA_DIRECTORY_CACHE_SUBMENU,
653 + NETDATA_EBPF_CHART_TYPE_LINE,
654 + 21200,
655 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
656 + NETDATA_SYSTEMD_DC_HIT_RATIO_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT);
657 +
658 + ebpf_create_charts_on_systemd(NETDATA_DC_REFERENCE_CHART,
659 + "Count file access.",
660 + EBPF_COMMON_DIMENSION_FILES,
661 + NETDATA_DIRECTORY_CACHE_SUBMENU,
662 + NETDATA_EBPF_CHART_TYPE_LINE,
663 + 21201,
664 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
665 + NETDATA_SYSTEMD_DC_REFERENCE_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT);
666 +
667 + ebpf_create_charts_on_systemd(NETDATA_DC_REQUEST_NOT_CACHE_CHART,
668 + "Access to files that were not present inside directory cache.",
669 + EBPF_COMMON_DIMENSION_FILES,
670 + NETDATA_DIRECTORY_CACHE_SUBMENU,
671 + NETDATA_EBPF_CHART_TYPE_LINE,
672 + 21202,
673 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
674 + NETDATA_SYSTEMD_DC_NOT_CACHE_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT);
675 +
676 + ebpf_create_charts_on_systemd(NETDATA_DC_REQUEST_NOT_FOUND_CHART,
677 + "Number of requests for files that were not found on filesystem.",
678 + EBPF_COMMON_DIMENSION_FILES,
679 + NETDATA_DIRECTORY_CACHE_SUBMENU,
680 + NETDATA_EBPF_CHART_TYPE_LINE,
681 + 21202,
682 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
683 + NETDATA_SYSTEMD_DC_NOT_FOUND_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT);
684 +}
685 +
686 +/**
687 + * Send Directory Cache charts
688 + *
689 + * Send collected data to Netdata.
690 + *
691 + * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
692 + * otherwise function returns 1 to avoid chart recreation
693 + */
694 +static int ebpf_send_systemd_dc_charts()
695 +{
696 + int ret = 1;
697 + collected_number value;
698 + ebpf_cgroup_target_t *ect;
699 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_HIT_CHART);
700 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
701 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
702 + write_chart_dimension(ect->name, (long long) ect->publish_dc.ratio);
703 + } else
704 + ret = 0;
705 + }
706 + write_end_chart();
707 +
708 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REFERENCE_CHART);
709 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
710 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
711 + write_chart_dimension(ect->name, (long long) ect->publish_dc.cache_access);
712 + }
713 + }
714 + write_end_chart();
715 +
716 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REQUEST_NOT_CACHE_CHART);
717 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
718 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
719 + value = (collected_number) (!ect->publish_dc.cache_access) ? 0 :
720 + (long long )ect->publish_dc.curr.file_system - (long long)ect->publish_dc.prev.file_system;
721 + ect->publish_dc.prev.file_system = ect->publish_dc.curr.file_system;
722 +
723 + write_chart_dimension(ect->name, (long long) value);
724 + }
725 + }
726 + write_end_chart();
727 +
728 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REQUEST_NOT_FOUND_CHART);
729 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
730 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
731 + value = (collected_number) (!ect->publish_dc.cache_access) ? 0 :
732 + (long long)ect->publish_dc.curr.not_found - (long long)ect->publish_dc.prev.not_found;
733 +
734 + ect->publish_dc.prev.not_found = ect->publish_dc.curr.not_found;
735 +
736 + write_chart_dimension(ect->name, (long long) value);
737 + }
738 + }
739 + write_end_chart();
740 +
741 + return ret;
742 +}
743 +
744 +/**
745 + * Send Directory Cache charts
746 + *
747 + * Send collected data to Netdata.
748 + *
749 + */
750 +static void ebpf_send_specific_dc_data(char *type, netdata_publish_dcstat_t *pdc)
751 +{
752 + collected_number value;
753 + write_begin_chart(type, NETDATA_DC_HIT_CHART);
754 + write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_RATIO].name,
755 + (long long) pdc->ratio);
756 + write_end_chart();
757 +
758 + write_begin_chart(type, NETDATA_DC_REFERENCE_CHART);
759 + write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE].name,
760 + (long long) pdc->cache_access);
761 + write_end_chart();
762 +
763 + value = (collected_number) (!pdc->cache_access) ? 0 :
764 + (long long )pdc->curr.file_system - (long long)pdc->prev.file_system;
765 + pdc->prev.file_system = pdc->curr.file_system;
766 +
767 + write_begin_chart(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART);
768 + write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_SLOW].name, (long long) value);
769 + write_end_chart();
770 +
771 + value = (collected_number) (!pdc->cache_access) ? 0 :
772 + (long long)pdc->curr.not_found - (long long)pdc->prev.not_found;
773 + pdc->prev.not_found = pdc->curr.not_found;
774 +
775 + write_begin_chart(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART);
776 + write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_MISS].name, (long long) value);
777 + write_end_chart();
778 +}
779 +
780 +/**
781 + * Send data to Netdata calling auxiliar functions.
782 +*/
783 +void ebpf_dc_send_cgroup_data()
784 +{
785 + if (!ebpf_cgroup_pids)
786 + return;
787 +
788 + pthread_mutex_lock(&mutex_cgroup_shm);
789 + ebpf_cgroup_target_t *ect;
790 + ebpf_dc_calc_chart_values();
791 +
792 + int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
793 + if (has_systemd) {
794 + static int systemd_charts = 0;
795 + if (!systemd_charts) {
796 + ebpf_create_systemd_dc_charts();
797 + systemd_charts = 1;
798 + }
799 +
800 + systemd_charts = ebpf_send_systemd_dc_charts();
801 + }
802 +
803 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
804 + if (ect->systemd)
805 + continue;
806 +
807 + if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_DC_CHART) && ect->updated) {
808 + ebpf_create_specific_dc_charts(ect->name);
809 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_DC_CHART;
810 + }
811 +
812 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_DC_CHART) {
813 + if (ect->updated) {
814 + ebpf_send_specific_dc_data(ect->name, &ect->publish_dc);
815 + } else {
816 + ebpf_obsolete_specific_dc_charts(ect->name);
817 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_DC_CHART;
818 + }
819 + }
820 + }
821 +
822 + pthread_mutex_unlock(&mutex_cgroup_shm);
823 +}
824 +
825 /**
826 * Main loop for this collector.
827 */
@@ -488,6 +836,7 @@ static void dcstat_collector(ebpf_module_t *em)
836 netdata_publish_dcstat_t publish;
837 memset(&publish, 0, sizeof(publish));
838 int apps = em->apps_charts;
839 + int cgroups = em->cgroup_charts;
840 while (!close_ebpf_plugin) {
841 pthread_mutex_lock(&collect_data_mutex);
842 pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
@@ -495,6 +844,9 @@ static void dcstat_collector(ebpf_module_t *em)
844 if (apps)
845 read_apps_table();
846
847 + if (cgroups)
848 + ebpf_update_dc_cgroup();
849 +
850 pthread_mutex_lock(&lock);
851
852 dcstat_send_global(&publish);
@@ -502,6 +854,9 @@ static void dcstat_collector(ebpf_module_t *em)
854 if (apps)
855 ebpf_dcache_send_apps_data(apps_groups_root_target);
856
857 + if (cgroups)
858 + ebpf_dc_send_cgroup_data();
859 +
860 pthread_mutex_unlock(&lock);
861 pthread_mutex_unlock(&collect_data_mutex);
862 }
collectors/ebpf.plugin/ebpf_dcstat.h
+11
@@ -17,6 +17,17 @@
17 // configuration file
18 #define NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE "dcstat.conf"
19
20 +// Contexts
21 +#define NETDATA_CGROUP_DC_HIT_RATIO_CONTEXT "cgroup.dc_ratio"
22 +#define NETDATA_CGROUP_DC_REFERENCE_CONTEXT "cgroup.dc_reference"
23 +#define NETDATA_CGROUP_DC_NOT_CACHE_CONTEXT "cgroup.dc_not_cache"
24 +#define NETDATA_CGROUP_DC_NOT_FOUND_CONTEXT "cgroup.dc_not_found"
25 +
26 +#define NETDATA_SYSTEMD_DC_HIT_RATIO_CONTEXT "services.dc_ratio"
27 +#define NETDATA_SYSTEMD_DC_REFERENCE_CONTEXT "services.dc_reference"
28 +#define NETDATA_SYSTEMD_DC_NOT_CACHE_CONTEXT "services.dc_not_cache"
29 +#define NETDATA_SYSTEMD_DC_NOT_FOUND_CONTEXT "services.dc_not_found"
30 +
31 #define NETDATA_LATENCY_DCSTAT_SLEEP_MS 700000ULL
32
33 enum directory_cache_indexes {
collectors/ebpf.plugin/ebpf_fd.c
+328
@@ -249,6 +249,41 @@ static void read_apps_table()
249 }
250 }
251
252 +/**
253 + * Update cgroup
254 + *
255 + * Update cgroup data based in
256 + */
257 +static void ebpf_update_fd_cgroup()
258 +{
259 + ebpf_cgroup_target_t *ect ;
260 + netdata_fd_stat_t *fv = fd_vector;
261 + int fd = fd_maps[NETDATA_FD_PID_STATS].map_fd;
262 + size_t length = sizeof(netdata_fd_stat_t) * ebpf_nprocs;
263 +
264 + pthread_mutex_lock(&mutex_cgroup_shm);
265 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
266 + struct pid_on_target2 *pids;
267 + for (pids = ect->pids; pids; pids = pids->next) {
268 + int pid = pids->pid;
269 + netdata_fd_stat_t *out = &pids->fd;
270 + if (fd_pid[pid]) {
271 + netdata_fd_stat_t *in = fd_pid[pid];
272 +
273 + memcpy(out, in, sizeof(netdata_fd_stat_t));
274 + } else {
275 + memset(fv, 0, length);
276 + if (!bpf_map_lookup_elem(fd, &pid, fv)) {
277 + fd_apps_accumulator(fv);
278 +
279 + memcpy(out, fv, sizeof(netdata_publish_swap_t));
280 + }
281 + }
282 + }
283 + }
284 + pthread_mutex_unlock(&mutex_cgroup_shm);
285 +}
286 +
287 /**
288 * Sum PIDs
289 *
@@ -336,6 +371,292 @@ void ebpf_fd_send_apps_data(ebpf_module_t *em, struct target *root)
371 }
372 }
373
374 +/**
375 + * Sum PIDs
376 + *
377 + * Sum values for all targets.
378 + *
379 + * @param fd structure used to store data
380 + * @param pids input data
381 + */
382 +static void ebpf_fd_sum_cgroup_pids(netdata_fd_stat_t *fd, struct pid_on_target2 *pids)
383 +{
384 + netdata_fd_stat_t accumulator;
385 + memset(&accumulator, 0, sizeof(accumulator));
386 +
387 + while (pids) {
388 + netdata_fd_stat_t *w = &pids->fd;
389 +
390 + accumulator.open_err += w->open_err;
391 + accumulator.open_call += w->open_call;
392 + accumulator.close_call += w->close_call;
393 + accumulator.close_err += w->close_err;
394 +
395 + pids = pids->next;
396 + }
397 +
398 + fd->open_call = (accumulator.open_call >= fd->open_call) ? accumulator.open_call : fd->open_call;
399 + fd->open_err = (accumulator.open_err >= fd->open_err) ? accumulator.open_err : fd->open_err;
400 + fd->close_call = (accumulator.close_call >= fd->close_call) ? accumulator.close_call : fd->close_call;
401 + fd->close_err = (accumulator.close_err >= fd->close_err) ? accumulator.close_err : fd->close_err;
402 +}
403 +
404 +/**
405 + * Create specific file descriptor charts
406 + *
407 + * Create charts for cgroup/application.
408 + *
409 + * @param type the chart type.
410 + * @param em the main thread structure.
411 + */
412 +static void ebpf_create_specific_fd_charts(char *type, ebpf_module_t *em)
413 +{
414 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN, "Number of open files",
415 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
416 + NETDATA_CGROUP_FD_OPEN_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
417 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5400,
418 + ebpf_create_global_dimension,
419 + &fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN],
420 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
421 +
422 + if (em->mode < MODE_ENTRY) {
423 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR, "Fails to open files",
424 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
425 + NETDATA_CGROUP_FD_OPEN_ERR_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
426 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5401,
427 + ebpf_create_global_dimension,
428 + &fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN],
429 + 1,
430 + NETDATA_EBPF_MODULE_NAME_SWAP);
431 + }
432 +
433 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSED, "Files closed",
434 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
435 + NETDATA_CGROUP_FD_CLOSE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
436 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5402,
437 + ebpf_create_global_dimension,
438 + &fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE],
439 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
440 +
441 + if (em->mode < MODE_ENTRY) {
442 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR, "Fails to close files",
443 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
444 + NETDATA_CGROUP_FD_CLOSE_ERR_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
445 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5403,
446 + ebpf_create_global_dimension,
447 + &fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE],
448 + 1,
449 + NETDATA_EBPF_MODULE_NAME_SWAP);
450 + }
451 +}
452 +
453 +/**
454 + * Obsolete specific file descriptor charts
455 + *
456 + * Obsolete charts for cgroup/application.
457 + *
458 + * @param type the chart type.
459 + * @param em the main thread structure.
460 + */
461 +static void ebpf_obsolete_specific_fd_charts(char *type, ebpf_module_t *em)
462 +{
463 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_OPEN, "Number of open files",
464 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
465 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_OPEN_CONTEXT,
466 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5400);
467 +
468 + if (em->mode < MODE_ENTRY) {
469 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR, "Fails to open files",
470 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
471 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_OPEN_ERR_CONTEXT,
472 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5401);
473 + }
474 +
475 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_CLOSED, "Files closed",
476 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
477 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_CLOSE_CONTEXT,
478 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5402);
479 +
480 + if (em->mode < MODE_ENTRY) {
481 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR, "Fails to close files",
482 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
483 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_CLOSE_ERR_CONTEXT,
484 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5403);
485 + }
486 +}
487 +
488 +/*
489 + * Send specific file descriptor data
490 + *
491 + * Send data for specific cgroup/apps.
492 + *
493 + * @param type chart type
494 + * @param values structure with values that will be sent to netdata
495 + */
496 +static void ebpf_send_specific_fd_data(char *type, netdata_fd_stat_t *values, ebpf_module_t *em)
497 +{
498 + write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN);
499 + write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].name, (long long)values->open_call);
500 + write_end_chart();
501 +
502 + if (em->mode < MODE_ENTRY) {
503 + write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
504 + write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].name, (long long)values->open_err);
505 + write_end_chart();
506 + }
507 +
508 + write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSED);
509 + write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].name, (long long)values->close_call);
510 + write_end_chart();
511 +
512 + if (em->mode < MODE_ENTRY) {
513 + write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
514 + write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].name, (long long)values->close_err);
515 + write_end_chart();
516 + }
517 +}
518 +
519 +/**
520 + * Create systemd file descriptor charts
521 + *
522 + * Create charts when systemd is enabled
523 + *
524 + * @param em the main collector structure
525 + **/
526 +static void ebpf_create_systemd_fd_charts(ebpf_module_t *em)
527 +{
528 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_OPEN, "Number of open files",
529 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
530 + NETDATA_EBPF_CHART_TYPE_STACKED, 20061,
531 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_OPEN_CONTEXT,
532 + NETDATA_EBPF_MODULE_NAME_PROCESS);
533 +
534 + if (em->mode < MODE_ENTRY) {
535 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR, "Fails to open files",
536 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
537 + NETDATA_EBPF_CHART_TYPE_STACKED, 20062,
538 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_OPEN_ERR_CONTEXT,
539 + NETDATA_EBPF_MODULE_NAME_PROCESS);
540 + }
541 +
542 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_CLOSED, "Files closed",
543 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
544 + NETDATA_EBPF_CHART_TYPE_STACKED, 20063,
545 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_CLOSE_CONTEXT,
546 + NETDATA_EBPF_MODULE_NAME_PROCESS);
547 +
548 + if (em->mode < MODE_ENTRY) {
549 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR, "Fails to close files",
550 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
551 + NETDATA_EBPF_CHART_TYPE_STACKED, 20064,
552 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_CLOSE_ERR_CONTEXT,
553 + NETDATA_EBPF_MODULE_NAME_PROCESS);
554 + }
555 +}
556 +
557 +/**
558 + * Send Systemd charts
559 + *
560 + * Send collected data to Netdata.
561 + *
562 + * @param em the main collector structure
563 + *
564 + * @return It returns the status for chart creation, if it is necessary to remove a specific dimension zero is returned
565 + * otherwise function returns 1 to avoid chart recreation
566 + */
567 +static int ebpf_send_systemd_fd_charts(ebpf_module_t *em)
568 +{
569 + int ret = 1;
570 + ebpf_cgroup_target_t *ect;
571 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN);
572 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
573 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
574 + write_chart_dimension(ect->name, ect->publish_systemd_fd.open_call);
575 + } else
576 + ret = 0;
577 + }
578 + write_end_chart();
579 +
580 + if (em->mode < MODE_ENTRY) {
581 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
582 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
583 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
584 + write_chart_dimension(ect->name, ect->publish_systemd_fd.open_err);
585 + }
586 + }
587 + write_end_chart();
588 + }
589 +
590 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSED);
591 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
592 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
593 + write_chart_dimension(ect->name, ect->publish_systemd_fd.close_call);
594 + }
595 + }
596 + write_end_chart();
597 +
598 + if (em->mode < MODE_ENTRY) {
599 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
600 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
601 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
602 + write_chart_dimension(ect->name, ect->publish_systemd_fd.close_err);
603 + }
604 + }
605 + write_end_chart();
606 + }
607 +
608 + return ret;
609 +}
610 +
611 +/**
612 + * Send data to Netdata calling auxiliar functions.
613 + *
614 + * @param em the main collector structure
615 +*/
616 +static void ebpf_fd_send_cgroup_data(ebpf_module_t *em)
617 +{
618 + if (!ebpf_cgroup_pids)
619 + return;
620 +
621 + pthread_mutex_lock(&mutex_cgroup_shm);
622 + ebpf_cgroup_target_t *ect;
623 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
624 + ebpf_fd_sum_cgroup_pids(&ect->publish_systemd_fd, ect->pids);
625 + }
626 +
627 + int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
628 + if (has_systemd) {
629 + static int systemd_charts = 0;
630 + if (!systemd_charts) {
631 + ebpf_create_systemd_fd_charts(em);
632 + systemd_charts = 1;
633 + }
634 +
635 + systemd_charts = ebpf_send_systemd_fd_charts(em);
636 + }
637 +
638 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
639 + if (ect->systemd)
640 + continue;
641 +
642 + if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_FD_CHART) && ect->updated) {
643 + ebpf_create_specific_fd_charts(ect->name, em);
644 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_FD_CHART;
645 + }
646 +
647 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_FD_CHART ) {
648 + if (ect->updated) {
649 + ebpf_send_specific_fd_data(ect->name, &ect->publish_systemd_fd, em);
650 + } else {
651 + ebpf_obsolete_specific_fd_charts(ect->name, em);
652 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_FD_CHART;
653 + }
654 + }
655 + }
656 +
657 + pthread_mutex_unlock(&mutex_cgroup_shm);
658 +}
659 +
660 /**
661 * Main loop for this collector.
662 */
@@ -348,6 +669,7 @@ static void fd_collector(ebpf_module_t *em)
669 ebpf_fd_read_hash, em);
670
671 int apps = em->apps_charts;
672 + int cgroups = em->cgroup_charts;
673 while (!close_ebpf_plugin) {
674 pthread_mutex_lock(&collect_data_mutex);
675 pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
@@ -355,6 +677,9 @@ static void fd_collector(ebpf_module_t *em)
677 if (apps)
678 read_apps_table();
679
680 + if (cgroups)
681 + ebpf_update_fd_cgroup();
682 +
683 pthread_mutex_lock(&lock);
684
685 ebpf_fd_send_data(em);
@@ -362,6 +687,9 @@ static void fd_collector(ebpf_module_t *em)
687 if (apps)
688 ebpf_fd_send_apps_data(em, apps_groups_root_target);
689
690 + if (cgroups)
691 + ebpf_fd_send_cgroup_data(em);
692 +
693 pthread_mutex_unlock(&lock);
694 pthread_mutex_unlock(&collect_data_mutex);
695 }
collectors/ebpf.plugin/ebpf_fd.h
+11
@@ -24,6 +24,17 @@
24 // Process configuration name
25 #define NETDATA_FD_CONFIG_FILE "fd.conf"
26
27 +// Contexts
28 +#define NETDATA_CGROUP_FD_OPEN_CONTEXT "cgroup.fd_open"
29 +#define NETDATA_CGROUP_FD_OPEN_ERR_CONTEXT "cgroup.fd_open_error"
30 +#define NETDATA_CGROUP_FD_CLOSE_CONTEXT "cgroup.fd_close"
31 +#define NETDATA_CGROUP_FD_CLOSE_ERR_CONTEXT "cgroup.fd_close_error"
32 +
33 +#define NETDATA_SYSTEMD_FD_OPEN_CONTEXT "services.fd_open"
34 +#define NETDATA_SYSTEMD_FD_OPEN_ERR_CONTEXT "services.fd_open_error"
35 +#define NETDATA_SYSTEMD_FD_CLOSE_CONTEXT "services.fd_close"
36 +#define NETDATA_SYSTEMD_FD_CLOSE_ERR_CONTEXT "services.fd_close_error"
37 +
38 typedef struct netdata_fd_stat {
39 uint64_t pid_tgid; // Unique identifier
40 uint32_t pid; // Process ID
collectors/ebpf.plugin/ebpf_oomkill.c
+213 -31
@@ -37,6 +37,10 @@ static ebpf_tracepoint_t oomkill_tracepoints[] = {
37 static struct bpf_link **probe_links = NULL;
38 static struct bpf_object *objects = NULL;
39
40 +static netdata_publish_syscall_t oomkill_publish_aggregated = {.name = "oomkill", .dimension = "oomkill",
41 + .algorithm = "absolute",
42 + .next = NULL};
43 +
44 /**
45 * Clean up the main thread.
46 *
@@ -60,32 +64,8 @@ static void oomkill_cleanup(void *ptr)
64 }
65 }
66
63 -static void oomkill_write_data()
67 +static void oomkill_write_data(int32_t *keys, uint32_t total)
68 {
65 - // the first `i` entries of `keys` will contain the currently active PIDs
66 - // in the eBPF map.
67 - uint32_t i = 0;
68 - int32_t keys[NETDATA_OOMKILL_MAX_ENTRIES] = {0};
69 -
70 - uint32_t curr_key = 0;
71 - uint32_t key = 0;
72 - int mapfd = oomkill_maps[OOMKILL_MAP_KILLCNT].map_fd;
73 - while (bpf_map_get_next_key(mapfd, &curr_key, &key) == 0) {
74 - curr_key = key;
75 -
76 - keys[i] = key;
77 - i += 1;
78 -
79 - // delete this key now that we've recorded its existence. there's no
80 - // race here, as the same PID will only get OOM killed once.
81 - int test = bpf_map_delete_elem(mapfd, &key);
82 - if (unlikely(test < 0)) {
83 - // since there's only 1 thread doing these deletions, it should be
84 - // impossible to get this condition.
85 - error("key unexpectedly not available for deletion.");
86 - }
87 - }
88 -
69 // for each app, see if it was OOM killed. record as 1 if so otherwise 0.
70 struct target *w;
71 for (w = apps_groups_root_target; w != NULL; w = w->next) {
@@ -94,7 +74,7 @@ static void oomkill_write_data()
74 struct pid_on_target *pids = w->root_pid;
75 while (pids) {
76 uint32_t j;
97 - for (j = 0; j < i; j++) {
77 + for (j = 0; j < total; j++) {
78 if (pids->pid == keys[j]) {
79 was_oomkilled = true;
80 // set to 0 so we consider it "done".
@@ -117,7 +97,7 @@ static void oomkill_write_data()
97 // we have no choice but to dump it into `other`.
98 uint32_t j;
99 uint32_t rem_count = 0;
120 - for (j = 0; j < i; j++) {
100 + for (j = 0; j < total; j++) {
101 int32_t key = keys[j];
102 if (key != 0) {
103 rem_count += 1;
@@ -128,12 +108,207 @@ static void oomkill_write_data()
108 }
109 }
110
111 +/**
112 + * Create specific OOMkill charts
113 + *
114 + * Create charts for cgroup/application.
115 + *
116 + * @param type the chart type.
117 + */
118 +static void ebpf_create_specific_oomkill_charts(char *type)
119 +{
120 + ebpf_create_chart(type, NETDATA_OOMKILL_CHART, "OOM kills. This chart is provided by eBPF plugin.",
121 + EBPF_COMMON_DIMENSION_KILLS, NETDATA_EBPF_MEMORY_GROUP,
122 + NULL, NETDATA_EBPF_CHART_TYPE_LINE,
123 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5600,
124 + ebpf_create_global_dimension,
125 + &oomkill_publish_aggregated, 1, NETDATA_EBPF_MODULE_NAME_OOMKILL);
126 +}
127 +
128 +/**
129 + * Create Systemd OOMkill Charts
130 + *
131 + * Create charts when systemd is enabled
132 + **/
133 +static void ebpf_create_systemd_oomkill_charts()
134 +{
135 + ebpf_create_charts_on_systemd(NETDATA_OOMKILL_CHART, "OOM kills. This chart is provided by eBPF plugin.",
136 + EBPF_COMMON_DIMENSION_KILLS, NETDATA_EBPF_MEMORY_GROUP,
137 + NETDATA_EBPF_CHART_TYPE_LINE, 20191,
138 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NULL,
139 + NETDATA_EBPF_MODULE_NAME_OOMKILL);
140 +}
141 +
142 +/**
143 + * Send Systemd charts
144 + *
145 + * Send collected data to Netdata.
146 + *
147 + * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
148 + * otherwise function returns 1 to avoid chart recreation
149 + */
150 +static int ebpf_send_systemd_oomkill_charts()
151 +{
152 + int ret = 1;
153 + ebpf_cgroup_target_t *ect;
154 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_OOMKILL_CHART);
155 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
156 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
157 + write_chart_dimension(ect->name, (long long) ect->oomkill);
158 + ect->oomkill = 0;
159 + } else
160 + ret = 0;
161 + }
162 + write_end_chart();
163 +
164 + return ret;
165 +}
166 +
167 +/*
168 + * Send Specific OOMkill data
169 + *
170 + * Send data for specific cgroup/apps.
171 + *
172 + * @param type chart type
173 + * @param value value for oomkill
174 + */
175 +static void ebpf_send_specific_oomkill_data(char *type, int value)
176 +{
177 + write_begin_chart(type, NETDATA_OOMKILL_CHART);
178 + write_chart_dimension(oomkill_publish_aggregated.name, (long long)value);
179 + write_end_chart();
180 +}
181 +
182 +/**
183 + * Create specific OOMkill charts
184 + *
185 + * Create charts for cgroup/application.
186 + *
187 + * @param type the chart type.
188 + */
189 +static void ebpf_obsolete_specific_oomkill_charts(char *type)
190 +{
191 + ebpf_write_chart_obsolete(type, NETDATA_OOMKILL_CHART, "OOM kills. This chart is provided by eBPF plugin.",
192 + EBPF_COMMON_DIMENSION_KILLS, NETDATA_EBPF_MEMORY_GROUP,
193 + NETDATA_EBPF_CHART_TYPE_LINE, NULL,
194 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5600);
195 +}
196 +
197 +/**
198 + * Send data to Netdata calling auxiliar functions.
199 + *
200 + * @param root the target list.
201 +*/
202 +void ebpf_oomkill_send_cgroup_data()
203 +{
204 + if (!ebpf_cgroup_pids)
205 + return;
206 +
207 + pthread_mutex_lock(&mutex_cgroup_shm);
208 + ebpf_cgroup_target_t *ect;
209 +
210 + int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
211 + if (has_systemd) {
212 + static int systemd_charts = 0;
213 + if (!systemd_charts) {
214 + ebpf_create_systemd_oomkill_charts();
215 + systemd_charts = 1;
216 + }
217 + systemd_charts = ebpf_send_systemd_oomkill_charts();
218 + }
219 +
220 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
221 + if (ect->systemd)
222 + continue;
223 +
224 + if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_OOMKILL_CHART) && ect->updated) {
225 + ebpf_create_specific_oomkill_charts(ect->name);
226 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_OOMKILL_CHART;
227 + }
228 +
229 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_OOMKILL_CHART && ect->updated) {
230 + ebpf_send_specific_oomkill_data(ect->name, ect->oomkill);
231 + } else {
232 + ebpf_obsolete_specific_oomkill_charts(ect->name);
233 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_OOMKILL_CHART;
234 + }
235 + }
236 +
237 + pthread_mutex_unlock(&mutex_cgroup_shm);
238 +}
239 +
240 +/**
241 + * Read data
242 + *
243 + * Read OOMKILL events from table.
244 + *
245 + * @param keys vector where data will be stored
246 + *
247 + * @return It returns the number of read elements
248 + */
249 +static uint32_t oomkill_read_data(int32_t *keys)
250 +{
251 + // the first `i` entries of `keys` will contain the currently active PIDs
252 + // in the eBPF map.
253 + uint32_t i = 0;
254 +
255 + uint32_t curr_key = 0;
256 + uint32_t key = 0;
257 + int mapfd = oomkill_maps[OOMKILL_MAP_KILLCNT].map_fd;
258 + while (bpf_map_get_next_key(mapfd, &curr_key, &key) == 0) {
259 + curr_key = key;
260 +
261 + keys[i] = (int32_t)key;
262 + i += 1;
263 +
264 + // delete this key now that we've recorded its existence. there's no
265 + // race here, as the same PID will only get OOM killed once.
266 + int test = bpf_map_delete_elem(mapfd, &key);
267 + if (unlikely(test < 0)) {
268 + // since there's only 1 thread doing these deletions, it should be
269 + // impossible to get this condition.
270 + error("key unexpectedly not available for deletion.");
271 + }
272 + }
273 +
274 + return i;
275 +}
276 +
277 +/**
278 + * Update cgroup
279 + *
280 + * Update cgroup data based in
281 + *
282 + * @param keys vector with pids that had oomkill event
283 + * @param total number of elements in keys vector.
284 + */
285 +static void ebpf_update_oomkill_cgroup(int32_t *keys, uint32_t total)
286 +{
287 + ebpf_cgroup_target_t *ect;
288 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
289 + ect->oomkill = 0;
290 + struct pid_on_target2 *pids;
291 + for (pids = ect->pids; pids; pids = pids->next) {
292 + uint32_t j;
293 + int32_t pid = pids->pid;
294 + for (j = 0; j < total; j++) {
295 + if (pid == keys[j]) {
296 + ect->oomkill = 1;
297 + break;
298 + }
299 + }
300 + }
301 + }
302 +}
303 +
304 /**
305 * Main loop for this collector.
306 */
307 static void oomkill_collector(ebpf_module_t *em)
308 {
136 - UNUSED(em);
309 + int cgroups = em->cgroup_charts;
310 + int32_t keys[NETDATA_OOMKILL_MAX_ENTRIES];
311 + memset(keys, 0, sizeof(keys));
312
313 // loop and read until ebpf plugin is closed.
314 while (!close_ebpf_plugin) {
@@ -141,9 +316,16 @@ static void oomkill_collector(ebpf_module_t *em)
316 pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
317 pthread_mutex_lock(&lock);
318
319 + uint32_t count = oomkill_read_data(keys);
320 + if (cgroups && count)
321 + ebpf_update_oomkill_cgroup(keys, count);
322 +
323 // write everything from the ebpf map.
145 - write_begin_chart(NETDATA_APPS_FAMILY, "oomkills");
146 - oomkill_write_data();
324 + if (cgroups)
325 + ebpf_oomkill_send_cgroup_data();
326 +
327 + write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_OOMKILL_CHART);
328 + oomkill_write_data(keys, count);
329 write_end_chart();
330
331 pthread_mutex_unlock(&lock);
@@ -163,7 +345,7 @@ void ebpf_oomkill_create_apps_charts(struct ebpf_module *em, void *ptr)
345 UNUSED(em);
346
347 struct target *root = ptr;
166 - ebpf_create_charts_on_apps("oomkills",
348 + ebpf_create_charts_on_apps(NETDATA_OOMKILL_CHART,
349 "OOM kills",
350 EBPF_COMMON_DIMENSION_KILLS,
351 "mem",
collectors/ebpf.plugin/ebpf_oomkill.h
+2
@@ -20,6 +20,8 @@ typedef uint8_t oomkill_ebpf_val_t;
20 #define NETDATA_OOMKILL_SLEEP_MS 650000ULL
21 #define NETDATA_OOMKILL_CONFIG_FILE "oomkill.conf"
22
23 +#define NETDATA_OOMKILL_CHART "oomkills"
24 +
25 extern struct config oomkill_config;
26 extern void *ebpf_oomkill_thread(void *ptr);
27 extern void ebpf_oomkill_create_apps_charts(struct ebpf_module *em, void *ptr);
collectors/ebpf.plugin/ebpf_process.c
+293 -3
@@ -289,6 +289,36 @@ static void ebpf_process_update_apps_data()
289 }
290 }
291
292 +/**
293 + * Update cgroup
294 + *
295 + * Update cgroup data based in
296 + */
297 +static void ebpf_update_process_cgroup()
298 +{
299 + ebpf_cgroup_target_t *ect ;
300 + int pid_fd = process_maps[NETDATA_PROCESS_PID_TABLE].map_fd;
301 +
302 + pthread_mutex_lock(&mutex_cgroup_shm);
303 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
304 + struct pid_on_target2 *pids;
305 + for (pids = ect->pids; pids; pids = pids->next) {
306 + int pid = pids->pid;
307 + ebpf_process_stat_t *out = &pids->ps;
308 + if (global_process_stats[pid]) {
309 + ebpf_process_stat_t *in = global_process_stats[pid];
310 +
311 + memcpy(out, in, sizeof(ebpf_process_stat_t));
312 + } else {
313 + if (bpf_map_lookup_elem(pid_fd, &pid, out)) {
314 + memset(out, 0, sizeof(ebpf_process_stat_t));
315 + }
316 + }
317 + }
318 + }
319 + pthread_mutex_unlock(&mutex_cgroup_shm);
320 +}
321 +
322 /*****************************************************************
323 *
324 * FUNCTIONS TO CREATE CHARTS
@@ -499,6 +529,252 @@ void *ebpf_cgroup_update_shm(void *ptr)
529 return NULL;
530 }
531
532 +/**
533 + * Sum PIDs
534 + *
535 + * Sum values for all targets.
536 + *
537 + * @param ps structure used to store data
538 + * @param pids input data
539 + */
540 +static void ebpf_process_sum_cgroup_pids(ebpf_process_stat_t *ps, struct pid_on_target2 *pids)
541 +{
542 + ebpf_process_stat_t accumulator;
543 + memset(&accumulator, 0, sizeof(accumulator));
544 +
545 + while (pids) {
546 + ebpf_process_stat_t *ps = &pids->ps;
547 +
548 + accumulator.exit_call += ps->exit_call;
549 + accumulator.release_call += ps->release_call;
550 + accumulator.fork_call += ps->fork_call;
551 + accumulator.clone_call += ps->clone_call;
552 +
553 + accumulator.fork_err += ps->fork_err;
554 + accumulator.clone_err += ps->clone_err;
555 +
556 + pids = pids->next;
557 + }
558 +
559 + ps->exit_call = (accumulator.exit_call >= ps->exit_call) ? accumulator.exit_call : ps->exit_call;
560 + ps->release_call = (accumulator.release_call >= ps->release_call) ? accumulator.release_call : ps->release_call;
561 + ps->fork_call = (accumulator.fork_call >= ps->fork_call) ? accumulator.fork_call : ps->fork_call;
562 + ps->clone_call = (accumulator.clone_call >= ps->clone_call) ? accumulator.clone_call : ps->clone_call;
563 +
564 + ps->fork_err = (accumulator.fork_err >= ps->fork_err) ? accumulator.fork_err : ps->fork_err;
565 + ps->clone_err = (accumulator.clone_err >= ps->clone_err) ? accumulator.clone_err : ps->clone_err;
566 +}
567 +
568 +/*
569 + * Send Specific Process data
570 + *
571 + * Send data for specific cgroup/apps.
572 + *
573 + * @param type chart type
574 + * @param values structure with values that will be sent to netdata
575 + */
576 +static void ebpf_send_specific_process_data(char *type, ebpf_process_stat_t *values)
577 +{
578 + write_begin_chart(type, NETDATA_SYSCALL_APPS_TASK_PROCESS);
579 + write_chart_dimension(process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK].name,
580 + (long long) values->fork_call);
581 + write_end_chart();
582 +
583 + write_begin_chart(type, NETDATA_SYSCALL_APPS_TASK_THREAD);
584 + write_chart_dimension(process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_CLONE].name,
585 + (long long) values->clone_call);
586 + write_end_chart();
587 +
588 + write_begin_chart(type, NETDATA_SYSCALL_APPS_TASK_CLOSE);
589 + write_chart_dimension(process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_EXIT].name,
590 + (long long) values->release_call);
591 + write_end_chart();
592 +}
593 +
594 +/**
595 + * Create specific process charts
596 + *
597 + * Create charts for cgroup/application
598 + *
599 + * @param type the chart type.
600 + */
601 +static void ebpf_create_specific_process_charts(char *type)
602 +{
603 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_TASK_PROCESS, "Process started",
604 + EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_CGROUP_GROUP,
605 + NETDATA_CGROUP_PROCESS_CREATE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
606 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5000,
607 + ebpf_create_global_dimension, &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK],
608 + 1, NETDATA_EBPF_MODULE_NAME_PROCESS);
609 +
610 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_TASK_THREAD, "Threads started",
611 + EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_CGROUP_GROUP,
612 + NETDATA_CGROUP_THREAD_CREATE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
613 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5001,
614 + ebpf_create_global_dimension,
615 + &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_CLONE],
616 + 1, NETDATA_EBPF_MODULE_NAME_PROCESS);
617 +
618 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_TASK_CLOSE, "Tasks closed",
619 + EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_CGROUP_GROUP,
620 + NETDATA_CGROUP_PROCESS_CLOSE_CONTEXT,
621 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5002,
622 + ebpf_create_global_dimension,
623 + &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_EXIT],
624 + 1, NETDATA_EBPF_MODULE_NAME_PROCESS);
625 +}
626 +
627 +/**
628 + * Obsolete specific process charts
629 + *
630 + * Obsolete charts for cgroup/application
631 + *
632 + * @param type the chart type.
633 + */
634 +static void ebpf_obsolete_specific_process_charts(char *type)
635 +{
636 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_TASK_PROCESS, "Process started",
637 + EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_GROUP, NETDATA_EBPF_CHART_TYPE_LINE,
638 + NETDATA_CGROUP_PROCESS_CREATE_CONTEXT, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5000);
639 +
640 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_TASK_THREAD, "Threads started",
641 + EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_GROUP, NETDATA_EBPF_CHART_TYPE_LINE,
642 + NETDATA_CGROUP_THREAD_CREATE_CONTEXT, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5001);
643 +
644 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_TASK_CLOSE,"Tasks closed",
645 + EBPF_COMMON_DIMENSION_CALL, NETDATA_PROCESS_GROUP, NETDATA_EBPF_CHART_TYPE_LINE,
646 + NETDATA_CGROUP_PROCESS_CLOSE_CONTEXT, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5002);
647 +}
648 +
649 +/**
650 + * Create Systemd process Charts
651 + *
652 + * Create charts when systemd is enabled
653 + **/
654 +static void ebpf_create_systemd_process_charts()
655 +{
656 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_TASK_PROCESS, "Process started",
657 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_PROCESS_GROUP,
658 + NETDATA_EBPF_CHART_TYPE_STACKED, 20065,
659 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_PROCESS_CREATE_CONTEXT,
660 + NETDATA_EBPF_MODULE_NAME_PROCESS);
661 +
662 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_TASK_THREAD, "Threads started",
663 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_PROCESS_GROUP,
664 + NETDATA_EBPF_CHART_TYPE_STACKED, 20066,
665 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_THREAD_CREATE_CONTEXT,
666 + NETDATA_EBPF_MODULE_NAME_PROCESS);
667 +
668 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_TASK_CLOSE, "Tasks closed",
669 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_PROCESS_GROUP,
670 + NETDATA_EBPF_CHART_TYPE_STACKED, 20067,
671 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_PROCESS_CLOSE_CONTEXT,
672 + NETDATA_EBPF_MODULE_NAME_PROCESS);
673 +}
674 +
675 +/**
676 + * Send Systemd charts
677 + *
678 + * Send collected data to Netdata.
679 + *
680 + * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
681 + * otherwise function returns 1 to avoid chart recreation
682 + */
683 +static int ebpf_send_systemd_process_charts()
684 +{
685 + int ret = 1;
686 + ebpf_cgroup_target_t *ect;
687 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_TASK_PROCESS);
688 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
689 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
690 + write_chart_dimension(ect->name, ect->publish_systemd_ps.fork_call);
691 + } else
692 + ret = 0;
693 + }
694 + write_end_chart();
695 +
696 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_TASK_THREAD);
697 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
698 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
699 + write_chart_dimension(ect->name, ect->publish_systemd_ps.clone_call);
700 + }
701 + }
702 + write_end_chart();
703 +
704 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_TASK_CLOSE);
705 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
706 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
707 + write_chart_dimension(ect->name, ect->publish_systemd_ps.release_call);
708 + }
709 + }
710 + write_end_chart();
711 +
712 + return ret;
713 +}
714 +
715 +/**
716 + * Send data to Netdata calling auxiliar functions.
717 +*/
718 +static void ebpf_process_send_cgroup_data()
719 +{
720 + if (!ebpf_cgroup_pids)
721 + return;
722 +
723 + pthread_mutex_lock(&mutex_cgroup_shm);
724 + ebpf_cgroup_target_t *ect;
725 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
726 + ebpf_process_sum_cgroup_pids(&ect->publish_systemd_ps, ect->pids);
727 + }
728 +
729 + int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
730 +
731 + if (has_systemd) {
732 + static int systemd_chart = 0;
733 + if (!systemd_chart) {
734 + ebpf_create_systemd_process_charts();
735 + systemd_chart = 1;
736 + }
737 +
738 + systemd_chart = ebpf_send_systemd_process_charts();
739 + }
740 +
741 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
742 + if (ect->systemd)
743 + continue;
744 +
745 + if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_PROCESS_CHART) && ect->updated) {
746 + ebpf_create_specific_process_charts(ect->name);
747 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_PROCESS_CHART;
748 + }
749 +
750 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_PROCESS_CHART) {
751 + if (ect->updated) {
752 + ebpf_send_specific_process_data(ect->name, &ect->publish_systemd_ps);
753 + } else {
754 + ebpf_obsolete_specific_process_charts(ect->name);
755 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_PROCESS_CHART;
756 + }
757 + }
758 + }
759 +
760 + pthread_mutex_unlock(&mutex_cgroup_shm);
761 +}
762 +
763 +/**
764 + * Update Cgroup algorithm
765 + *
766 + * Change algorithm from absolute to incremental
767 + */
768 +void ebpf_process_update_cgroup_algorithm()
769 +{
770 + int i;
771 + for (i = 0; i < NETDATA_KEY_PUBLISH_PROCESS_END; i++) {
772 + netdata_publish_syscall_t *ptr = &process_publish_aggregated[i];
773 + freez(ptr->algorithm);
774 + ptr->algorithm = strdupz(ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
775 + }
776 +}
777 +
778 /**
779 * Main loop for this collector.
780 *
@@ -517,6 +793,10 @@ static void process_collector(usec_t step, ebpf_module_t *em)
793 heartbeat_init(&hb);
794 int publish_global = em->global_charts;
795 int apps_enabled = em->apps_charts;
796 + int cgroups = em->cgroup_charts;
797 + if (cgroups)
798 + ebpf_process_update_cgroup_algorithm();
799 +
800 int pid_fd = process_maps[NETDATA_PROCESS_PID_TABLE].map_fd;
801 while (!close_ebpf_plugin) {
802 usec_t dt = heartbeat_next(&hb, step);
@@ -534,9 +814,15 @@ static void process_collector(usec_t step, ebpf_module_t *em)
814 pthread_mutex_unlock(&collect_data_mutex);
815
816 int publish_apps = 0;
537 - if (apps_enabled && all_pids_count > 0) {
538 - publish_apps = 1;
539 - ebpf_process_update_apps_data();
817 + if (all_pids_count > 0) {
818 + if (apps_enabled) {
819 + publish_apps = 1;
820 + ebpf_process_update_apps_data();
821 + }
822 +
823 + if (cgroups) {
824 + ebpf_update_process_cgroup();
825 + }
826 }
827
828 pthread_mutex_lock(&lock);
@@ -547,6 +833,10 @@ static void process_collector(usec_t step, ebpf_module_t *em)
833 if (publish_apps) {
834 ebpf_process_send_apps_data(apps_groups_root_target);
835 }
836 +
837 + if (cgroups) {
838 + ebpf_process_send_cgroup_data();
839 + }
840 pthread_mutex_unlock(&lock);
841
842 fflush(stdout);
collectors/ebpf.plugin/ebpf_process.h
+11 -1
@@ -7,7 +7,8 @@
7 #define NETDATA_EBPF_MODULE_NAME_PROCESS "process"
8
9 // Groups used on Dashboard
10 -#define NETDATA_PROCESS_GROUP "Process"
10 +#define NETDATA_PROCESS_GROUP "process"
11 +#define NETDATA_PROCESS_CGROUP_GROUP "process (eBPF)"
12
13 // Global chart name
14 #define NETDATA_EXIT_SYSCALL "exit"
@@ -23,6 +24,15 @@
24 // Process configuration name
25 #define NETDATA_PROCESS_CONFIG_FILE "process.conf"
26
27 +// Contexts
28 +#define NETDATA_CGROUP_PROCESS_CREATE_CONTEXT "cgroup.process_create"
29 +#define NETDATA_CGROUP_THREAD_CREATE_CONTEXT "cgroup.thread_create"
30 +#define NETDATA_CGROUP_PROCESS_CLOSE_CONTEXT "cgroup.task_close"
31 +
32 +#define NETDATA_SYSTEMD_PROCESS_CREATE_CONTEXT "services.process_create"
33 +#define NETDATA_SYSTEMD_THREAD_CREATE_CONTEXT "services.thread_create"
34 +#define NETDATA_SYSTEMD_PROCESS_CLOSE_CONTEXT "services.task_close"
35 +
36 // Index from kernel
37 typedef enum ebpf_process_index {
38 NETDATA_KEY_CALLS_DO_EXIT,
collectors/ebpf.plugin/ebpf_swap.c
+34 -36
@@ -398,18 +398,16 @@ static void ebpf_create_specific_swap_charts(char *type)
398 {
399 ebpf_create_chart(type, NETDATA_MEM_SWAP_READ_CHART,
400 "Calls to function <code>swap_readpage</code>.",
401 - EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
402 - NULL,
403 - NETDATA_EBPF_CHART_TYPE_LINE,
401 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_CGROUP_SWAP_SUBMENU,
402 + NETDATA_CGROUP_SWAP_READ_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
403 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5100,
404 ebpf_create_global_dimension,
405 swap_publish_aggregated, 1, NETDATA_EBPF_MODULE_NAME_SWAP);
406
407 ebpf_create_chart(type, NETDATA_MEM_SWAP_WRITE_CHART,
408 "Calls to function <code>swap_writepage</code>.",
410 - EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
411 - NULL,
412 - NETDATA_EBPF_CHART_TYPE_LINE,
409 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_CGROUP_SWAP_SUBMENU,
410 + NETDATA_CGROUP_SWAP_WRITE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
411 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5101,
412 ebpf_create_global_dimension,
413 &swap_publish_aggregated[NETDATA_KEY_SWAP_WRITEPAGE_CALL], 1, NETDATA_EBPF_MODULE_NAME_SWAP);
@@ -425,13 +423,13 @@ static void ebpf_create_specific_swap_charts(char *type)
423 static void ebpf_obsolete_specific_swap_charts(char *type)
424 {
425 ebpf_write_chart_obsolete(type, NETDATA_MEM_SWAP_READ_CHART,"Calls to function <code>swap_readpage</code>.",
428 - EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
429 - NETDATA_EBPF_CHART_TYPE_LINE, NULL,
426 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_CGROUP_SWAP_SUBMENU,
427 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SWAP_READ_CONTEXT,
428 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5100);
429
430 ebpf_write_chart_obsolete(type, NETDATA_MEM_SWAP_WRITE_CHART, "Calls to function <code>swap_writepage</code>.",
433 - EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_SWAP_SUBMENU,
434 - NETDATA_EBPF_CHART_TYPE_LINE,NULL,
431 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_CGROUP_SWAP_SUBMENU,
432 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SWAP_WRITE_CONTEXT,
433 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5101);
434 }
435
@@ -463,20 +461,16 @@ static void ebpf_create_systemd_swap_charts()
461 {
462 ebpf_create_charts_on_systemd(NETDATA_MEM_SWAP_READ_CHART,
463 "Calls to <code>swap_readpage</code>.",
466 - EBPF_COMMON_DIMENSION_CALL,
467 - NETDATA_SWAP_SUBMENU,
468 - NETDATA_EBPF_CHART_TYPE_STACKED,
469 - 20191,
470 - ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
464 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_CGROUP_SWAP_SUBMENU,
465 + NETDATA_EBPF_CHART_TYPE_STACKED, 20191,
466 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_SWAP_READ_CONTEXT,
467 NETDATA_EBPF_MODULE_NAME_SWAP);
468
469 ebpf_create_charts_on_systemd(NETDATA_MEM_SWAP_WRITE_CHART,
470 "Calls to function <code>swap_writepage</code>.",
475 - EBPF_COMMON_DIMENSION_CALL,
476 - NETDATA_SWAP_SUBMENU,
477 - NETDATA_EBPF_CHART_TYPE_STACKED,
478 - 20192,
479 - ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
471 + EBPF_COMMON_DIMENSION_CALL, NETDATA_SYSTEM_CGROUP_SWAP_SUBMENU,
472 + NETDATA_EBPF_CHART_TYPE_STACKED, 20192,
473 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_SWAP_WRITE_CONTEXT,
474 NETDATA_EBPF_MODULE_NAME_SWAP);
475 }
476
@@ -485,8 +479,6 @@ static void ebpf_create_systemd_swap_charts()
479 */
480 void ebpf_swap_send_cgroup_data()
481 {
488 - static int systemd_charts = 0;
489 -
482 if (!ebpf_cgroup_pids)
483 return;
484
@@ -494,31 +486,37 @@ void ebpf_swap_send_cgroup_data()
486 ebpf_cgroup_target_t *ect;
487 for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
488 ebpf_swap_sum_cgroup_pids(&ect->publish_systemd_swap, ect->pids);
497 - if (!ect->systemd && !(ect->flags & NETDATA_EBPF_CGROUP_HAS_SWAP_CHART)) {
498 - ebpf_create_specific_swap_charts(ect->name);
499 - ect->flags |= NETDATA_EBPF_CGROUP_HAS_SWAP_CHART;
500 - }
489 }
490
491 int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
492
505 - if (!systemd_charts) {
506 - if (has_systemd) {
493 + if (has_systemd) {
494 + static int systemd_charts = 0;
495 + if (!systemd_charts) {
496 ebpf_create_systemd_swap_charts();
497 + systemd_charts = 1;
498 + fflush(stdout);
499 }
509 - systemd_charts = 1;
510 - }
500
512 - if (has_systemd) {
501 systemd_charts = ebpf_send_systemd_swap_charts();
502 }
503
504 for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
517 - if (ect->flags & NETDATA_EBPF_CGROUP_HAS_SWAP_CHART && ect->updated) {
518 - ebpf_send_specific_swap_data(ect->name, &ect->publish_systemd_swap);
519 - } else {
520 - ebpf_obsolete_specific_swap_charts(ect->name);
521 - ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_SWAP_CHART;
505 + if (ect->systemd)
506 + continue;
507 +
508 + if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_SWAP_CHART) && ect->updated) {
509 + ebpf_create_specific_swap_charts(ect->name);
510 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_SWAP_CHART;
511 + }
512 +
513 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_SWAP_CHART) {
514 + if (ect->updated) {
515 + ebpf_send_specific_swap_data(ect->name, &ect->publish_systemd_swap);
516 + } else {
517 + ebpf_obsolete_specific_swap_charts(ect->name);
518 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_SWAP_CHART;
519 + }
520 }
521 }
522
collectors/ebpf.plugin/ebpf_swap.h
+6
@@ -17,6 +17,12 @@
17 // configuration file
18 #define NETDATA_DIRECTORY_SWAP_CONFIG_FILE "swap.conf"
19
20 +// Contexts
21 +#define NETDATA_CGROUP_SWAP_READ_CONTEXT "cgroup.swap_read"
22 +#define NETDATA_CGROUP_SWAP_WRITE_CONTEXT "cgroup.swap_write"
23 +#define NETDATA_SYSTEMD_SWAP_READ_CONTEXT "services.swap_read"
24 +#define NETDATA_SYSTEMD_SWAP_WRITE_CONTEXT "services.swap_write"
25 +
26 typedef struct netdata_publish_swap {
27 uint64_t read;
28 uint64_t write;
collectors/ebpf.plugin/ebpf_vfs.c
+667 -3
@@ -479,6 +479,41 @@ static void ebpf_vfs_read_apps()
479 }
480 }
481
482 +/**
483 + * Update cgroup
484 + *
485 + * Update cgroup data based in
486 + */
487 +static void read_update_vfs_cgroup()
488 +{
489 + ebpf_cgroup_target_t *ect ;
490 + netdata_publish_vfs_t *vv = vfs_vector;
491 + int fd = vfs_maps[NETDATA_VFS_PID].map_fd;
492 + size_t length = sizeof(netdata_publish_vfs_t) * ebpf_nprocs;
493 +
494 + pthread_mutex_lock(&mutex_cgroup_shm);
495 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
496 + struct pid_on_target2 *pids;
497 + for (pids = ect->pids; pids; pids = pids->next) {
498 + int pid = pids->pid;
499 + netdata_publish_vfs_t *out = &pids->vfs;
500 + if (vfs_pid[pid]) {
501 + netdata_publish_vfs_t *in = vfs_pid[pid];
502 +
503 + memcpy(out, in, sizeof(netdata_publish_vfs_t));
504 + } else {
505 + memset(vv, 0, length);
506 + if (!bpf_map_lookup_elem(fd, &pid, vv)) {
507 + vfs_apps_accumulator(vv);
508 +
509 + memcpy(out, vv, sizeof(netdata_publish_swap_t));
510 + }
511 + }
512 + }
513 + }
514 + pthread_mutex_unlock(&mutex_cgroup_shm);
515 +}
516 +
517 /**
518 * VFS read hash
519 *
@@ -511,6 +546,628 @@ void *ebpf_vfs_read_hash(void *ptr)
546 return NULL;
547 }
548
549 +/**
550 + * Sum PIDs
551 + *
552 + * Sum values for all targets.
553 + *
554 + * @param vfs structure used to store data
555 + * @param pids input data
556 + */
557 +static void ebpf_vfs_sum_cgroup_pids(netdata_publish_vfs_t *vfs, struct pid_on_target2 *pids)
558 + {
559 + netdata_publish_vfs_t accumulator;
560 + memset(&accumulator, 0, sizeof(accumulator));
561 +
562 + while (pids) {
563 + netdata_publish_vfs_t *w = &pids->vfs;
564 +
565 + accumulator.write_call += w->write_call;
566 + accumulator.writev_call += w->writev_call;
567 + accumulator.read_call += w->read_call;
568 + accumulator.readv_call += w->readv_call;
569 + accumulator.unlink_call += w->unlink_call;
570 + accumulator.fsync_call += w->fsync_call;
571 + accumulator.open_call += w->open_call;
572 + accumulator.create_call += w->create_call;
573 +
574 + accumulator.write_bytes += w->write_bytes;
575 + accumulator.writev_bytes += w->writev_bytes;
576 + accumulator.read_bytes += w->read_bytes;
577 + accumulator.readv_bytes += w->readv_bytes;
578 +
579 + accumulator.write_err += w->write_err;
580 + accumulator.writev_err += w->writev_err;
581 + accumulator.read_err += w->read_err;
582 + accumulator.readv_err += w->readv_err;
583 + accumulator.unlink_err += w->unlink_err;
584 + accumulator.fsync_err += w->fsync_err;
585 + accumulator.open_err += w->open_err;
586 + accumulator.create_err += w->create_err;
587 +
588 + pids = pids->next;
589 + }
590 +
591 + // These conditions were added, because we are using incremental algorithm
592 + vfs->write_call = (accumulator.write_call >= vfs->write_call) ? accumulator.write_call : vfs->write_call;
593 + vfs->writev_call = (accumulator.writev_call >= vfs->writev_call) ? accumulator.writev_call : vfs->writev_call;
594 + vfs->read_call = (accumulator.read_call >= vfs->read_call) ? accumulator.read_call : vfs->read_call;
595 + vfs->readv_call = (accumulator.readv_call >= vfs->readv_call) ? accumulator.readv_call : vfs->readv_call;
596 + vfs->unlink_call = (accumulator.unlink_call >= vfs->unlink_call) ? accumulator.unlink_call : vfs->unlink_call;
597 + vfs->fsync_call = (accumulator.fsync_call >= vfs->fsync_call) ? accumulator.fsync_call : vfs->fsync_call;
598 + vfs->open_call = (accumulator.open_call >= vfs->open_call) ? accumulator.open_call : vfs->open_call;
599 + vfs->create_call = (accumulator.create_call >= vfs->create_call) ? accumulator.create_call : vfs->create_call;
600 +
601 + vfs->write_bytes = (accumulator.write_bytes >= vfs->write_bytes) ? accumulator.write_bytes : vfs->write_bytes;
602 + vfs->writev_bytes = (accumulator.writev_bytes >= vfs->writev_bytes) ? accumulator.writev_bytes : vfs->writev_bytes;
603 + vfs->read_bytes = (accumulator.read_bytes >= vfs->read_bytes) ? accumulator.read_bytes : vfs->read_bytes;
604 + vfs->readv_bytes = (accumulator.readv_bytes >= vfs->readv_bytes) ? accumulator.readv_bytes : vfs->readv_bytes;
605 +
606 + vfs->write_err = (accumulator.write_err >= vfs->write_err) ? accumulator.write_err : vfs->write_err;
607 + vfs->writev_err = (accumulator.writev_err >= vfs->writev_err) ? accumulator.writev_err : vfs->writev_err;
608 + vfs->read_err = (accumulator.read_err >= vfs->read_err) ? accumulator.read_err : vfs->read_err;
609 + vfs->readv_err = (accumulator.readv_err >= vfs->readv_err) ? accumulator.readv_err : vfs->readv_err;
610 + vfs->unlink_err = (accumulator.unlink_err >= vfs->unlink_err) ? accumulator.unlink_err : vfs->unlink_err;
611 + vfs->fsync_err = (accumulator.fsync_err >= vfs->fsync_err) ? accumulator.fsync_err : vfs->fsync_err;
612 + vfs->open_err = (accumulator.open_err >= vfs->open_err) ? accumulator.open_err : vfs->open_err;
613 + vfs->create_err = (accumulator.create_err >= vfs->create_err) ? accumulator.create_err : vfs->create_err;
614 +}
615 +
616 +/**
617 + * Create specific VFS charts
618 + *
619 + * Create charts for cgroup/application.
620 + *
621 + * @param type the chart type.
622 + * @param em the main thread structure.
623 + */
624 +static void ebpf_create_specific_vfs_charts(char *type, ebpf_module_t *em)
625 +{
626 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_DELETED,"Files deleted",
627 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_UNLINK_CONTEXT,
628 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5500,
629 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK],
630 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
631 +
632 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "Write to disk",
633 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_WRITE_CONTEXT,
634 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5501,
635 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
636 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
637 +
638 + if (em->mode < MODE_ENTRY) {
639 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "Fails to write",
640 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_WRITE_ERROR_CONTEXT,
641 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5502,
642 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
643 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
644 + }
645 +
646 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "Read from disk",
647 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_READ_CONTEXT,
648 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5503,
649 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
650 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
651 +
652 + if (em->mode < MODE_ENTRY) {
653 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "Fails to read",
654 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_READ_ERROR_CONTEXT,
655 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5504,
656 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
657 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
658 + }
659 +
660 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "Bytes written on disk",
661 + EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_WRITE_BYTES_CONTEXT,
662 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5505,
663 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
664 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
665 +
666 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "Bytes read from disk",
667 + EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_READ_BYTES_CONTEXT,
668 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5506,
669 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
670 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
671 +
672 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC, "Calls for <code>vfs_fsync</code>",
673 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NULL,
674 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5507,
675 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
676 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
677 +
678 + if (em->mode < MODE_ENTRY) {
679 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "Sync error",
680 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NULL,
681 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5508,
682 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
683 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
684 + }
685 +
686 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN, "Calls for <code>vfs_open</code>",
687 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NULL,
688 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5509,
689 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
690 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
691 +
692 + if (em->mode < MODE_ENTRY) {
693 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "Open error",
694 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NULL,
695 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5510,
696 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
697 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
698 + }
699 +
700 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE, "Calls for <code>vfs_create</code>",
701 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NULL,
702 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5511,
703 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
704 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
705 +
706 + if (em->mode < MODE_ENTRY) {
707 + ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "Create error",
708 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NULL,
709 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5512,
710 + ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
711 + 1, NETDATA_EBPF_MODULE_NAME_SWAP);
712 + }
713 +}
714 +
715 +/**
716 + * Obsolete specific VFS charts
717 + *
718 + * Obsolete charts for cgroup/application.
719 + *
720 + * @param type the chart type.
721 + * @param em the main thread structure.
722 + */
723 +static void ebpf_obsolete_specific_vfs_charts(char *type, ebpf_module_t *em)
724 +{
725 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_DELETED, "Files deleted",
726 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
727 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_UNLINK_CONTEXT,
728 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5500);
729 +
730 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "Write to disk",
731 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
732 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_WRITE_CONTEXT,
733 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5501);
734 +
735 + if (em->mode < MODE_ENTRY) {
736 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "Fails to write",
737 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
738 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_WRITE_ERROR_CONTEXT,
739 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5502);
740 + }
741 +
742 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "Read from disk",
743 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
744 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_READ_CONTEXT,
745 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5503);
746 +
747 + if (em->mode < MODE_ENTRY) {
748 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "Fails to read",
749 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
750 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_READ_ERROR_CONTEXT,
751 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5504);
752 + }
753 +
754 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "Bytes written on disk",
755 + EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_GROUP,
756 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_WRITE_BYTES_CONTEXT,
757 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5505);
758 +
759 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "Bytes read from disk",
760 + EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_GROUP,
761 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_READ_BYTES_CONTEXT,
762 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5506);
763 +
764 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_FSYNC, "Calls for <code>vfs_fsync</code>",
765 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
766 + NETDATA_EBPF_CHART_TYPE_LINE, NULL,
767 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5507);
768 +
769 + if (em->mode < MODE_ENTRY) {
770 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "Sync error",
771 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
772 + NETDATA_EBPF_CHART_TYPE_LINE, NULL,
773 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5508);
774 + }
775 +
776 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_OPEN, "Calls for <code>vfs_open</code>",
777 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
778 + NETDATA_EBPF_CHART_TYPE_LINE, NULL,
779 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5509);
780 +
781 + if (em->mode < MODE_ENTRY) {
782 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "Open error",
783 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
784 + NETDATA_EBPF_CHART_TYPE_LINE, NULL,
785 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5510);
786 + }
787 +
788 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_CREATE, "Calls for <code>vfs_create</code>",
789 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
790 + NETDATA_EBPF_CHART_TYPE_LINE, NULL,
791 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5511);
792 +
793 + if (em->mode < MODE_ENTRY) {
794 + ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "Create error",
795 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
796 + NETDATA_EBPF_CHART_TYPE_LINE, NULL,
797 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5512);
798 + }
799 +}
800 +
801 +/*
802 + * Send specific VFS data
803 + *
804 + * Send data for specific cgroup/apps.
805 + *
806 + * @param type chart type
807 + * @param values structure with values that will be sent to netdata
808 + */
809 +static void ebpf_send_specific_vfs_data(char *type, netdata_publish_vfs_t *values, ebpf_module_t *em)
810 +{
811 + write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_DELETED);
812 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].name, (long long)values->unlink_call);
813 + write_end_chart();
814 +
815 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS);
816 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
817 + (long long)values->write_call + (long long)values->writev_call);
818 + write_end_chart();
819 +
820 + if (em->mode < MODE_ENTRY) {
821 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR);
822 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
823 + (long long)values->write_err + (long long)values->writev_err);
824 + write_end_chart();
825 + }
826 +
827 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS);
828 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
829 + (long long)values->read_call + (long long)values->readv_call);
830 + write_end_chart();
831 +
832 + if (em->mode < MODE_ENTRY) {
833 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR);
834 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
835 + (long long)values->read_err + (long long)values->readv_err);
836 + write_end_chart();
837 + }
838 +
839 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES);
840 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
841 + (long long)values->write_bytes + (long long)values->writev_bytes);
842 + write_end_chart();
843 +
844 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES);
845 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
846 + (long long)values->read_bytes + (long long)values->readv_bytes);
847 + write_end_chart();
848 +
849 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC);
850 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].name,
851 + (long long)values->fsync_call);
852 + write_end_chart();
853 +
854 + if (em->mode < MODE_ENTRY) {
855 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR);
856 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].name,
857 + (long long)values->fsync_err);
858 + write_end_chart();
859 + }
860 +
861 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN);
862 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].name,
863 + (long long)values->open_call);
864 + write_end_chart();
865 +
866 + if (em->mode < MODE_ENTRY) {
867 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR);
868 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].name,
869 + (long long)values->open_err);
870 + write_end_chart();
871 + }
872 +
873 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE);
874 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].name,
875 + (long long)values->create_call);
876 + write_end_chart();
877 +
878 + if (em->mode < MODE_ENTRY) {
879 + write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR);
880 + write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].name,
881 + (long long)values->create_err);
882 + write_end_chart();
883 + }
884 +}
885 +
886 +/**
887 + * Create Systemd Socket Charts
888 + *
889 + * Create charts when systemd is enabled
890 + *
891 + * @param em the main collector structure
892 + **/
893 +static void ebpf_create_systemd_vfs_charts(ebpf_module_t *em)
894 +{
895 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_DELETED, "Files deleted",
896 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
897 + NETDATA_EBPF_CHART_TYPE_STACKED, 20065,
898 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_UNLINK_CONTEXT,
899 + NETDATA_EBPF_MODULE_NAME_VFS);
900 +
901 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "Write to disk",
902 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
903 + NETDATA_EBPF_CHART_TYPE_STACKED, 20066,
904 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_WRITE_CONTEXT,
905 + NETDATA_EBPF_MODULE_NAME_VFS);
906 +
907 + if (em->mode < MODE_ENTRY) {
908 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "Fails to write",
909 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
910 + NETDATA_EBPF_CHART_TYPE_STACKED, 20067,
911 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
912 + NETDATA_SYSTEMD_VFS_WRITE_ERROR_CONTEXT, NETDATA_EBPF_MODULE_NAME_VFS);
913 + }
914 +
915 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "Read from disk",
916 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
917 + NETDATA_EBPF_CHART_TYPE_STACKED, 20068,
918 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_READ_CONTEXT,
919 + NETDATA_EBPF_MODULE_NAME_VFS);
920 +
921 + if (em->mode < MODE_ENTRY) {
922 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "Fails to read",
923 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
924 + NETDATA_EBPF_CHART_TYPE_STACKED, 20069,
925 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
926 + NETDATA_SYSTEMD_VFS_READ_ERROR_CONTEXT, NETDATA_EBPF_MODULE_NAME_VFS);
927 + }
928 +
929 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "Bytes written on disk",
930 + EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP,
931 + NETDATA_EBPF_CHART_TYPE_STACKED, 20070,
932 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_WRITE_BYTES_CONTEXT,
933 + NETDATA_EBPF_MODULE_NAME_VFS);
934 +
935 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "Bytes read from disk",
936 + EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP,
937 + NETDATA_EBPF_CHART_TYPE_STACKED, 20071,
938 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_READ_BYTES_CONTEXT,
939 + NETDATA_EBPF_MODULE_NAME_VFS);
940 +
941 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_FSYNC, "Calls to <code>vfs_fsync</code>",
942 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
943 + NETDATA_EBPF_CHART_TYPE_STACKED, 20072,
944 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NULL,
945 + NETDATA_EBPF_MODULE_NAME_VFS);
946 +
947 + if (em->mode < MODE_ENTRY) {
948 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "Sync error",
949 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
950 + NETDATA_EBPF_CHART_TYPE_STACKED, 20073,
951 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NULL,
952 + NETDATA_EBPF_MODULE_NAME_VFS);
953 + }
954 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_OPEN, "Calls to <code>vfs_open</code>",
955 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
956 + NETDATA_EBPF_CHART_TYPE_STACKED, 20074,
957 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NULL,
958 + NETDATA_EBPF_MODULE_NAME_VFS);
959 +
960 + if (em->mode < MODE_ENTRY) {
961 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "Open error",
962 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
963 + NETDATA_EBPF_CHART_TYPE_STACKED, 20075,
964 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NULL,
965 + NETDATA_EBPF_MODULE_NAME_VFS);
966 + }
967 +
968 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_CREATE, "Calls to <code>vfs_create</code>",
969 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
970 + NETDATA_EBPF_CHART_TYPE_STACKED, 20076,
971 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NULL,
972 + NETDATA_EBPF_MODULE_NAME_VFS);
973 +
974 + if (em->mode < MODE_ENTRY) {
975 + ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "Create error",
976 + EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
977 + NETDATA_EBPF_CHART_TYPE_STACKED, 20077,
978 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NULL,
979 + NETDATA_EBPF_MODULE_NAME_VFS);
980 + }
981 +}
982 +
983 +/**
984 + * Send Systemd charts
985 + *
986 + * Send collected data to Netdata.
987 + *
988 + * @param em the main collector structure
989 + *
990 + * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
991 + * otherwise function returns 1 to avoid chart recreation
992 + */
993 +static int ebpf_send_systemd_vfs_charts(ebpf_module_t *em)
994 +{
995 + int ret = 1;
996 + ebpf_cgroup_target_t *ect;
997 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_DELETED);
998 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
999 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1000 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.unlink_call);
1001 + } else
1002 + ret = 0;
1003 + }
1004 + write_end_chart();
1005 +
1006 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS);
1007 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1008 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1009 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.write_call +
1010 + ect->publish_systemd_vfs.writev_call);
1011 + }
1012 + }
1013 + write_end_chart();
1014 +
1015 + if (em->mode < MODE_ENTRY) {
1016 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR);
1017 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1018 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1019 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.write_err +
1020 + ect->publish_systemd_vfs.writev_err);
1021 + }
1022 + }
1023 + write_end_chart();
1024 + }
1025 +
1026 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_CALLS);
1027 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1028 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1029 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.read_call +
1030 + ect->publish_systemd_vfs.readv_call);
1031 + }
1032 + }
1033 + write_end_chart();
1034 +
1035 + if (em->mode < MODE_ENTRY) {
1036 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR);
1037 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1038 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1039 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.read_err +
1040 + ect->publish_systemd_vfs.readv_err);
1041 + }
1042 + }
1043 + write_end_chart();
1044 + }
1045 +
1046 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES);
1047 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1048 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1049 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.write_bytes +
1050 + ect->publish_systemd_vfs.writev_bytes);
1051 + }
1052 + }
1053 + write_end_chart();
1054 +
1055 +
1056 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_BYTES);
1057 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1058 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1059 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.read_bytes +
1060 + ect->publish_systemd_vfs.readv_bytes);
1061 + }
1062 + }
1063 + write_end_chart();
1064 +
1065 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_FSYNC);
1066 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1067 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1068 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.fsync_call);
1069 + }
1070 + }
1071 + write_end_chart();
1072 +
1073 + if (em->mode < MODE_ENTRY) {
1074 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR);
1075 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1076 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1077 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.fsync_err);
1078 + }
1079 + }
1080 + write_end_chart();
1081 + }
1082 +
1083 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_OPEN);
1084 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1085 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1086 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.open_call);
1087 + }
1088 + }
1089 + write_end_chart();
1090 +
1091 + if (em->mode < MODE_ENTRY) {
1092 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR);
1093 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1094 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1095 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.open_err);
1096 + }
1097 + }
1098 + write_end_chart();
1099 + }
1100 +
1101 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_CREATE);
1102 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1103 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1104 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.create_call);
1105 + }
1106 + }
1107 + write_end_chart();
1108 +
1109 + if (em->mode < MODE_ENTRY) {
1110 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR);
1111 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1112 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1113 + write_chart_dimension(ect->name, ect->publish_systemd_vfs.create_err);
1114 + }
1115 + }
1116 + write_end_chart();
1117 + }
1118 +
1119 + return ret;
1120 +}
1121 +
1122 +/**
1123 + * Send data to Netdata calling auxiliar functions.
1124 + *
1125 + * @param em the main collector structure
1126 +*/
1127 +static void ebpf_vfs_send_cgroup_data(ebpf_module_t *em)
1128 +{
1129 + if (!ebpf_cgroup_pids)
1130 + return;
1131 +
1132 + pthread_mutex_lock(&mutex_cgroup_shm);
1133 + ebpf_cgroup_target_t *ect;
1134 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1135 + ebpf_vfs_sum_cgroup_pids(&ect->publish_systemd_vfs, ect->pids);
1136 + }
1137 +
1138 + int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
1139 + if (has_systemd) {
1140 + static int systemd_charts = 0;
1141 + if (!systemd_charts) {
1142 + ebpf_create_systemd_vfs_charts(em);
1143 + systemd_charts = 1;
1144 + }
1145 +
1146 + systemd_charts = ebpf_send_systemd_vfs_charts(em);
1147 + }
1148 +
1149 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1150 + if (ect->systemd)
1151 + continue;
1152 +
1153 + if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_VFS_CHART) && ect->updated) {
1154 + ebpf_create_specific_vfs_charts(ect->name, em);
1155 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_VFS_CHART;
1156 + }
1157 +
1158 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_VFS_CHART) {
1159 + if (ect->updated) {
1160 + ebpf_send_specific_vfs_data(ect->name, &ect->publish_systemd_vfs, em);
1161 + } else {
1162 + ebpf_obsolete_specific_vfs_charts(ect->name, em);
1163 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_VFS_CHART;
1164 + }
1165 + }
1166 + }
1167 +
1168 + pthread_mutex_unlock(&mutex_cgroup_shm);
1169 +}
1170 +
1171 /**
1172 * Main loop for this collector.
1173 *
@@ -526,6 +1183,7 @@ static void vfs_collector(ebpf_module_t *em)
1183 ebpf_vfs_read_hash, em);
1184
1185 int apps = em->apps_charts;
1186 + int cgroups = em->cgroup_charts;
1187 while (!close_ebpf_plugin) {
1188 pthread_mutex_lock(&collect_data_mutex);
1189 pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
@@ -533,6 +1191,9 @@ static void vfs_collector(ebpf_module_t *em)
1191 if (apps)
1192 ebpf_vfs_read_apps();
1193
1194 + if (cgroups)
1195 + read_update_vfs_cgroup();
1196 +
1197 pthread_mutex_lock(&lock);
1198
1199 ebpf_vfs_send_data(em);
@@ -541,6 +1202,9 @@ static void vfs_collector(ebpf_module_t *em)
1202 if (apps)
1203 ebpf_vfs_send_apps_data(em, apps_groups_root_target);
1204
1205 + if (cgroups)
1206 + ebpf_vfs_send_cgroup_data(em);
1207 +
1208 pthread_mutex_unlock(&lock);
1209 pthread_mutex_unlock(&collect_data_mutex);
1210 }
@@ -637,7 +1301,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
1301
1302 ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
1303 NETDATA_VFS_FSYNC,
640 - "Calls to vfs_fsync",
1304 + "Calls for <code>vfs_fsync</code>",
1305 EBPF_COMMON_DIMENSION_CALL,
1306 NETDATA_VFS_GROUP,
1307 NULL,
@@ -663,7 +1327,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
1327
1328 ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
1329 NETDATA_VFS_OPEN,
666 - "Calls to vfs_open",
1330 + "Calls for <code>vfs_open</code>",
1331 EBPF_COMMON_DIMENSION_CALL,
1332 NETDATA_VFS_GROUP,
1333 NULL,
@@ -689,7 +1353,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
1353
1354 ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
1355 NETDATA_VFS_CREATE,
692 - "Calls to vfs_create",
1356 + "Calls for <code>vfs_create</code>",
1357 EBPF_COMMON_DIMENSION_CALL,
1358 NETDATA_VFS_GROUP,
1359 NULL,
collectors/ebpf.plugin/ebpf_vfs.h
+18
@@ -40,6 +40,24 @@
40
41 // Group used on Dashboard
42 #define NETDATA_VFS_GROUP "vfs"
43 +#define NETDATA_VFS_CGROUP_GROUP "vfs (eBPF)"
44 +
45 +// Contexts
46 +#define NETDATA_CGROUP_VFS_UNLINK_CONTEXT "cgroup.vfs_unlink"
47 +#define NETDATA_CGROUP_VFS_WRITE_CONTEXT "cgroup.vfs_write"
48 +#define NETDATA_CGROUP_VFS_WRITE_ERROR_CONTEXT "cgroup.vfs_write_error"
49 +#define NETDATA_CGROUP_VFS_READ_CONTEXT "cgroup.vfs_read"
50 +#define NETDATA_CGROUP_VFS_READ_ERROR_CONTEXT "cgroup.vfs_read_error"
51 +#define NETDATA_CGROUP_VFS_WRITE_BYTES_CONTEXT "cgroup.vfs_write_bytes"
52 +#define NETDATA_CGROUP_VFS_READ_BYTES_CONTEXT "cgroup.vfs_read_bytes"
53 +
54 +#define NETDATA_SYSTEMD_VFS_UNLINK_CONTEXT "services.vfs_unlink"
55 +#define NETDATA_SYSTEMD_VFS_WRITE_CONTEXT "services.vfs_write"
56 +#define NETDATA_SYSTEMD_VFS_WRITE_ERROR_CONTEXT "services.vfs_write_error"
57 +#define NETDATA_SYSTEMD_VFS_READ_CONTEXT "services.vfs_read"
58 +#define NETDATA_SYSTEMD_VFS_READ_ERROR_CONTEXT "services.vfs_read_error"
59 +#define NETDATA_SYSTEMD_VFS_WRITE_BYTES_CONTEXT "services.vfs_write_bytes"
60 +#define NETDATA_SYSTEMD_VFS_READ_BYTES_CONTEXT "services.vfs_read_bytes"
61
62 typedef struct netdata_publish_vfs {
63 uint64_t pid_tgid;
web/gui/dashboard_info.js
+165 -7
@@ -2430,13 +2430,13 @@ netdataDashboard.context = {
2430 // Apps eBPF stuff
2431
2432 'apps.file_open': {
2433 - info: 'Calls to the internal function <code>do_sys_open</code> ( For kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ), which is the common function called from' +
2433 + info: 'Calls to the internal function <code>do_sys_open</code> (for kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ), which is the common function called from' +
2434 ' <a href="https://www.man7.org/linux/man-pages/man2/open.2.html" target="_blank">open(2)</a> ' +
2435 ' and <a href="https://www.man7.org/linux/man-pages/man2/openat.2.html" target="_blank">openat(2)</a>. '
2436 },
2437
2438 'apps.file_open_error': {
2439 - info: 'Failed calls to the internal function <code>do_sys_open</code> ( For kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ).'
2439 + info: 'Failed calls to the internal function <code>do_sys_open</code> (for kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ).'
2440 },
2441
2442 'apps.file_closed': {
@@ -2477,11 +2477,11 @@ netdataDashboard.context = {
2477 },
2478
2479 'apps.process_create': {
2480 - info: 'Calls to either <a href="https://www.ece.uic.edu/~yshi1/linux/lkse/node4.html#SECTION00421000000000000000" target="_blank">do_fork</a>, or <code>kernel_clone</code> if you are running kernel newer than 5.9.16, to create a new task, which is the common name used to define process and tasks inside the kernel. Netdata identifies the process by counting the number of calls to <a href="https://linux.die.net/man/2/clone" target="_blank">sys_clone</a> that do not have the flag <code>CLONE_THREAD</code> set.'
2480 + info: 'Calls to either <a href="https://programming.vip/docs/the-execution-procedure-of-do_fork-function-in-linux.html" target="_blank">do_fork</a>, or <code>kernel_clone</code> if you are running kernel newer than 5.9.16, to create a new task, which is the common name used to define process and tasks inside the kernel. Netdata identifies the process by counting the number of calls to <a href="https://linux.die.net/man/2/clone" target="_blank">sys_clone</a> that do not have the flag <code>CLONE_THREAD</code> set.'
2481 },
2482
2483 'apps.thread_create': {
2484 - info: 'Calls to either <a href="https://www.ece.uic.edu/~yshi1/linux/lkse/node4.html#SECTION00421000000000000000" target="_blank">do_fork</a>, or <code>kernel_clone</code> if you are running kernel newer than 5.9.16, to create a new task, which is the common name used to define process and tasks inside the kernel. Netdata identifies the threads by counting the number of calls to <a href="https://linux.die.net/man/2/clone" target="_blank">sys_clone</a> that have the flag <code>CLONE_THREAD</code> set.'
2484 + info: 'Calls to either <a href="https://programming.vip/docs/the-execution-procedure-of-do_fork-function-in-linux.html" target="_blank">do_fork</a>, or <code>kernel_clone</code> if you are running kernel newer than 5.9.16, to create a new task, which is the common name used to define process and tasks inside the kernel. Netdata identifies the threads by counting the number of calls to <a href="https://linux.die.net/man/2/clone" target="_blank">sys_clone</a> that have the flag <code>CLONE_THREAD</code> set.'
2485 },
2486
2487 'apps.task_close': {
@@ -3874,6 +3874,89 @@ netdataDashboard.context = {
3874 info: 'The number of write requests merged.'
3875 },
3876
3877 + 'services.swap_read': {
3878 + info: 'The function <code>swap_readpage</code> is called when the kernel reads a page from swap memory. This chart is provided by eBPF plugin.'
3879 + },
3880 +
3881 + 'services.swap_write': {
3882 + info: 'The function <code>swap_writepage</code> is called when the kernel writes a page to swap memory. This chart is provided by eBPF plugin.'
3883 + },
3884 +
3885 + 'services.fd_open': {
3886 + info: 'Calls to the internal function <code>do_sys_open</code> (for kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ), which is the common function called from' +
3887 + ' <a href="https://www.man7.org/linux/man-pages/man2/open.2.html" target="_blank">open(2)</a> ' +
3888 + ' and <a href="https://www.man7.org/linux/man-pages/man2/openat.2.html" target="_blank">openat(2)</a>. '
3889 + },
3890 +
3891 + 'services.fd_open_error': {
3892 + info: 'Failed calls to the internal function <code>do_sys_open</code> (for kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ).'
3893 + },
3894 +
3895 + 'services.fd_close': {
3896 + info: 'Calls to the internal function <a href="https://elixir.bootlin.com/linux/v5.10/source/fs/file.c#L665" target="_blank">__close_fd</a> or <a href="https://elixir.bootlin.com/linux/v5.11/source/fs/file.c#L617" target="_blank">close_fd</a> according to your kernel version, which is called from' +
3897 + ' <a href="https://www.man7.org/linux/man-pages/man2/close.2.html" target="_blank">close(2)</a>. '
3898 + },
3899 +
3900 + 'services.fd_close_error': {
3901 + info: 'Failed calls to the internal function <a href="https://elixir.bootlin.com/linux/v5.10/source/fs/file.c#L665" target="_blank">__close_fd</a> or <a href="https://elixir.bootlin.com/linux/v5.11/source/fs/file.c#L617" target="_blank">close_fd</a> according to your kernel version.'
3902 + },
3903 +
3904 + 'services.vfs_unlink': {
3905 + info: 'Calls to the function <a href="https://www.kernel.org/doc/htmldocs/filesystems/API-vfs-unlink.html" target="_blank">vfs_unlink</a>. This chart does not show all events that remove files from the filesystem, because filesystems can create their own functions to remove files.'
3906 + },
3907 +
3908 + 'services.vfs_write': {
3909 + info: 'Successful calls to the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_write</a>. This chart may not show all filesystem events if it uses other functions to store data on disk.'
3910 + },
3911 +
3912 + 'services.vfs_write_error': {
3913 + info: 'Failed calls to the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_write</a>. This chart may not show all filesystem events if it uses other functions to store data on disk.'
3914 + },
3915 +
3916 + 'services.vfs_read': {
3917 + info: 'Successful calls to the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_read</a>. This chart may not show all filesystem events if it uses other functions to store data on disk.'
3918 + },
3919 +
3920 + 'services.vfs_read_error': {
3921 + info: 'Failed calls to the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_read</a>. This chart may not show all filesystem events if it uses other functions to store data on disk.'
3922 + },
3923 +
3924 + 'services.vfs_write_bytes': {
3925 + info: 'Total of bytes successfully written using the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_write</a>.'
3926 + },
3927 +
3928 + 'services.vfs_read_bytes': {
3929 + info: 'Total of bytes successfully read using the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_read</a>.'
3930 + },
3931 +
3932 + 'services.process_create': {
3933 + info: 'Calls to either <a href="https://programming.vip/docs/the-execution-procedure-of-do_fork-function-in-linux.html" target="_blank">do_fork</a>, or <code>kernel_clone</code> if you are running kernel newer than 5.9.16, to create a new task, which is the common name used to define process and tasks inside the kernel. Netdata identifies the process by counting the number of calls to <a href="https://linux.die.net/man/2/clone" target="_blank">sys_clone</a> that do not have the flag <code>CLONE_THREAD</code> set.'
3934 + },
3935 +
3936 + 'services.thread_create': {
3937 + info: 'Calls to either <a href="https://programming.vip/docs/the-execution-procedure-of-do_fork-function-in-linux.html" target="_blank">do_fork</a>, or <code>kernel_clone</code> if you are running kernel newer than 5.9.16, to create a new task, which is the common name used to define process and tasks inside the kernel. Netdata identifies the threads by counting the number of calls to <a href="https://linux.die.net/man/2/clone" target="_blank">sys_clone</a> that have the flag <code>CLONE_THREAD</code> set.'
3938 + },
3939 +
3940 + 'services.task_close': {
3941 + info: 'Calls to the functions responsible for closing (<a href="https://www.informit.com/articles/article.aspx?p=370047&seqNum=4" target="_blank">do_exit</a>) and releasing (<a href="https://www.informit.com/articles/article.aspx?p=370047&seqNum=4" target="_blank">release_task</a>) tasks.'
3942 + },
3943 +
3944 + 'services.dc_ratio': {
3945 + info: 'Percentage of file accesses that were present in the directory cache. 100% means that every file that was accessed was present in the directory cache. If files are not present in the directory cache 1) they are not present in the file system, 2) the files were not accessed before. Read more about <a href="https://www.kernel.org/doc/htmldocs/filesystems/the_directory_cache.html" target="_blank">directory cache</a>. Netdata also gives a summary for these charts in <a href="#menu_filesystem_submenu_directory_cache__eBPF_">Filesystem submenu</a>.'
3946 + },
3947 +
3948 + 'services.dc_reference': {
3949 + info: 'Counters of file accesses. <code>Reference</code> is when there is a file access, see the <code>filesystem.dc_reference</code> chart for more context. Read more about <a href="https://www.kernel.org/doc/htmldocs/filesystems/the_directory_cache.html" target="_blank">directory cache</a>.'
3950 + },
3951 +
3952 + 'services.dc_not_cache': {
3953 + info: 'Counters of file accesses. <code>Slow</code> is when there is a file access and the file is not present in the directory cache, see the <code>filesystem.dc_reference</code> chart for more context. Read more about <a href="https://www.kernel.org/doc/htmldocs/filesystems/the_directory_cache.html" target="_blank">directory cache</a>.'
3954 + },
3955 +
3956 + 'services.dc_not_found': {
3957 + info: 'Counters of file accesses. <code>Miss</code> is when there is file access and the file is not found in the filesystem, see the <code>filesystem.dc_reference</code> chart for more context. Read more about <a href="https://www.kernel.org/doc/htmldocs/filesystems/the_directory_cache.html" target="_blank">directory cache</a>.'
3958 + },
3959 +
3960 // ------------------------------------------------------------------------
3961 // beanstalkd
3962 // system charts
@@ -5483,16 +5566,91 @@ netdataDashboard.context = {
5566 },
5567
5568 // ------------------------------------------------------------------------
5486 - // Services units
5569 + // Cgroup units
5570
5488 - 'services.swap_read_call': {
5571 + 'cgroup.swap_read': {
5572 info: 'The function <code>swap_readpage</code> is called when the kernel reads a page from swap memory. This chart is provided by eBPF plugin.'
5573 },
5574
5492 - 'services.swap_write_call': {
5575 + 'cgroup.swap_write': {
5576 info: 'The function <code>swap_writepage</code> is called when the kernel writes a page to swap memory. This chart is provided by eBPF plugin.'
5577 },
5578
5579 + 'cgroup.fd_open': {
5580 + info: 'Calls to the internal function <code>do_sys_open</code> (for kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ), which is the common function called from' +
5581 + ' <a href="https://www.man7.org/linux/man-pages/man2/open.2.html" target="_blank">open(2)</a> ' +
5582 + ' and <a href="https://www.man7.org/linux/man-pages/man2/openat.2.html" target="_blank">openat(2)</a>. '
5583 + },
5584 +
5585 + 'cgroup.fd_open_error': {
5586 + info: 'Failed calls to the internal function <code>do_sys_open</code> (for kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ).'
5587 + },
5588 +
5589 + 'cgroup.fd_close': {
5590 + info: 'Calls to the internal function <a href="https://elixir.bootlin.com/linux/v5.10/source/fs/file.c#L665" target="_blank">__close_fd</a> or <a href="https://elixir.bootlin.com/linux/v5.11/source/fs/file.c#L617" target="_blank">close_fd</a> according to your kernel version, which is called from' +
5591 + ' <a href="https://www.man7.org/linux/man-pages/man2/close.2.html" target="_blank">close(2)</a>. '
5592 + },
5593 +
5594 + 'cgroup.fd_close_error': {
5595 + info: 'Failed calls to the internal function <a href="https://elixir.bootlin.com/linux/v5.10/source/fs/file.c#L665" target="_blank">__close_fd</a> or <a href="https://elixir.bootlin.com/linux/v5.11/source/fs/file.c#L617" target="_blank">close_fd</a> according to your kernel version.'
5596 + },
5597 +
5598 + 'cgroup.vfs_unlink': {
5599 + info: 'Calls to the function <a href="https://www.kernel.org/doc/htmldocs/filesystems/API-vfs-unlink.html" target="_blank">vfs_unlink</a>. This chart does not show all events that remove files from the filesystem, because filesystems can create their own functions to remove files.'
5600 + },
5601 +
5602 + 'cgroup.vfs_write': {
5603 + info: 'Successful calls to the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_write</a>. This chart may not show all filesystem events if it uses other functions to store data on disk.'
5604 + },
5605 +
5606 + 'cgroup.vfs_write_error': {
5607 + info: 'Failed calls to the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_write</a>. This chart may not show all filesystem events if it uses other functions to store data on disk.'
5608 + },
5609 +
5610 + 'cgroup.vfs_read': {
5611 + info: 'Successful calls to the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_read</a>. This chart may not show all filesystem events if it uses other functions to store data on disk.'
5612 + },
5613 +
5614 + 'cgroup.vfs_read_error': {
5615 + info: 'Failed calls to the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_read</a>. This chart may not show all filesystem events if it uses other functions to store data on disk.'
5616 + },
5617 +
5618 + 'cgroup.vfs_write_bytes': {
5619 + info: 'Total of bytes successfully written using the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_write</a>.'
5620 + },
5621 +
5622 + 'cgroup.vfs_read_bytes': {
5623 + info: 'Total of bytes successfully read using the function <a href="https://topic.alibabacloud.com/a/kernel-state-file-operation-__-work-information-kernel_8_8_20287135.html" target="_blank">vfs_read</a>.'
5624 + },
5625 +
5626 + 'cgroup.process_create': {
5627 + info: 'Calls to either <a href="https://programming.vip/docs/the-execution-procedure-of-do_fork-function-in-linux.html" target="_blank">do_fork</a>, or <code>kernel_clone</code> if you are running kernel newer than 5.9.16, to create a new task, which is the common name used to define process and tasks inside the kernel. Netdata identifies the process by counting the number of calls to <a href="https://linux.die.net/man/2/clone" target="_blank">sys_clone</a> that do not have the flag <code>CLONE_THREAD</code> set.'
5628 + },
5629 +
5630 + 'cgroup.thread_create': {
5631 + info: 'Calls to either <a href="https://programming.vip/docs/the-execution-procedure-of-do_fork-function-in-linux.html" target="_blank">do_fork</a>, or <code>kernel_clone</code> if you are running kernel newer than 5.9.16, to create a new task, which is the common name used to define process and tasks inside the kernel. Netdata identifies the threads by counting the number of calls to <a href="https://linux.die.net/man/2/clone" target="_blank">sys_clone</a> that have the flag <code>CLONE_THREAD</code> set.'
5632 + },
5633 +
5634 + 'cgroup.task_close': {
5635 + info: 'Calls to the functions responsible for closing (<a href="https://www.informit.com/articles/article.aspx?p=370047&seqNum=4" target="_blank">do_exit</a>) and releasing (<a href="https://www.informit.com/articles/article.aspx?p=370047&seqNum=4" target="_blank">release_task</a>) tasks.'
5636 + },
5637 +
5638 + 'cgroup.dc_ratio': {
5639 + info: 'Percentage of file accesses that were present in the directory cache. 100% means that every file that was accessed was present in the directory cache. If files are not present in the directory cache 1) they are not present in the file system, 2) the files were not accessed before. Read more about <a href="https://www.kernel.org/doc/htmldocs/filesystems/the_directory_cache.html" target="_blank">directory cache</a>. Netdata also gives a summary for these charts in <a href="#menu_filesystem_submenu_directory_cache__eBPF_">Filesystem submenu</a>.'
5640 + },
5641 +
5642 + 'cgroup.dc_reference': {
5643 + info: 'Counters of file accesses. <code>Reference</code> is when there is a file access, see the <code>filesystem.dc_reference</code> chart for more context. Read more about <a href="https://www.kernel.org/doc/htmldocs/filesystems/the_directory_cache.html" target="_blank">directory cache</a>.'
5644 + },
5645 +
5646 + 'cgroup.dc_not_cache': {
5647 + info: 'Counters of file accesses. <code>Slow</code> is when there is a file access and the file is not present in the directory cache, see the <code>filesystem.dc_reference</code> chart for more context. Read more about <a href="https://www.kernel.org/doc/htmldocs/filesystems/the_directory_cache.html" target="_blank">directory cache</a>.'
5648 + },
5649 +
5650 + 'cgroup.dc_not_found': {
5651 + info: 'Counters of file accesses. <code>Miss</code> is when there is file access and the file is not found in the filesystem, see the <code>filesystem.dc_reference</code> chart for more context. Read more about <a href="https://www.kernel.org/doc/htmldocs/filesystems/the_directory_cache.html" target="_blank">directory cache</a>.'
5652 + },
5653 +
5654 // ------------------------------------------------------------------------
5655 // ACLK Internal Stats
5656 'netdata.aclk_status': {