diff --git a/config/sample-config.yaml b/config/sample-config.yaml index ab143251f..c6c47ab04 100644 --- a/config/sample-config.yaml +++ b/config/sample-config.yaml @@ -152,6 +152,20 @@ frontend: # flow on current scope - Flows - DnsFlows + # UDN + - UdnId_Bytes + - UdnId_Packets + - min_UdnId_TimeFlowRttNs + - max_UdnId_TimeFlowRttNs + - avg_UdnId_TimeFlowRttNs + - p90_UdnId_TimeFlowRttNs + - p99_UdnId_TimeFlowRttNs + - min_UdnId_DnsLatencyMs + - max_UdnId_DnsLatencyMs + - avg_UdnId_DnsLatencyMs + - p90_UdnId_DnsLatencyMs + - p99_UdnId_DnsLatencyMs + - UdnId_Flows columns: - id: StartTime name: Start Time @@ -586,6 +600,13 @@ frontend: field: Interfaces default: false width: 15 + - id: UDN + name: User Defined Network + tooltip: The user defined network identifier. + field: UdnId + filter: udn + default: false + width: 15 - id: Bytes name: Bytes tooltip: The total aggregated number of bytes. @@ -1022,6 +1043,10 @@ frontend: component: autocomplete placeholder: 'E.g: Ingress, Egress' hint: Specify the direction of the Flow observed at the network interface observation point. + - id: udn + name: User Defined Network + component: autocomplete + hint: Specify a user defined network name. - id: id name: Conversation Id component: text @@ -1086,6 +1111,14 @@ frontend: feature: multiCluster filter: cluster_name stepInto: zone + - id: udn + name: UDN + shortName: UDN + description: User Defined Network + labels: + - UdnId + filter: udn + stepInto: host - id: zone name: Zone shortName: AZ @@ -1099,17 +1132,21 @@ frontend: filters: - src_zone - dst_zone - stepInto: host + stepInto: namespace - id: host name: Node + shortName: Node description: Node on which the resources are running labels: - SrcK8S_HostName - DstK8S_HostName groups: - - clusters + - udns - zones + - clusters - clusters+zones + - clusters+udns + - udns+zones filters: - src_host_name - dst_host_name @@ -1128,6 +1165,9 @@ frontend: - zones - zones+hosts - hosts + - udns + - udns+zones + - udns+hosts filters: - src_namespace - dst_namespace @@ -1154,6 +1194,10 @@ frontend: - hosts - hosts+namespaces - namespaces + - udns + - udns+zones + - udns+hosts + - udns+namespaces filters: - src_owner_name - dst_owner_name @@ -1193,6 +1237,11 @@ frontend: - namespaces - namespaces+owners - owners + - udns + - udns+zones + - udns+hosts + - udns+namespaces + - udns+owners filters: - src_resource - dst_resource @@ -1366,6 +1415,10 @@ frontend: - name: K8S_ClusterName type: string description: Cluster name or identifier + - name: UdnId + type: string + description: User Defined Network + lokiLabel: true - name: _RecordType type: string description: "Type of record: 'flowLog' for regular flow logs, or 'newConnection', 'heartbeat', 'endConnection' for conversation tracking" diff --git a/mocks/loki/flow_metrics_dropped_udn.json b/mocks/loki/flow_metrics_dropped_udn.json new file mode 100644 index 000000000..c62d99a73 --- /dev/null +++ b/mocks/loki/flow_metrics_dropped_udn.json @@ -0,0 +1,132 @@ +{ + "status": "success", + "data": { + "resultType": "matrix", + "result": [ + { + "metric": { + "UdnId": "my-udn" + }, + "values": [ + [ + 1708011360, + "0.041666666666666664" + ], + [ + 1708011720, + "0.6236111111111111" + ] + ] + }, + { + "metric": { + "UdnId": "my-udn-2" + }, + "values": [ + [ + 1708011360, + "0.036111111111111115" + ], + [ + 1708011720, + "0.49166666666666664" + ] + ] + } + ], + "stats": { + "summary": { + "bytesProcessedPerSecond": 379050316, + "linesProcessedPerSecond": 577163, + "totalBytesProcessed": 221936446, + "totalLinesProcessed": 337933, + "execTime": 0.585506558, + "queueTime": 5.295528995, + "subqueries": 0, + "totalEntriesReturned": 2, + "splits": 6, + "shards": 48, + "totalPostFilterLines": 810, + "totalStructuredMetadataBytesProcessed": 0 + }, + "querier": { + "store": { + "totalChunksRef": 0, + "totalChunksDownloaded": 0, + "chunksDownloadTime": 0, + "chunk": { + "headChunkBytes": 0, + "headChunkLines": 0, + "decompressedBytes": 0, + "decompressedLines": 0, + "compressedBytes": 0, + "totalDuplicates": 0, + "postFilterLines": 0, + "headChunkStructuredMetadataBytes": 0, + "decompressedStructuredMetadataBytes": 0 + } + } + }, + "ingester": { + "totalReached": 48, + "totalChunksMatched": 375, + "totalBatches": 56, + "totalLinesSent": 802, + "store": { + "totalChunksRef": 16, + "totalChunksDownloaded": 16, + "chunksDownloadTime": 7855086, + "chunk": { + "headChunkBytes": 18755808, + "headChunkLines": 28594, + "decompressedBytes": 203180638, + "decompressedLines": 309339, + "compressedBytes": 43253118, + "totalDuplicates": 0, + "postFilterLines": 810, + "headChunkStructuredMetadataBytes": 0, + "decompressedStructuredMetadataBytes": 0 + } + } + }, + "cache": { + "chunk": { + "entriesFound": 0, + "entriesRequested": 0, + "entriesStored": 0, + "bytesReceived": 0, + "bytesSent": 0, + "requests": 0, + "downloadTime": 0 + }, + "index": { + "entriesFound": 0, + "entriesRequested": 0, + "entriesStored": 0, + "bytesReceived": 0, + "bytesSent": 0, + "requests": 0, + "downloadTime": 0 + }, + "result": { + "entriesFound": 4, + "entriesRequested": 6, + "entriesStored": 3, + "bytesReceived": 1372, + "bytesSent": 0, + "requests": 9, + "downloadTime": 63334 + }, + "statsResult": { + "entriesFound": 0, + "entriesRequested": 0, + "entriesStored": 0, + "bytesReceived": 0, + "bytesSent": 0, + "requests": 0, + "downloadTime": 0 + } + } + } + } +} diff --git a/mocks/loki/flow_metrics_udn.json b/mocks/loki/flow_metrics_udn.json new file mode 100644 index 000000000..68b3b4b00 --- /dev/null +++ b/mocks/loki/flow_metrics_udn.json @@ -0,0 +1,345 @@ +{ + "status": "success", + "data": { + "resultType": "matrix", + "result": [ + { + "metric": { + "UdnId": "my-udn" + }, + "values": [ + [ + 1708009560, + "30.462500000000002" + ], + [ + 1708009920, + "83.63333333333333" + ], + [ + 1708010280, + "106.85972222222223" + ], + [ + 1708010640, + "107.56805555555555" + ], + [ + 1708011000, + "106.51805555555556" + ], + [ + 1708011360, + "109.6125" + ], + [ + 1708011720, + "110.91944444444444" + ] + ] + }, + { + "metric": { + "UdnId": "my-udn-2" + }, + "values": [ + [ + 1708009560, + "0.004166666666666667" + ], + [ + 1708009920, + "0.016666666666666666" + ], + [ + 1708010280, + "0.034722222222222224" + ], + [ + 1708010640, + "0.041666666666666664" + ], + [ + 1708011000, + "0.06388888888888888" + ], + [ + 1708011360, + "0.04861111111111111" + ], + [ + 1708011720, + "0.02361111111111111" + ] + ] + }, + { + "metric": { + "UdnId": "my-udn-3" + }, + "values": [ + [ + 1708009560, + "31.53055555555556" + ], + [ + 1708009920, + "83.43611111111112" + ], + [ + 1708010280, + "104.72083333333335" + ], + [ + 1708010640, + "105.5486111111111" + ], + [ + 1708011000, + "104.40833333333333" + ], + [ + 1708011360, + "110.03055555555555" + ], + [ + 1708011720, + "110.98749999999998" + ] + ] + }, + { + "metric": { + "UdnId": "my-udn-4" + }, + "values": [ + [ + 1708009560, + "0.09444444444444444" + ], + [ + 1708009920, + "0.3902777777777778" + ], + [ + 1708010280, + "0.4361111111111111" + ], + [ + 1708010640, + "0.3138888888888889" + ], + [ + 1708011000, + "0.4388888888888889" + ], + [ + 1708011360, + "0.5305555555555554" + ], + [ + 1708011720, + "0.5791666666666667" + ] + ] + }, + { + "metric": { + "UdnId": "my-udn-5" + }, + "values": [ + [ + 1708009560, + "28.173611111111114" + ], + [ + 1708009920, + "69.80277777777779" + ], + [ + 1708010280, + "90.45694444444445" + ], + [ + 1708010640, + "98.41944444444445" + ], + [ + 1708011000, + "90.15416666666668" + ], + [ + 1708011360, + "111.44027777777778" + ], + [ + 1708011720, + "113.11527777777778" + ] + ] + }, + { + "metric": { + "UdnId": "my-udn-6" + }, + "values": [ + [ + 1708009560, + "57.96527777777777" + ], + [ + 1708009920, + "134.44583333333335" + ], + [ + 1708010280, + "147.5902777777778" + ], + [ + 1708010640, + "162.97222222222226" + ], + [ + 1708011000, + "162.59444444444446" + ], + [ + 1708011360, + "175.71666666666664" + ], + [ + 1708011720, + "179.0402777777778" + ] + ] + }, + { + "metric": {}, + "values": [ + [ + 1708009560, + "1.0333333333333334" + ], + [ + 1708009920, + "2.9722222222222223" + ], + [ + 1708010280, + "3.791666666666667" + ], + [ + 1708010640, + "3.6625" + ], + [ + 1708011000, + "3.808333333333333" + ], + [ + 1708011360, + "3.8805555555555555" + ], + [ + 1708011720, + "3.863888888888889" + ] + ] + } + ], + "stats": { + "summary": { + "bytesProcessedPerSecond": 328874222, + "linesProcessedPerSecond": 500497, + "totalBytesProcessed": 211370848, + "totalLinesProcessed": 321675, + "execTime": 0.642710294, + "queueTime": 8.042418995, + "subqueries": 0, + "totalEntriesReturned": 7, + "splits": 6, + "shards": 48, + "totalPostFilterLines": 199944, + "totalStructuredMetadataBytesProcessed": 0 + }, + "querier": { + "store": { + "totalChunksRef": 0, + "totalChunksDownloaded": 0, + "chunksDownloadTime": 0, + "chunk": { + "headChunkBytes": 0, + "headChunkLines": 0, + "decompressedBytes": 0, + "decompressedLines": 0, + "compressedBytes": 0, + "totalDuplicates": 0, + "postFilterLines": 0, + "headChunkStructuredMetadataBytes": 0, + "decompressedStructuredMetadataBytes": 0 + } + } + }, + "ingester": { + "totalReached": 48, + "totalChunksMatched": 375, + "totalBatches": 394, + "totalLinesSent": 168379, + "store": { + "totalChunksRef": 16, + "totalChunksDownloaded": 16, + "chunksDownloadTime": 13901153, + "chunk": { + "headChunkBytes": 18864260, + "headChunkLines": 28785, + "decompressedBytes": 192506588, + "decompressedLines": 292890, + "compressedBytes": 43190086, + "totalDuplicates": 0, + "postFilterLines": 199944, + "headChunkStructuredMetadataBytes": 0, + "decompressedStructuredMetadataBytes": 0 + } + } + }, + "cache": { + "chunk": { + "entriesFound": 0, + "entriesRequested": 0, + "entriesStored": 0, + "bytesReceived": 0, + "bytesSent": 0, + "requests": 0, + "downloadTime": 0 + }, + "index": { + "entriesFound": 0, + "entriesRequested": 0, + "entriesStored": 0, + "bytesReceived": 0, + "bytesSent": 0, + "requests": 0, + "downloadTime": 0 + }, + "result": { + "entriesFound": 4, + "entriesRequested": 6, + "entriesStored": 3, + "bytesReceived": 3008, + "bytesSent": 0, + "requests": 9, + "downloadTime": 59230 + }, + "statsResult": { + "entriesFound": 0, + "entriesRequested": 0, + "entriesStored": 0, + "bytesReceived": 0, + "bytesSent": 0, + "requests": 0, + "downloadTime": 0 + } + } + } + } +} \ No newline at end of file diff --git a/mocks/loki/flow_records.json b/mocks/loki/flow_records.json index df48a59dd..fdaff90d3 100644 --- a/mocks/loki/flow_records.json +++ b/mocks/loki/flow_records.json @@ -9,6 +9,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-7.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "yet-another-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -45,6 +46,7 @@ "SrcK8S_Namespace": "openshift-service-ca-operator", "SrcK8S_OwnerName": "service-ca-operator", "SrcK8S_Type": "Pod", + "UdnId": "another-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -60,6 +62,7 @@ "DstK8S_Type": "Node", "FlowDirection": "0", "K8S_FlowLayer": "infra", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -97,6 +100,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-137.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -126,6 +130,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-7.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -154,6 +159,7 @@ "DstK8S_Type": "Pod", "FlowDirection": "0", "K8S_FlowLayer": "infra", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -173,6 +179,7 @@ "SrcK8S_Namespace": "default", "SrcK8S_OwnerName": "kubernetes", "SrcK8S_Type": "Service", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -196,6 +203,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -219,6 +227,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "telemeter-client", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -246,6 +255,7 @@ "SrcK8S_Namespace": "openshift-dns", "SrcK8S_OwnerName": "dns-default", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -277,6 +287,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "alertmanager-main", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -300,6 +311,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "alertmanager-main", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -323,6 +335,7 @@ "SrcK8S_Namespace": "openshift-dns", "SrcK8S_OwnerName": "dns-default", "SrcK8S_Type": "Service", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -354,6 +367,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "alertmanager-main", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -385,6 +399,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "alertmanager-main", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -416,6 +431,7 @@ "SrcK8S_Namespace": "openshift-service-ca-operator", "SrcK8S_OwnerName": "service-ca-operator", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -521,4 +537,4 @@ } } } -} +} \ No newline at end of file diff --git a/mocks/loki/flow_records_has_dropped.json b/mocks/loki/flow_records_has_dropped.json index 8675b3766..5919dcefa 100644 --- a/mocks/loki/flow_records_has_dropped.json +++ b/mocks/loki/flow_records_has_dropped.json @@ -10,6 +10,7 @@ "SrcK8S_Namespace": "openshift-service-ca-operator", "SrcK8S_OwnerName": "service-ca-operator", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -26,6 +27,7 @@ "SrcK8S_Namespace": "openshift-service-ca", "SrcK8S_OwnerName": "service-ca", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -42,6 +44,7 @@ "SrcK8S_Namespace": "openshift-network-diagnostics", "SrcK8S_OwnerName": "network-check-source", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -58,6 +61,7 @@ "SrcK8S_Namespace": "openshift-console-operator", "SrcK8S_OwnerName": "console-operator", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -74,6 +78,7 @@ "SrcK8S_Namespace": "openshift-console", "SrcK8S_OwnerName": "console", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -103,6 +108,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-137.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -121,6 +127,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -143,6 +150,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-adapter", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -160,6 +168,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-7.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -183,6 +192,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -201,6 +211,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-137.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -224,6 +235,7 @@ "SrcK8S_Namespace": "openshift-dns", "SrcK8S_OwnerName": "dns-default", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -243,6 +255,7 @@ "SrcK8S_Namespace": "openshift-console", "SrcK8S_OwnerName": "console", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -261,6 +274,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-7.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -280,6 +294,7 @@ "SrcK8S_Namespace": "openshift-user-workload-monitoring", "SrcK8S_OwnerName": "prometheus-operator", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -299,6 +314,7 @@ "SrcK8S_Namespace": "netobserv", "SrcK8S_OwnerName": "netobserv-controller-manager", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -317,6 +333,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-7.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -336,6 +353,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -355,6 +373,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -374,6 +393,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -393,6 +413,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -412,6 +433,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -431,6 +453,7 @@ "SrcK8S_Namespace": "openshift-console", "SrcK8S_OwnerName": "console", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -450,6 +473,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -469,6 +493,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -488,6 +513,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -507,6 +533,7 @@ "SrcK8S_Namespace": "openshift-ingress", "SrcK8S_OwnerName": "router-default", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -530,6 +557,7 @@ "SrcK8S_Namespace": "netobserv", "SrcK8S_OwnerName": "loki", "SrcK8S_Type": "Service", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -601,6 +629,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -620,6 +649,7 @@ "SrcK8S_Namespace": "netobserv", "SrcK8S_OwnerName": "netobserv-plugin", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -725,4 +755,4 @@ } } } -} +} \ No newline at end of file diff --git a/mocks/loki/flow_records_sent.json b/mocks/loki/flow_records_sent.json index efbd99a45..cffdb4c79 100644 --- a/mocks/loki/flow_records_sent.json +++ b/mocks/loki/flow_records_sent.json @@ -7,6 +7,7 @@ "stream": { "FlowDirection": "1", "K8S_FlowLayer": "infra", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -30,6 +31,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-7.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -55,6 +57,7 @@ "stream": { "FlowDirection": "0", "K8S_FlowLayer": "infra", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -125,6 +128,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -144,6 +148,7 @@ "DstK8S_Type": "Node", "FlowDirection": "0", "K8S_FlowLayer": "infra", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -173,6 +178,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-137.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -214,6 +220,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-7.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -252,6 +259,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "prometheus-k8s", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -270,6 +278,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-7.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -296,6 +305,7 @@ "K8S_FlowLayer": "infra", "SrcK8S_OwnerName": "ip-10-0-1-137.ec2.internal", "SrcK8S_Type": "Node", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -319,6 +329,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "alertmanager-main", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -342,6 +353,7 @@ "SrcK8S_Namespace": "openshift-monitoring", "SrcK8S_OwnerName": "alertmanager-main", "SrcK8S_Type": "Pod", + "UdnId": "my-udn", "app": "netobserv-flowcollector" }, "values": [ @@ -451,4 +463,4 @@ } } } -} +} \ No newline at end of file diff --git a/pkg/handler/lokiclientmock/loki_client_mock.go b/pkg/handler/lokiclientmock/loki_client_mock.go index d8402cc79..7bccadcb0 100644 --- a/pkg/handler/lokiclientmock/loki_client_mock.go +++ b/pkg/handler/lokiclientmock/loki_client_mock.go @@ -36,6 +36,8 @@ func (o *LokiClientMock) Get(url string) ([]byte, int, error) { path += "_cause.json" } else if strings.Contains(url, "by(K8S_ClusterName)") { path += "_cluster.json" + } else if strings.Contains(url, "by(UdnId)") { + path += "_udn.json" } else if strings.Contains(url, "by(SrcK8S_Zone,DstK8S_Zone)") { path += "_zone.json" } else if strings.Contains(url, "by(SrcK8S_HostName,DstK8S_HostName)") { diff --git a/pkg/handler/resources.go b/pkg/handler/resources.go index 7bcfa74ef..8bf0d9295 100644 --- a/pkg/handler/resources.go +++ b/pkg/handler/resources.go @@ -44,6 +44,35 @@ func (h *Handlers) GetClusters(ctx context.Context) func(w http.ResponseWriter, } } +func (h *Handlers) GetUDNs(ctx context.Context) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + params := r.URL.Query() + namespace := params.Get(namespaceKey) + isDev := namespace != "" + + clients, err := newClients(h.Cfg, r.Header, false, namespace) + if err != nil { + writeError(w, http.StatusInternalServerError, err.Error()) + return + } + var code int + startTime := time.Now() + defer func() { + metrics.ObserveHTTPCall("GetUDNs", code, startTime) + }() + + // Fetch and merge values for K8S_ClusterName + values, code, err := h.getLabelValues(ctx, clients, fields.UDN, isDev) + if err != nil { + writeError(w, code, err.Error()) + return + } + + code = http.StatusOK + writeJSON(w, code, utils.NonEmpty(utils.Dedup(values))) + } +} + func (h *Handlers) GetZones(ctx context.Context) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() diff --git a/pkg/model/fields/fields.go b/pkg/model/fields/fields.go index e54d86803..7963d1a3f 100644 --- a/pkg/model/fields/fields.go +++ b/pkg/model/fields/fields.go @@ -34,6 +34,7 @@ const ( SrcZone = Src + Zone DstZone = Dst + Zone Cluster = "K8S_ClusterName" + UDN = "UDN" Layer = "K8S_FlowLayer" Packets = "Packets" Proto = "Proto" diff --git a/pkg/server/routes.go b/pkg/server/routes.go index f2cb594dc..09e6b7c16 100644 --- a/pkg/server/routes.go +++ b/pkg/server/routes.go @@ -51,6 +51,7 @@ func setupRoutes(ctx context.Context, cfg *config.Config, authChecker auth.Check // Common endpoints api.HandleFunc("/flow/metrics", h.GetTopology(ctx)) api.HandleFunc("/resources/clusters", h.GetClusters(ctx)) + api.HandleFunc("/resources/udns", h.GetUDNs(ctx)) api.HandleFunc("/resources/zones", h.GetZones(ctx)) api.HandleFunc("/resources/namespaces", h.GetNamespaces(ctx)) api.HandleFunc("/resources/names", h.GetNames(ctx)) diff --git a/scripts/update-config.sh b/scripts/update-config.sh index c3d7dbcc3..a9a2adc8c 100755 --- a/scripts/update-config.sh +++ b/scripts/update-config.sh @@ -9,6 +9,9 @@ yq eval-all --inplace 'select(fileIndex==0).frontend.columns = select(fileIndex= echo " - filters..." yq eval-all --inplace 'select(fileIndex==0).frontend.filters = select(fileIndex==1).filters | select(fileIndex==0)' ./config/sample-config.yaml ./tmp/config.yaml +echo " - scopes..." +yq eval-all --inplace 'select(fileIndex==0).frontend.scopes = select(fileIndex==1).scopes | select(fileIndex==0)' ./config/sample-config.yaml ./tmp/config.yaml + echo " - fields..." yq eval-all --inplace 'select(fileIndex==0).frontend.fields = select(fileIndex==1).fields | select(fileIndex==0)' ./config/sample-config.yaml ./tmp/config.yaml diff --git a/web/console-extensions.json b/web/console-extensions.json index 36cadb0a5..ee76b1484 100644 --- a/web/console-extensions.json +++ b/web/console-extensions.json @@ -243,6 +243,40 @@ } } }, + { + "type": "console.tab/horizontalNav", + "properties": { + "model": { + "version": "v1", + "group": "k8s.ovn.org", + "kind": "ClusterUserDefinedNetwork" + }, + "component": { + "$codeRef": "netflowTab.default" + }, + "page": { + "name": "%plugin__netobserv-plugin~Network Traffic%", + "href": "netflow" + } + } + }, + { + "type": "console.tab/horizontalNav", + "properties": { + "model": { + "version": "v1", + "group": "k8s.ovn.org", + "kind": "UserDefinedNetwork" + }, + "component": { + "$codeRef": "netflowTab.default" + }, + "page": { + "name": "%plugin__netobserv-plugin~Network Traffic%", + "href": "netflow" + } + } + }, { "type": "console.tab", "properties": { diff --git a/web/locales/en/plugin__netobserv-plugin.json b/web/locales/en/plugin__netobserv-plugin.json index 8462b37e7..0c09fab7f 100644 --- a/web/locales/en/plugin__netobserv-plugin.json +++ b/web/locales/en/plugin__netobserv-plugin.json @@ -9,6 +9,7 @@ "IP": "IP", "No information available for this content. Change scope to get more details.": "No information available for this content. Change scope to get more details.", "Cluster name": "Cluster name", + "UDN": "UDN", "Source": "Source", "Destination": "Destination", "Stats": "Stats", diff --git a/web/src/api/ipfix.ts b/web/src/api/ipfix.ts index 2072d946b..8f89c4aa1 100644 --- a/web/src/api/ipfix.ts +++ b/web/src/api/ipfix.ts @@ -179,6 +179,8 @@ export interface Fields { _IsFirst?: string; /** In conversation tracking, a counter of flow logs per conversation */ numFlowLogs?: number; + /** User Defined Network identifier */ + UdnId?: string; } export type Field = keyof Fields | keyof Labels; diff --git a/web/src/api/loki.ts b/web/src/api/loki.ts index 7a587d2e1..b535837f7 100644 --- a/web/src/api/loki.ts +++ b/web/src/api/loki.ts @@ -73,6 +73,7 @@ export interface TopologyMetricPeer { namespace?: string; host?: string; cluster?: string; + udn?: string; } export type GenericMetric = { diff --git a/web/src/api/routes.ts b/web/src/api/routes.ts index b5c27ede2..f8aa4c0be 100644 --- a/web/src/api/routes.ts +++ b/web/src/api/routes.ts @@ -75,6 +75,16 @@ export const getClusters = (forcedNamespace?: string): Promise => { }); }; +export const getUDNs = (forcedNamespace?: string): Promise => { + const params = { namespace: forcedNamespace }; + return axios.get(ContextSingleton.getHost() + '/api/resources/udns', { params }).then(r => { + if (r.status >= 400) { + throw new Error(`${r.statusText} [code=${r.status}]`); + } + return r.data; + }); +}; + export const getZones = (forcedNamespace?: string): Promise => { const params = { namespace: forcedNamespace }; return axios.get(ContextSingleton.getHost() + '/api/resources/zones', { params }).then(r => { diff --git a/web/src/app.tsx b/web/src/app.tsx index b4c8185d2..33354a764 100755 --- a/web/src/app.tsx +++ b/web/src/app.tsx @@ -44,6 +44,10 @@ export const pages = [ { id: 'dev-tab', name: 'Dev tab' + }, + { + id: 'udn-tab', + name: 'UDN tab' } ]; @@ -94,6 +98,10 @@ export class App extends React.Component<{}, AppState> { }} /> ); + case 'udn-tab': + return ( + + ); default: return ; } diff --git a/web/src/components/drawer/element/element-panel-content.tsx b/web/src/components/drawer/element/element-panel-content.tsx index c57030902..558f12da1 100644 --- a/web/src/components/drawer/element/element-panel-content.tsx +++ b/web/src/components/drawer/element/element-panel-content.tsx @@ -75,10 +75,39 @@ export const ElementPanelContent: React.FC = ({ [filterDefinitions, filters, setFilters, t] ); + const udnName = React.useCallback( + (d: NodeData) => { + if (!d.peer.udn) { + return <>; + } + const fields = createPeer({ udn: d.peer.udn }); + const isFiltered = isElementFiltered(fields, filters, filterDefinitions); + return ( + + {t('UDN')} + + {d.peer.udn} + +