@cryptotaxi247 / netdata-1 / commits / 688503d3b

eBPF cgroup integration (#11642)

thiagoftsm committed Oct 12, 2021 at 19:24 UTC 688503d3b0f36082736a3292143ea4a296b24de3
16 files changed +1462 -141
collectors/ebpf.plugin/README.md
+19
@@ -306,6 +306,25 @@ When the integration is enabled, eBPF collector allocates memory for each proces
306 it uses per-cpu maps to speed up the update of hash tables. This also implies storing data for the same PID
307 for each processor it runs.
308
309 +### Integration with `cgroups.plugin`
310 +
311 +The eBPF collector also creates charts for each cgroup through an integration with the
312 +[`cgroups.plugin`](/collectors/cgroups.plugin/README.md). This integration helps you understand how a specific cgroup
313 +interacts with the Linux kernel.
314 +
315 +The integration with `cgroups.plugin` is disabled by default to avoid creating overhead on your system.
316 +If you want to _enable_ the integration with `cgroups.plugin`, change the `cgroups`setting to
317 +`yes`.
318 +
319 +```conf
320 +[global]
321 + cgroups = yes
322 +```
323 +
324 +If you do not need to monitor specific metrics for your `cgroups`, you can enable `cgroups` inside
325 +`ebpf.d.conf`, and then disable the plugin for a specific `thread` by following the steps in the
326 +['Configuration` section](docs/agent/collectors/ebpf.plugin#configuration)
327 +
328 #### `[ebpf programs]`
329
330 The eBPF collector enables and runs the following eBPF programs by default:
collectors/ebpf.plugin/ebpf.c
+3 -1
@@ -659,7 +659,9 @@ static inline void ebpf_enable_specific_chart(struct ebpf_module *em, int disabl
659 {
660 em->enabled = CONFIG_BOOLEAN_YES;
661
662 - if (!disable_apps) {
662 + // oomkill stores data inside apps submenu, so it always need to have apps_enabled for plugin to create
663 + // its chart, without this comparison eBPF.plugin will try to store invalid data when apps is disabled.
664 + if (!disable_apps || !strcmp(em->thread_name, "oomkill")) {
665 em->apps_charts = CONFIG_BOOLEAN_YES;
666 }
667
collectors/ebpf.plugin/ebpf_apps.h
+2 -1
@@ -15,7 +15,7 @@
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"
18 +#define NETDATA_APPS_IPC_SHM_GROUP "ipc shm (eBPF)"
19
20 #include "ebpf_process.h"
21 #include "ebpf_dcstat.h"
@@ -27,6 +27,7 @@
27 #include "ebpf_mount.h"
28 #include "ebpf_oomkill.h"
29 #include "ebpf_shm.h"
30 +#include "ebpf_socket.h"
31 #include "ebpf_softirq.h"
32 #include "ebpf_sync.h"
33 #include "ebpf_swap.h"
collectors/ebpf.plugin/ebpf_cachestat.c
+335 -8
@@ -279,6 +279,43 @@ static void read_apps_table()
279 }
280 }
281
282 +/**
283 + * Update cgroup
284 + *
285 + * Update cgroup data based in
286 + */
287 +static void ebpf_update_cachestat_cgroup()
288 +{
289 + netdata_cachestat_pid_t *cv = cachestat_vector;
290 + int fd = cachestat_maps[NETDATA_CACHESTAT_PID_STATS].map_fd;
291 + size_t length = sizeof(netdata_cachestat_pid_t) * ebpf_nprocs;
292 +
293 + ebpf_cgroup_target_t *ect;
294 + pthread_mutex_lock(&mutex_cgroup_shm);
295 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
296 + struct pid_on_target2 *pids;
297 + for (pids = ect->pids; pids; pids = pids->next) {
298 + int pid = pids->pid;
299 + netdata_cachestat_pid_t *out = &pids->cachestat;
300 + if (likely(cachestat_pid) && cachestat_pid[pid]) {
301 + netdata_publish_cachestat_t *in = cachestat_pid[pid];
302 +
303 + memcpy(out, &in->current, sizeof(netdata_cachestat_pid_t));
304 + } else {
305 + memset(cv, 0, length);
306 + if (bpf_map_lookup_elem(fd, &pid, cv)) {
307 + continue;
308 + }
309 +
310 + cachestat_apps_accumulator(cv);
311 +
312 + memcpy(out, cv, sizeof(netdata_cachestat_pid_t));
313 + }
314 + }
315 + }
316 + pthread_mutex_unlock(&mutex_cgroup_shm);
317 +}
318 +
319 /**
320 * Create apps charts
321 *
@@ -463,7 +500,7 @@ void ebpf_cache_send_apps_data(struct target *root)
500
501 uint64_t mpa = current->mark_page_accessed - prev->mark_page_accessed;
502 uint64_t mbd = current->mark_buffer_dirty - prev->mark_buffer_dirty;
466 - w->cachestat.dirty = current->mark_buffer_dirty;
503 + w->cachestat.dirty = mbd;
504 uint64_t apcl = current->add_to_page_cache_lru - prev->add_to_page_cache_lru;
505 uint64_t apd = current->account_page_dirtied - prev->account_page_dirtied;
506
@@ -503,6 +540,287 @@ void ebpf_cache_send_apps_data(struct target *root)
540 write_end_chart();
541 }
542
543 +/**
544 + * Cachestat sum PIDs
545 + *
546 + * Sum values for all PIDs associated to a group
547 + *
548 + * @param publish output structure.
549 + * @param root structure with listed IPs
550 + */
551 +void ebpf_cachestat_sum_cgroup_pids(netdata_publish_cachestat_t *publish, struct pid_on_target2 *root)
552 +{
553 + memcpy(&publish->prev, &publish->current,sizeof(publish->current));
554 + memset(&publish->current, 0, sizeof(publish->current));
555 +
556 + netdata_cachestat_pid_t *dst = &publish->current;
557 + while (root) {
558 + netdata_cachestat_pid_t *src = &root->cachestat;
559 +
560 + dst->account_page_dirtied += src->account_page_dirtied;
561 + dst->add_to_page_cache_lru += src->add_to_page_cache_lru;
562 + dst->mark_buffer_dirty += src->mark_buffer_dirty;
563 + dst->mark_page_accessed += src->mark_page_accessed;
564 +
565 + root = root->next;
566 + }
567 +}
568 +
569 +/**
570 + * Calc chart values
571 + *
572 + * Do necessary math to plot charts.
573 + */
574 +void ebpf_cachestat_calc_chart_values()
575 +{
576 + ebpf_cgroup_target_t *ect;
577 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
578 + ebpf_cachestat_sum_cgroup_pids(&ect->publish_cachestat, ect->pids);
579 +
580 + netdata_cachestat_pid_t *current = &ect->publish_cachestat.current;
581 + netdata_cachestat_pid_t *prev = &ect->publish_cachestat.prev;
582 +
583 + uint64_t mpa = current->mark_page_accessed - prev->mark_page_accessed;
584 + uint64_t mbd = current->mark_buffer_dirty - prev->mark_buffer_dirty;
585 + ect->publish_cachestat.dirty = mbd;
586 + uint64_t apcl = current->add_to_page_cache_lru - prev->add_to_page_cache_lru;
587 + uint64_t apd = current->account_page_dirtied - prev->account_page_dirtied;
588 +
589 + cachestat_update_publish(&ect->publish_cachestat, mpa, mbd, apcl, apd);
590 + }
591 +}
592 +
593 +/**
594 + * Create Systemd cachestat Charts
595 + *
596 + * Create charts when systemd is enabled
597 + **/
598 +static void ebpf_create_systemd_cachestat_charts()
599 +{
600 + ebpf_create_charts_on_systemd(NETDATA_CACHESTAT_HIT_RATIO_CHART,
601 + "Hit is calculating using total cache added without dirties per total added because of red misses.",
602 + EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_CACHESTAT_SUBMENU,
603 + NETDATA_EBPF_CHART_TYPE_LINE, 21100,
604 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
605 + NETDATA_SYSTEMD_CACHESTAT_HIT_RATIO_CONTEXT, NETDATA_EBPF_MODULE_NAME_CACHESTAT);
606 +
607 + ebpf_create_charts_on_systemd(NETDATA_CACHESTAT_DIRTY_CHART,
608 + "Number of dirty pages added to the page cache.",
609 + EBPF_CACHESTAT_DIMENSION_PAGE, NETDATA_CACHESTAT_SUBMENU,
610 + NETDATA_EBPF_CHART_TYPE_LINE, 21101,
611 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
612 + NETDATA_SYSTEMD_CACHESTAT_MODIFIED_CACHE_CONTEXT, NETDATA_EBPF_MODULE_NAME_CACHESTAT);
613 +
614 + ebpf_create_charts_on_systemd(NETDATA_CACHESTAT_HIT_CHART, "Hits are function calls that Netdata counts.",
615 + EBPF_CACHESTAT_DIMENSION_HITS, NETDATA_CACHESTAT_SUBMENU,
616 + NETDATA_EBPF_CHART_TYPE_LINE, 21102,
617 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
618 + NETDATA_SYSTEMD_CACHESTAT_HIT_FILE_CONTEXT, NETDATA_EBPF_MODULE_NAME_CACHESTAT);
619 +
620 + ebpf_create_charts_on_systemd(NETDATA_CACHESTAT_MISSES_CHART, "Misses are function calls that Netdata counts.",
621 + EBPF_CACHESTAT_DIMENSION_MISSES, NETDATA_CACHESTAT_SUBMENU,
622 + NETDATA_EBPF_CHART_TYPE_LINE, 21103,
623 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
624 + NETDATA_SYSTEMD_CACHESTAT_MISS_FILES_CONTEXT, NETDATA_EBPF_MODULE_NAME_CACHESTAT);
625 +}
626 +
627 +/**
628 + * Send Cache Stat charts
629 + *
630 + * Send collected data to Netdata.
631 + *
632 + * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
633 + * otherwise function returns 1 to avoid chart recreation
634 + */
635 +static int ebpf_send_systemd_cachestat_charts()
636 +{
637 + int ret = 1;
638 + ebpf_cgroup_target_t *ect;
639 +
640 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_CACHESTAT_HIT_RATIO_CHART);
641 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
642 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
643 + write_chart_dimension(ect->name, (long long)ect->publish_cachestat.ratio);
644 + } else
645 + ret = 0;
646 + }
647 + write_end_chart();
648 +
649 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_CACHESTAT_DIRTY_CHART);
650 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
651 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
652 + write_chart_dimension(ect->name, (long long)ect->publish_cachestat.dirty);
653 + }
654 + }
655 + write_end_chart();
656 +
657 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_CACHESTAT_HIT_CHART);
658 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
659 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
660 + write_chart_dimension(ect->name, (long long)ect->publish_cachestat.hit);
661 + }
662 + }
663 + write_end_chart();
664 +
665 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_CACHESTAT_MISSES_CHART);
666 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
667 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
668 + write_chart_dimension(ect->name, (long long)ect->publish_cachestat.miss);
669 + }
670 + }
671 + write_end_chart();
672 +
673 + return ret;
674 +}
675 +
676 +/**
677 + * Send Directory Cache charts
678 + *
679 + * Send collected data to Netdata.
680 + */
681 +static void ebpf_send_specific_cachestat_data(char *type, netdata_publish_cachestat_t *npc)
682 +{
683 + write_begin_chart(type, NETDATA_CACHESTAT_HIT_RATIO_CHART);
684 + write_chart_dimension(cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_RATIO].name, (long long)npc->ratio);
685 + write_end_chart();
686 +
687 + write_begin_chart(type, NETDATA_CACHESTAT_DIRTY_CHART);
688 + write_chart_dimension(cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_DIRTY].name, (long long)npc->dirty);
689 + write_end_chart();
690 +
691 + write_begin_chart(type, NETDATA_CACHESTAT_HIT_CHART);
692 + write_chart_dimension(cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_HIT].name, (long long)npc->hit);
693 + write_end_chart();
694 +
695 + write_begin_chart(type, NETDATA_CACHESTAT_MISSES_CHART);
696 + write_chart_dimension(cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_MISS].name, (long long)npc->miss);
697 + write_end_chart();
698 +}
699 +
700 +/**
701 + * Create specific cache Stat charts
702 + *
703 + * Create charts for cgroup/application.
704 + *
705 + * @param type the chart type.
706 + */
707 +static void ebpf_create_specific_cachestat_charts(char *type)
708 +{
709 + ebpf_create_chart(type, NETDATA_CACHESTAT_HIT_RATIO_CHART,
710 + "Hit is calculating using total cache added without dirties per total added because of red misses.",
711 + EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_CACHESTAT_CGROUP_SUBMENU,
712 + NETDATA_CGROUP_CACHESTAT_HIT_RATIO_CONTEXT,
713 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5200,
714 + ebpf_create_global_dimension,
715 + cachestat_counter_publish_aggregated, 1, NETDATA_EBPF_MODULE_NAME_CACHESTAT);
716 +
717 + ebpf_create_chart(type, NETDATA_CACHESTAT_DIRTY_CHART,
718 + "Number of dirty pages added to the page cache.",
719 + EBPF_CACHESTAT_DIMENSION_PAGE, NETDATA_CACHESTAT_CGROUP_SUBMENU,
720 + NETDATA_CGROUP_CACHESTAT_MODIFIED_CACHE_CONTEXT,
721 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5201,
722 + ebpf_create_global_dimension,
723 + &cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_DIRTY], 1,
724 + NETDATA_EBPF_MODULE_NAME_CACHESTAT);
725 +
726 + ebpf_create_chart(type, NETDATA_CACHESTAT_HIT_CHART,
727 + "Hits are function calls that Netdata counts.",
728 + EBPF_CACHESTAT_DIMENSION_HITS, NETDATA_CACHESTAT_CGROUP_SUBMENU,
729 + NETDATA_CGROUP_CACHESTAT_HIT_FILES_CONTEXT,
730 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5202,
731 + ebpf_create_global_dimension,
732 + &cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_HIT], 1,
733 + NETDATA_EBPF_MODULE_NAME_CACHESTAT);
734 +
735 + ebpf_create_chart(type, NETDATA_CACHESTAT_MISSES_CHART,
736 + "Misses are function calls that Netdata counts.",
737 + EBPF_CACHESTAT_DIMENSION_MISSES, NETDATA_CACHESTAT_CGROUP_SUBMENU,
738 + NETDATA_CGROUP_CACHESTAT_MISS_FILES_CONTEXT,
739 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5203,
740 + ebpf_create_global_dimension,
741 + &cachestat_counter_publish_aggregated[NETDATA_CACHESTAT_IDX_MISS], 1,
742 + NETDATA_EBPF_MODULE_NAME_CACHESTAT);
743 +}
744 +
745 +/**
746 + * Obsolete specific cache stat charts
747 + *
748 + * Obsolete charts for cgroup/application.
749 + *
750 + * @param type the chart type.
751 + */
752 +static void ebpf_obsolete_specific_cachestat_charts(char *type)
753 +{
754 + ebpf_write_chart_obsolete(type, NETDATA_CACHESTAT_HIT_RATIO_CHART,
755 + "Hit is calculating using total cache added without dirties per total added because of red misses.",
756 + EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_CACHESTAT_SUBMENU,
757 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_CACHESTAT_HIT_RATIO_CONTEXT,
758 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5200);
759 +
760 + ebpf_write_chart_obsolete(type, NETDATA_CACHESTAT_DIRTY_CHART,
761 + "Number of dirty pages added to the page cache.",
762 + EBPF_CACHESTAT_DIMENSION_PAGE, NETDATA_CACHESTAT_SUBMENU,
763 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_CACHESTAT_MODIFIED_CACHE_CONTEXT,
764 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5201);
765 +
766 + ebpf_write_chart_obsolete(type, NETDATA_CACHESTAT_HIT_CHART,
767 + "Hits are function calls that Netdata counts.",
768 + EBPF_CACHESTAT_DIMENSION_HITS, NETDATA_CACHESTAT_SUBMENU,
769 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_CACHESTAT_HIT_FILES_CONTEXT,
770 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5202);
771 +
772 + ebpf_write_chart_obsolete(type, NETDATA_CACHESTAT_MISSES_CHART,
773 + "Misses are function calls that Netdata counts.",
774 + EBPF_CACHESTAT_DIMENSION_MISSES, NETDATA_CACHESTAT_SUBMENU,
775 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_CACHESTAT_MISS_FILES_CONTEXT,
776 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5203);
777 +}
778 +
779 +/**
780 + * Send data to Netdata calling auxiliar functions.
781 +*/
782 +void ebpf_cachestat_send_cgroup_data()
783 +{
784 + if (!ebpf_cgroup_pids)
785 + return;
786 +
787 + pthread_mutex_lock(&mutex_cgroup_shm);
788 + ebpf_cgroup_target_t *ect;
789 + ebpf_cachestat_calc_chart_values();
790 +
791 + int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
792 + if (has_systemd) {
793 + static int systemd_charts = 0;
794 + if (!systemd_charts) {
795 + ebpf_create_systemd_cachestat_charts();
796 + systemd_charts = 1;
797 + }
798 +
799 + systemd_charts = ebpf_send_systemd_cachestat_charts();
800 + }
801 +
802 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
803 + if (ect->systemd)
804 + continue;
805 +
806 + if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_CACHESTAT_CHART) && ect->updated) {
807 + ebpf_create_specific_cachestat_charts(ect->name);
808 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_CACHESTAT_CHART;
809 + }
810 +
811 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_CACHESTAT_CHART) {
812 + if (ect->updated) {
813 + ebpf_send_specific_cachestat_data(ect->name, &ect->publish_cachestat);
814 + } else {
815 + ebpf_obsolete_specific_cachestat_charts(ect->name);
816 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_CACHESTAT_CHART;
817 + }
818 + }
819 + }
820 +
821 + pthread_mutex_unlock(&mutex_cgroup_shm);
822 +}
823 +
824 /**
825 * Main loop for this collector.
826 */
@@ -517,6 +835,7 @@ static void cachestat_collector(ebpf_module_t *em)
835 netdata_publish_cachestat_t publish;
836 memset(&publish, 0, sizeof(publish));
837 int apps = em->apps_charts;
838 + int cgroups = em->cgroup_charts;
839 while (!close_ebpf_plugin) {
840 pthread_mutex_lock(&collect_data_mutex);
841 pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
@@ -524,6 +843,9 @@ static void cachestat_collector(ebpf_module_t *em)
843 if (apps)
844 read_apps_table();
845
846 + if (cgroups)
847 + ebpf_update_cachestat_cgroup();
848 +
849 pthread_mutex_lock(&lock);
850
851 cachestat_send_global(&publish);
@@ -531,6 +853,9 @@ static void cachestat_collector(ebpf_module_t *em)
853 if (apps)
854 ebpf_cache_send_apps_data(apps_groups_root_target);
855
856 + if (cgroups)
857 + ebpf_cachestat_send_cgroup_data();
858 +
859 pthread_mutex_unlock(&lock);
860 pthread_mutex_unlock(&collect_data_mutex);
861 }
@@ -597,18 +922,20 @@ static void ebpf_create_memory_charts()
922 * We are not testing the return, because callocz does this and shutdown the software
923 * case it was not possible to allocate.
924 *
600 - * @param length is the length for the vectors used inside the collector.
925 + * @param apps is apps enabled?
926 */
602 -static void ebpf_cachestat_allocate_global_vectors(size_t length)
927 +static void ebpf_cachestat_allocate_global_vectors(int apps)
928 {
604 - cachestat_pid = callocz((size_t)pid_max, sizeof(netdata_publish_cachestat_t *));
929 + if (apps)
930 + cachestat_pid = callocz((size_t)pid_max, sizeof(netdata_publish_cachestat_t *));
931 +
932 cachestat_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_cachestat_pid_t));
933
934 cachestat_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
935
609 - memset(cachestat_hash_values, 0, length * sizeof(netdata_idx_t));
610 - memset(cachestat_counter_aggregated_data, 0, length * sizeof(netdata_syscall_stat_t));
611 - memset(cachestat_counter_publish_aggregated, 0, length * sizeof(netdata_publish_syscall_t));
936 + memset(cachestat_hash_values, 0, NETDATA_CACHESTAT_END * sizeof(netdata_idx_t));
937 + memset(cachestat_counter_aggregated_data, 0, NETDATA_CACHESTAT_END * sizeof(netdata_syscall_stat_t));
938 + memset(cachestat_counter_publish_aggregated, 0, NETDATA_CACHESTAT_END * sizeof(netdata_publish_syscall_t));
939 }
940
941 /*****************************************************************
@@ -639,7 +966,7 @@ void *ebpf_cachestat_thread(void *ptr)
966 goto endcachestat;
967
968 pthread_mutex_lock(&lock);
642 - ebpf_cachestat_allocate_global_vectors(NETDATA_CACHESTAT_END);
969 + ebpf_cachestat_allocate_global_vectors(em->apps_charts);
970
971 probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string, &objects);
972 if (!probe_links) {
collectors/ebpf.plugin/ebpf_cachestat.h
+12
@@ -13,6 +13,7 @@
13 #define NETDATA_CACHESTAT_MISSES_CHART "cachestat_misses"
14
15 #define NETDATA_CACHESTAT_SUBMENU "page_cache"
16 +#define NETDATA_CACHESTAT_CGROUP_SUBMENU "page cache (eBPF)"
17
18 #define EBPF_CACHESTAT_DIMENSION_PAGE "pages/s"
19 #define EBPF_CACHESTAT_DIMENSION_HITS "hits/s"
@@ -23,6 +24,17 @@
24 // configuration file
25 #define NETDATA_CACHESTAT_CONFIG_FILE "cachestat.conf"
26
27 +// Contexts
28 +#define NETDATA_CGROUP_CACHESTAT_HIT_RATIO_CONTEXT "cgroup.cachestat_ratio"
29 +#define NETDATA_CGROUP_CACHESTAT_MODIFIED_CACHE_CONTEXT "cgroup.cachestat_dirties"
30 +#define NETDATA_CGROUP_CACHESTAT_HIT_FILES_CONTEXT "cgroup.cachestat_hits"
31 +#define NETDATA_CGROUP_CACHESTAT_MISS_FILES_CONTEXT "cgroup.cachestat_misses"
32 +
33 +#define NETDATA_SYSTEMD_CACHESTAT_HIT_RATIO_CONTEXT "services.cachestat_ratio"
34 +#define NETDATA_SYSTEMD_CACHESTAT_MODIFIED_CACHE_CONTEXT "services.cachestat_dirties"
35 +#define NETDATA_SYSTEMD_CACHESTAT_HIT_FILE_CONTEXT "services.cachestat_hits"
36 +#define NETDATA_SYSTEMD_CACHESTAT_MISS_FILES_CONTEXT "services.cachestat_misses"
37 +
38 // variables
39 enum cachestat_counters {
40 NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU,
collectors/ebpf.plugin/ebpf_cgroup.h
+6
@@ -20,6 +20,9 @@ struct pid_on_target2 {
20 netdata_publish_vfs_t vfs;
21 ebpf_process_stat_t ps;
22 netdata_dcstat_pid_t dc;
23 + netdata_publish_shm_t shm;
24 + ebpf_bandwidth_t socket;
25 + netdata_cachestat_pid_t cachestat;
26
27 struct pid_on_target2 *next;
28 };
@@ -49,6 +52,9 @@ typedef struct ebpf_cgroup_target {
52 ebpf_process_stat_t publish_systemd_ps;
53 netdata_publish_dcstat_t publish_dc;
54 int oomkill;
55 + netdata_publish_shm_t publish_shm;
56 + ebpf_socket_publish_apps_t publish_socket;
57 + netdata_publish_cachestat_t publish_cachestat;
58
59 struct pid_on_target2 *pids;
60 struct ebpf_cgroup_target *next;
collectors/ebpf.plugin/ebpf_dcstat.c
+14 -15
@@ -303,7 +303,7 @@ static void ebpf_update_dc_cgroup()
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]) {
306 + if (likely(dcstat_pid) && dcstat_pid[pid]) {
307 netdata_publish_dcstat_t *in = dcstat_pid[pid];
308
309 memcpy(out, &in->curr, sizeof(netdata_dcstat_pid_t));
@@ -601,14 +601,11 @@ void ebpf_dc_sum_cgroup_pids(netdata_publish_dcstat_t *publish, struct pid_on_ta
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 - }
604 + netdata_dcstat_pid_t *src = &root->dc;
605 +
606 + dst->cache_access += src->cache_access;
607 + dst->file_system += src->file_system;
608 + dst->not_found += src->not_found;
609
610 root = root->next;
611 }
@@ -903,16 +900,18 @@ static void ebpf_create_filesystem_charts()
900 * We are not testing the return, because callocz does this and shutdown the software
901 * case it was not possible to allocate.
902 *
906 - * @param length is the length for the vectors used inside the collector.
903 + * @param apps is apps enabled?
904 */
908 -static void ebpf_dcstat_allocate_global_vectors(size_t length)
905 +static void ebpf_dcstat_allocate_global_vectors(int apps)
906 {
910 - dcstat_pid = callocz((size_t)pid_max, sizeof(netdata_publish_dcstat_t *));
907 + if (apps)
908 + dcstat_pid = callocz((size_t)pid_max, sizeof(netdata_publish_dcstat_t *));
909 +
910 dcstat_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_dcstat_pid_t));
911 dcstat_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
912
914 - memset(dcstat_counter_aggregated_data, 0, length*sizeof(netdata_syscall_stat_t));
915 - memset(dcstat_counter_publish_aggregated, 0, length*sizeof(netdata_publish_syscall_t));
913 + memset(dcstat_counter_aggregated_data, 0, NETDATA_DCSTAT_IDX_END * sizeof(netdata_syscall_stat_t));
914 + memset(dcstat_counter_publish_aggregated, 0, NETDATA_DCSTAT_IDX_END * sizeof(netdata_publish_syscall_t));
915 }
916
917 /*****************************************************************
@@ -944,7 +943,7 @@ void *ebpf_dcstat_thread(void *ptr)
943 if (!em->enabled)
944 goto enddcstat;
945
947 - ebpf_dcstat_allocate_global_vectors(NETDATA_DCSTAT_IDX_END);
946 + ebpf_dcstat_allocate_global_vectors(em->apps_charts);
947
948 pthread_mutex_lock(&lock);
949
collectors/ebpf.plugin/ebpf_fd.c
+10 -6
@@ -39,7 +39,7 @@ static netdata_idx_t fd_hash_values[NETDATA_FD_COUNTER];
39 static netdata_idx_t *fd_values = NULL;
40
41 netdata_fd_stat_t *fd_vector = NULL;
42 -netdata_fd_stat_t **fd_pid;
42 +netdata_fd_stat_t **fd_pid = NULL;
43
44 /*****************************************************************
45 *
@@ -267,7 +267,7 @@ static void ebpf_update_fd_cgroup()
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]) {
270 + if (likely(fd_pid) && fd_pid[pid]) {
271 netdata_fd_stat_t *in = fd_pid[pid];
272
273 memcpy(out, in, sizeof(netdata_fd_stat_t));
@@ -276,7 +276,7 @@ static void ebpf_update_fd_cgroup()
276 if (!bpf_map_lookup_elem(fd, &pid, fv)) {
277 fd_apps_accumulator(fv);
278
279 - memcpy(out, fv, sizeof(netdata_publish_swap_t));
279 + memcpy(out, fv, sizeof(netdata_fd_stat_t));
280 }
281 }
282 }
@@ -801,10 +801,14 @@ static void ebpf_create_fd_global_charts(ebpf_module_t *em)
801 *
802 * We are not testing the return, because callocz does this and shutdown the software
803 * case it was not possible to allocate.
804 + *
805 + * @param apps is apps enabled?
806 */
805 -static void ebpf_fd_allocate_global_vectors()
807 +static void ebpf_fd_allocate_global_vectors(int apps)
808 {
807 - fd_pid = callocz((size_t)pid_max, sizeof(netdata_fd_stat_t *));
809 + if (apps)
810 + fd_pid = callocz((size_t)pid_max, sizeof(netdata_fd_stat_t *));
811 +
812 fd_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_fd_stat_t));
813
814 fd_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
@@ -829,7 +833,7 @@ void *ebpf_fd_thread(void *ptr)
833 if (!em->enabled)
834 goto endfd;
835
832 - ebpf_fd_allocate_global_vectors();
836 + ebpf_fd_allocate_global_vectors(em->apps_charts);
837
838 probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string, &objects);
839 if (!probe_links) {
collectors/ebpf.plugin/ebpf_shm.c
+337 -4
@@ -136,6 +136,46 @@ static void shm_fill_pid(uint32_t current_pid, netdata_publish_shm_t *publish)
136 memcpy(curr, publish, sizeof(netdata_publish_shm_t));
137 }
138
139 +/**
140 + * Update cgroup
141 + *
142 + * Update cgroup data based in
143 + */
144 +static void ebpf_update_shm_cgroup()
145 +{
146 + netdata_publish_shm_t *cv = shm_vector;
147 + int fd = shm_maps[NETDATA_PID_SHM_TABLE].map_fd;
148 + size_t length = sizeof(netdata_publish_shm_t) * ebpf_nprocs;
149 + ebpf_cgroup_target_t *ect;
150 +
151 + memset(cv, 0, length);
152 +
153 + pthread_mutex_lock(&mutex_cgroup_shm);
154 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
155 + struct pid_on_target2 *pids;
156 + for (pids = ect->pids; pids; pids = pids->next) {
157 + int pid = pids->pid;
158 + netdata_publish_shm_t *out = &pids->shm;
159 + if (likely(shm_pid) && shm_pid[pid]) {
160 + netdata_publish_shm_t *in = shm_pid[pid];
161 +
162 + memcpy(out, in, sizeof(netdata_publish_shm_t));
163 + } else {
164 + if (!bpf_map_lookup_elem(fd, &pid, cv)) {
165 + shm_apps_accumulator(cv);
166 +
167 + memcpy(out, cv, sizeof(netdata_publish_shm_t));
168 +
169 + // now that we've consumed the value, zero it out in the map.
170 + memset(cv, 0, length);
171 + bpf_map_update_elem(fd, &pid, cv, BPF_EXIST);
172 + }
173 + }
174 + }
175 + }
176 + pthread_mutex_unlock(&mutex_cgroup_shm);
177 +}
178 +
179 /**
180 * Read APPS table
181 *
@@ -315,6 +355,288 @@ void ebpf_shm_send_apps_data(struct target *root)
355 write_end_chart();
356 }
357
358 +/**
359 + * Sum values for all targets.
360 + */
361 +static void ebpf_shm_sum_cgroup_pids(netdata_publish_shm_t *shm, struct pid_on_target2 *root)
362 +{
363 + netdata_publish_shm_t shmv;
364 + memset(&shmv, 0, sizeof(shmv));
365 + while (root) {
366 + netdata_publish_shm_t *w = &root->shm;
367 + shmv.get += w->get;
368 + shmv.at += w->at;
369 + shmv.dt += w->dt;
370 + shmv.ctl += w->ctl;
371 +
372 + root = root->next;
373 + }
374 +
375 + memcpy(shm, &shmv, sizeof(shmv));
376 +}
377 +
378 +/**
379 + * Create specific shared memory charts
380 + *
381 + * Create charts for cgroup/application.
382 + *
383 + * @param type the chart type.
384 + */
385 +static void ebpf_create_specific_shm_charts(char *type)
386 +{
387 + ebpf_create_chart(type, NETDATA_SHMGET_CHART,
388 + "Calls to syscall <code>shmget(2)</code>.",
389 + EBPF_COMMON_DIMENSION_CALL,
390 + NETDATA_APPS_IPC_SHM_GROUP,
391 + NETDATA_CGROUP_SHM_GET_CONTEXT,
392 + NETDATA_EBPF_CHART_TYPE_LINE,
393 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5800,
394 + ebpf_create_global_dimension,
395 + &shm_publish_aggregated[NETDATA_KEY_SHMGET_CALL],
396 + 1,
397 + NETDATA_EBPF_MODULE_NAME_SHM);
398 +
399 + ebpf_create_chart(type, NETDATA_SHMAT_CHART,
400 + "Calls to syscall <code>shmat(2)</code>.",
401 + EBPF_COMMON_DIMENSION_CALL,
402 + NETDATA_APPS_IPC_SHM_GROUP,
403 + NETDATA_CGROUP_SHM_AT_CONTEXT,
404 + NETDATA_EBPF_CHART_TYPE_LINE,
405 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5801,
406 + ebpf_create_global_dimension,
407 + &shm_publish_aggregated[NETDATA_KEY_SHMAT_CALL],
408 + 1,
409 + NETDATA_EBPF_MODULE_NAME_SHM);
410 +
411 + ebpf_create_chart(type, NETDATA_SHMDT_CHART,
412 + "Calls to syscall <code>shmdt(2)</code>.",
413 + EBPF_COMMON_DIMENSION_CALL,
414 + NETDATA_APPS_IPC_SHM_GROUP,
415 + NETDATA_CGROUP_SHM_DT_CONTEXT,
416 + NETDATA_EBPF_CHART_TYPE_LINE,
417 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5802,
418 + ebpf_create_global_dimension,
419 + &shm_publish_aggregated[NETDATA_KEY_SHMDT_CALL],
420 + 1,
421 + NETDATA_EBPF_MODULE_NAME_SHM);
422 +
423 + ebpf_create_chart(type, NETDATA_SHMCTL_CHART,
424 + "Calls to syscall <code>shmctl(2)</code>.",
425 + EBPF_COMMON_DIMENSION_CALL,
426 + NETDATA_APPS_IPC_SHM_GROUP,
427 + NETDATA_CGROUP_SHM_CTL_CONTEXT,
428 + NETDATA_EBPF_CHART_TYPE_LINE,
429 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5803,
430 + ebpf_create_global_dimension,
431 + &shm_publish_aggregated[NETDATA_KEY_SHMCTL_CALL],
432 + 1,
433 + NETDATA_EBPF_MODULE_NAME_SHM);
434 +}
435 +
436 +/**
437 + * Obsolete specific shared memory charts
438 + *
439 + * Obsolete charts for cgroup/application.
440 + *
441 + * @param type the chart type.
442 + */
443 +static void ebpf_obsolete_specific_shm_charts(char *type)
444 +{
445 + ebpf_write_chart_obsolete(type, NETDATA_SHMGET_CHART,
446 + "Calls to syscall <code>shmget(2)</code>.",
447 + EBPF_COMMON_DIMENSION_CALL,
448 + NETDATA_APPS_IPC_SHM_GROUP,
449 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_GET_CONTEXT,
450 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5800);
451 +
452 + ebpf_write_chart_obsolete(type, NETDATA_SHMAT_CHART,
453 + "Calls to syscall <code>shmat(2)</code>.",
454 + EBPF_COMMON_DIMENSION_CALL,
455 + NETDATA_APPS_IPC_SHM_GROUP,
456 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_AT_CONTEXT,
457 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5801);
458 +
459 + ebpf_write_chart_obsolete(type, NETDATA_SHMDT_CHART,
460 + "Calls to syscall <code>shmdt(2)</code>.",
461 + EBPF_COMMON_DIMENSION_CALL,
462 + NETDATA_APPS_IPC_SHM_GROUP,
463 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_DT_CONTEXT,
464 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5802);
465 +
466 + ebpf_write_chart_obsolete(type, NETDATA_SHMCTL_CHART,
467 + "Calls to syscall <code>shmctl(2)</code>.",
468 + EBPF_COMMON_DIMENSION_CALL,
469 + NETDATA_APPS_IPC_SHM_GROUP,
470 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_CTL_CONTEXT,
471 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5803);
472 +}
473 +
474 +/**
475 + * Create Systemd Swap Charts
476 + *
477 + * Create charts when systemd is enabled
478 + **/
479 +static void ebpf_create_systemd_shm_charts()
480 +{
481 + ebpf_create_charts_on_systemd(NETDATA_SHMGET_CHART,
482 + "Calls to syscall <code>shmget(2)</code>.",
483 + EBPF_COMMON_DIMENSION_CALL,
484 + NETDATA_APPS_IPC_SHM_GROUP,
485 + NETDATA_EBPF_CHART_TYPE_STACKED,
486 + 20191,
487 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
488 + NETDATA_SYSTEMD_SHM_GET_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM);
489 +
490 + ebpf_create_charts_on_systemd(NETDATA_SHMAT_CHART,
491 + "Calls to syscall <code>shmat(2)</code>.",
492 + EBPF_COMMON_DIMENSION_CALL,
493 + NETDATA_APPS_IPC_SHM_GROUP,
494 + NETDATA_EBPF_CHART_TYPE_STACKED,
495 + 20192,
496 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
497 + NETDATA_SYSTEMD_SHM_AT_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM);
498 +
499 + ebpf_create_charts_on_systemd(NETDATA_SHMDT_CHART,
500 + "Calls to syscall <code>shmdt(2)</code>.",
501 + EBPF_COMMON_DIMENSION_CALL,
502 + NETDATA_APPS_IPC_SHM_GROUP,
503 + NETDATA_EBPF_CHART_TYPE_STACKED,
504 + 20193,
505 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
506 + NETDATA_SYSTEMD_SHM_DT_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM);
507 +
508 + ebpf_create_charts_on_systemd(NETDATA_SHMCTL_CHART,
509 + "Calls to syscall <code>shmctl(2)</code>.",
510 + EBPF_COMMON_DIMENSION_CALL,
511 + NETDATA_APPS_IPC_SHM_GROUP,
512 + NETDATA_EBPF_CHART_TYPE_STACKED,
513 + 20193,
514 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
515 + NETDATA_SYSTEMD_SHM_CTL_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM);
516 +}
517 +
518 +/**
519 + * Send Systemd charts
520 + *
521 + * Send collected data to Netdata.
522 + *
523 + * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
524 + * otherwise function returns 1 to avoid chart recreation
525 + */
526 +static int ebpf_send_systemd_shm_charts()
527 +{
528 + int ret = 1;
529 + ebpf_cgroup_target_t *ect;
530 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMGET_CHART);
531 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
532 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
533 + write_chart_dimension(ect->name, (long long)ect->publish_shm.get);
534 + } else
535 + ret = 0;
536 + }
537 + write_end_chart();
538 +
539 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMAT_CHART);
540 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
541 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
542 + write_chart_dimension(ect->name, (long long)ect->publish_shm.at);
543 + }
544 + }
545 + write_end_chart();
546 +
547 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMDT_CHART);
548 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
549 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
550 + write_chart_dimension(ect->name, (long long)ect->publish_shm.dt);
551 + }
552 + }
553 + write_end_chart();
554 +
555 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMCTL_CHART);
556 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
557 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
558 + write_chart_dimension(ect->name, (long long)ect->publish_shm.ctl);
559 + }
560 + }
561 + write_end_chart();
562 +
563 + return ret;
564 +}
565 +
566 +/*
567 + * Send Specific Shared memory data
568 + *
569 + * Send data for specific cgroup/apps.
570 + *
571 + * @param type chart type
572 + * @param values structure with values that will be sent to netdata
573 + */
574 +static void ebpf_send_specific_shm_data(char *type, netdata_publish_shm_t *values)
575 +{
576 + write_begin_chart(type, NETDATA_SHMGET_CHART);
577 + write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMGET_CALL].name, (long long)values->get);
578 + write_end_chart();
579 +
580 + write_begin_chart(type, NETDATA_SHMAT_CHART);
581 + write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMAT_CALL].name, (long long)values->at);
582 + write_end_chart();
583 +
584 + write_begin_chart(type, NETDATA_SHMDT_CHART);
585 + write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMDT_CALL].name, (long long)values->dt);
586 + write_end_chart();
587 +
588 + write_begin_chart(type, NETDATA_SHMCTL_CHART);
589 + write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMCTL_CALL].name, (long long)values->ctl);
590 + write_end_chart();
591 +}
592 +
593 +/**
594 + * Send data to Netdata calling auxiliar functions.
595 +*/
596 +void ebpf_shm_send_cgroup_data()
597 +{
598 + if (!ebpf_cgroup_pids)
599 + return;
600 +
601 + pthread_mutex_lock(&mutex_cgroup_shm);
602 + ebpf_cgroup_target_t *ect;
603 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
604 + ebpf_shm_sum_cgroup_pids(&ect->publish_shm, ect->pids);
605 + }
606 +
607 + int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
608 + if (has_systemd) {
609 + static int systemd_charts = 0;
610 + if (!systemd_charts) {
611 + ebpf_create_systemd_shm_charts();
612 + systemd_charts = 1;
613 + }
614 +
615 + systemd_charts = ebpf_send_systemd_shm_charts();
616 + }
617 +
618 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
619 + if (ect->systemd)
620 + continue;
621 +
622 + if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_SHM_CHART) && ect->updated) {
623 + ebpf_create_specific_shm_charts(ect->name);
624 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_SHM_CHART;
625 + }
626 +
627 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_SHM_CHART) {
628 + if (ect->updated) {
629 + ebpf_send_specific_shm_data(ect->name, &ect->publish_shm);
630 + } else {
631 + ebpf_obsolete_specific_shm_charts(ect->name);
632 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_SWAP_CHART;
633 + }
634 + }
635 + }
636 +
637 + pthread_mutex_unlock(&mutex_cgroup_shm);
638 +}
639 +
640 /**
641 * Main loop for this collector.
642 */
@@ -332,6 +654,7 @@ static void shm_collector(ebpf_module_t *em)
654 );
655
656 int apps = em->apps_charts;
657 + int cgroups = em->cgroup_charts;
658 while (!close_ebpf_plugin) {
659 pthread_mutex_lock(&collect_data_mutex);
660 pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
@@ -340,6 +663,10 @@ static void shm_collector(ebpf_module_t *em)
663 read_apps_table();
664 }
665
666 + if (cgroups) {
667 + ebpf_update_shm_cgroup();
668 + }
669 +
670 pthread_mutex_lock(&lock);
671
672 shm_send_global();
@@ -348,6 +675,10 @@ static void shm_collector(ebpf_module_t *em)
675 ebpf_shm_send_apps_data(apps_groups_root_target);
676 }
677
678 + if (cgroups) {
679 + ebpf_shm_send_cgroup_data();
680 + }
681 +
682 pthread_mutex_unlock(&lock);
683 pthread_mutex_unlock(&collect_data_mutex);
684 }
@@ -412,11 +743,13 @@ void ebpf_shm_create_apps_charts(struct ebpf_module *em, void *ptr)
743 * We are not testing the return, because callocz does this and shutdown the software
744 * case it was not possible to allocate.
745 *
415 - * @param length is the length for the vectors used inside the collector.
746 + * @param apps is apps enabled?
747 */
417 -static void ebpf_shm_allocate_global_vectors()
748 +static void ebpf_shm_allocate_global_vectors(int apps)
749 {
419 - shm_pid = callocz((size_t)pid_max, sizeof(netdata_publish_shm_t *));
750 + if (apps)
751 + shm_pid = callocz((size_t)pid_max, sizeof(netdata_publish_shm_t *));
752 +
753 shm_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_publish_shm_t));
754
755 shm_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
@@ -477,7 +810,7 @@ void *ebpf_shm_thread(void *ptr)
810 goto endshm;
811 }
812
480 - ebpf_shm_allocate_global_vectors();
813 + ebpf_shm_allocate_global_vectors(em->apps_charts);
814
815 int algorithms[NETDATA_SHM_END] = {
816 NETDATA_EBPF_INCREMENTAL_IDX,
collectors/ebpf.plugin/ebpf_shm.h
+11
@@ -18,6 +18,17 @@
18 // configuration file
19 #define NETDATA_DIRECTORY_SHM_CONFIG_FILE "shm.conf"
20
21 +// Contexts
22 +#define NETDATA_CGROUP_SHM_GET_CONTEXT "cgroup.shmget"
23 +#define NETDATA_CGROUP_SHM_AT_CONTEXT "cgroup.shmat"
24 +#define NETDATA_CGROUP_SHM_DT_CONTEXT "cgroup.shmdt"
25 +#define NETDATA_CGROUP_SHM_CTL_CONTEXT "cgroup.shmctl"
26 +
27 +#define NETDATA_SYSTEMD_SHM_GET_CONTEXT "services.shmget"
28 +#define NETDATA_SYSTEMD_SHM_AT_CONTEXT "services.shmat"
29 +#define NETDATA_SYSTEMD_SHM_DT_CONTEXT "services.shmdt"
30 +#define NETDATA_SYSTEMD_SHM_CTL_CONTEXT "services.shmctl"
31 +
32 typedef struct netdata_publish_shm {
33 uint64_t get;
34 uint64_t at;
collectors/ebpf.plugin/ebpf_socket.c
+467 -7
@@ -1619,6 +1619,455 @@ static void ebpf_socket_update_apps_data()
1619 }
1620 }
1621
1622 +/**
1623 + * Update cgroup
1624 + *
1625 + * Update cgroup data based in
1626 + */
1627 +static void ebpf_update_socket_cgroup()
1628 +{
1629 + ebpf_cgroup_target_t *ect ;
1630 +
1631 + ebpf_bandwidth_t *eb = bandwidth_vector;
1632 + int fd = socket_maps[NETDATA_SOCKET_TABLE_BANDWIDTH].map_fd;
1633 +
1634 + pthread_mutex_lock(&mutex_cgroup_shm);
1635 + for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
1636 + struct pid_on_target2 *pids;
1637 + for (pids = ect->pids; pids; pids = pids->next) {
1638 + int pid = pids->pid;
1639 + ebpf_bandwidth_t *out = &pids->socket;
1640 + ebpf_socket_publish_apps_t *publish = &ect->publish_socket;
1641 + if (likely(socket_bandwidth_curr) && socket_bandwidth_curr[pid]) {
1642 + ebpf_socket_publish_apps_t *in = socket_bandwidth_curr[pid];
1643 +
1644 + publish->bytes_sent = in->bytes_sent;
1645 + publish->bytes_received = in->bytes_received;
1646 + publish->call_tcp_sent = in->call_tcp_sent;
1647 + publish->call_tcp_received = in->call_tcp_received;
1648 + publish->retransmit = in->retransmit;
1649 + publish->call_udp_sent = in->call_udp_sent;
1650 + publish->call_udp_received = in->call_udp_received;
1651 + } else {
1652 + if (!bpf_map_lookup_elem(fd, &pid, eb)) {
1653 + ebpf_socket_bandwidth_accumulator(eb);
1654 +
1655 + memcpy(out, eb, sizeof(ebpf_bandwidth_t));
1656 +
1657 + publish->bytes_sent = out->bytes_sent;
1658 + publish->bytes_received = out->bytes_received;
1659 + publish->call_tcp_sent = out->call_tcp_sent;
1660 + publish->call_tcp_received = out->call_tcp_received;
1661 + publish->retransmit = out->retransmit;
1662 + publish->call_udp_sent = out->call_udp_sent;
1663 + publish->call_udp_received = out->call_udp_received;
1664 + }
1665 + }
1666 + }
1667 + }
1668 + pthread_mutex_unlock(&mutex_cgroup_shm);
1669 +}
1670 +
1671 +/**
1672 + * Sum PIDs
1673 + *
1674 + * Sum values for all targets.
1675 + *
1676 + * @param fd structure used to store data
1677 + * @param pids input data
1678 + */
1679 +static void ebpf_socket_sum_cgroup_pids(ebpf_socket_publish_apps_t *socket, struct pid_on_target2 *pids)
1680 +{
1681 + ebpf_socket_publish_apps_t accumulator;
1682 + memset(&accumulator, 0, sizeof(accumulator));
1683 +
1684 + while (pids) {
1685 + ebpf_bandwidth_t *w = &pids->socket;
1686 +
1687 + accumulator.bytes_received += w->bytes_received;
1688 + accumulator.bytes_sent += w->bytes_sent;
1689 + accumulator.call_tcp_received += w->call_tcp_received;
1690 + accumulator.call_tcp_sent += w->call_tcp_sent;
1691 + accumulator.retransmit += w->retransmit;
1692 + accumulator.call_udp_received += w->call_udp_received;
1693 + accumulator.call_udp_sent += w->call_udp_sent;
1694 +
1695 + pids = pids->next;
1696 + }
1697 +
1698 + socket->bytes_sent = (accumulator.bytes_sent >= socket->bytes_sent) ? accumulator.bytes_sent : socket->bytes_sent;
1699 + socket->bytes_received = (accumulator.bytes_received >= socket->bytes_received) ? accumulator.bytes_received : socket->bytes_received;
1700 + socket->call_tcp_sent = (accumulator.call_tcp_sent >= socket->call_tcp_sent) ? accumulator.call_tcp_sent : socket->call_tcp_sent;
1701 + socket->call_tcp_received = (accumulator.call_tcp_received >= socket->call_tcp_received) ? accumulator.call_tcp_received : socket->call_tcp_received;
1702 + socket->retransmit = (accumulator.retransmit >= socket->retransmit) ? accumulator.retransmit : socket->retransmit;
1703 + socket->call_udp_sent = (accumulator.call_udp_sent >= socket->call_udp_sent) ? accumulator.call_udp_sent : socket->call_udp_sent;
1704 + socket->call_udp_received = (accumulator.call_udp_received >= socket->call_udp_received) ? accumulator.call_udp_received : socket->call_udp_received;
1705 +}
1706 +
1707 +/**
1708 + * Create specific socket charts
1709 + *
1710 + * Create charts for cgroup/application.
1711 + *
1712 + * @param type the chart type.
1713 + */
1714 +static void ebpf_create_specific_socket_charts(char *type)
1715 +{
1716 + ebpf_create_chart(type, NETDATA_NET_APPS_BANDWIDTH_RECV,
1717 + "Bytes received",
1718 + EBPF_COMMON_DIMENSION_CALL, NETDATA_CGROUP_NET_GROUP,
1719 + NETDATA_CGROUP_SOCKET_BYTES_RECV_CONTEXT,
1720 + NETDATA_EBPF_CHART_TYPE_LINE,
1721 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5300,
1722 + ebpf_create_global_dimension,
1723 + &socket_publish_aggregated[NETDATA_IDX_TCP_CLEANUP_RBUF], 1, NETDATA_EBPF_MODULE_NAME_SWAP);
1724 +
1725 + ebpf_create_chart(type, NETDATA_NET_APPS_BANDWIDTH_SENT,
1726 + "Bytes sent",
1727 + EBPF_COMMON_DIMENSION_CALL, NETDATA_CGROUP_NET_GROUP,
1728 + NETDATA_CGROUP_SOCKET_BYTES_SEND_CONTEXT,
1729 + NETDATA_EBPF_CHART_TYPE_LINE,
1730 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5301,
1731 + ebpf_create_global_dimension,
1732 + socket_publish_aggregated, 1, NETDATA_EBPF_MODULE_NAME_SWAP);
1733 +
1734 + ebpf_create_chart(type, NETDATA_NET_APPS_BANDWIDTH_TCP_RECV_CALLS,
1735 + "Calls to tcp_cleanup_rbuf.",
1736 + EBPF_COMMON_DIMENSION_CALL, NETDATA_CGROUP_NET_GROUP,
1737 + NETDATA_CGROUP_SOCKET_TCP_RECV_CONTEXT,
1738 + NETDATA_EBPF_CHART_TYPE_LINE,
1739 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5302,
1740 + ebpf_create_global_dimension,
1741 + &socket_publish_aggregated[NETDATA_IDX_TCP_CLEANUP_RBUF], 1, NETDATA_EBPF_MODULE_NAME_SWAP);
1742 +
1743 + ebpf_create_chart(type, NETDATA_NET_APPS_BANDWIDTH_TCP_SEND_CALLS,
1744 + "Calls to tcp_sendmsg.",
1745 + EBPF_COMMON_DIMENSION_CALL, NETDATA_CGROUP_NET_GROUP,
1746 + NETDATA_CGROUP_SOCKET_TCP_SEND_CONTEXT,
1747 + NETDATA_EBPF_CHART_TYPE_LINE,
1748 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5303,
1749 + ebpf_create_global_dimension,
1750 + socket_publish_aggregated, 1, NETDATA_EBPF_MODULE_NAME_SWAP);
1751 +
1752 + ebpf_create_chart(type, NETDATA_NET_APPS_BANDWIDTH_TCP_RETRANSMIT,
1753 + "Calls to tcp_retransmit.",
1754 + EBPF_COMMON_DIMENSION_CALL, NETDATA_CGROUP_NET_GROUP,
1755 + NETDATA_CGROUP_SOCKET_TCP_RETRANSMIT_CONTEXT,
1756 + NETDATA_EBPF_CHART_TYPE_LINE,
1757 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5304,
1758 + ebpf_create_global_dimension,
1759 + &socket_publish_aggregated[NETDATA_IDX_TCP_RETRANSMIT], 1, NETDATA_EBPF_MODULE_NAME_SWAP);
1760 +
1761 + ebpf_create_chart(type, NETDATA_NET_APPS_BANDWIDTH_UDP_SEND_CALLS,
1762 + "Calls to udp_sendmsg",
1763 + EBPF_COMMON_DIMENSION_CALL, NETDATA_CGROUP_NET_GROUP,
1764 + NETDATA_CGROUP_SOCKET_UDP_SEND_CONTEXT,
1765 + NETDATA_EBPF_CHART_TYPE_LINE,
1766 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5305,
1767 + ebpf_create_global_dimension,
1768 + &socket_publish_aggregated[NETDATA_IDX_UDP_SENDMSG], 1, NETDATA_EBPF_MODULE_NAME_SWAP);
1769 +
1770 + ebpf_create_chart(type, NETDATA_NET_APPS_BANDWIDTH_UDP_RECV_CALLS,
1771 + "Calls to udp_recvmsg",
1772 + EBPF_COMMON_DIMENSION_CALL, NETDATA_CGROUP_NET_GROUP,
1773 + NETDATA_CGROUP_SOCKET_UDP_RECV_CONTEXT,
1774 + NETDATA_EBPF_CHART_TYPE_LINE,
1775 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5306,
1776 + ebpf_create_global_dimension,
1777 + &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF], 1, NETDATA_EBPF_MODULE_NAME_SWAP);
1778 +}
1779 +
1780 +/**
1781 + * Obsolete specific socket charts
1782 + *
1783 + * Obsolete charts for cgroup/application.
1784 + *
1785 + * @param type the chart type.
1786 + */
1787 +static void ebpf_obsolete_specific_socket_charts(char *type)
1788 +{
1789 + ebpf_write_chart_obsolete(type, NETDATA_NET_APPS_BANDWIDTH_RECV, "Bytes received",
1790 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP,
1791 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_SERVICES_SOCKET_BYTES_RECV_CONTEXT,
1792 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5300);
1793 +
1794 + ebpf_write_chart_obsolete(type, NETDATA_NET_APPS_BANDWIDTH_SENT,"Bytes sent",
1795 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP,
1796 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_SERVICES_SOCKET_BYTES_SEND_CONTEXT,
1797 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5301);
1798 +
1799 + ebpf_write_chart_obsolete(type, NETDATA_NET_APPS_BANDWIDTH_TCP_RECV_CALLS, "Calls to tcp_cleanup_rbuf.",
1800 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP,
1801 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_SERVICES_SOCKET_TCP_RECV_CONTEXT,
1802 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5302);
1803 +
1804 + ebpf_write_chart_obsolete(type, NETDATA_NET_APPS_BANDWIDTH_TCP_SEND_CALLS, "Calls to tcp_sendmsg.",
1805 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP,
1806 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_SERVICES_SOCKET_TCP_SEND_CONTEXT,
1807 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5303);
1808 +
1809 + ebpf_write_chart_obsolete(type, NETDATA_NET_APPS_BANDWIDTH_TCP_RETRANSMIT, "Calls to tcp_retransmit.",
1810 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP,
1811 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_SERVICES_SOCKET_TCP_RETRANSMIT_CONTEXT,
1812 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5304);
1813 +
1814 + ebpf_write_chart_obsolete(type, NETDATA_NET_APPS_BANDWIDTH_UDP_SEND_CALLS, "Calls to udp_sendmsg",
1815 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP,
1816 + NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_SERVICES_SOCKET_UDP_SEND_CONTEXT,
1817 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5305);
1818 +
1819 + ebpf_write_chart_obsolete(type, NETDATA_NET_APPS_BANDWIDTH_UDP_RECV_CALLS, "Calls to udp_recvmsg",
1820 + EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP, NETDATA_EBPF_CHART_TYPE_LINE,
1821 + NETDATA_SERVICES_SOCKET_UDP_RECV_CONTEXT,
1822 + NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5306);
1823 +}
1824 +
1825 +/*
1826 + * Send Specific Swap data
1827 + *
1828 + * Send data for specific cgroup/apps.
1829 + *
1830 + * @param type chart type
1831 + * @param values structure with values that will be sent to netdata
1832 + */
1833 +static void ebpf_send_specific_socket_data(char *type, ebpf_socket_publish_apps_t *values)
1834 +{
1835 + write_begin_chart(type, NETDATA_NET_APPS_BANDWIDTH_SENT);
1836 + write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_TCP_SENDMSG].name,
1837 + (long long) values->bytes_sent);
1838 + write_end_chart();
1839 +
1840 + write_begin_chart(type, NETDATA_NET_APPS_BANDWIDTH_RECV);
1841 + write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_TCP_CLEANUP_RBUF].name,
1842 + (long long) values->bytes_received);
1843 + write_end_chart();
1844 +
1845 + write_begin_chart(type, NETDATA_NET_APPS_BANDWIDTH_TCP_SEND_CALLS);
1846 + write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_TCP_SENDMSG].name,
1847 + (long long) values->call_tcp_sent);
1848 + write_end_chart();
1849 +
1850 + write_begin_chart(type, NETDATA_NET_APPS_BANDWIDTH_TCP_RECV_CALLS);
1851 + write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_TCP_CLEANUP_RBUF].name,
1852 + (long long) values->call_tcp_received);
1853 + write_end_chart();
1854 +
1855 + write_begin_chart(type, NETDATA_NET_APPS_BANDWIDTH_TCP_RETRANSMIT);
1856 + write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_TCP_RETRANSMIT].name,
1857 + (long long) values->retransmit);
1858 + write_end_chart();
1859 +
1860 + write_begin_chart(type, NETDATA_NET_APPS_BANDWIDTH_UDP_SEND_CALLS);
1861 + write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_UDP_SENDMSG].name,
1862 + (long long) values->call_udp_sent);
1863 + write_end_chart();
1864 +
1865 + write_begin_chart(type, NETDATA_NET_APPS_BANDWIDTH_UDP_RECV_CALLS);
1866 + write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF].name,
1867 + (long long) values->call_udp_received);
1868 + write_end_chart();
1869 +}
1870 +
1871 +/**
1872 + * Create Systemd Socket Charts
1873 + *
1874 + * Create charts when systemd is enabled
1875 + **/
1876 +static void ebpf_create_systemd_socket_charts()
1877 +{
1878 + ebpf_create_charts_on_systemd(NETDATA_NET_APPS_BANDWIDTH_RECV,
1879 + "Bytes received", EBPF_COMMON_DIMENSION_BITS,
1880 + NETDATA_APPS_NET_GROUP,
1881 + NETDATA_EBPF_CHART_TYPE_STACKED,
1882 + 20080,
1883 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
1884 + NETDATA_SERVICES_SOCKET_BYTES_RECV_CONTEXT, NETDATA_EBPF_MODULE_NAME_SOCKET);
1885 +
1886 + ebpf_create_charts_on_systemd(NETDATA_NET_APPS_BANDWIDTH_SENT,
1887 + "Bytes sent", EBPF_COMMON_DIMENSION_BITS,
1888 + NETDATA_APPS_NET_GROUP,
1889 + NETDATA_EBPF_CHART_TYPE_STACKED,
1890 + 20081,
1891 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
1892 + NETDATA_SERVICES_SOCKET_BYTES_SEND_CONTEXT, NETDATA_EBPF_MODULE_NAME_SOCKET);
1893 +
1894 + ebpf_create_charts_on_systemd(NETDATA_NET_APPS_BANDWIDTH_TCP_RECV_CALLS,
1895 + "Calls to tcp_cleanup_rbuf.",
1896 + EBPF_COMMON_DIMENSION_CALL,
1897 + NETDATA_APPS_NET_GROUP,
1898 + NETDATA_EBPF_CHART_TYPE_STACKED,
1899 + 20082,
1900 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
1901 + NETDATA_SERVICES_SOCKET_TCP_RECV_CONTEXT, NETDATA_EBPF_MODULE_NAME_SOCKET);
1902 +
1903 + ebpf_create_charts_on_systemd(NETDATA_NET_APPS_BANDWIDTH_TCP_SEND_CALLS,
1904 + "Calls to tcp_sendmsg.",
1905 + EBPF_COMMON_DIMENSION_CALL,
1906 + NETDATA_APPS_NET_GROUP,
1907 + NETDATA_EBPF_CHART_TYPE_STACKED,
1908 + 20083,
1909 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
1910 + NETDATA_SERVICES_SOCKET_TCP_SEND_CONTEXT, NETDATA_EBPF_MODULE_NAME_SOCKET);
1911 +
1912 + ebpf_create_charts_on_systemd(NETDATA_NET_APPS_BANDWIDTH_TCP_RETRANSMIT,
1913 + "Calls to tcp_retransmit",
1914 + EBPF_COMMON_DIMENSION_CALL,
1915 + NETDATA_APPS_NET_GROUP,
1916 + NETDATA_EBPF_CHART_TYPE_STACKED,
1917 + 20084,
1918 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
1919 + NETDATA_SERVICES_SOCKET_TCP_RETRANSMIT_CONTEXT, NETDATA_EBPF_MODULE_NAME_SOCKET);
1920 +
1921 + ebpf_create_charts_on_systemd(NETDATA_NET_APPS_BANDWIDTH_UDP_SEND_CALLS,
1922 + "Calls to udp_sendmsg",
1923 + EBPF_COMMON_DIMENSION_CALL,
1924 + NETDATA_APPS_NET_GROUP,
1925 + NETDATA_EBPF_CHART_TYPE_STACKED,
1926 + 20085,
1927 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
1928 + NETDATA_SERVICES_SOCKET_UDP_SEND_CONTEXT, NETDATA_EBPF_MODULE_NAME_SOCKET);
1929 +
1930 + ebpf_create_charts_on_systemd(NETDATA_NET_APPS_BANDWIDTH_UDP_RECV_CALLS,
1931 + "Calls to udp_recvmsg",
1932 + EBPF_COMMON_DIMENSION_CALL,
1933 + NETDATA_APPS_NET_GROUP,
1934 + NETDATA_EBPF_CHART_TYPE_STACKED,
1935 + 20086,
1936 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
1937 + NETDATA_SERVICES_SOCKET_UDP_RECV_CONTEXT, NETDATA_EBPF_MODULE_NAME_SOCKET);
1938 +}
1939 +
1940 +/**
1941 + * Send Systemd charts
1942 + *
1943 + * Send collected data to Netdata.
1944 + *
1945 + * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
1946 + * otherwise function returns 1 to avoid chart recreation
1947 + */
1948 +static int ebpf_send_systemd_socket_charts()
1949 +{
1950 + int ret = 1;
1951 + ebpf_cgroup_target_t *ect;
1952 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_NET_APPS_BANDWIDTH_SENT);
1953 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1954 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1955 + write_chart_dimension(ect->name, (long long)ect->publish_socket.bytes_sent);
1956 + } else
1957 + ret = 0;
1958 + }
1959 + write_end_chart();
1960 +
1961 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_NET_APPS_BANDWIDTH_RECV);
1962 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1963 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1964 + write_chart_dimension(ect->name, (long long)ect->publish_socket.bytes_received);
1965 + }
1966 + }
1967 + write_end_chart();
1968 +
1969 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_NET_APPS_BANDWIDTH_TCP_SEND_CALLS);
1970 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1971 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1972 + write_chart_dimension(ect->name, (long long)ect->publish_socket.call_tcp_sent);
1973 + }
1974 + }
1975 + write_end_chart();
1976 +
1977 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_NET_APPS_BANDWIDTH_TCP_RECV_CALLS);
1978 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1979 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1980 + write_chart_dimension(ect->name, (long long)ect->publish_socket.call_tcp_received);
1981 + }
1982 + }
1983 + write_end_chart();
1984 +
1985 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_NET_APPS_BANDWIDTH_TCP_RETRANSMIT);
1986 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1987 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1988 + write_chart_dimension(ect->name, (long long)ect->publish_socket.retransmit);
1989 + }
1990 + }
1991 + write_end_chart();
1992 +
1993 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_NET_APPS_BANDWIDTH_UDP_SEND_CALLS);
1994 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
1995 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
1996 + write_chart_dimension(ect->name, (long long)ect->publish_socket.call_udp_sent);
1997 + }
1998 + }
1999 + write_end_chart();
2000 +
2001 + write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_NET_APPS_BANDWIDTH_UDP_RECV_CALLS);
2002 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
2003 + if (unlikely(ect->systemd) && unlikely(ect->updated)) {
2004 + write_chart_dimension(ect->name, (long long)ect->publish_socket.call_udp_received);
2005 + }
2006 + }
2007 + write_end_chart();
2008 +
2009 + return ret;
2010 +}
2011 +
2012 +/**
2013 + * Update Cgroup algorithm
2014 + *
2015 + * Change algorithm from absolute to incremental
2016 + */
2017 +void ebpf_socket_update_cgroup_algorithm()
2018 +{
2019 + int i;
2020 + for (i = 0; i < NETDATA_MAX_SOCKET_VECTOR; i++) {
2021 + netdata_publish_syscall_t *ptr = &socket_publish_aggregated[i];
2022 + freez(ptr->algorithm);
2023 + ptr->algorithm = strdupz(ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2024 + }
2025 +}
2026 +
2027 +/**
2028 + * Send data to Netdata calling auxiliar functions.
2029 +*/
2030 +static void ebpf_socket_send_cgroup_data()
2031 +{
2032 + if (!ebpf_cgroup_pids)
2033 + return;
2034 +
2035 + pthread_mutex_lock(&mutex_cgroup_shm);
2036 + ebpf_cgroup_target_t *ect;
2037 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
2038 + ebpf_socket_sum_cgroup_pids(&ect->publish_socket, ect->pids);
2039 + }
2040 +
2041 + int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
2042 + if (has_systemd) {
2043 + static int systemd_charts = 0;
2044 + if (!systemd_charts) {
2045 + ebpf_create_systemd_socket_charts();
2046 + systemd_charts = 1;
2047 + }
2048 + systemd_charts = ebpf_send_systemd_socket_charts();
2049 + }
2050 +
2051 + for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
2052 + if (ect->systemd)
2053 + continue;
2054 +
2055 + if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_SOCKET_CHART)) {
2056 + ebpf_create_specific_socket_charts(ect->name);
2057 + ect->flags |= NETDATA_EBPF_CGROUP_HAS_SOCKET_CHART;
2058 + }
2059 +
2060 + if (ect->flags & NETDATA_EBPF_CGROUP_HAS_SOCKET_CHART && ect->updated) {
2061 + ebpf_send_specific_socket_data(ect->name, &ect->publish_socket);
2062 + } else {
2063 + ebpf_obsolete_specific_socket_charts(ect->name);
2064 + ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_SOCKET_CHART;
2065 + }
2066 + }
2067 +
2068 + pthread_mutex_unlock(&mutex_cgroup_shm);
2069 +}
2070 +
2071 /*****************************************************************
2072 *
2073 * FUNCTIONS WITH THE MAIN LOOP
@@ -1637,7 +2086,6 @@ struct netdata_static_thread socket_threads = {"EBPF SOCKET READ",
2086 */
2087 static void socket_collector(usec_t step, ebpf_module_t *em)
2088 {
1640 - UNUSED(em);
2089 UNUSED(step);
2090 heartbeat_t hb;
2091 heartbeat_init(&hb);
@@ -1647,6 +2095,10 @@ static void socket_collector(usec_t step, ebpf_module_t *em)
2095 netdata_thread_create(socket_threads.thread, socket_threads.name,
2096 NETDATA_THREAD_OPTION_JOINABLE, ebpf_socket_read_hash, em);
2097
2098 + int cgroups = em->cgroup_charts;
2099 + if (cgroups)
2100 + ebpf_socket_update_cgroup_algorithm();
2101 +
2102 int socket_apps_enabled = ebpf_modules[EBPF_MODULE_SOCKET_IDX].apps_charts;
2103 int socket_global_enabled = ebpf_modules[EBPF_MODULE_SOCKET_IDX].global_charts;
2104 int network_connection = em->optional;
@@ -1660,6 +2112,9 @@ static void socket_collector(usec_t step, ebpf_module_t *em)
2112 if (socket_apps_enabled)
2113 ebpf_socket_update_apps_data();
2114
2115 + if (cgroups)
2116 + ebpf_update_socket_cgroup();
2117 +
2118 calculate_nv_plot();
2119
2120 pthread_mutex_lock(&lock);
@@ -1669,6 +2124,9 @@ static void socket_collector(usec_t step, ebpf_module_t *em)
2124 if (socket_apps_enabled)
2125 ebpf_socket_send_apps_data(em, apps_groups_root_target);
2126
2127 + if (cgroups)
2128 + ebpf_socket_send_cgroup_data();
2129 +
2130 fflush(stdout);
2131
2132 if (network_connection) {
@@ -1924,15 +2382,17 @@ static void ebpf_socket_cleanup(void *ptr)
2382 * We are not testing the return, because callocz does this and shutdown the software
2383 * case it was not possible to allocate.
2384 *
1927 - * @param length is the length for the vectors used inside the collector.
2385 + * @param apps is apps enabled?
2386 */
1929 -static void ebpf_socket_allocate_global_vectors(size_t length)
2387 +static void ebpf_socket_allocate_global_vectors(int apps)
2388 {
1931 - memset(socket_aggregated_data, 0 ,length * sizeof(netdata_syscall_stat_t));
1932 - memset(socket_publish_aggregated, 0 ,length * sizeof(netdata_publish_syscall_t));
2389 + memset(socket_aggregated_data, 0 ,NETDATA_MAX_SOCKET_VECTOR * sizeof(netdata_syscall_stat_t));
2390 + memset(socket_publish_aggregated, 0 ,NETDATA_MAX_SOCKET_VECTOR * sizeof(netdata_publish_syscall_t));
2391 socket_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
2392
1935 - socket_bandwidth_curr = callocz((size_t)pid_max, sizeof(ebpf_socket_publish_apps_t *));
2393 + if (apps)
2394 + socket_bandwidth_curr = callocz((size_t)pid_max, sizeof(ebpf_socket_publish_apps_t *));
2395 +
2396 bandwidth_vector = callocz((size_t)ebpf_nprocs, sizeof(ebpf_bandwidth_t));
2397
2398 socket_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_socket_t));
@@ -2880,7 +3340,7 @@ void *ebpf_socket_thread(void *ptr)
3340 }
3341 pthread_mutex_lock(&lock);
3342
2883 - ebpf_socket_allocate_global_vectors(NETDATA_MAX_SOCKET_VECTOR);
3343 + ebpf_socket_allocate_global_vectors(em->apps_charts);
3344 initialize_inbound_outbound();
3345
3346 if (running_on_kernel < NETDATA_EBPF_KERNEL_5_0)
collectors/ebpf.plugin/ebpf_socket.h
+18
@@ -75,6 +75,7 @@ typedef enum ebpf_socket_idx {
75
76 #define NETDATA_SOCKET_KERNEL_FUNCTIONS "kernel"
77 #define NETDATA_NETWORK_CONNECTIONS_GROUP "network connections"
78 +#define NETDATA_CGROUP_NET_GROUP "network (eBPF)"
79
80 // Global chart name
81 #define NETDATA_TCP_FUNCTION_COUNT "tcp_functions"
@@ -112,6 +113,23 @@ typedef enum ebpf_socket_idx {
113 #define NETDATA_MINIMUM_IPV4_CIDR 0
114 #define NETDATA_MAXIMUM_IPV4_CIDR 32
115
116 +// Contexts
117 +#define NETDATA_CGROUP_SOCKET_BYTES_RECV_CONTEXT "cgroup.net_bytes_recv"
118 +#define NETDATA_CGROUP_SOCKET_BYTES_SEND_CONTEXT "cgroup.net_bytes_send"
119 +#define NETDATA_CGROUP_SOCKET_TCP_RECV_CONTEXT "cgroup.net_tcp_recv"
120 +#define NETDATA_CGROUP_SOCKET_TCP_SEND_CONTEXT "cgroup.net_tcp_send"
121 +#define NETDATA_CGROUP_SOCKET_TCP_RETRANSMIT_CONTEXT "cgroup.net_retransmit"
122 +#define NETDATA_CGROUP_SOCKET_UDP_RECV_CONTEXT "cgroup.net_udp_recv"
123 +#define NETDATA_CGROUP_SOCKET_UDP_SEND_CONTEXT "cgroup.net_udp_send"
124 +
125 +#define NETDATA_SERVICES_SOCKET_BYTES_RECV_CONTEXT "services.net_bytes_recv"
126 +#define NETDATA_SERVICES_SOCKET_BYTES_SEND_CONTEXT "services.net_bytes_send"
127 +#define NETDATA_SERVICES_SOCKET_TCP_RECV_CONTEXT "services.net_tcp_recv"
128 +#define NETDATA_SERVICES_SOCKET_TCP_SEND_CONTEXT "services.net_tcp_send"
129 +#define NETDATA_SERVICES_SOCKET_TCP_RETRANSMIT_CONTEXT "services.net_retransmit"
130 +#define NETDATA_SERVICES_SOCKET_UDP_RECV_CONTEXT "services.net_udp_recv"
131 +#define NETDATA_SERVICES_SOCKET_UDP_SEND_CONTEXT "services.net_udp_send"
132 +
133 typedef struct ebpf_socket_publish_apps {
134 // Data read
135 uint64_t bytes_sent; // Bytes sent
collectors/ebpf.plugin/ebpf_swap.c
+7 -5
@@ -154,7 +154,7 @@ static void ebpf_update_swap_cgroup()
154 for (pids = ect->pids; pids; pids = pids->next) {
155 int pid = pids->pid;
156 netdata_publish_swap_t *out = &pids->swap;
157 - if (swap_pid[pid]) {
157 + if (likely(swap_pid) && swap_pid[pid]) {
158 netdata_publish_swap_t *in = swap_pid[pid];
159
160 memcpy(out, in, sizeof(netdata_publish_swap_t));
@@ -604,11 +604,13 @@ void ebpf_swap_create_apps_charts(struct ebpf_module *em, void *ptr)
604 * We are not testing the return, because callocz does this and shutdown the software
605 * case it was not possible to allocate.
606 *
607 - * @param length is the length for the vectors used inside the collector.
607 + * @param apps is apps enabled?
608 */
609 -static void ebpf_swap_allocate_global_vectors()
609 +static void ebpf_swap_allocate_global_vectors(int apps)
610 {
611 - swap_pid = callocz((size_t)pid_max, sizeof(netdata_publish_swap_t *));
611 + if (apps)
612 + swap_pid = callocz((size_t)pid_max, sizeof(netdata_publish_swap_t *));
613 +
614 swap_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_publish_swap_t));
615
616 swap_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
@@ -665,7 +667,7 @@ void *ebpf_swap_thread(void *ptr)
667 goto endswap;
668 }
669
668 - ebpf_swap_allocate_global_vectors();
670 + ebpf_swap_allocate_global_vectors(em->apps_charts);
671
672 int algorithms[NETDATA_SWAP_END] = { NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX };
673 ebpf_global_labels(swap_aggregated_data, swap_publish_aggregated, swap_dimension_name, swap_dimension_name,
collectors/ebpf.plugin/ebpf_vfs.c
+8 -6
@@ -497,7 +497,7 @@ static void read_update_vfs_cgroup()
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]) {
500 + if (likely(vfs_pid) && vfs_pid[pid]) {
501 netdata_publish_vfs_t *in = vfs_pid[pid];
502
503 memcpy(out, in, sizeof(netdata_publish_vfs_t));
@@ -506,7 +506,7 @@ static void read_update_vfs_cgroup()
506 if (!bpf_map_lookup_elem(fd, &pid, vv)) {
507 vfs_apps_accumulator(vv);
508
509 - memcpy(out, vv, sizeof(netdata_publish_swap_t));
509 + memcpy(out, vv, sizeof(netdata_publish_vfs_t));
510 }
511 }
512 }
@@ -1524,16 +1524,18 @@ void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr)
1524 * We are not testing the return, because callocz does this and shutdown the software
1525 * case it was not possible to allocate.
1526 *
1527 - * @param length is the length for the vectors used inside the collector.
1527 + * @param apps is apps enabled?
1528 */
1529 -static void ebpf_vfs_allocate_global_vectors()
1529 +static void ebpf_vfs_allocate_global_vectors(int apps)
1530 {
1531 memset(vfs_aggregated_data, 0, sizeof(vfs_aggregated_data));
1532 memset(vfs_publish_aggregated, 0, sizeof(vfs_publish_aggregated));
1533
1534 vfs_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
1535 vfs_vector = callocz(ebpf_nprocs, sizeof(netdata_publish_vfs_t));
1536 - vfs_pid = callocz((size_t)pid_max, sizeof(netdata_publish_vfs_t *));
1536 +
1537 + if (apps)
1538 + vfs_pid = callocz((size_t)pid_max, sizeof(netdata_publish_vfs_t *));
1539 }
1540
1541 /*****************************************************************
@@ -1560,7 +1562,7 @@ void *ebpf_vfs_thread(void *ptr)
1562
1563 ebpf_update_pid_table(&vfs_maps[NETDATA_VFS_PID], em);
1564
1563 - ebpf_vfs_allocate_global_vectors();
1565 + ebpf_vfs_allocate_global_vectors(em->apps_charts);
1566
1567 if (!em->enabled)
1568 goto endvfs;
libnetdata/ebpf/ebpf.c
+2 -2
@@ -333,7 +333,7 @@ void ebpf_update_map_sizes(struct bpf_object *program, ebpf_module_t *em)
333 info("Changing map %s from size %u to %u ", map_name, w->internal_input, w->user_input);
334 #endif
335 bpf_map__resize(map, w->user_input);
336 - } else if (((w->type & apps_type) == apps_type) && (!em->apps_charts)) {
336 + } else if (((w->type & apps_type) == apps_type) && (!em->apps_charts) && (!em->cgroup_charts)) {
337 w->user_input = ND_EBPF_DEFAULT_MIN_PID;
338 bpf_map__resize(map, w->user_input);
339 }
@@ -439,7 +439,7 @@ static void ebpf_update_controller(ebpf_module_t *em, struct bpf_object *obj)
439 w->type |= NETDATA_EBPF_MAP_CONTROLLER_UPDATED;
440
441 uint32_t key = NETDATA_CONTROLLER_APPS_ENABLED;
442 - int value = em->apps_charts;
442 + int value = em->apps_charts | em->cgroup_charts;
443 int ret = bpf_map_update_elem(w->map_fd, &key, &value, 0);
444 if (ret)
445 error("Add key(%u) for controller table failed.", key);
web/gui/dashboard_info.js
+211 -86
@@ -1062,6 +1062,14 @@ netdataDashboard.submenu = {
1062 info: '<a href="https://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Processor_states" target="_blank">Idle States (C-states)</a> '+
1063 'are used to save power when the processor is idle.'
1064 },
1065 +
1066 + 'services.net': {
1067 + title: 'network (eBPF)',
1068 + },
1069 +
1070 + 'services.page_cache': {
1071 + title: 'pache cache (eBPF)',
1072 + },
1073 };
1074
1075 // ----------------------------------------------------------------------------
@@ -3819,6 +3827,149 @@ netdataDashboard.context = {
3827 'The ratios (in %) are tracked as recent trends over 10-, 60-, and 300-second windows.'
3828 },
3829
3830 + 'cgroup.swap_read': {
3831 + 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.'
3832 + },
3833 +
3834 + 'cgroup.swap_write': {
3835 + 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.'
3836 + },
3837 +
3838 + 'cgroup.fd_open': {
3839 + 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' +
3840 + ' <a href="https://www.man7.org/linux/man-pages/man2/open.2.html" target="_blank">open(2)</a> ' +
3841 + ' and <a href="https://www.man7.org/linux/man-pages/man2/openat.2.html" target="_blank">openat(2)</a>. '
3842 + },
3843 +
3844 + 'cgroup.fd_open_error': {
3845 + 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>. ).'
3846 + },
3847 +
3848 + 'cgroup.fd_close': {
3849 + 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' +
3850 + ' <a href="https://www.man7.org/linux/man-pages/man2/close.2.html" target="_blank">close(2)</a>. '
3851 + },
3852 +
3853 + 'cgroup.fd_close_error': {
3854 + 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.'
3855 + },
3856 +
3857 + 'cgroup.vfs_unlink': {
3858 + 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.'
3859 + },
3860 +
3861 + 'cgroup.vfs_write': {
3862 + 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.'
3863 + },
3864 +
3865 + 'cgroup.vfs_write_error': {
3866 + 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.'
3867 + },
3868 +
3869 + 'cgroup.vfs_read': {
3870 + 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.'
3871 + },
3872 +
3873 + 'cgroup.vfs_read_error': {
3874 + 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.'
3875 + },
3876 +
3877 + 'cgroup.vfs_write_bytes': {
3878 + 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>.'
3879 + },
3880 +
3881 + 'cgroup.vfs_read_bytes': {
3882 + 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>.'
3883 + },
3884 +
3885 + 'cgroup.process_create': {
3886 + 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.'
3887 + },
3888 +
3889 + 'cgroup.thread_create': {
3890 + 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.'
3891 + },
3892 +
3893 + 'cgroup.task_close': {
3894 + 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.'
3895 + },
3896 +
3897 + 'cgroup.dc_ratio': {
3898 + 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>.'
3899 + },
3900 +
3901 + 'cgroup.dc_reference': {
3902 + 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>.'
3903 + },
3904 +
3905 + 'cgroup.dc_not_cache': {
3906 + 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>.'
3907 + },
3908 +
3909 + 'cgroup.dc_not_found': {
3910 + 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>.'
3911 + },
3912 +
3913 + 'cgroup.shmget': {
3914 + info: 'Number of times the syscall <code>shmget</code> is called. Netdata also gives a summary for these charts in <a href="#menu_system_submenu_ipc_shared_memory">System overview</a>.'
3915 + },
3916 +
3917 + 'cgroup.shmat': {
3918 + info: 'Number of times the syscall <code>shmat</code> is called.'
3919 + },
3920 +
3921 + 'cgroup.shmdt': {
3922 + info: 'Number of times the syscall <code>shmdt</code> is called.'
3923 + },
3924 +
3925 + 'cgroup.shmctl': {
3926 + info: 'Number of times the syscall <code>shmctl</code> is called.'
3927 + },
3928 +
3929 + 'cgroup.net_bytes_send': {
3930 + info: 'Bytes sent by functions <code>tcp_sendmsg</code>.'
3931 + },
3932 +
3933 + 'cgroup.net_bytes_recv': {
3934 + info: 'Bytes received by functions <code>tcp_cleanup_rbuf</code> . We use <code>tcp_cleanup_rbuf</code> instead <code>tcp_recvmsg</code>, because this last misses <code>tcp_read_sock()</code> traffic and we would also need to have more probes to get the socket and package size.'
3935 + },
3936 +
3937 + 'cgroup.net_tcp_send': {
3938 + info: 'The function <code>tcp_sendmsg</code> is used to collect number of bytes sent from TCP connections.'
3939 + },
3940 +
3941 + 'cgroup.net_tcp_recv': {
3942 + info: 'The function <code>tcp_cleanup_rbuf</code> is used to collect number of bytes received from TCP connections.'
3943 + },
3944 +
3945 + 'cgroup.net_retransmit': {
3946 + info: 'The function <code>tcp_retransmit_skb</code> is called when the host did not receive the expected return from a packet sent.'
3947 + },
3948 +
3949 + 'cgroup.net_udp_send': {
3950 + info: 'The function <code>udp_sendmsg</code> is used to collect number of bytes sent from UDP connections.'
3951 + },
3952 +
3953 + 'cgroup.net_udp_recv': {
3954 + info: 'The function <code>udp_recvmsg</code> is used to collect number of bytes received from UDP connections.'
3955 + },
3956 +
3957 + 'cgroup.cachestat_ratio': {
3958 + info: 'When the processor needs to read or write a location in main memory, it checks for a corresponding entry in the page cache. If the entry is there, a page cache hit has occurred and the read is from the cache. If the entry is not there, a page cache miss has occurred and the kernel allocates a new entry and copies in data from the disk. Netdata calculates the percentage of accessed files that are cached on memory. <a href="https://github.com/iovisor/bcc/blob/master/tools/cachestat.py#L126-L138" target="_blank">The ratio</a> is calculated counting the accessed cached pages (without counting dirty pages and pages added because of read misses) divided by total access without dirty pages.'
3959 + },
3960 +
3961 + 'cgroup.cachestat_dirties': {
3962 + info: 'Number of <a href="https://en.wikipedia.org/wiki/Page_cache#Memory_conservation" target="_blank">dirty(modified) pages</a> cache. Pages in the page cache modified after being brought in are called dirty pages. Since non-dirty pages in the page cache have identical copies in <a href="https://en.wikipedia.org/wiki/Secondary_storage" target="_blank">secondary storage</a> (e.g. hard disk drive or solid-state drive), discarding and reusing their space is much quicker than paging out application memory, and is often preferred over flushing the dirty pages into secondary storage and reusing their space.'
3963 + },
3964 +
3965 + 'cgroup.cachestat_hits': {
3966 + info: 'When the processor needs to read or write a location in main memory, it checks for a corresponding entry in the page cache. If the entry is there, a page cache hit has occurred and the read is from the cache. Hits show pages accessed that were not modified (we are excluding dirty pages), this counting also excludes the recent pages inserted for read.'
3967 + },
3968 +
3969 + 'cgroup.cachestat_misses': {
3970 + info: 'When the processor needs to read or write a location in main memory, it checks for a corresponding entry in the page cache. If the entry is not there, a page cache miss has occurred and the cache allocates a new entry and copies in data for the main memory. Misses count page insertions to the memory not related to writing.'
3971 + },
3972 +
3973 // ------------------------------------------------------------------------
3974 // containers (systemd)
3975
@@ -4020,6 +4171,66 @@ netdataDashboard.context = {
4171 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>.'
4172 },
4173
4174 + 'services.shmget': {
4175 + info: 'Number of times the syscall <code>shmget</code> is called. Netdata also gives a summary for these charts in <a href="#menu_system_submenu_ipc_shared_memory">System overview</a>.'
4176 + },
4177 +
4178 + 'services.shmat': {
4179 + info: 'Number of times the syscall <code>shmat</code> is called.'
4180 + },
4181 +
4182 + 'services.shmdt': {
4183 + info: 'Number of times the syscall <code>shmdt</code> is called.'
4184 + },
4185 +
4186 + 'services.shmctl': {
4187 + info: 'Number of times the syscall <code>shmctl</code> is called.'
4188 + },
4189 +
4190 + 'services.net_bytes_send': {
4191 + info: 'Bytes sent by functions <code>tcp_sendmsg</code>.'
4192 + },
4193 +
4194 + 'services.net_bytes_recv': {
4195 + info: 'Bytes received by functions <code>tcp_cleanup_rbuf</code> . We use <code>tcp_cleanup_rbuf</code> instead <code>tcp_recvmsg</code>, because this last misses <code>tcp_read_sock()</code> traffic and we would also need to have more probes to get the socket and package size.'
4196 + },
4197 +
4198 + 'services.net_tcp_send': {
4199 + info: 'The function <code>tcp_sendmsg</code> is used to collect number of bytes sent from TCP connections.'
4200 + },
4201 +
4202 + 'services.net_tcp_recv': {
4203 + info: 'The function <code>tcp_cleanup_rbuf</code> is used to collect number of bytes received from TCP connections.'
4204 + },
4205 +
4206 + 'services.net_retransmit': {
4207 + info: 'The function <code>tcp_retransmit_skb</code> is called when the host did not receive the expected return from a packet sent.'
4208 + },
4209 +
4210 + 'services.net_udp_send': {
4211 + info: 'The function <code>udp_sendmsg</code> is used to collect number of bytes sent from UDP connections.'
4212 + },
4213 +
4214 + 'services.net_udp_recv': {
4215 + info: 'The function <code>udp_recvmsg</code> is used to collect number of bytes received from UDP connections.'
4216 + },
4217 +
4218 + 'services.cachestat_ratio': {
4219 + info: 'When the processor needs to read or write a location in main memory, it checks for a corresponding entry in the page cache. If the entry is there, a page cache hit has occurred and the read is from the cache. If the entry is not there, a page cache miss has occurred and the kernel allocates a new entry and copies in data from the disk. Netdata calculates the percentage of accessed files that are cached on memory. <a href="https://github.com/iovisor/bcc/blob/master/tools/cachestat.py#L126-L138" target="_blank">The ratio</a> is calculated counting the accessed cached pages (without counting dirty pages and pages added because of read misses) divided by total access without dirty pages.'
4220 + },
4221 +
4222 + 'services.cachestat_dirties': {
4223 + info: 'Number of <a href="https://en.wikipedia.org/wiki/Page_cache#Memory_conservation" target="_blank">dirty(modified) pages</a> cache. Pages in the page cache modified after being brought in are called dirty pages. Since non-dirty pages in the page cache have identical copies in <a href="https://en.wikipedia.org/wiki/Secondary_storage" target="_blank">secondary storage</a> (e.g. hard disk drive or solid-state drive), discarding and reusing their space is much quicker than paging out application memory, and is often preferred over flushing the dirty pages into secondary storage and reusing their space.'
4224 + },
4225 +
4226 + 'services.cachestat_hits': {
4227 + info: 'When the processor needs to read or write a location in main memory, it checks for a corresponding entry in the page cache. If the entry is there, a page cache hit has occurred and the read is from the cache. Hits show pages accessed that were not modified (we are excluding dirty pages), this counting also excludes the recent pages inserted for read.'
4228 + },
4229 +
4230 + 'services.cachestat_misses': {
4231 + info: 'When the processor needs to read or write a location in main memory, it checks for a corresponding entry in the page cache. If the entry is not there, a page cache miss has occurred and the cache allocates a new entry and copies in data for the main memory. Misses count page insertions to the memory not related to writing.'
4232 + },
4233 +
4234 // ------------------------------------------------------------------------
4235 // beanstalkd
4236 // system charts
@@ -5628,92 +5839,6 @@ netdataDashboard.context = {
5839 info: 'Number of times the syscall <code>shmctl</code> is called.'
5840 },
5841
5631 - // ------------------------------------------------------------------------
5632 - // Cgroup units
5633 -
5634 - 'cgroup.swap_read': {
5635 - 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.'
5636 - },
5637 -
5638 - 'cgroup.swap_write': {
5639 - 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.'
5640 - },
5641 -
5642 - 'cgroup.fd_open': {
5643 - 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' +
5644 - ' <a href="https://www.man7.org/linux/man-pages/man2/open.2.html" target="_blank">open(2)</a> ' +
5645 - ' and <a href="https://www.man7.org/linux/man-pages/man2/openat.2.html" target="_blank">openat(2)</a>. '
5646 - },
5647 -
5648 - 'cgroup.fd_open_error': {
5649 - 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>. ).'
5650 - },
5651 -
5652 - 'cgroup.fd_close': {
5653 - 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' +
5654 - ' <a href="https://www.man7.org/linux/man-pages/man2/close.2.html" target="_blank">close(2)</a>. '
5655 - },
5656 -
5657 - 'cgroup.fd_close_error': {
5658 - 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.'
5659 - },
5660 -
5661 - 'cgroup.vfs_unlink': {
5662 - 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.'
5663 - },
5664 -
5665 - 'cgroup.vfs_write': {
5666 - 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.'
5667 - },
5668 -
5669 - 'cgroup.vfs_write_error': {
5670 - 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.'
5671 - },
5672 -
5673 - 'cgroup.vfs_read': {
5674 - 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.'
5675 - },
5676 -
5677 - 'cgroup.vfs_read_error': {
5678 - 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.'
5679 - },
5680 -
5681 - 'cgroup.vfs_write_bytes': {
5682 - 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>.'
5683 - },
5684 -
5685 - 'cgroup.vfs_read_bytes': {
5686 - 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>.'
5687 - },
5688 -
5689 - 'cgroup.process_create': {
5690 - 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.'
5691 - },
5692 -
5693 - 'cgroup.thread_create': {
5694 - 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.'
5695 - },
5696 -
5697 - 'cgroup.task_close': {
5698 - 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.'
5699 - },
5700 -
5701 - 'cgroup.dc_ratio': {
5702 - 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>.'
5703 - },
5704 -
5705 - 'cgroup.dc_reference': {
5706 - 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>.'
5707 - },
5708 -
5709 - 'cgroup.dc_not_cache': {
5710 - 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>.'
5711 - },
5712 -
5713 - 'cgroup.dc_not_found': {
5714 - 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>.'
5715 - },
5716 -
5842 // ------------------------------------------------------------------------
5843 // ACLK Internal Stats
5844 'netdata.aclk_status': {