diff --git a/pkg/core/manager/insight/summary.go b/pkg/core/manager/insight/summary.go index ab7ebb46..5be256f8 100644 --- a/pkg/core/manager/insight/summary.go +++ b/pkg/core/manager/insight/summary.go @@ -36,10 +36,13 @@ const ( // GetDetailsForCluster returns ClusterDetail object for a given cluster func (i *InsightManager) GetDetailsForCluster(ctx context.Context, client *multicluster.MultiClusterClient, name string) (*ClusterDetail, error) { + // get server version and measure latency + start := time.Now() serverVersion, err := client.ClientSet.DiscoveryClient.ServerVersion() if err != nil { return nil, fmt.Errorf("failed to get server version: %w", err) } + latency := time.Since(start).Milliseconds() // Get the list of nodes nodes, err := client.ClientSet.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) @@ -144,6 +147,7 @@ func (i *InsightManager) GetDetailsForCluster(ctx context.Context, client *multi MetricsEnabled: metricsEnabled, CPUMetrics: cpuMetrics, MemoryMetrics: memoryMetrics, + Latency: latency, }, nil } diff --git a/pkg/core/manager/insight/types.go b/pkg/core/manager/insight/types.go index a4177733..48f5d83a 100644 --- a/pkg/core/manager/insight/types.go +++ b/pkg/core/manager/insight/types.go @@ -82,6 +82,9 @@ type ClusterDetail struct { PodsCapacity int64 `json:"podsCapacity"` PodsUsage int64 `json:"podsUsage"` + // Latency is the latency of the cluster in milliseconds + Latency int64 `json:"latency"` + MetricsEnabled bool `json:"metricsEnabled"` CPUMetrics ResourceMetrics `json:"cpuMetrics"` diff --git a/ui/src/hooks/useClusterLatency.ts b/ui/src/hooks/useClusterLatency.ts new file mode 100644 index 00000000..4f465166 --- /dev/null +++ b/ui/src/hooks/useClusterLatency.ts @@ -0,0 +1,48 @@ +import { useAxios } from '@/utils/request' +import { useState, useEffect, useRef, useCallback } from 'react' +import axios from 'axios' + +export const useClusterLatency = (cluster: string) => { + const latencyRef = useRef(0) + const [loading, setLoading] = useState(true) + const initialized = useRef(false) + + const { response: summaryResponse, refetch: summaryRefetch } = useAxios({ + url: `${axios.defaults.baseURL}/rest-api/v1/insight/summary`, + method: 'GET', + manual: true, + }) + + useEffect(() => { + if (summaryResponse?.success) { + latencyRef.current = summaryResponse?.data?.latency + setLoading(false) + } else { + latencyRef.current = 0 + setLoading(true) + } + }, [summaryResponse]) + + const fetchLatency = useCallback(() => { + if (cluster) { + summaryRefetch({ + option: { + params: { + cluster, + }, + }, + }) + } + }, [cluster, summaryRefetch]) + + // Only execute once when component is first mounted + useEffect(() => { + if (!initialized.current) { + initialized.current = true + fetchLatency() + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + return { latency: latencyRef, loading, refetch: fetchLatency } +} diff --git a/ui/src/pages/cluster/components/clusterCard/index.tsx b/ui/src/pages/cluster/components/clusterCard/index.tsx index 1da317fb..65f4bc83 100644 --- a/ui/src/pages/cluster/components/clusterCard/index.tsx +++ b/ui/src/pages/cluster/components/clusterCard/index.tsx @@ -1,10 +1,12 @@ import React from 'react' -import { Button, Popconfirm } from 'antd' +import { Button, Popconfirm, Tag } from 'antd' import { useSelector } from 'react-redux' import { useTranslation } from 'react-i18next' import { utcDateToLocalDate } from '@/utils/tools' import k8sPng from '@/assets/kubernetes.png' import EditPopForm from '../editPopForm' +import { useClusterLatency } from '@/hooks/useClusterLatency' +import { LoadingOutlined } from '@ant-design/icons' import styles from './styles.module.less' @@ -30,6 +32,11 @@ const ClusterCard = (props: IProps) => { handleSubmit, customStyle, } = props + + const { latency, loading: latencyLoading } = useClusterLatency( + item?.metadata?.name, + ) + return (
goDetailPage(item)}> @@ -43,13 +50,36 @@ const ClusterCard = (props: IProps) => { <> {item?.spec?.displayName} - ({item?.metadata?.name}) +  ({item?.metadata?.name}) ) : ( {item?.metadata?.name} )}
+
+ {latencyLoading ? ( + + ) : ( + + + {latency.current}ms + + + )} +
{item?.spec?.description || '--'}
diff --git a/ui/src/pages/insightDetail/components/sourceTable/index.tsx b/ui/src/pages/insightDetail/components/sourceTable/index.tsx index a297ba87..7bdd65ca 100644 --- a/ui/src/pages/insightDetail/components/sourceTable/index.tsx +++ b/ui/src/pages/insightDetail/components/sourceTable/index.tsx @@ -32,7 +32,7 @@ export const PodStatusCell = ({ cluster, namespace, name }) => { const color = { Running: 'success', - Terminating: 'default', + Terminated: 'default', Unknown: 'error', }[status.current] || 'warning' diff --git a/ui/src/pages/insightDetail/components/summaryCard/index.tsx b/ui/src/pages/insightDetail/components/summaryCard/index.tsx index f8a4b23d..50a63db2 100644 --- a/ui/src/pages/insightDetail/components/summaryCard/index.tsx +++ b/ui/src/pages/insightDetail/components/summaryCard/index.tsx @@ -346,7 +346,7 @@ const SummaryCard = ({ auditStat, summary }: SummaryCardProps) => { color={ { Running: 'success', - Terminating: 'default', + Terminated: 'default', Unknown: 'error', }[summary?.resource?.status] || 'warning' } @@ -532,6 +532,12 @@ const SummaryCard = ({ auditStat, summary }: SummaryCardProps) => { )} {summary?.countByGVK ? renderStatistics(summary?.countByGVK) : null} + {summary?.latency && ( +
+
Latency
+
{summary?.latency}ms
+
+ )}