From 120cd11d58b51b6f1a60e378300c2ccf29fd4710 Mon Sep 17 00:00:00 2001 From: Lijiao <15910218274@163.com> Date: Fri, 13 Mar 2020 02:35:44 +0000 Subject: [PATCH 1/5] add warning message when final data illegal --- src/webui/scripts/start.js | 2 +- src/webui/src/App.scss | 5 +++ src/webui/src/App.tsx | 49 ++++++++++++++++++++++++----- src/webui/src/static/const.ts | 2 +- src/webui/src/static/model/trial.ts | 2 +- 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/webui/scripts/start.js b/src/webui/scripts/start.js index e6236bd6a2..49a489a484 100644 --- a/src/webui/scripts/start.js +++ b/src/webui/scripts/start.js @@ -41,7 +41,7 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { } // Tools like Cloud9 rely on this. -const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; +const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 9000; const HOST = process.env.HOST || '0.0.0.0'; if (process.env.HOST) { diff --git a/src/webui/src/App.scss b/src/webui/src/App.scss index c6e8fcebfa..fdd51cde0c 100644 --- a/src/webui/src/App.scss +++ b/src/webui/src/App.scss @@ -43,3 +43,8 @@ color: #333; } } + +.warning{ + padding-bottom: 15px; + background-color: #f2f2f2; +} diff --git a/src/webui/src/App.tsx b/src/webui/src/App.tsx index e10e4bd664..a91fcface9 100644 --- a/src/webui/src/App.tsx +++ b/src/webui/src/App.tsx @@ -3,6 +3,7 @@ import { Stack } from 'office-ui-fabric-react'; import { COLUMN } from './static/const'; import { EXPERIMENT, TRIALS } from './static/datamodel'; import NavCon from './components/NavCon'; +import MessageInfo from './components/Modals/MessageInfo'; import './App.scss'; interface AppState { @@ -11,6 +12,8 @@ interface AppState { experimentUpdateBroadcast: number; trialsUpdateBroadcast: number; metricGraphMode: 'max' | 'min'; // tuner's optimize_mode filed + isilLegalFinal: boolean; + expWarningMessage: string; } class App extends React.Component<{}, AppState> { @@ -23,7 +26,9 @@ class App extends React.Component<{}, AppState> { columnList: COLUMN, experimentUpdateBroadcast: 0, trialsUpdateBroadcast: 0, - metricGraphMode: 'max' + metricGraphMode: 'max', + isilLegalFinal: false, + expWarningMessage: '' }; } @@ -33,6 +38,30 @@ class App extends React.Component<{}, AppState> { this.setState(state => ({ trialsUpdateBroadcast: state.trialsUpdateBroadcast + 1 })); this.timerId = window.setTimeout(this.refresh, this.state.interval * 1000); this.setState({ metricGraphMode: (EXPERIMENT.optimizeMode === 'minimize' ? 'min' : 'max') }); + // final result is legal + // 选一条succeed trial,查看final result格式是否支持 + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + window.setInterval(this.test, this.state.interval * 1000); + + } + + test = () => { + console.info('例行检查'); // eslint-disable-line + for(let i = 0; this.state.isilLegalFinal === false; i++){ + if(TRIALS.succeededTrials()[0] !== undefined && TRIALS.succeededTrials()[0].final !== undefined){ + const oneSucceedTrial = JSON.parse(TRIALS.succeededTrials()[0].final!.data); + if (typeof oneSucceedTrial === 'number' || oneSucceedTrial.hasOwnProperty('default')) { + return; + } else { + console.info('数据不合常理'); // eslint-disable-line + // 非法 + this.setState(() => ({ + isilLegalFinal: true, + expWarningMessage: 'WebUI support final result as number and dictornary includes default keys, your experiment final result is illegal, please check your data.' + })); + } + } + } } changeInterval = (interval: number): void => { @@ -54,18 +83,19 @@ class App extends React.Component<{}, AppState> { } render(): React.ReactNode { - const { interval, columnList, experimentUpdateBroadcast, trialsUpdateBroadcast, metricGraphMode } = this.state; + const { interval, columnList, experimentUpdateBroadcast, trialsUpdateBroadcast, + metricGraphMode, isilLegalFinal, expWarningMessage } = this.state; if (experimentUpdateBroadcast === 0 || trialsUpdateBroadcast === 0) { return null; // TODO: render a loading page } const reactPropsChildren = React.Children.map(this.props.children, child => React.cloneElement( child as React.ReactElement<any>, { - interval, - columnList, changeColumn: this.changeColumn, - experimentUpdateBroadcast, - trialsUpdateBroadcast, - metricGraphMode, changeMetricGraphMode: this.changeMetricGraphMode + interval, + columnList, changeColumn: this.changeColumn, + experimentUpdateBroadcast, + trialsUpdateBroadcast, + metricGraphMode, changeMetricGraphMode: this.changeMetricGraphMode }) ); @@ -73,11 +103,14 @@ class App extends React.Component<{}, AppState> { <Stack className="nni" style={{ minHeight: window.innerHeight }}> <div className="header"> <div className="headerCon"> - <NavCon changeInterval={this.changeInterval} refreshFunction={this.lastRefresh}/> + <NavCon changeInterval={this.changeInterval} refreshFunction={this.lastRefresh} /> </div> </div> <Stack className="contentBox"> <Stack className="content"> + {isilLegalFinal && <div className="warning"> + <MessageInfo info={expWarningMessage} typeInfo="warning" /> + </div>} {reactPropsChildren} </Stack> </Stack> diff --git a/src/webui/src/static/const.ts b/src/webui/src/static/const.ts index a950fe1d80..c58eb8fe80 100644 --- a/src/webui/src/static/const.ts +++ b/src/webui/src/static/const.ts @@ -2,7 +2,7 @@ const METRIC_GROUP_UPDATE_THRESHOLD = 100; const METRIC_GROUP_UPDATE_SIZE = 20; -const MANAGER_IP = `/api/v1/nni`; +const MANAGER_IP = `http://13.77.78.63:8080/api/v1/nni`; const DOWNLOAD_IP = `/logs`; const WEBUIDOC = 'https://nni.readthedocs.io/en/latest/Tutorial/WebUI.html'; const trialJobStatus = [ diff --git a/src/webui/src/static/model/trial.ts b/src/webui/src/static/model/trial.ts index 60d45ed50b..49f6a95142 100644 --- a/src/webui/src/static/model/trial.ts +++ b/src/webui/src/static/model/trial.ts @@ -5,7 +5,7 @@ class Trial implements TableObj { private metricsInitialized: boolean = false; private infoField: TrialJobInfo | undefined; private intermediates: (MetricDataRecord | undefined)[] = [ ]; - private final: MetricDataRecord | undefined; + public final: MetricDataRecord | undefined; private finalAcc: number | undefined; constructor(info?: TrialJobInfo, metrics?: MetricDataRecord[]) { From 57d663eed51ffb7cd4b8376cfe6aa7f49b0ec83a Mon Sep 17 00:00:00 2001 From: Lijiao <15910218274@163.com> Date: Fri, 13 Mar 2020 02:37:02 +0000 Subject: [PATCH 2/5] update --- src/webui/src/App.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/webui/src/App.tsx b/src/webui/src/App.tsx index a91fcface9..aa41569ff6 100644 --- a/src/webui/src/App.tsx +++ b/src/webui/src/App.tsx @@ -18,6 +18,7 @@ interface AppState { class App extends React.Component<{}, AppState> { private timerId!: number | null; + private dataFormatimer!: number | null; constructor(props: {}) { super(props); @@ -41,7 +42,7 @@ class App extends React.Component<{}, AppState> { // final result is legal // 选一条succeed trial,查看final result格式是否支持 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - window.setInterval(this.test, this.state.interval * 1000); + this.dataFormatimer = window.setInterval(this.test, this.state.interval * 1000); } @@ -59,6 +60,7 @@ class App extends React.Component<{}, AppState> { isilLegalFinal: true, expWarningMessage: 'WebUI support final result as number and dictornary includes default keys, your experiment final result is illegal, please check your data.' })); + window.clearInterval(this.dataFormatimer); } } } From 36354beb0dfd3ce86c431e1a74922a2d33a821b9 Mon Sep 17 00:00:00 2001 From: Lijiao <15910218274@163.com> Date: Fri, 13 Mar 2020 08:26:53 +0000 Subject: [PATCH 3/5] update --- src/webui/src/App.tsx | 5 +++-- src/webui/src/static/const.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/webui/src/App.tsx b/src/webui/src/App.tsx index aa41569ff6..027091b736 100644 --- a/src/webui/src/App.tsx +++ b/src/webui/src/App.tsx @@ -18,7 +18,7 @@ interface AppState { class App extends React.Component<{}, AppState> { private timerId!: number | null; - private dataFormatimer!: number | null; + private dataFormatimer!: number; constructor(props: {}) { super(props); @@ -43,7 +43,6 @@ class App extends React.Component<{}, AppState> { // 选一条succeed trial,查看final result格式是否支持 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.dataFormatimer = window.setInterval(this.test, this.state.interval * 1000); - } test = () => { @@ -51,6 +50,8 @@ class App extends React.Component<{}, AppState> { for(let i = 0; this.state.isilLegalFinal === false; i++){ if(TRIALS.succeededTrials()[0] !== undefined && TRIALS.succeededTrials()[0].final !== undefined){ const oneSucceedTrial = JSON.parse(TRIALS.succeededTrials()[0].final!.data); + console.info(oneSucceedTrial); // eslint-disable-line + console.info(typeof oneSucceedTrial); // eslint-disable-line if (typeof oneSucceedTrial === 'number' || oneSucceedTrial.hasOwnProperty('default')) { return; } else { diff --git a/src/webui/src/static/const.ts b/src/webui/src/static/const.ts index c58eb8fe80..a675dde452 100644 --- a/src/webui/src/static/const.ts +++ b/src/webui/src/static/const.ts @@ -2,7 +2,7 @@ const METRIC_GROUP_UPDATE_THRESHOLD = 100; const METRIC_GROUP_UPDATE_SIZE = 20; -const MANAGER_IP = `http://13.77.78.63:8080/api/v1/nni`; +const MANAGER_IP = `http://13.77.78.63:8282/api/v1/nni`; const DOWNLOAD_IP = `/logs`; const WEBUIDOC = 'https://nni.readthedocs.io/en/latest/Tutorial/WebUI.html'; const trialJobStatus = [ From 9331b1e5dfcde365c19021a67a2599bbc69ec25e Mon Sep 17 00:00:00 2001 From: Lijiao <15910218274@163.com> Date: Wed, 18 Mar 2020 02:32:38 +0000 Subject: [PATCH 4/5] update --- src/webui/scripts/start.js | 2 +- src/webui/src/App.tsx | 22 +++++++++++----------- src/webui/src/static/const.ts | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/webui/scripts/start.js b/src/webui/scripts/start.js index 49a489a484..e6236bd6a2 100644 --- a/src/webui/scripts/start.js +++ b/src/webui/scripts/start.js @@ -41,7 +41,7 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { } // Tools like Cloud9 rely on this. -const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 9000; +const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; const HOST = process.env.HOST || '0.0.0.0'; if (process.env.HOST) { diff --git a/src/webui/src/App.tsx b/src/webui/src/App.tsx index 027091b736..7adb8239f1 100644 --- a/src/webui/src/App.tsx +++ b/src/webui/src/App.tsx @@ -40,33 +40,33 @@ class App extends React.Component<{}, AppState> { this.timerId = window.setTimeout(this.refresh, this.state.interval * 1000); this.setState({ metricGraphMode: (EXPERIMENT.optimizeMode === 'minimize' ? 'min' : 'max') }); // final result is legal - // 选一条succeed trial,查看final result格式是否支持 + // get a succeed trial,see final result data's format // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.dataFormatimer = window.setInterval(this.test, this.state.interval * 1000); + this.dataFormatimer = window.setInterval(this.getFinalDataFormat, this.state.interval * 1000); } - test = () => { - console.info('例行检查'); // eslint-disable-line + getFinalDataFormat = (): void => { for(let i = 0; this.state.isilLegalFinal === false; i++){ if(TRIALS.succeededTrials()[0] !== undefined && TRIALS.succeededTrials()[0].final !== undefined){ - const oneSucceedTrial = JSON.parse(TRIALS.succeededTrials()[0].final!.data); - console.info(oneSucceedTrial); // eslint-disable-line - console.info(typeof oneSucceedTrial); // eslint-disable-line + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const oneSucceedTrial = JSON.parse(JSON.parse(TRIALS.succeededTrials()[0].final!.data)); if (typeof oneSucceedTrial === 'number' || oneSucceedTrial.hasOwnProperty('default')) { - return; + window.clearInterval(this.dataFormatimer); + break; } else { - console.info('数据不合常理'); // eslint-disable-line - // 非法 + // illegal final data this.setState(() => ({ isilLegalFinal: true, expWarningMessage: 'WebUI support final result as number and dictornary includes default keys, your experiment final result is illegal, please check your data.' })); window.clearInterval(this.dataFormatimer); } + } else { + break; } } } - + changeInterval = (interval: number): void => { this.setState({ interval }); if (this.timerId === null && interval !== 0) { diff --git a/src/webui/src/static/const.ts b/src/webui/src/static/const.ts index a675dde452..a950fe1d80 100644 --- a/src/webui/src/static/const.ts +++ b/src/webui/src/static/const.ts @@ -2,7 +2,7 @@ const METRIC_GROUP_UPDATE_THRESHOLD = 100; const METRIC_GROUP_UPDATE_SIZE = 20; -const MANAGER_IP = `http://13.77.78.63:8282/api/v1/nni`; +const MANAGER_IP = `/api/v1/nni`; const DOWNLOAD_IP = `/logs`; const WEBUIDOC = 'https://nni.readthedocs.io/en/latest/Tutorial/WebUI.html'; const trialJobStatus = [ From 673c7f5f9a0bb38e75019d64e6f650feb105151c Mon Sep 17 00:00:00 2001 From: Lijiao <15910218274@163.com> Date: Thu, 19 Mar 2020 09:29:22 +0000 Subject: [PATCH 5/5] fix comments --- src/webui/src/App.tsx | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/webui/src/App.tsx b/src/webui/src/App.tsx index 7adb8239f1..3778c675af 100644 --- a/src/webui/src/App.tsx +++ b/src/webui/src/App.tsx @@ -12,7 +12,7 @@ interface AppState { experimentUpdateBroadcast: number; trialsUpdateBroadcast: number; metricGraphMode: 'max' | 'min'; // tuner's optimize_mode filed - isilLegalFinal: boolean; + isillegalFinal: boolean; expWarningMessage: string; } @@ -28,7 +28,7 @@ class App extends React.Component<{}, AppState> { experimentUpdateBroadcast: 0, trialsUpdateBroadcast: 0, metricGraphMode: 'max', - isilLegalFinal: false, + isillegalFinal: false, expWarningMessage: '' }; } @@ -46,7 +46,7 @@ class App extends React.Component<{}, AppState> { } getFinalDataFormat = (): void => { - for(let i = 0; this.state.isilLegalFinal === false; i++){ + for(let i = 0; this.state.isillegalFinal === false; i++){ if(TRIALS.succeededTrials()[0] !== undefined && TRIALS.succeededTrials()[0].final !== undefined){ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const oneSucceedTrial = JSON.parse(JSON.parse(TRIALS.succeededTrials()[0].final!.data)); @@ -56,7 +56,7 @@ class App extends React.Component<{}, AppState> { } else { // illegal final data this.setState(() => ({ - isilLegalFinal: true, + isillegalFinal: true, expWarningMessage: 'WebUI support final result as number and dictornary includes default keys, your experiment final result is illegal, please check your data.' })); window.clearInterval(this.dataFormatimer); @@ -87,18 +87,19 @@ class App extends React.Component<{}, AppState> { render(): React.ReactNode { const { interval, columnList, experimentUpdateBroadcast, trialsUpdateBroadcast, - metricGraphMode, isilLegalFinal, expWarningMessage } = this.state; + metricGraphMode, isillegalFinal, expWarningMessage + } = this.state; if (experimentUpdateBroadcast === 0 || trialsUpdateBroadcast === 0) { return null; // TODO: render a loading page } const reactPropsChildren = React.Children.map(this.props.children, child => React.cloneElement( child as React.ReactElement<any>, { - interval, - columnList, changeColumn: this.changeColumn, - experimentUpdateBroadcast, - trialsUpdateBroadcast, - metricGraphMode, changeMetricGraphMode: this.changeMetricGraphMode + interval, + columnList, changeColumn: this.changeColumn, + experimentUpdateBroadcast, + trialsUpdateBroadcast, + metricGraphMode, changeMetricGraphMode: this.changeMetricGraphMode }) ); @@ -111,7 +112,7 @@ class App extends React.Component<{}, AppState> { </div> <Stack className="contentBox"> <Stack className="content"> - {isilLegalFinal && <div className="warning"> + {isillegalFinal && <div className="warning"> <MessageInfo info={expWarningMessage} typeInfo="warning" /> </div>} {reactPropsChildren}