瀏覽代碼

improve memory in system view

Signed-off-by: nameczz <zizhao.chen@zilliz.com>
nameczz 3 年之前
父節點
當前提交
2d2c2a2311

+ 110 - 94
client/src/plugins/system/DataCard.tsx

@@ -1,9 +1,12 @@
-
 import { FC } from 'react';
 import { useTranslation } from 'react-i18next';
 import { makeStyles } from '@material-ui/core';
 import Progress from './Progress';
-import { getByteString } from '../../utils/Format';
+import {
+  formatByteSize,
+  formatSystemTime,
+  getByteString,
+} from '../../utils/Format';
 import { DataProgressProps, DataSectionProps, DataCardProps } from './Types';
 
 const getStyles = makeStyles(() => ({
@@ -32,7 +35,7 @@ const getStyles = makeStyles(() => ({
     color: '#82838E',
     fontSize: '14px',
     lineHeight: '36px',
-    marginLeft: "8px",
+    marginLeft: '8px',
   },
 
   rootName: {
@@ -57,7 +60,7 @@ const getStyles = makeStyles(() => ({
     borderSpacing: '0 1px',
     display: 'table',
     marginTop: '24px',
-    width: '100%'
+    width: '100%',
   },
 
   sectionRow: {
@@ -91,32 +94,33 @@ const getStyles = makeStyles(() => ({
     lineHeight: '24px',
     display: 'flex',
     justifyContent: 'space-between',
-  }
+  },
 }));
 
-const DataSection: FC<DataSectionProps> = (props) => {
+const DataSection: FC<DataSectionProps> = props => {
   const classes = getStyles();
   const { titles, contents } = props;
 
   return (
     <div className={classes.sectionRoot}>
       <div className={classes.sectionRow}>
-        {titles.map((titleEntry) => <div key={titleEntry} className={classes.sectionHeaderCell}>{titleEntry}</div>)}
+        {titles.map(titleEntry => (
+          <div key={titleEntry} className={classes.sectionHeaderCell}>
+            {titleEntry}
+          </div>
+        ))}
       </div>
-      {contents.map((contentEntry) => {
+      {contents.map(contentEntry => {
         return (
           <div key={contentEntry.label} className={classes.sectionRow}>
-            <div className={classes.sectionCell}>
-              {contentEntry.label}
-            </div>
-            <div className={classes.sectionCell}>
-              {contentEntry.value}
-            </div>
-          </div>)
+            <div className={classes.sectionCell}>{contentEntry.label}</div>
+            <div className={classes.sectionCell}>{contentEntry.value}</div>
+          </div>
+        );
       })}
     </div>
   );
-}
+};
 
 const DataProgress: FC<DataProgressProps> = ({ percent = 0, desc = '' }) => {
   const classes = getStyles();
@@ -126,90 +130,102 @@ const DataProgress: FC<DataProgressProps> = ({ percent = 0, desc = '' }) => {
         <span>{`${Number(percent * 100).toFixed(2)}%`}</span>
         <span>{desc}</span>
       </div>
-      <Progress percent={percent} color='#06AFF2' />
+      <Progress percent={percent} color="#06AFF2" />
     </div>
-  )
+  );
 };
 
-const DataCard: FC<DataCardProps & React.HTMLAttributes<HTMLDivElement>> = (props) => {
-  const classes = getStyles();
-  const { t } = useTranslation('systemView');
-  const { t: commonTrans } = useTranslation();
-  const capacityTrans: { [key in string]: string } = commonTrans('capacity');
-  const { node, extend } = props;
-
-  const hardwareTitle = [t('hardwareTitle'), t('valueTitle')];
-  const hardwareContent = [];
-
-  const configTitle = [t('configTitle'), t('valueTitle')];
-  const systemConfig: { label: string; value: any; }[] = [];
-
-  const systemTitle = [t('systemTitle'), t('valueTitle')];
-  const systemContent = [];
-
-  const {
-    created_time: createTime,
-    updated_time: updateTime,
-    system_info = {},
-    hardware_infos: infos = {},
-    system_configurations,
-  } = node?.infos || {};
-
-  const {
-    cpu_core_count: cpu = 0,
-    cpu_core_usage: cpuUsage = 0,
-    memory = 1,
-    memory_usage: memoryUsage = 0,
-    disk = 1,
-    disk_usage: diskUsage = 0,
-  } = infos;
-
-  if (extend) {
-    hardwareContent.push({ label: t('thCPUCount'), value: cpu });
-    hardwareContent.push({
-      label: t('thCPUUsage'), value: <DataProgress percent={cpuUsage / 100} />
-    });
-    hardwareContent.push({
-      label: t('thMemUsage'), value: <DataProgress percent={memoryUsage / memory} desc={getByteString(memoryUsage, memory, capacityTrans)} />
+const DataCard: FC<DataCardProps & React.HTMLAttributes<HTMLDivElement>> =
+  props => {
+    const classes = getStyles();
+    const { t } = useTranslation('systemView');
+    const { t: commonTrans } = useTranslation();
+    const capacityTrans: { [key in string]: string } = commonTrans('capacity');
+    const { node, extend } = props;
+
+    const hardwareTitle = [t('hardwareTitle'), t('valueTitle')];
+    const hardwareContent = [];
+
+    const configTitle = [t('configTitle'), t('valueTitle')];
+    const systemConfig: { label: string; value: any }[] = [];
+
+    const systemTitle = [t('systemTitle'), t('valueTitle')];
+    const systemContent = [];
+
+    const {
+      created_time: createTime,
+      updated_time: updateTime,
+      system_info = {},
+      hardware_infos: infos = {},
+      system_configurations,
+    } = node?.infos || {};
+
+    const {
+      cpu_core_count: cpu = 0,
+      cpu_core_usage: cpuUsage = 0,
+      // memory = 1,
+      memory_usage: memoryUsage = 0,
+      disk = 1,
+      disk_usage: diskUsage = 0,
+    } = infos;
+    const memUsage = formatByteSize(memoryUsage, capacityTrans);
+    if (extend) {
+      hardwareContent.push({ label: t('thCPUCount'), value: cpu });
+      hardwareContent.push({
+        label: t('thCPUUsage'),
+        value: <DataProgress percent={cpuUsage / 100} />,
+      });
+      hardwareContent.push({
+        label: t('thMemUsage'),
+        value: `${memUsage.value} ${memUsage.unit}`,
+      });
+      hardwareContent.push({
+        label: t('thDiskUsage'),
+        value: (
+          <DataProgress
+            percent={diskUsage / disk}
+            desc={getByteString(diskUsage, disk, capacityTrans)}
+          />
+        ),
+      });
+    }
+
+    if (system_configurations) {
+      Object.keys(system_configurations).forEach(key => {
+        systemConfig.push({ label: key, value: system_configurations[key] });
+      });
+    }
+
+    const { system_version: version, deploy_mode: mode = '' } = system_info;
+    systemContent.push({ label: t('thVersion'), value: version });
+    systemContent.push({ label: t('thDeployMode'), value: mode });
+    systemContent.push({
+      label: t('thCreateTime'),
+      value: createTime ? formatSystemTime(createTime) : '',
     });
-    hardwareContent.push({
-      label: t('thDiskUsage'), value: <DataProgress percent={diskUsage / disk} desc={getByteString(diskUsage, disk, capacityTrans)} />
+    systemContent.push({
+      label: t('thUpdateTime'),
+      value: updateTime ? formatSystemTime(updateTime) : '',
     });
-  }
 
-  if (system_configurations) {
-    Object.keys(system_configurations).forEach(key => {
-      systemConfig.push({ label: key, value: system_configurations[key] });
-    });
-  }
-
-  const {
-    system_version: version,
-    deploy_mode: mode = '',
-  } = system_info;
-  systemContent.push({ label: t('thVersion'), value: version });
-  systemContent.push({ label: t('thDeployMode'), value: mode });
-  systemContent.push({ label: t('thCreateTime'), value: createTime ? new Date(createTime.substring(0, 29)).toLocaleString() : '' });
-  systemContent.push({ label: t('thUpdateTime'), value: updateTime ? new Date(updateTime.substring(0, 29)).toLocaleString() : '' });
-
-  return (
-    <div className={classes.root}>
-      <div className={classes.title}>
-        <div>
-          <span className={classes.rootName}>Milvus / </span>
-          <span className={classes.childName}>{node?.infos?.name}</span>
+    return (
+      <div className={classes.root}>
+        <div className={classes.title}>
+          <div>
+            <span className={classes.rootName}>Milvus / </span>
+            <span className={classes.childName}>{node?.infos?.name}</span>
+          </div>
+          <div className={classes.ip}>{`${t('thIP')}:${infos?.ip || ''}`}</div>
         </div>
-        <div className={classes.ip}>{`${t('thIP')}:${infos?.ip || ''}`}</div>
+        {extend && (
+          <DataSection titles={hardwareTitle} contents={hardwareContent} />
+        )}
+        <DataSection titles={systemTitle} contents={systemContent} />
+        {systemConfig.length ? (
+          <DataSection titles={configTitle} contents={systemConfig} />
+        ) : null}
       </div>
-      {extend && <DataSection titles={hardwareTitle} contents={hardwareContent} />}
-      <DataSection titles={systemTitle} contents={systemContent} />
-      {systemConfig.length ?
-        <DataSection titles={configTitle} contents={systemConfig} />
-        :
-        null
-      }
-    </div>
-  );
-};
+    );
+  };
 
-export default DataCard;
+export default DataCard;

+ 40 - 17
client/src/plugins/system/NodeListView.tsx

@@ -6,7 +6,7 @@ import { DataGrid } from '@mui/x-data-grid';
 import { useNavigationHook } from '../../hooks/Navigation';
 import { ALL_ROUTER_TYPES } from '../../router/Types';
 import MiniTopo from './MiniTopology';
-import { getByteString } from '../../utils/Format';
+import { getByteString, formatByteSize } from '../../utils/Format';
 import DataCard from './DataCard';
 import { NodeListViewProps, Node } from './Types';
 
@@ -17,8 +17,7 @@ const getStyles = makeStyles((theme: Theme) => ({
     display: 'grid',
     gridTemplateColumns: 'auto 400px',
     gridTemplateRows: '40px 400px auto',
-    gridTemplateAreas:
-      `"a a"
+    gridTemplateAreas: `"a a"
        "b ."
        "b d"`,
   },
@@ -54,17 +53,19 @@ const getStyles = makeStyles((theme: Theme) => ({
   },
   dataCard: {
     gridArea: 'd',
-  }
+  },
 }));
 
-const NodeListView: FC<NodeListViewProps> = (props) => {
+const NodeListView: FC<NodeListViewProps> = props => {
   useNavigationHook(ALL_ROUTER_TYPES.SYSTEM);
   const { t } = useTranslation('systemView');
   const { t: commonTrans } = useTranslation();
   const capacityTrans: { [key in string]: string } = commonTrans('capacity');
 
   const classes = getStyles();
-  const [selectedChildNode, setSelectedChildNode] = useState<Node | undefined>();
+  const [selectedChildNode, setSelectedChildNode] = useState<
+    Node | undefined
+  >();
   const [rows, setRows] = useState<any[]>([]);
   const { selectedCord, childNodes, setCord } = props;
 
@@ -103,22 +104,39 @@ const NodeListView: FC<NodeListViewProps> = (props) => {
 
   useEffect(() => {
     if (selectedCord) {
-      const connectedIds = selectedCord.connected.map(node => node.connected_identifier);
+      const connectedIds = selectedCord.connected.map(
+        node => node.connected_identifier
+      );
       const newRows: any[] = [];
       childNodes.forEach(node => {
         if (connectedIds.includes(node.identifier)) {
+          const memUsage = formatByteSize(
+            node?.infos?.hardware_infos.memory_usage,
+            capacityTrans
+          );
           const dataRow = {
             id: node?.identifier,
             ip: node?.infos?.hardware_infos.ip,
             cpuCore: node?.infos?.hardware_infos.cpu_core_count,
-            cpuUsage: node?.infos?.hardware_infos.cpu_core_usage,
-            diskUsage: getByteString(node?.infos?.hardware_infos.disk_usage, node?.infos?.hardware_infos.disk, capacityTrans),
-            memUsage: getByteString(node?.infos?.hardware_infos.memory_usage, node?.infos?.hardware_infos.memory, capacityTrans),
+            cpuUsage: Number(
+              node?.infos?.hardware_infos.cpu_core_usage
+            ).toFixed(2),
+            diskUsage: getByteString(
+              node?.infos?.hardware_infos.disk_usage,
+              node?.infos?.hardware_infos.disk,
+              capacityTrans
+            ),
+            // memUsage: getByteString(
+            //   node?.infos?.hardware_infos.memory_usage,
+            //   node?.infos?.hardware_infos.memory,
+            //   capacityTrans
+            // ),
+            memUsage: `${memUsage.value}${memUsage.unit}`,
             name: node?.infos?.name,
-          }
+          };
           newRows.push(dataRow);
         }
-      })
+      });
       setRows(newRows);
     }
   }, [selectedCord, childNodes, capacityTrans]);
@@ -126,7 +144,7 @@ const NodeListView: FC<NodeListViewProps> = (props) => {
   // select first node
   useEffect(() => {
     const timeoutID = window.setTimeout(() => {
-      const el = document.querySelectorAll<HTMLElement>(".MuiDataGrid-row")[0];
+      const el = document.querySelectorAll<HTMLElement>('.MuiDataGrid-row')[0];
       if (el instanceof HTMLElement) {
         el.click();
       }
@@ -145,16 +163,21 @@ const NodeListView: FC<NodeListViewProps> = (props) => {
           columns={columns}
           hideFooterPagination
           hideFooterSelectedRowCount
-          onRowClick={(rowData) => {
-            const selectedNode = childNodes.find(node => rowData.row.id === node.identifier);
+          onRowClick={rowData => {
+            const selectedNode = childNodes.find(
+              node => rowData.row.id === node.identifier
+            );
             setSelectedChildNode(selectedNode);
           }}
         />
       </div>
-      <MiniTopo selectedCord={selectedCord} setCord={setCord} selectedChildNode={selectedChildNode} />
+      <MiniTopo
+        selectedCord={selectedCord}
+        setCord={setCord}
+        selectedChildNode={selectedChildNode}
+      />
       <DataCard className={classes.dataCard} node={selectedChildNode} />
     </div>
-
   );
 };
 

+ 43 - 16
client/src/plugins/system/SystemView.tsx

@@ -59,10 +59,9 @@ const getStyles = makeStyles((theme: Theme) => ({
     border: 0,
     backgroundColor: 'white',
     width: '100%',
-  }
+  },
 }));
 
-
 const parseJson = (jsonData: any) => {
   const nodes: any[] = [];
   const childNodes: any[] = [];
@@ -74,12 +73,12 @@ const parseJson = (jsonData: any) => {
     diskUsage: 0,
     memory: 0,
     memoryUsage: 0,
-  }
+  };
 
   jsonData?.response?.nodes_info.forEach((node: any) => {
     const type = node?.infos?.type;
     // coordinator node
-    if (type?.toLowerCase().includes("coord")) {
+    if (type?.toLowerCase().includes('coord')) {
       nodes.push(node);
       // other nodes
     } else {
@@ -93,8 +92,12 @@ const parseJson = (jsonData: any) => {
     system.diskUsage += info.disk_usage;
   });
   return { nodes, childNodes, system };
-}
+};
 
+/**
+ * Todo: Milvus V2.0.0 Memory data is not ready for now, open it after Milvus ready.
+ * @returns
+ */
 const SystemView: any = () => {
   useNavigationHook(ALL_ROUTER_TYPES.SYSTEM);
   const { t } = useTranslation('systemView');
@@ -102,7 +105,11 @@ const SystemView: any = () => {
   const classes = getStyles();
   const INTERVAL = 10000;
 
-  const [data, setData] = useState<{ nodes: any, childNodes: any, system: any }>({ nodes: [], childNodes: [], system: {} });
+  const [data, setData] = useState<{
+    nodes: any;
+    childNodes: any;
+    system: any;
+  }>({ nodes: [], childNodes: [], system: {} });
   const [selectedNode, setNode] = useState<any>();
   const [selectedCord, setCord] = useState<any>();
   const { nodes, childNodes, system } = data;
@@ -126,13 +133,26 @@ const SystemView: any = () => {
   const latency = system?.latency || 0;
   const childView = useRef<HTMLInputElement>(null);
 
-
-
   return (
     <div className={classes.root}>
-      <div className={clsx(classes.cardContainer, selectedCord && classes.transparent)}>
-        <ProgressCard title={t('diskTitle')} usage={system.diskUsage} total={system.disk} />
-        <ProgressCard title={t('memoryTitle')} usage={system.memoryUsage} total={system.memory} />
+      <div
+        className={clsx(
+          classes.cardContainer,
+          selectedCord && classes.transparent
+        )}
+      >
+        <ProgressCard
+          title={t('diskTitle')}
+          usage={system.diskUsage}
+          total={system.disk}
+        />
+        {/* <ProgressCard
+          title={t('memoryTitle')}
+          usage={system.memoryUsage}
+          total={system.memory}
+        /> */}
+        <LineChartCard title={t('memoryTitle')} value={qps} />
+
         <LineChartCard title={t('qpsTitle')} value={qps} />
         <LineChartCard title={t('latencyTitle')} value={latency} />
       </div>
@@ -143,13 +163,20 @@ const SystemView: any = () => {
 
       <div
         ref={childView}
-        className={clsx(classes.childView,
-          selectedCord ? classes.showChildView : classes.hideChildView)}
+        className={clsx(
+          classes.childView,
+          selectedCord ? classes.showChildView : classes.hideChildView
+        )}
       >
-        {selectedCord && (<NodeListView selectedCord={selectedCord} childNodes={childNodes} setCord={setCord} />)}
+        {selectedCord && (
+          <NodeListView
+            selectedCord={selectedCord}
+            childNodes={childNodes}
+            setCord={setCord}
+          />
+        )}
       </div>
-    </div >
-
+    </div>
   );
 };
 

+ 31 - 10
client/src/utils/Format.ts

@@ -144,14 +144,11 @@ export const getCreateFieldType = (config: Field): CreateFieldType => {
 export const formatAddress = (address: string): string =>
   address.trim().replace(/(http|https):\/\//, '');
 
-// generate a sting like 20.22/98.33MB with proper unit
-export const getByteString = (
-  value1: number,
-  value2: number,
+export const formatByteSize = (
+  size: number,
   capacityTrans: { [key in string]: string }
-) => {
-  if (!value1 || !value2) return `0${capacityTrans.b}`;
-  const power = Math.round(Math.log(value1) / Math.log(1024));
+): { value: string; unit: string; power: number } => {
+  const power = Math.round(Math.log(size) / Math.log(1024));
   let unit = '';
   switch (power) {
     case 1:
@@ -173,10 +170,34 @@ export const getByteString = (
       unit = capacityTrans.b;
       break;
   }
-  const byteValue1 = value1 / 1024 ** power;
-  const byteValue2 = value2 / 1024 ** power;
+  const byteValue = size / 1024 ** power;
+  return {
+    value: byteValue.toFixed(2),
+    unit,
+    power,
+  };
+};
+
+// generate a sting like 20.22/98.33MB with proper unit
+export const getByteString = (
+  value1: number,
+  value2: number,
+  capacityTrans: { [key in string]: string }
+) => {
+  if (!value1 || !value2) return `0${capacityTrans.b}`;
+  const formatValue1 = formatByteSize(value1, capacityTrans);
+  const formatValue2 = value2 / 1024 ** formatValue1.power;
+  return `${formatValue1.value}/${formatValue2.toFixed(2)} ${
+    formatValue1.unit
+  }`;
+};
 
-  return `${byteValue1.toFixed(2)}/${byteValue2.toFixed(2)} ${unit}`;
+/**
+ * time: 2022-02-15 07:03:32.2981238 +0000 UTC m=+2.434915801
+ * @returns 2022-02-15 07:03:32
+ */
+export const formatSystemTime = (time: string): string => {
+  return time.split('.')[0] || '';
 };
 
 /**