Browse Source

Merge pull request #79 from nameczz/feature/add-statistics-api

add overview statistics
ryjiang 4 years ago
parent
commit
a4364ff7be

+ 2 - 2
client/src/context/Auth.tsx

@@ -21,8 +21,8 @@ export const AuthProvider = (props: { children: React.ReactNode }) => {
       const milvusAddress = window.localStorage.getItem(MILVUS_ADDRESS) || '';
       try {
         const res = await MilvusHttp.check(milvusAddress);
-        setAddress(res.data.connected ? milvusAddress : '');
-        if (!res.data.connected) {
+        setAddress(res.connected ? milvusAddress : '');
+        if (!res.connected) {
           window.localStorage.removeItem(MILVUS_ADDRESS);
         }
       } catch (error) {

+ 1 - 1
client/src/http/Axios.ts

@@ -12,7 +12,7 @@ export const url =
   process.env.REACT_APP_BASE_URL;
 
 const axiosInstance = axios.create({
-  baseURL: `${url}`,
+  baseURL: `${url}/api/v1`,
   timeout: 10000,
 });
 

+ 1 - 1
client/src/http/BaseModel.ts

@@ -47,7 +47,7 @@ export default class BaseModel {
       url: path,
       params,
     });
-    return res.data;
+    return res.data.data;
   }
 
   /**

+ 5 - 0
client/src/http/Collection.ts

@@ -13,6 +13,7 @@ export class CollectionHttp extends BaseModel implements CollectionView {
 
   static COLLECTIONS_URL = '/collections';
   static COLLECTIONS_INDEX_STATUS_URL = '/collections/indexes/status';
+  static COLLECTIONS_STATISTICS_URL = '/collections/statistics';
 
   static CHECK_URL = '/milvus/check';
 
@@ -52,6 +53,10 @@ export class CollectionHttp extends BaseModel implements CollectionView {
     });
   }
 
+  static getStatistics() {
+    return super.search({ path: this.COLLECTIONS_STATISTICS_URL, params: {} });
+  }
+
   get _autoId() {
     return this.autoID;
   }

+ 41 - 23
client/src/pages/overview/Overview.tsx

@@ -1,15 +1,16 @@
 import { makeStyles, Theme, Typography } from '@material-ui/core';
+import { useEffect, useMemo, useState } from 'react';
 import { useTranslation } from 'react-i18next';
 import EmptyCard from '../../components/cards/EmptyCard';
 import icons from '../../components/icons/Icons';
 import { StatusEnum } from '../../components/status/Types';
 import { useNavigationHook } from '../../hooks/Navigation';
+import { CollectionHttp } from '../../http/Collection';
 import { ALL_ROUTER_TYPES } from '../../router/Types';
 import { formatNumber } from '../../utils/Common';
 import CollectionCard from './collectionCard/CollectionCard';
 import { CollectionData } from './collectionCard/Types';
 import StatisticsCard from './statisticsCard/StatisticsCard';
-import { StatisticsCardProps } from './statisticsCard/Types';
 
 const useStyles = makeStyles((theme: Theme) => ({
   collectionTitle: {
@@ -30,28 +31,45 @@ const Overview = () => {
   const classes = useStyles();
   const { t: overviewTrans } = useTranslation('overview');
   const { t: collectionTrans } = useTranslation('collection');
+  const [statistics, setStatistics] = useState<{
+    collectionCount: number;
+    totalData: number;
+  }>({
+    collectionCount: 0,
+    totalData: 0,
+  });
 
-  const mockStatistics: StatisticsCardProps = {
-    data: [
-      {
-        label: overviewTrans('load'),
-        value: formatNumber(4337),
-        valueColor: '#07d197',
-      },
-      {
-        label: overviewTrans('all'),
-        value: formatNumber(30000),
-        valueColor: '#06aff2',
-      },
-      {
-        label: overviewTrans('data'),
-        value: overviewTrans('rows', {
-          number: formatNumber(209379100),
-        }) as string,
-        valueColor: '#0689d2',
-      },
-    ],
-  };
+  useEffect(() => {
+    const fetchData = async () => {
+      const res = await CollectionHttp.getStatistics();
+      setStatistics(res);
+    };
+    fetchData();
+  }, []);
+
+  const statisticsData = useMemo(() => {
+    return {
+      data: [
+        {
+          label: overviewTrans('load'),
+          value: formatNumber(4337),
+          valueColor: '#07d197',
+        },
+        {
+          label: overviewTrans('all'),
+          value: formatNumber(statistics.collectionCount),
+          valueColor: '#06aff2',
+        },
+        {
+          label: overviewTrans('data'),
+          value: overviewTrans('rows', {
+            number: formatNumber(statistics.totalData),
+          }) as string,
+          valueColor: '#0689d2',
+        },
+      ],
+    };
+  }, [overviewTrans, statistics]);
 
   const mockCollections: CollectionData[] = [
     {
@@ -95,7 +113,7 @@ const Overview = () => {
 
   return (
     <section className="page-wrapper">
-      <StatisticsCard data={mockStatistics.data} />
+      <StatisticsCard data={statisticsData.data} />
       <Typography className={classes.collectionTitle}>
         {overviewTrans('load')}
       </Typography>

+ 5 - 0
server/src/collections/collections.controller.ts

@@ -21,6 +21,11 @@ export class CollectionsController {
     return await this.collectionsService.showCollections();
   }
 
+  @Get('statistics')
+  async getStatistics() {
+    return await this.collectionsService.getStatistics();
+  }
+
   @Post()
   @UsePipes(new ValidationPipe())
   async createCollection(@Body() data: CreateCollection) {

+ 30 - 0
server/src/collections/collections.service.ts

@@ -74,6 +74,10 @@ export class CollectionsService {
     return res;
   }
 
+  /**
+   * Get all collections meta data
+   * @returns {id:string, collection_name:string, schema:Field[], autoID:boolean, rowCount: string}
+   */
   async showCollections() {
     const data = [];
     const res = await this.getCollectionNames();
@@ -98,6 +102,32 @@ export class CollectionsService {
     return data;
   }
 
+  /**
+   * Get collections statistics data
+   * @returns {collectionCount:number, totalData:number}
+   */
+  async getStatistics() {
+    const data = {
+      collectionCount: 0,
+      totalData: 0,
+    };
+    const res = await this.getCollectionNames();
+    if (res.collection_names.length > 0) {
+      for (const name of res.collection_names) {
+        const collectionStatistics = await this.getCollectionStatistics({
+          collection_name: name,
+        });
+        const rowCount = findKeyValue(collectionStatistics.stats, ROW_COUNT);
+        data.totalData += isNaN(Number(rowCount)) ? 0 : Number(rowCount);
+      }
+    }
+    return data;
+  }
+
+  /**
+   * Get all collection index status
+   * @returns {collection_name:string, index_state: IndexState}[]
+   */
   async getCollectionsIndexStatus() {
     const data = [];
     const res = await this.getCollectionNames();

+ 1 - 0
server/src/main.ts

@@ -14,6 +14,7 @@ async function bootstrap() {
   const document = SwaggerModule.createDocument(app, config);
   SwaggerModule.setup('api', app, document);
 
+  app.setGlobalPrefix('/api/v1');
   await app.listen(3000);
 }
 bootstrap();