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': {