Commit 0330333c authored by Lijiao's avatar Lijiao Committed by fishyds
Browse files

[WebUI] Default metric is latest or final result, !local, show trial log...

[WebUI] Default metric is latest or final result, !local, show trial log hyperlink or address (#913)

* Add intermediate column

* update

* show trial log link or address

* fix some comments

* update
parent 4baa4c9e
......@@ -33,6 +33,8 @@ interface OverviewState {
isTop10: boolean;
titleMaxbgcolor: string;
titleMinbgcolor?: string;
// trial stdout is content(false) or link(true)
isLogCollection: boolean;
}
class Overview extends React.Component<{}, OverviewState> {
......@@ -76,7 +78,8 @@ class Overview extends React.Component<{}, OverviewState> {
totalCurrentTrial: 0
},
isTop10: true,
titleMaxbgcolor: '#999'
titleMaxbgcolor: '#999',
isLogCollection: false
};
}
......@@ -95,6 +98,12 @@ class Overview extends React.Component<{}, OverviewState> {
const endTimenum = sessionData.endTime;
const assessor = sessionData.params.assessor;
const advisor = sessionData.params.advisor;
// default logCollection is true
const logCollection = res.data.params.logCollection;
let expLogCollection: boolean = false;
if (logCollection !== undefined && logCollection !== 'none') {
expLogCollection = true;
}
trialPro.push({
id: sessionData.id,
author: sessionData.params.authorName,
......@@ -111,7 +120,8 @@ class Overview extends React.Component<{}, OverviewState> {
tuner: sessionData.params.tuner,
assessor: assessor ? assessor : undefined,
advisor: advisor ? advisor : undefined,
clusterMetaData: clusterMetaData ? clusterMetaData : undefined
clusterMetaData: clusterMetaData ? clusterMetaData : undefined,
logCollection: logCollection
});
// search space format loguniform max and min
const temp = sessionData.params.searchSpace;
......@@ -134,7 +144,8 @@ class Overview extends React.Component<{}, OverviewState> {
if (this._isMounted) {
this.setState({
trialProfile: trialPro[0],
searchSpace: searchSpace
searchSpace: searchSpace,
isLogCollection: expLogCollection
});
}
}
......@@ -379,7 +390,7 @@ class Overview extends React.Component<{}, OverviewState> {
const {
trialProfile, searchSpace, tableData, accuracyData,
accNodata, status, errorStr, trialNumber, bestAccuracy,
titleMaxbgcolor, titleMinbgcolor
titleMaxbgcolor, titleMinbgcolor, isLogCollection
} = this.state;
return (
......@@ -410,7 +421,7 @@ class Overview extends React.Component<{}, OverviewState> {
</Row>
</Col>
<Col span={8} className="overviewBoder">
<Title1 text="Trial Profile" icon="4.png" />
<Title1 text="Profile" icon="4.png" />
<Row className="experiment">
{/* the scroll bar all the trial profile in the searchSpace div*/}
<div className="experiment searchSpace">
......@@ -453,6 +464,7 @@ class Overview extends React.Component<{}, OverviewState> {
<Col span={16} id="succeTable">
<SuccessTable
tableSource={tableData}
logCollection={isLogCollection}
trainingPlatform={trialProfile.trainingServicePlatform}
/>
</Col>
......
......@@ -21,8 +21,9 @@ interface TrialDetailState {
searchResultSource: Array<TableObj>;
isHasSearch: boolean;
experimentStatus: string;
entriesTable: number;
experimentPlatform: string;
experimentLogCollection: boolean;
entriesTable: number;
searchSpace: string;
defaultMetric?: Array<number>;
}
......@@ -49,7 +50,6 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
);
private titleOfIntermediate = (
// <Title1 text="Intermediate Result" icon="intermediate.png" />
<div className="panelTitle">
<Icon type="line-chart" />
<span>Intermediate Result</span>
......@@ -65,9 +65,10 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
tableListSource: [],
searchResultSource: [],
experimentStatus: '',
experimentPlatform: '',
experimentLogCollection: false,
entriesTable: 20,
isHasSearch: false,
experimentPlatform: '',
searchSpace: '',
defaultMetric: [0, 1]
};
......@@ -279,6 +280,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
alert('TableList component was not properly initialized.');
}
// get and set logCollection val
checkExperimentPlatform = () => {
axios(`${MANAGER_IP}/experiment`, {
method: 'GET'
......@@ -290,10 +292,17 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
res.data.params.trainingServicePlatform
:
'';
// default logCollection is true
const logCollection = res.data.params.logCollection;
let expLogCollection: boolean = false;
if (logCollection !== undefined && logCollection !== 'none') {
expLogCollection = true;
}
if (this._isMounted) {
this.setState({
experimentPlatform: trainingPlatform,
searchSpace: res.data.params.searchSpace
searchSpace: res.data.params.searchSpace,
experimentLogCollection: expLogCollection
});
}
}
......@@ -318,7 +327,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
const {
tableListSource, searchResultSource, isHasSearch,
entriesTable, experimentPlatform, searchSpace,
defaultMetric
defaultMetric, experimentLogCollection
} = this.state;
const source = isHasSearch ? searchResultSource : tableListSource;
return (
......@@ -392,8 +401,9 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
<TableList
entries={entriesTable}
tableSource={source}
updateList={this.getDetailSource}
platform={experimentPlatform}
updateList={this.getDetailSource}
logCollection={experimentLogCollection}
ref={(tabList) => this.tableList = tabList}
/>
</div>
......
import * as React from 'react';
import axios from 'axios';
import { Modal, Input, Table } from 'antd';
const { TextArea } = Input;
import { Table } from 'antd';
import OpenRow from '../public-child/OpenRow';
import DefaultMetric from '../public-child/DefaultMetrc';
import { DOWNLOAD_IP } from '../../static/const';
import { TableObj } from '../../static/interface';
import { convertDuration } from '../../static/function';
import '../../static/style/tableStatus.css';
......@@ -13,72 +10,25 @@ import '../../static/style/tableList.scss';
interface SuccessTableProps {
tableSource: Array<TableObj>;
trainingPlatform: string;
logCollection: boolean;
}
interface SuccessTableState {
isShowLogModal: boolean;
logContent: string;
}
class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState> {
class SuccessTable extends React.Component<SuccessTableProps, {}> {
public _isMounted = false;
constructor(props: SuccessTableProps) {
super(props);
this.state = {
isShowLogModal: false,
logContent: ''
};
}
showLogModalOverview = (id: string) => {
axios(`${DOWNLOAD_IP}/trial_${id}.log`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
if (this._isMounted) {
this.setState(() => ({
logContent: res.data
}));
}
}
})
.catch(error => {
if (error.response.status === 500) {
if (this._isMounted) {
this.setState(() => ({
logContent: 'failed to get log message'
}));
}
}
});
if (this._isMounted) {
this.setState({
isShowLogModal: true
});
}
}
hideLogModalOverview = () => {
if (this._isMounted) {
this.setState({
isShowLogModal: false,
logContent: '' // close modal, delete data
});
}
}
openRow = (record: TableObj) => {
const { trainingPlatform } = this.props;
const { trainingPlatform, logCollection } = this.props;
return (
<OpenRow
showLogModalOverview={this.showLogModalOverview}
trainingPlatform={trainingPlatform}
record={record}
logCollection={logCollection}
/>
);
}
......@@ -93,7 +43,6 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
render() {
const { tableSource } = this.props;
const { isShowLogModal, logContent } = this.state;
let bgColor = '';
const columns = [{
......@@ -168,25 +117,9 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
className="commonTableStyle"
pagination={false}
/>
{/* trial log modal */}
<Modal
title="trial log"
visible={isShowLogModal}
onCancel={this.hideLogModalOverview}
footer={null}
destroyOnClose={true}
width="80%"
>
<div id="trialLogContent" style={{ height: window.innerHeight * 0.6 }}>
<TextArea
value={logContent}
disabled={true}
className="logcontent"
/>
</div>
</Modal>
</div >
);
}
}
export default SuccessTable;
......@@ -22,6 +22,7 @@ class TrialInfo extends React.Component<TrialInfoProps, {}> {
trialConcurrency: tiralProInfo.runConcurren,
tuner: tiralProInfo.tuner,
assessor: tiralProInfo.assessor ? tiralProInfo.assessor : undefined,
logCollection: tiralProInfo.logCollection ? tiralProInfo.logCollection : undefined,
advisor: tiralProInfo.advisor ? tiralProInfo.advisor : undefined,
clusterMetaData: tiralProInfo.clusterMetaData ? tiralProInfo.clusterMetaData : undefined
});
......
......@@ -19,7 +19,7 @@ class DefaultMetric extends React.Component<DefaultMetricProps, {}> {
accuracy = record.acc.default;
}
let wei = 0;
if (accuracy) {
if (accuracy !== undefined) {
if (accuracy.toString().indexOf('.') !== -1) {
wei = accuracy.toString().length - accuracy.toString().indexOf('.') - 1;
}
......@@ -27,7 +27,7 @@ class DefaultMetric extends React.Component<DefaultMetricProps, {}> {
return (
<div>
{
record.acc && record.acc.default
record.acc !== undefined && record.acc.default !== undefined
?
wei > 6
?
......
import * as React from 'react';
import { TableObj } from '../../static/interface';
interface IntermediateValProps {
record: TableObj;
}
class IntermediateVal extends React.Component<IntermediateValProps, {}> {
constructor(props: IntermediateValProps) {
super(props);
}
render() {
const { record } = this.props;
const interArr = record.description.intermediate;
const status = record.status;
let lastVal;
let wei = 0;
if (interArr !== undefined) {
lastVal = interArr[interArr.length - 1];
}
let result: string = JSON.stringify(lastVal);
if (lastVal !== undefined) {
if (lastVal.toString().indexOf('.') !== -1) {
wei = lastVal.toString().length - lastVal.toString().indexOf('.') - 1;
if (wei > 6) {
result = `${lastVal.toFixed(6)}`;
}
if (status === 'SUCCEEDED') {
result = `${lastVal.toFixed(6)} (FINAL)`;
} else {
result = `${lastVal.toFixed(6)} (LATEST)`;
}
}
} else {
result = '--';
}
return (
<div>{result}</div>
);
}
}
export default IntermediateVal;
......@@ -17,19 +17,15 @@ class LogPathChild extends React.Component<LogpathChildProps, {}> {
const isLink = /^http/gi.test(eachLogpath);
return (
<div>
<div className="logpath">
<span className="logName">{logName}</span>
{
isLink
?
<div className="logpath">
<span className="logName">{logName}</span>
<a className="logContent logHref" href={eachLogpath} target="_blank">{eachLogpath}</a>
</div>
:
<div className="logpath">
<span className="logName">{logName}</span>
<span className="logContent">{eachLogpath}</span>
</div>
}
</div>
);
......
......@@ -8,8 +8,8 @@ const TabPane = Tabs.TabPane;
interface OpenRowProps {
trainingPlatform: string;
showLogModalOverview: Function;
record: TableObj;
logCollection: boolean;
}
class OpenRow extends React.Component<OpenRowProps, {}> {
......@@ -20,7 +20,7 @@ class OpenRow extends React.Component<OpenRowProps, {}> {
}
render() {
const { trainingPlatform, record, showLogModalOverview } = this.props;
const { trainingPlatform, record, logCollection } = this.props;
let isHasParameters = true;
if (record.description.parameters.error) {
......@@ -62,7 +62,7 @@ class OpenRow extends React.Component<OpenRowProps, {}> {
<PaiTrialLog
logStr={logPathRow}
id={record.id}
showLogModal={showLogModalOverview}
logCollection={logCollection}
/>
:
<TrialLog logStr={logPathRow} id={record.id} />
......
......@@ -5,8 +5,7 @@ import { DOWNLOAD_IP } from '../../static/const';
interface PaiTrialChildProps {
logString: string;
id: string;
showLogModal: Function;
isdisLogbtn?: boolean;
logCollect: boolean;
}
class PaiTrialChild extends React.Component<PaiTrialChildProps, {}> {
......@@ -17,7 +16,7 @@ class PaiTrialChild extends React.Component<PaiTrialChildProps, {}> {
}
render() {
const { logString, id } = this.props;
const { logString, id, logCollect } = this.props;
return (
<div>
{
......@@ -26,7 +25,9 @@ class PaiTrialChild extends React.Component<PaiTrialChildProps, {}> {
<div />
:
<Row>
<Row>
{
logCollect
?
<a
target="_blank"
href={`${DOWNLOAD_IP}/trial_${id}.log`}
......@@ -34,7 +35,9 @@ class PaiTrialChild extends React.Component<PaiTrialChildProps, {}> {
>
trial stdout
</a>
</Row>
:
<span>trial stdout: {logString}</span>
}
</Row>
}
</div>
......
......@@ -2,13 +2,12 @@ import * as React from 'react';
import { Row } from 'antd';
import { DOWNLOAD_IP } from '../../static/const';
import PaiTrialChild from './PaiTrialChild';
import LogPathChild from './LogPathChild';
interface PaitrialLogProps {
logStr: string;
id: string;
showLogModal: Function;
trialStatus?: string;
isdisLogbutton?: boolean;
logCollection: boolean;
}
class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
......@@ -19,9 +18,7 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
}
render() {
const { logStr, id, showLogModal,
isdisLogbutton
} = this.props;
const { logStr, id, logCollection } = this.props;
const isTwopath = logStr.indexOf(',') !== -1
?
true
......@@ -34,6 +31,9 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
isTwopath
?
<Row>
{
logCollection
?
<Row>
<a
target="_blank"
......@@ -44,13 +44,24 @@ class PaitrialLog extends React.Component<PaitrialLogProps, {}> {
</a>
<a target="_blank" href={logStr.split(',')[1]}>hdfsLog</a>
</Row>
:
<Row>
<LogPathChild
eachLogpath={logStr.split(',')[0]}
logName="trial stdout:"
/>
<LogPathChild
eachLogpath={logStr.split(',')[1]}
logName="hdfsLog:"
/>
</Row>
}
</Row>
:
<PaiTrialChild
logString={logStr}
id={id}
showLogModal={showLogModal}
isdisLogbtn={isdisLogbutton}
logCollect={logCollection}
/>
}
</div>
......
......@@ -5,11 +5,12 @@ import {
Row, Table, Button, Popconfirm, Modal, Checkbox
} from 'antd';
const CheckboxGroup = Checkbox.Group;
import { MANAGER_IP, DOWNLOAD_IP, trialJobStatus, COLUMN, COLUMN_INDEX } from '../../static/const';
import { MANAGER_IP, trialJobStatus, COLUMN, COLUMN_INDEX } from '../../static/const';
import { convertDuration, intermediateGraphOption, killJob } from '../../static/function';
import { TableObj, TrialJob } from '../../static/interface';
import OpenRow from '../public-child/OpenRow';
import DefaultMetric from '../public-child/DefaultMetrc';
// import DefaultMetric from '../public-child/DefaultMetrc';
import IntermediateVal from '../public-child/IntermediateVal';
import '../../static/style/search.scss';
require('../../static/style/tableStatus.css');
require('../../static/style/logPath.scss');
......@@ -30,6 +31,7 @@ interface TableListProps {
tableSource: Array<TableObj>;
updateList: Function;
platform: string;
logCollection: boolean;
}
interface TableListState {
......@@ -38,8 +40,6 @@ interface TableListState {
isObjFinal: boolean;
isShowColumn: boolean;
columnSelected: Array<string>; // user select columnKeys
logModal: boolean;
logMessage: string;
}
interface ColumnIndex {
......@@ -61,9 +61,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
modalVisible: false,
isObjFinal: false,
isShowColumn: false,
logModal: false,
columnSelected: COLUMN,
logMessage: ''
columnSelected: COLUMN
};
}
......@@ -107,51 +105,6 @@ class TableList extends React.Component<TableListProps, TableListState> {
}
}
updateTrialLogMessage = (id: string) => {
this._trialId = id;
axios(`${DOWNLOAD_IP}/trial_${this._trialId}.log`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
if (this._isMounted) {
this.setState(() => ({
logMessage: res.data
}));
}
}
})
.catch(error => {
if (error.response.status === 500) {
if (this._isMounted) {
this.setState(() => ({
logMessage: 'failed to get log message'
}));
}
}
});
}
showLogModal = (id: string) => {
this.updateTrialLogMessage(id);
this.intervalTrialLog = window.setInterval(this.updateTrialLogMessage.bind(this, this._trialId), 10000);
if (this._isMounted) {
this.setState({
logModal: true
});
}
}
hideLogModal = () => {
window.clearInterval(this.intervalTrialLog);
if (this._isMounted) {
this.setState({
logModal: false,
logMessage: ''
});
}
}
hideShowColumnModal = () => {
if (this._isMounted) {
this.setState({
......@@ -222,12 +175,12 @@ class TableList extends React.Component<TableListProps, TableListState> {
}
openRow = (record: TableObj) => {
const { platform } = this.props;
const { platform, logCollection } = this.props;
return (
<OpenRow
showLogModalOverview={this.showLogModal}
trainingPlatform={platform}
record={record}
logCollection={logCollection}
/>
);
}
......@@ -243,7 +196,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
render() {
const { entries, tableSource, updateList } = this.props;
const { intermediateOption, modalVisible, isShowColumn, columnSelected} = this.state;
const { intermediateOption, modalVisible, isShowColumn, columnSelected } = this.state;
let showTitle = COLUMN;
let bgColor = '';
const trialJob: Array<TrialJob> = [];
......@@ -348,17 +301,19 @@ class TableList extends React.Component<TableListProps, TableListState> {
title: 'Default Metric',
dataIndex: 'acc',
key: 'acc',
width: 200,
width: 160,
sorter: (a: TableObj, b: TableObj) => {
if (a.acc !== undefined && b.acc !== undefined) {
return JSON.parse(a.acc.default) - JSON.parse(b.acc.default);
const aa = a.description.intermediate;
const bb = b.description.intermediate;
if (aa !== undefined && bb !== undefined) {
return aa[aa.length - 1] - bb[bb.length - 1];
} else {
return NaN;
}
},
render: (text: string, record: TableObj) => {
return (
<DefaultMetric record={record}/>
<IntermediateVal record={record} />
);
}
});
......
......@@ -46,6 +46,7 @@ interface Experiment {
assessor?: object;
advisor?: object;
clusterMetaData?: object;
logCollection?: string;
}
// trial accuracy
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment