diff --git a/api/flowcollector/v1beta2/flowcollector_types.go b/api/flowcollector/v1beta2/flowcollector_types.go index 8ceef368ec..1641a368c1 100644 --- a/api/flowcollector/v1beta2/flowcollector_types.go +++ b/api/flowcollector/v1beta2/flowcollector_types.go @@ -564,7 +564,7 @@ type MetricsServerConfig struct { } // Metric name. More information in https://github.com/netobserv/network-observability-operator/blob/main/docs/Metrics.md. -// +kubebuilder:validation:Enum:="namespace_egress_bytes_total";"namespace_egress_packets_total";"namespace_ingress_bytes_total";"namespace_ingress_packets_total";"namespace_flows_total";"node_egress_bytes_total";"node_egress_packets_total";"node_ingress_bytes_total";"node_ingress_packets_total";"node_flows_total";"workload_egress_bytes_total";"workload_egress_packets_total";"workload_ingress_bytes_total";"workload_ingress_packets_total";"workload_flows_total";"namespace_drop_bytes_total";"namespace_drop_packets_total";"node_drop_bytes_total";"node_drop_packets_total";"workload_drop_bytes_total";"workload_drop_packets_total";"namespace_rtt_seconds";"node_rtt_seconds";"workload_rtt_seconds";"namespace_dns_latency_seconds";"node_dns_latency_seconds";"workload_dns_latency_seconds";"node_network_policy_events_total";"namespace_network_policy_events_total";"workload_network_policy_events_total";"node_ipsec_flows_total";"node_to_node_ingress_flows_total" +// +kubebuilder:validation:Enum:="namespace_egress_bytes_total";"namespace_egress_packets_total";"namespace_ingress_bytes_total";"namespace_ingress_packets_total";"namespace_flows_total";"node_egress_bytes_total";"node_egress_packets_total";"node_ingress_bytes_total";"node_ingress_packets_total";"node_flows_total";"workload_egress_bytes_total";"workload_egress_packets_total";"workload_ingress_bytes_total";"workload_ingress_packets_total";"workload_flows_total";"network_egress_bytes_total";"network_egress_packets_total";"network_ingress_bytes_total";"network_ingress_packets_total";"network_flows_total";"namespace_drop_bytes_total";"namespace_drop_packets_total";"node_drop_bytes_total";"node_drop_packets_total";"workload_drop_bytes_total";"workload_drop_packets_total";"network_drop_bytes_total";"network_drop_packets_total";"namespace_rtt_seconds";"node_rtt_seconds";"workload_rtt_seconds";"network_rtt_seconds";"namespace_dns_latency_seconds";"node_dns_latency_seconds";"workload_dns_latency_seconds";"network_dns_latency_seconds";"node_network_policy_events_total";"namespace_network_policy_events_total";"workload_network_policy_events_total";"node_ipsec_flows_total";"workload_ipsec_flows_total";"network_ipsec_flows_total";"node_to_node_ingress_flows_total" type FLPMetric string // `FLPMetrics` define the desired FLP configuration regarding metrics diff --git a/bundle/manifests/flows.netobserv.io_flowcollectors.yaml b/bundle/manifests/flows.netobserv.io_flowcollectors.yaml index 168fcc5420..4554742017 100644 --- a/bundle/manifests/flows.netobserv.io_flowcollectors.yaml +++ b/bundle/manifests/flows.netobserv.io_flowcollectors.yaml @@ -5978,22 +5978,33 @@ spec: - workload_ingress_bytes_total - workload_ingress_packets_total - workload_flows_total + - network_egress_bytes_total + - network_egress_packets_total + - network_ingress_bytes_total + - network_ingress_packets_total + - network_flows_total - namespace_drop_bytes_total - namespace_drop_packets_total - node_drop_bytes_total - node_drop_packets_total - workload_drop_bytes_total - workload_drop_packets_total + - network_drop_bytes_total + - network_drop_packets_total - namespace_rtt_seconds - node_rtt_seconds - workload_rtt_seconds + - network_rtt_seconds - namespace_dns_latency_seconds - node_dns_latency_seconds - workload_dns_latency_seconds + - network_dns_latency_seconds - node_network_policy_events_total - namespace_network_policy_events_total - workload_network_policy_events_total - node_ipsec_flows_total + - workload_ipsec_flows_total + - network_ipsec_flows_total - node_to_node_ingress_flows_total type: string type: array diff --git a/config/crd/bases/flows.netobserv.io_flowcollectors.yaml b/config/crd/bases/flows.netobserv.io_flowcollectors.yaml index 3ccc59be57..7d73f73129 100644 --- a/config/crd/bases/flows.netobserv.io_flowcollectors.yaml +++ b/config/crd/bases/flows.netobserv.io_flowcollectors.yaml @@ -5530,22 +5530,33 @@ spec: - workload_ingress_bytes_total - workload_ingress_packets_total - workload_flows_total + - network_egress_bytes_total + - network_egress_packets_total + - network_ingress_bytes_total + - network_ingress_packets_total + - network_flows_total - namespace_drop_bytes_total - namespace_drop_packets_total - node_drop_bytes_total - node_drop_packets_total - workload_drop_bytes_total - workload_drop_packets_total + - network_drop_bytes_total + - network_drop_packets_total - namespace_rtt_seconds - node_rtt_seconds - workload_rtt_seconds + - network_rtt_seconds - namespace_dns_latency_seconds - node_dns_latency_seconds - workload_dns_latency_seconds + - network_dns_latency_seconds - node_network_policy_events_total - namespace_network_policy_events_total - workload_network_policy_events_total - node_ipsec_flows_total + - workload_ipsec_flows_total + - network_ipsec_flows_total - node_to_node_ingress_flows_total type: string type: array diff --git a/helm/crds/flows.netobserv.io_flowcollectors.yaml b/helm/crds/flows.netobserv.io_flowcollectors.yaml index 360026bde7..518049cdeb 100644 --- a/helm/crds/flows.netobserv.io_flowcollectors.yaml +++ b/helm/crds/flows.netobserv.io_flowcollectors.yaml @@ -5534,22 +5534,33 @@ spec: - workload_ingress_bytes_total - workload_ingress_packets_total - workload_flows_total + - network_egress_bytes_total + - network_egress_packets_total + - network_ingress_bytes_total + - network_ingress_packets_total + - network_flows_total - namespace_drop_bytes_total - namespace_drop_packets_total - node_drop_bytes_total - node_drop_packets_total - workload_drop_bytes_total - workload_drop_packets_total + - network_drop_bytes_total + - network_drop_packets_total - namespace_rtt_seconds - node_rtt_seconds - workload_rtt_seconds + - network_rtt_seconds - namespace_dns_latency_seconds - node_dns_latency_seconds - workload_dns_latency_seconds + - network_dns_latency_seconds - node_network_policy_events_total - namespace_network_policy_events_total - workload_network_policy_events_total - node_ipsec_flows_total + - workload_ipsec_flows_total + - network_ipsec_flows_total - node_to_node_ingress_flows_total type: string type: array diff --git a/internal/pkg/dashboards/dashboard_test.go b/internal/pkg/dashboards/dashboard_test.go index e12fe8373f..df4954281c 100644 --- a/internal/pkg/dashboards/dashboard_test.go +++ b/internal/pkg/dashboards/dashboard_test.go @@ -105,6 +105,7 @@ func TestCreateFlowMetricsDashboard_DefaultList(t *testing.T) { "TCP latencies", "Byte and packet drops", "DNS", + "IPsec", }, d.Titles()) topRow := d.FindRow("") @@ -115,6 +116,7 @@ func TestCreateFlowMetricsDashboard_DefaultList(t *testing.T) { "Drops", "DNS latency, p99", "DNS error rate", + "IPsec encrypted traffic", }, topRow.Titles()) trafficRow := d.FindRow("Traffic rates per node") diff --git a/internal/pkg/helper/otel/otel-config.json b/internal/pkg/helper/otel/otel-config.json index 590a971e2c..e78f661530 100644 --- a/internal/pkg/helper/otel/otel-config.json +++ b/internal/pkg/helper/otel/otel-config.json @@ -30,6 +30,7 @@ "TimeFlowRttNs": "tcp.rtt", "Interfaces": "interface.names", "IfDirections": "interface.directions", + "IPSecStatus": "ipsec.status", "FlowDirection": "host.direction", "DnsErrno": "dns.errno", "DnsFlags": "dns.flags", diff --git a/internal/pkg/helper/otel/otel_config_test.go b/internal/pkg/helper/otel/otel_config_test.go index 9b940b4036..89b705a689 100644 --- a/internal/pkg/helper/otel/otel_config_test.go +++ b/internal/pkg/helper/otel/otel_config_test.go @@ -36,6 +36,7 @@ func TestOtelTransformConfig(t *testing.T) { {Input: "DstSubnetLabel", Output: "destination.subnet.label", Multiplier: 0}, {Input: "Flags", Output: "tcp.flags", Multiplier: 0}, {Input: "FlowDirection", Output: "host.direction", Multiplier: 0}, + {Input: "IPSecStatus", Output: "ipsec.status", Multiplier: 0}, {Input: "IcmpCode", Output: "icmp.code", Multiplier: 0}, {Input: "IcmpType", Output: "icmp.type", Multiplier: 0}, {Input: "IfDirections", Output: "interface.directions", Multiplier: 0}, diff --git a/internal/pkg/metrics/predefined_metrics.go b/internal/pkg/metrics/predefined_metrics.go index a086a68001..4afa93b483 100644 --- a/internal/pkg/metrics/predefined_metrics.go +++ b/internal/pkg/metrics/predefined_metrics.go @@ -14,6 +14,7 @@ const ( tagNamespaces = "namespaces" tagNodes = "nodes" tagWorkloads = "workloads" + tagNetworks = "networks" tagIngress = "ingress" tagEgress = "egress" tagBytes = "bytes" @@ -26,6 +27,7 @@ var ( tagNodes: {"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_HostName", "DstK8S_HostName"}, tagNamespaces: {"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_Namespace", "DstK8S_Namespace", "K8S_FlowLayer", "SrcSubnetLabel", "DstSubnetLabel"}, tagWorkloads: {"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_Namespace", "DstK8S_Namespace", "K8S_FlowLayer", "SrcSubnetLabel", "DstSubnetLabel", "SrcK8S_OwnerName", "DstK8S_OwnerName", "SrcK8S_OwnerType", "DstK8S_OwnerType", "SrcK8S_Type", "DstK8S_Type"}, + tagNetworks: {"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_NetworkName", "DstK8S_NetworkName", "K8S_FlowLayer"}, } mapValueFields = map[string]string{ tagBytes: "Bytes", @@ -44,7 +46,7 @@ type taggedMetricDefinition struct { } func init() { - for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads} { + for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads, tagNetworks} { groupTrimmed := strings.TrimSuffix(group, "s") labels := mapLabels[group] // Bytes / packets metrics @@ -88,7 +90,7 @@ func init() { tags: []string{group, group + "-flows", "flows"}, }) } - for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads} { + for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads, tagNetworks} { groupTrimmed := strings.TrimSuffix(group, "s") labels := mapLabels[group] // RTT metrics @@ -109,7 +111,7 @@ func init() { tags: []string{group, "rtt"}, }) } - for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads} { + for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads, tagNetworks} { groupTrimmed := strings.TrimSuffix(group, "s") labels := mapLabels[group] // Drops metrics @@ -144,7 +146,7 @@ func init() { tags: []string{group, tagBytes, "drop"}, }) } - for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads} { + for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads, tagNetworks} { groupTrimmed := strings.TrimSuffix(group, "s") labels := mapLabels[group] // DNS metrics @@ -168,7 +170,7 @@ func init() { }) } - for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads} { + for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads, tagNetworks} { groupTrimmed := strings.TrimSuffix(group, "s") labels := mapLabels[group] // Netpol metrics @@ -195,7 +197,7 @@ func init() { }) } - for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads} { + for _, group := range []string{tagNodes, tagNamespaces, tagWorkloads, tagNetworks} { groupTrimmed := strings.TrimSuffix(group, "s") labels := mapLabels[group] // IPSEC @@ -321,6 +323,9 @@ func GetDefinitions(fc *flowslatest.FlowCollectorSpec, allMetrics bool) []metric if !fc.Processor.IsMultiClusterEnabled() { labelsToRemove = append(labelsToRemove, "K8S_ClusterName") } + if !fc.Agent.EBPF.IsUDNMappingEnabled() && !fc.Processor.HasSecondaryIndexes() { + labelsToRemove = append(labelsToRemove, "SrcK8S_NetworkName", "DstK8S_NetworkName") + } var filterRecordType *metricslatest.MetricFilter if fc.Processor.LogTypes != nil { diff --git a/internal/pkg/metrics/predefined_metrics_test.go b/internal/pkg/metrics/predefined_metrics_test.go index 029690a022..98bdede8b8 100644 --- a/internal/pkg/metrics/predefined_metrics_test.go +++ b/internal/pkg/metrics/predefined_metrics_test.go @@ -24,6 +24,13 @@ func TestIncludeExclude(t *testing.T) { "namespace_network_policy_events_total", "namespace_rtt_seconds", "namespace_sampling", + "network_dns_latency_seconds", + "network_drop_bytes_total", + "network_ingress_bytes_total", + "network_ipsec_flows_total", + "network_network_policy_events_total", + "network_rtt_seconds", + "network_sampling", "node_dns_latency_seconds", "node_drop_bytes_total", "node_ingress_bytes_total", @@ -88,3 +95,204 @@ func TestGetDefinitionsRemoveZoneCluster(t *testing.T) { assert.Equal("Packets", res[2].Spec.ValueField) assert.Equal([]string{"SrcK8S_Namespace", "DstK8S_Namespace", "K8S_FlowLayer", "SrcSubnetLabel", "DstSubnetLabel", "SrcK8S_OwnerName", "DstK8S_OwnerName", "SrcK8S_OwnerType", "DstK8S_OwnerType", "SrcK8S_Type", "DstK8S_Type"}, res[2].Spec.Labels) } + +func TestGetDefinitionsNetworkMetrics(t *testing.T) { + assert := assert.New(t) + + res := GetDefinitions(util.SpecForMetrics("network_ingress_bytes_total", "network_egress_packets_total", "network_flows_total"), false) + assert.Len(res, 3) + // Results are in the order they appear in predefinedMetrics + assert.Equal("network_ingress_bytes_total", res[0].Spec.MetricName) + assert.Equal("Bytes", res[0].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_NetworkName", "DstK8S_NetworkName", "K8S_FlowLayer"}, res[0].Spec.Labels) + assert.Equal("network_egress_packets_total", res[1].Spec.MetricName) + assert.Equal("Packets", res[1].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_NetworkName", "DstK8S_NetworkName", "K8S_FlowLayer"}, res[1].Spec.Labels) + assert.Equal("network_flows_total", res[2].Spec.MetricName) + assert.Empty(res[2].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_NetworkName", "DstK8S_NetworkName", "K8S_FlowLayer"}, res[2].Spec.Labels) +} + +func TestGetDefinitionsNetworkRTT(t *testing.T) { + assert := assert.New(t) + + res := GetDefinitions(util.SpecForMetrics("network_rtt_seconds"), false) + assert.Len(res, 1) + assert.Equal("network_rtt_seconds", res[0].Spec.MetricName) + assert.Equal("TimeFlowRttNs", res[0].Spec.ValueField) + assert.Equal("1000000000", res[0].Spec.Divider) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_NetworkName", "DstK8S_NetworkName", "K8S_FlowLayer"}, res[0].Spec.Labels) + assert.Len(res[0].Spec.Filters, 1) + assert.Equal("TimeFlowRttNs", res[0].Spec.Filters[0].Field) +} + +func TestGetDefinitionsNetworkDNS(t *testing.T) { + assert := assert.New(t) + + res := GetDefinitions(util.SpecForMetrics("network_dns_latency_seconds"), false) + assert.Len(res, 1) + assert.Equal("network_dns_latency_seconds", res[0].Spec.MetricName) + assert.Equal("DnsLatencyMs", res[0].Spec.ValueField) + assert.Equal("1000", res[0].Spec.Divider) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_NetworkName", "DstK8S_NetworkName", "K8S_FlowLayer", "DnsFlagsResponseCode"}, res[0].Spec.Labels) +} + +func TestGetDefinitionsNetworkDrop(t *testing.T) { + assert := assert.New(t) + + res := GetDefinitions(util.SpecForMetrics("network_drop_packets_total", "network_drop_bytes_total"), false) + assert.Len(res, 2) + // Results are sorted alphabetically + assert.Equal("network_drop_packets_total", res[0].Spec.MetricName) + assert.Equal("PktDropPackets", res[0].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_NetworkName", "DstK8S_NetworkName", "K8S_FlowLayer", "PktDropLatestState", "PktDropLatestDropCause"}, res[0].Spec.Labels) + assert.Equal("network_drop_bytes_total", res[1].Spec.MetricName) + assert.Equal("PktDropBytes", res[1].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_NetworkName", "DstK8S_NetworkName", "K8S_FlowLayer", "PktDropLatestState", "PktDropLatestDropCause"}, res[1].Spec.Labels) +} + +func TestGetDefinitionsNetworkIPSec(t *testing.T) { + assert := assert.New(t) + + res := GetDefinitions(util.SpecForMetrics("network_ipsec_flows_total"), false) + assert.Len(res, 1) + assert.Equal("network_ipsec_flows_total", res[0].Spec.MetricName) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_NetworkName", "DstK8S_NetworkName", "K8S_FlowLayer", "IPSecStatus"}, res[0].Spec.Labels) +} + +func TestGetDefinitionsRemoveNetworkLabels(t *testing.T) { + assert := assert.New(t) + + spec := util.SpecForMetrics("network_ingress_bytes_total", "namespace_ingress_bytes_total") + // Disable multiNetworks feature (UDN mapping and secondary indexes) + spec.Agent.EBPF.Features = []flowslatest.AgentFeature{flowslatest.FlowRTT, flowslatest.DNSTracking, flowslatest.PacketDrop} // Remove UDNMapping if it was there + spec.Processor.Advanced = nil // Ensure no secondary indexes + res := GetDefinitions(spec, false) + assert.Len(res, 2) + // Namespace metric should keep all labels + assert.Equal("namespace_ingress_bytes_total", res[0].Spec.MetricName) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_Namespace", "DstK8S_Namespace", "K8S_FlowLayer", "SrcSubnetLabel", "DstSubnetLabel"}, res[0].Spec.Labels) + // Network metric should have network labels removed + assert.Equal("network_ingress_bytes_total", res[1].Spec.MetricName) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "K8S_FlowLayer"}, res[1].Spec.Labels) +} + +func TestGetDefinitionsNodeMetrics(t *testing.T) { + assert := assert.New(t) + + res := GetDefinitions(util.SpecForMetrics("node_ingress_bytes_total", "node_egress_packets_total", "node_flows_total"), false) + assert.Len(res, 3) + assert.Equal("node_ingress_bytes_total", res[0].Spec.MetricName) + assert.Equal("Bytes", res[0].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_HostName", "DstK8S_HostName"}, res[0].Spec.Labels) + assert.Equal("node_egress_packets_total", res[1].Spec.MetricName) + assert.Equal("Packets", res[1].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_HostName", "DstK8S_HostName"}, res[1].Spec.Labels) + assert.Equal("node_flows_total", res[2].Spec.MetricName) + assert.Empty(res[2].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_HostName", "DstK8S_HostName"}, res[2].Spec.Labels) +} + +func TestGetDefinitionsNamespaceMetrics(t *testing.T) { + assert := assert.New(t) + + res := GetDefinitions(util.SpecForMetrics("namespace_ingress_bytes_total", "namespace_egress_packets_total", "namespace_flows_total"), false) + assert.Len(res, 3) + assert.Equal("namespace_ingress_bytes_total", res[0].Spec.MetricName) + assert.Equal("Bytes", res[0].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_Namespace", "DstK8S_Namespace", "K8S_FlowLayer", "SrcSubnetLabel", "DstSubnetLabel"}, res[0].Spec.Labels) + assert.Equal("namespace_egress_packets_total", res[1].Spec.MetricName) + assert.Equal("Packets", res[1].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_Namespace", "DstK8S_Namespace", "K8S_FlowLayer", "SrcSubnetLabel", "DstSubnetLabel"}, res[1].Spec.Labels) + assert.Equal("namespace_flows_total", res[2].Spec.MetricName) + assert.Empty(res[2].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_Namespace", "DstK8S_Namespace", "K8S_FlowLayer", "SrcSubnetLabel", "DstSubnetLabel"}, res[2].Spec.Labels) +} + +func TestGetDefinitionsWorkloadMetrics(t *testing.T) { + assert := assert.New(t) + + res := GetDefinitions(util.SpecForMetrics("workload_ingress_bytes_total", "workload_egress_packets_total", "workload_flows_total"), false) + assert.Len(res, 3) + assert.Equal("workload_ingress_bytes_total", res[0].Spec.MetricName) + assert.Equal("Bytes", res[0].Spec.ValueField) + assert.Equal([]string{"K8S_ClusterName", "SrcK8S_Zone", "DstK8S_Zone", "SrcK8S_Namespace", "DstK8S_Namespace", "K8S_FlowLayer", "SrcSubnetLabel", "DstSubnetLabel", "SrcK8S_OwnerName", "DstK8S_OwnerName", "SrcK8S_OwnerType", "DstK8S_OwnerType", "SrcK8S_Type", "DstK8S_Type"}, res[0].Spec.Labels) + assert.Equal("workload_egress_packets_total", res[1].Spec.MetricName) + assert.Equal("Packets", res[1].Spec.ValueField) + assert.Equal("workload_flows_total", res[2].Spec.MetricName) + assert.Empty(res[2].Spec.ValueField) +} + +func TestGetDefinitionsAllMetricTypesForGroup(t *testing.T) { + assert := assert.New(t) + + // Test all metric types for a single group (node) + res := GetDefinitions(util.SpecForMetrics("node_ingress_bytes_total", "node_rtt_seconds", "node_drop_packets_total", "node_dns_latency_seconds", "node_ipsec_flows_total"), false) + assert.Len(res, 5) + + // Check that different metric types are present + metricNames := make([]string, len(res)) + for i, m := range res { + metricNames[i] = m.Spec.MetricName + } + assert.Contains(metricNames, "node_ingress_bytes_total") + assert.Contains(metricNames, "node_rtt_seconds") + assert.Contains(metricNames, "node_drop_packets_total") + assert.Contains(metricNames, "node_dns_latency_seconds") + assert.Contains(metricNames, "node_ipsec_flows_total") + + // Verify RTT has correct configuration + for _, m := range res { + if m.Spec.MetricName == "node_rtt_seconds" { + assert.Equal("TimeFlowRttNs", m.Spec.ValueField) + assert.Equal("1000000000", m.Spec.Divider) + assert.Len(m.Spec.Filters, 1) + } + } +} + +func TestGetDefinitionsMixedGroups(t *testing.T) { + assert := assert.New(t) + + // Test requesting metrics from different groups + res := GetDefinitions(util.SpecForMetrics("node_ingress_bytes_total", "namespace_flows_total", "workload_egress_packets_total", "network_rtt_seconds"), false) + assert.Len(res, 4) + + metricNames := make([]string, len(res)) + for i, m := range res { + metricNames[i] = m.Spec.MetricName + } + assert.Contains(metricNames, "node_ingress_bytes_total") + assert.Contains(metricNames, "namespace_flows_total") + assert.Contains(metricNames, "workload_egress_packets_total") + assert.Contains(metricNames, "network_rtt_seconds") +} + +func TestGetDefinitionsRemoveZoneLabels(t *testing.T) { + assert := assert.New(t) + + spec := util.SpecForMetrics("node_ingress_bytes_total", "network_ingress_bytes_total", "namespace_flows_total") + spec.Processor.AddZone = ptr.To(false) + res := GetDefinitions(spec, false) + assert.Len(res, 3) + + // All metrics should have zone labels removed + for _, m := range res { + assert.NotContains(m.Spec.Labels, "SrcK8S_Zone") + assert.NotContains(m.Spec.Labels, "DstK8S_Zone") + } +} + +func TestGetDefinitionsRemoveMultiClusterLabels(t *testing.T) { + assert := assert.New(t) + + spec := util.SpecForMetrics("node_ingress_bytes_total", "network_ingress_bytes_total", "namespace_flows_total") + spec.Processor.MultiClusterDeployment = ptr.To(false) + res := GetDefinitions(spec, false) + assert.Len(res, 3) + + // All metrics should have cluster label removed + for _, m := range res { + assert.NotContains(m.Spec.Labels, "K8S_ClusterName") + } +} diff --git a/internal/pkg/test/util/utils.go b/internal/pkg/test/util/utils.go index 61c06b18b3..3617818433 100644 --- a/internal/pkg/test/util/utils.go +++ b/internal/pkg/test/util/utils.go @@ -10,7 +10,7 @@ func SpecForMetrics(metrics ...string) *flowslatest.FlowCollectorSpec { Agent: flowslatest.FlowCollectorAgent{ EBPF: flowslatest.FlowCollectorEBPF{ Privileged: true, - Features: []flowslatest.AgentFeature{flowslatest.FlowRTT, flowslatest.DNSTracking, flowslatest.PacketDrop}, + Features: []flowslatest.AgentFeature{flowslatest.FlowRTT, flowslatest.DNSTracking, flowslatest.PacketDrop, flowslatest.UDNMapping, flowslatest.IPSec}, }, }, Processor: flowslatest.FlowCollectorFLP{