Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
1e2a2e29
"vscode:/vscode.git/clone" did not exist on "0b3683bf6d2d21313ccc9621ec7911ae6fb9ce0e"
Unverified
Commit
1e2a2e29
authored
May 18, 2020
by
Lijiaoa
Committed by
GitHub
May 18, 2020
Browse files
Show trial error message (#2424)
parent
95b5e5f3
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
227 additions
and
57 deletions
+227
-57
src/webui/src/App.tsx
src/webui/src/App.tsx
+37
-15
src/webui/src/components/Modals/MessageInfo.tsx
src/webui/src/components/Modals/MessageInfo.tsx
+1
-1
src/webui/src/components/overview/ProgressItem.tsx
src/webui/src/components/overview/ProgressItem.tsx
+2
-2
src/webui/src/static/function.ts
src/webui/src/static/function.ts
+14
-1
src/webui/src/static/model/experiment.ts
src/webui/src/static/model/experiment.ts
+71
-13
src/webui/src/static/model/trialmanager.ts
src/webui/src/static/model/trialmanager.ts
+99
-25
src/webui/src/static/style/progress.scss
src/webui/src/static/style/progress.scss
+3
-0
No files found.
src/webui/src/App.tsx
View file @
1e2a2e29
...
@@ -21,7 +21,7 @@ class App extends React.Component<{}, AppState> {
...
@@ -21,7 +21,7 @@ class App extends React.Component<{}, AppState> {
private
timerId
!
:
number
|
undefined
;
private
timerId
!
:
number
|
undefined
;
private
dataFormatimer
!
:
number
;
private
dataFormatimer
!
:
number
;
private
firstLoad
:
boolean
=
false
;
// when click refresh selector options
private
firstLoad
:
boolean
=
false
;
// when click refresh selector options
constructor
(
props
:
{})
{
constructor
(
props
:
{})
{
super
(
props
);
super
(
props
);
this
.
state
=
{
this
.
state
=
{
...
@@ -49,8 +49,8 @@ class App extends React.Component<{}, AppState> {
...
@@ -49,8 +49,8 @@ class App extends React.Component<{}, AppState> {
}
}
getFinalDataFormat
=
():
void
=>
{
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
){
if
(
TRIALS
.
succeededTrials
()[
0
]
!==
undefined
&&
TRIALS
.
succeededTrials
()[
0
].
final
!==
undefined
)
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const
oneSucceedTrial
=
JSON
.
parse
(
JSON
.
parse
(
TRIALS
.
succeededTrials
()[
0
].
final
!
.
data
));
const
oneSucceedTrial
=
JSON
.
parse
(
JSON
.
parse
(
TRIALS
.
succeededTrials
()[
0
].
final
!
.
data
));
if
(
typeof
oneSucceedTrial
===
'
number
'
||
oneSucceedTrial
.
hasOwnProperty
(
'
default
'
))
{
if
(
typeof
oneSucceedTrial
===
'
number
'
||
oneSucceedTrial
.
hasOwnProperty
(
'
default
'
))
{
...
@@ -71,14 +71,14 @@ class App extends React.Component<{}, AppState> {
...
@@ -71,14 +71,14 @@ class App extends React.Component<{}, AppState> {
}
}
changeInterval
=
(
interval
:
number
):
void
=>
{
changeInterval
=
(
interval
:
number
):
void
=>
{
window
.
clearTimeout
(
this
.
timerId
);
window
.
clearTimeout
(
this
.
timerId
);
if
(
interval
===
0
)
{
if
(
interval
===
0
)
{
return
;
return
;
}
}
// setState will trigger page refresh at once.
// setState will trigger page refresh at once.
// setState is asyc, interval not update to (this.state.interval) at once.
// setState is asyc, interval not update to (this.state.interval) at once.
this
.
setState
({
interval
},
()
=>
{
this
.
setState
({
interval
},
()
=>
{
this
.
firstLoad
=
true
;
this
.
firstLoad
=
true
;
this
.
refresh
();
this
.
refresh
();
});
});
...
@@ -96,7 +96,7 @@ class App extends React.Component<{}, AppState> {
...
@@ -96,7 +96,7 @@ class App extends React.Component<{}, AppState> {
// overview best trial module
// overview best trial module
changeEntries
=
(
entries
:
string
):
void
=>
{
changeEntries
=
(
entries
:
string
):
void
=>
{
this
.
setState
({
bestTrialEntries
:
entries
});
this
.
setState
({
bestTrialEntries
:
entries
});
}
}
render
():
React
.
ReactNode
{
render
():
React
.
ReactNode
{
...
@@ -106,15 +106,25 @@ class App extends React.Component<{}, AppState> {
...
@@ -106,15 +106,25 @@ class App extends React.Component<{}, AppState> {
if
(
experimentUpdateBroadcast
===
0
||
trialsUpdateBroadcast
===
0
)
{
if
(
experimentUpdateBroadcast
===
0
||
trialsUpdateBroadcast
===
0
)
{
return
null
;
// TODO: render a loading page
return
null
;
// TODO: render a loading page
}
}
const
errorList
=
[
{
errorWhere
:
TRIALS
.
jobListError
(),
errorMessage
:
TRIALS
.
getJobErrorMessage
()
},
{
errorWhere
:
EXPERIMENT
.
experimentError
(),
errorMessage
:
EXPERIMENT
.
getExperimentMessage
()
},
{
errorWhere
:
EXPERIMENT
.
statusError
(),
errorMessage
:
EXPERIMENT
.
getStatusMessage
()
},
{
errorWhere
:
TRIALS
.
MetricDataError
(),
errorMessage
:
TRIALS
.
getMetricDataErrorMessage
()
},
{
errorWhere
:
TRIALS
.
latestMetricDataError
(),
errorMessage
:
TRIALS
.
getLatestMetricDataErrorMessage
()
},
{
errorWhere
:
TRIALS
.
metricDataRangeError
(),
errorMessage
:
TRIALS
.
metricDataRangeErrorMessage
()
}
];
const
reactPropsChildren
=
React
.
Children
.
map
(
this
.
props
.
children
,
child
=>
const
reactPropsChildren
=
React
.
Children
.
map
(
this
.
props
.
children
,
child
=>
React
.
cloneElement
(
React
.
cloneElement
(
child
as
React
.
ReactElement
<
any
>
,
{
child
as
React
.
ReactElement
<
any
>
,
{
interval
,
interval
,
columnList
,
changeColumn
:
this
.
changeColumn
,
columnList
,
changeColumn
:
this
.
changeColumn
,
experimentUpdateBroadcast
,
experimentUpdateBroadcast
,
trialsUpdateBroadcast
,
trialsUpdateBroadcast
,
metricGraphMode
,
changeMetricGraphMode
:
this
.
changeMetricGraphMode
,
metricGraphMode
,
changeMetricGraphMode
:
this
.
changeMetricGraphMode
,
bestTrialEntries
,
changeEntries
:
this
.
changeEntries
bestTrialEntries
,
changeEntries
:
this
.
changeEntries
})
})
);
);
...
@@ -127,6 +137,16 @@ class App extends React.Component<{}, AppState> {
...
@@ -127,6 +137,16 @@ class App extends React.Component<{}, AppState> {
</
div
>
</
div
>
<
Stack
className
=
"contentBox"
>
<
Stack
className
=
"contentBox"
>
<
Stack
className
=
"content"
>
<
Stack
className
=
"content"
>
{
/* if api has error field, show error message */
}
{
errorList
.
map
((
item
,
key
)
=>
{
return
(
item
.
errorWhere
&&
<
div
key
=
{
key
}
className
=
"warning"
>
<
MessageInfo
info
=
{
item
.
errorMessage
}
typeInfo
=
"error"
/>
</
div
>
);
})
}
{
isillegalFinal
&&
<
div
className
=
"warning"
>
{
isillegalFinal
&&
<
div
className
=
"warning"
>
<
MessageInfo
info
=
{
expWarningMessage
}
typeInfo
=
"warning"
/>
<
MessageInfo
info
=
{
expWarningMessage
}
typeInfo
=
"warning"
/>
</
div
>
}
</
div
>
}
...
@@ -149,18 +169,20 @@ class App extends React.Component<{}, AppState> {
...
@@ -149,18 +169,20 @@ class App extends React.Component<{}, AppState> {
if
(
trialsUpdated
)
{
if
(
trialsUpdated
)
{
this
.
setState
(
state
=>
({
trialsUpdateBroadcast
:
state
.
trialsUpdateBroadcast
+
1
}));
this
.
setState
(
state
=>
({
trialsUpdateBroadcast
:
state
.
trialsUpdateBroadcast
+
1
}));
}
}
}
else
{
}
else
{
this
.
firstLoad
=
false
;
this
.
firstLoad
=
false
;
}
}
if
([
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
))
{
// experiment status and /trial-jobs api's status could decide website update
if
([
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
)
||
TRIALS
.
jobListError
())
{
// experiment finished, refresh once more to ensure consistency
// experiment finished, refresh once more to ensure consistency
this
.
setState
({
interval
:
0
});
this
.
setState
({
interval
:
0
});
this
.
lastRefresh
();
this
.
lastRefresh
();
return
;
return
;
}
}
this
.
timerId
=
window
.
setTimeout
(
this
.
refresh
,
this
.
state
.
interval
*
1000
);
this
.
timerId
=
window
.
setTimeout
(
this
.
refresh
,
this
.
state
.
interval
*
1000
);
}
}
...
...
src/webui/src/components/Modals/MessageInfo.tsx
View file @
1e2a2e29
...
@@ -18,7 +18,7 @@ class MessageInfo extends React.Component<MessageInfoProps, {}> {
...
@@ -18,7 +18,7 @@ class MessageInfo extends React.Component<MessageInfoProps, {}> {
return
(
return
(
<
MessageBar
<
MessageBar
messageBarType
=
{
MessageBarType
[
typeInfo
]
}
messageBarType
=
{
MessageBarType
[
typeInfo
]
}
isMultiline
=
{
fals
e
}
isMultiline
=
{
tru
e
}
className
=
{
className
}
className
=
{
className
}
>
>
{
info
}
{
info
}
...
...
src/webui/src/components/overview/ProgressItem.tsx
View file @
1e2a2e29
...
@@ -22,7 +22,7 @@ class ProgressBar extends React.Component<ProItemProps, {}> {
...
@@ -22,7 +22,7 @@ class ProgressBar extends React.Component<ProItemProps, {}> {
<
div
>
<
div
>
<
Stack
horizontal
className
=
{
`probar
${
bgclass
}
`
}
>
<
Stack
horizontal
className
=
{
`probar
${
bgclass
}
`
}
>
<
div
className
=
"name"
>
{
who
}
</
div
>
<
div
className
=
"name"
>
{
who
}
</
div
>
<
div
className
=
"showProgress"
style
=
{
{
width
:
'
8
0
%
'
}
}
>
<
div
className
=
"showProgress"
style
=
{
{
width
:
'
7
8%
'
}
}
>
<
ProgressIndicator
<
ProgressIndicator
barHeight
=
{
30
}
barHeight
=
{
30
}
percentComplete
=
{
percent
}
percentComplete
=
{
percent
}
...
@@ -32,7 +32,7 @@ class ProgressBar extends React.Component<ProItemProps, {}> {
...
@@ -32,7 +32,7 @@ class ProgressBar extends React.Component<ProItemProps, {}> {
<
StackItem
className
=
"right"
grow
=
{
70
}
>
{
maxString
}
</
StackItem
>
<
StackItem
className
=
"right"
grow
=
{
70
}
>
{
maxString
}
</
StackItem
>
</
Stack
>
</
Stack
>
</
div
>
</
div
>
<
div
className
=
"description"
style
=
{
{
width
:
'
2
0
%
'
}
}
>
{
description
}
</
div
>
<
div
className
=
"description"
style
=
{
{
width
:
'
2
2
%
'
}
}
>
{
description
}
</
div
>
</
Stack
>
</
Stack
>
<
br
/>
<
br
/>
</
div
>
</
div
>
...
...
src/webui/src/static/function.ts
View file @
1e2a2e29
...
@@ -3,6 +3,19 @@ import axios from 'axios';
...
@@ -3,6 +3,19 @@ import axios from 'axios';
import
{
MANAGER_IP
}
from
'
./const
'
;
import
{
MANAGER_IP
}
from
'
./const
'
;
import
{
MetricDataRecord
,
FinalType
,
TableObj
}
from
'
./interface
'
;
import
{
MetricDataRecord
,
FinalType
,
TableObj
}
from
'
./interface
'
;
async
function
requestAxios
(
url
:
string
)
{
const
response
=
await
axios
.
get
(
url
);
if
(
response
.
status
===
200
)
{
if
(
response
.
data
.
error
!==
undefined
)
{
throw
new
Error
(
`API
${
url
}
${
response
.
data
.
error
}
`
);
}
else
{
return
response
.
data
as
any
;
}
}
else
{
throw
new
Error
(
`API
${
url
}
${
response
.
status
}
error`
);
}
}
const
convertTime
=
(
num
:
number
):
string
=>
{
const
convertTime
=
(
num
:
number
):
string
=>
{
if
(
num
<=
0
)
{
if
(
num
<=
0
)
{
return
'
0
'
;
return
'
0
'
;
...
@@ -219,5 +232,5 @@ export {
...
@@ -219,5 +232,5 @@ export {
convertTime
,
convertDuration
,
getFinalResult
,
getFinal
,
downFile
,
convertTime
,
convertDuration
,
getFinalResult
,
getFinal
,
downFile
,
intermediateGraphOption
,
killJob
,
filterByStatus
,
filterDuration
,
intermediateGraphOption
,
killJob
,
filterByStatus
,
filterDuration
,
formatAccuracy
,
formatTimestamp
,
metricAccuracy
,
parseMetrics
,
formatAccuracy
,
formatTimestamp
,
metricAccuracy
,
parseMetrics
,
isArrayType
isArrayType
,
requestAxios
};
};
src/webui/src/static/model/experiment.ts
View file @
1e2a2e29
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
{
MANAGER_IP
}
from
'
../const
'
;
import
{
MANAGER_IP
}
from
'
../const
'
;
import
{
ExperimentProfile
,
NNIManagerStatus
}
from
'
../interface
'
;
import
{
ExperimentProfile
,
NNIManagerStatus
}
from
'
../interface
'
;
import
{
requestAxios
}
from
'
../function
'
;
function
compareProfiles
(
profile1
?:
ExperimentProfile
,
profile2
?:
ExperimentProfile
):
boolean
{
function
compareProfiles
(
profile1
?:
ExperimentProfile
,
profile2
?:
ExperimentProfile
):
boolean
{
if
(
!
profile1
||
!
profile2
)
{
if
(
!
profile1
||
!
profile2
)
{
...
@@ -14,32 +15,87 @@ function compareProfiles(profile1?: ExperimentProfile, profile2?: ExperimentProf
...
@@ -14,32 +15,87 @@ function compareProfiles(profile1?: ExperimentProfile, profile2?: ExperimentProf
class
Experiment
{
class
Experiment
{
private
profileField
?:
ExperimentProfile
=
undefined
;
private
profileField
?:
ExperimentProfile
=
undefined
;
private
statusField
?:
NNIManagerStatus
=
undefined
;
private
statusField
?:
NNIManagerStatus
=
undefined
;
private
isexperimentError
:
boolean
=
false
;
private
experimentErrorMessage
:
string
=
''
;
private
isStatusError
:
boolean
=
false
;
private
statusErrorMessage
:
string
=
''
;
public
async
init
():
Promise
<
void
>
{
public
async
init
():
Promise
<
void
>
{
while
(
!
this
.
profileField
||
!
this
.
statusField
)
{
while
(
!
this
.
profileField
||
!
this
.
statusField
)
{
if
(
this
.
isexperimentError
)
{
return
;
}
if
(
this
.
isStatusError
)
{
return
;
}
await
this
.
update
();
await
this
.
update
();
}
}
}
}
public
experimentError
():
boolean
{
return
this
.
isexperimentError
;
}
public
statusError
():
boolean
{
return
this
.
isStatusError
;
}
public
getExperimentMessage
():
string
{
return
this
.
experimentErrorMessage
;
}
public
getStatusMessage
():
string
{
return
this
.
statusErrorMessage
;
}
public
async
update
():
Promise
<
boolean
>
{
public
async
update
():
Promise
<
boolean
>
{
const
profilePromise
=
axios
.
get
(
`
${
MANAGER_IP
}
/experiment`
);
const
statusPromise
=
axios
.
get
(
`
${
MANAGER_IP
}
/check-status`
);
const
[
profileResponse
,
statusResponse
]
=
await
Promise
.
all
([
profilePromise
,
statusPromise
]);
let
updated
=
false
;
let
updated
=
false
;
if
(
statusResponse
.
status
===
200
)
{
updated
=
JSON
.
stringify
(
this
.
statusField
)
===
JSON
.
stringify
(
statusResponse
.
data
);
await
requestAxios
(
`
${
MANAGER_IP
}
/experiment`
)
this
.
statusField
=
statusResponse
.
data
;
.
then
(
data
=>
{
}
updated
=
updated
||
compareProfiles
(
this
.
profileField
,
data
);
if
(
profileResponse
.
status
===
200
)
{
this
.
profileField
=
data
;
updated
=
updated
||
compareProfiles
(
this
.
profileField
,
profileResponse
.
data
);
})
this
.
profileField
=
profileResponse
.
data
;
.
catch
(
error
=>
{
}
this
.
isexperimentError
=
true
;
this
.
experimentErrorMessage
=
`
${
error
.
message
}
`
;
updated
=
true
;
});
await
requestAxios
(
`
${
MANAGER_IP
}
/check-status`
)
.
then
(
data
=>
{
updated
=
JSON
.
stringify
(
this
.
statusField
)
===
JSON
.
stringify
(
data
);
this
.
statusField
=
data
;
})
.
catch
(
error
=>
{
this
.
isStatusError
=
true
;
this
.
statusErrorMessage
=
`
${
error
.
message
}
`
;
updated
=
true
;
});
return
updated
;
return
updated
;
}
}
get
profile
():
ExperimentProfile
{
get
profile
():
ExperimentProfile
{
if
(
!
this
.
profileField
)
{
if
(
!
this
.
profileField
)
{
throw
Error
(
'
Experiment profile not initialized
'
);
// throw Error('Experiment profile not initialized');
// set initProfile to prevent page broken
const
initProfile
=
{
data
:
{
"
id
"
:
""
,
"
revision
"
:
0
,
"
execDuration
"
:
0
,
"
logDir
"
:
""
,
"
nextSequenceId
"
:
0
,
"
params
"
:
{
"
authorName
"
:
""
,
"
experimentName
"
:
""
,
"
trialConcurrency
"
:
0
,
"
maxExecDuration
"
:
0
,
"
maxTrialNum
"
:
0
,
"
searchSpace
"
:
"
null
"
,
"
trainingServicePlatform
"
:
""
,
"
tuner
"
:
{
"
builtinTunerName
"
:
"
TPE
"
,
"
classArgs
"
:
{
"
optimize_mode
"
:
""
},
"
checkpointDir
"
:
""
},
"
versionCheck
"
:
true
,
"
clusterMetaData
"
:
[{
"
key
"
:
""
,
"
value
"
:
""
},
{
"
key
"
:
""
,
"
value
"
:
""
}]
},
"
startTime
"
:
0
,
"
endTime
"
:
0
}
};
this
.
profileField
=
initProfile
.
data
as
any
;
}
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return
this
.
profileField
!
;
return
this
.
profileField
!
;
...
@@ -68,7 +124,9 @@ class Experiment {
...
@@ -68,7 +124,9 @@ class Experiment {
get
status
():
string
{
get
status
():
string
{
if
(
!
this
.
statusField
)
{
if
(
!
this
.
statusField
)
{
throw
Error
(
'
Experiment status not initialized
'
);
// throw Error('Experiment status not initialized');
// this.statusField.status = '';
return
''
;
}
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return
this
.
statusField
!
.
status
;
return
this
.
statusField
!
.
status
;
...
...
src/webui/src/static/model/trialmanager.ts
View file @
1e2a2e29
...
@@ -2,6 +2,7 @@ import axios from 'axios';
...
@@ -2,6 +2,7 @@ import axios from 'axios';
import
{
MANAGER_IP
,
METRIC_GROUP_UPDATE_THRESHOLD
,
METRIC_GROUP_UPDATE_SIZE
}
from
'
../const
'
;
import
{
MANAGER_IP
,
METRIC_GROUP_UPDATE_THRESHOLD
,
METRIC_GROUP_UPDATE_SIZE
}
from
'
../const
'
;
import
{
MetricDataRecord
,
TableRecord
,
TrialJobInfo
}
from
'
../interface
'
;
import
{
MetricDataRecord
,
TableRecord
,
TrialJobInfo
}
from
'
../interface
'
;
import
{
Trial
}
from
'
./trial
'
;
import
{
Trial
}
from
'
./trial
'
;
import
{
requestAxios
}
from
'
../function
'
;
function
groupMetricsByTrial
(
metrics
:
MetricDataRecord
[]):
Map
<
string
,
MetricDataRecord
[]
>
{
function
groupMetricsByTrial
(
metrics
:
MetricDataRecord
[]):
Map
<
string
,
MetricDataRecord
[]
>
{
const
ret
=
new
Map
<
string
,
MetricDataRecord
[]
>
();
const
ret
=
new
Map
<
string
,
MetricDataRecord
[]
>
();
...
@@ -39,9 +40,20 @@ class TrialManager {
...
@@ -39,9 +40,20 @@ class TrialManager {
private
maxSequenceId
:
number
=
0
;
private
maxSequenceId
:
number
=
0
;
private
doingBatchUpdate
:
boolean
=
false
;
private
doingBatchUpdate
:
boolean
=
false
;
private
batchUpdatedAfterReading
:
boolean
=
false
;
private
batchUpdatedAfterReading
:
boolean
=
false
;
private
isJobListError
:
boolean
=
false
;
// trial-jobs api error filed
private
jobErrorMessage
:
string
=
''
;
// trial-jobs error message
private
isMetricdataError
:
boolean
=
false
;
// metric-data api error filed
private
MetricdataErrorMessage
:
string
=
''
;
// metric-data error message
private
isLatestMetricdataError
:
boolean
=
false
;
// metric-data-latest api error filed
private
latestMetricdataErrorMessage
:
string
=
''
;
// metric-data-latest error message
private
isMetricdataRangeError
:
boolean
=
false
;
// metric-data-range api error filed
private
metricdataRangeErrorMessage
:
string
=
''
;
// metric-data-latest error message
public
async
init
():
Promise
<
void
>
{
public
async
init
():
Promise
<
void
>
{
while
(
!
this
.
infoInitialized
||
!
this
.
metricInitialized
)
{
while
(
!
this
.
infoInitialized
||
!
this
.
metricInitialized
)
{
if
(
this
.
isMetricdataError
)
{
return
;
}
await
this
.
update
();
await
this
.
update
();
}
}
}
}
...
@@ -156,24 +168,70 @@ class TrialManager {
...
@@ -156,24 +168,70 @@ class TrialManager {
return
trials
;
return
trials
;
}
}
// if this.jobListError = true, show trial error message [/trial-jobs]
public
jobListError
():
boolean
{
return
this
.
isJobListError
;
}
// trial error message's content [/trial-jobs]
public
getJobErrorMessage
():
string
{
return
this
.
jobErrorMessage
;
}
// [/metric-data]
public
MetricDataError
():
boolean
{
return
this
.
isMetricdataError
;
}
// [/metric-data]
public
getMetricDataErrorMessage
():
string
{
return
this
.
MetricdataErrorMessage
;
}
// [/metric-data-latest]
public
latestMetricDataError
():
boolean
{
return
this
.
isLatestMetricdataError
;
}
// [/metric-data-latest]
public
getLatestMetricDataErrorMessage
():
string
{
return
this
.
latestMetricdataErrorMessage
;
}
public
metricDataRangeError
():
boolean
{
return
this
.
isMetricdataRangeError
;
}
public
metricDataRangeErrorMessage
():
string
{
return
this
.
metricdataRangeErrorMessage
;
}
private
async
updateInfo
():
Promise
<
boolean
>
{
private
async
updateInfo
():
Promise
<
boolean
>
{
const
response
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/trial-jobs`
);
let
updated
=
false
;
let
updated
=
false
;
if
(
response
.
status
===
200
)
{
requestAxios
(
`
${
MANAGER_IP
}
/trial-jobs`
)
const
newTrials
=
TrialManager
.
expandJobsToTrials
(
response
.
data
);
.
then
(
data
=>
{
for
(
const
trialInfo
of
newTrials
as
TrialJobInfo
[])
{
const
newTrials
=
TrialManager
.
expandJobsToTrials
(
data
as
any
);
if
(
this
.
trials
.
has
(
trialInfo
.
id
))
{
for
(
const
trialInfo
of
newTrials
as
TrialJobInfo
[])
{
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if
(
this
.
trials
.
has
(
trialInfo
.
id
))
{
updated
=
this
.
trials
.
get
(
trialInfo
.
id
)
!
.
updateTrialJobInfo
(
trialInfo
)
||
updated
;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
}
else
{
updated
=
this
.
trials
.
get
(
trialInfo
.
id
)
!
.
updateTrialJobInfo
(
trialInfo
)
||
updated
;
this
.
trials
.
set
(
trialInfo
.
id
,
new
Trial
(
trialInfo
,
undefined
));
}
else
{
updated
=
true
;
this
.
trials
.
set
(
trialInfo
.
id
,
new
Trial
(
trialInfo
,
undefined
));
updated
=
true
;
}
this
.
maxSequenceId
=
Math
.
max
(
this
.
maxSequenceId
,
trialInfo
.
sequenceId
);
}
}
this
.
maxSequenceId
=
Math
.
max
(
this
.
maxSequenceId
,
trialInfo
.
sequenceId
);
this
.
infoInitialized
=
true
;
}
})
this
.
infoInitialized
=
true
;
.
catch
(
error
=>
{
}
this
.
isJobListError
=
true
;
return
updated
;
this
.
jobErrorMessage
=
error
.
message
;
this
.
infoInitialized
=
true
;
updated
=
true
;
});
return
updated
;
}
}
private
async
updateMetrics
(
lastTime
?:
boolean
):
Promise
<
boolean
>
{
private
async
updateMetrics
(
lastTime
?:
boolean
):
Promise
<
boolean
>
{
...
@@ -188,13 +246,25 @@ class TrialManager {
...
@@ -188,13 +246,25 @@ class TrialManager {
}
}
private
async
updateAllMetrics
():
Promise
<
boolean
>
{
private
async
updateAllMetrics
():
Promise
<
boolean
>
{
const
response
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/metric-data`
);
return
requestAxios
(
`
${
MANAGER_IP
}
/metric-data`
)
return
(
response
.
status
===
200
)
&&
this
.
doUpdateMetrics
(
response
.
data
as
MetricDataRecord
[],
false
);
.
then
(
data
=>
this
.
doUpdateMetrics
(
data
as
any
,
false
))
.
catch
(
error
=>
{
this
.
isMetricdataError
=
true
;
this
.
MetricdataErrorMessage
=
`
${
error
.
message
}
`
;
this
.
doUpdateMetrics
([],
false
);
return
true
;
});
}
}
private
async
updateLatestMetrics
():
Promise
<
boolean
>
{
private
async
updateLatestMetrics
():
Promise
<
boolean
>
{
const
response
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/metric-data-latest`
);
return
requestAxios
(
`
${
MANAGER_IP
}
/metric-data-latest`
)
return
(
response
.
status
===
200
)
&&
this
.
doUpdateMetrics
(
response
.
data
as
MetricDataRecord
[],
true
);
.
then
(
data
=>
this
.
doUpdateMetrics
(
data
as
any
,
true
))
.
catch
(
error
=>
{
this
.
isLatestMetricdataError
=
true
;
this
.
latestMetricdataErrorMessage
=
`
${
error
.
message
}
`
;
this
.
doUpdateMetrics
([],
true
);
return
true
;
});
}
}
private
async
updateManyMetrics
():
Promise
<
void
>
{
private
async
updateManyMetrics
():
Promise
<
void
>
{
...
@@ -202,12 +272,16 @@ class TrialManager {
...
@@ -202,12 +272,16 @@ class TrialManager {
return
;
return
;
}
}
this
.
doingBatchUpdate
=
true
;
this
.
doingBatchUpdate
=
true
;
for
(
let
i
=
0
;
i
<
this
.
maxSequenceId
;
i
+=
METRIC_GROUP_UPDATE_SIZE
)
{
for
(
let
i
=
0
;
i
<
this
.
maxSequenceId
&&
this
.
isMetricdataRangeError
===
false
;
i
+=
METRIC_GROUP_UPDATE_SIZE
)
{
const
response
=
await
axios
.
get
(
`
${
MANAGER_IP
}
/metric-data-range/
${
i
}
/
${
i
+
METRIC_GROUP_UPDATE_SIZE
}
`
);
requestAxios
(
`
${
MANAGER_IP
}
/metric-data-range/
${
i
}
/
${
i
+
METRIC_GROUP_UPDATE_SIZE
}
`
)
if
(
response
.
status
===
200
)
{
.
then
(
data
=>
{
const
updated
=
this
.
doUpdateMetrics
(
response
.
data
as
MetricDataRecord
[],
false
);
const
updated
=
this
.
doUpdateMetrics
(
data
as
any
,
false
);
this
.
batchUpdatedAfterReading
=
this
.
batchUpdatedAfterReading
||
updated
;
this
.
batchUpdatedAfterReading
=
this
.
batchUpdatedAfterReading
||
updated
;
}
})
.
catch
(
error
=>
{
this
.
isMetricdataRangeError
=
true
;
this
.
metricdataRangeErrorMessage
=
`
${
error
.
message
}
`
;
});
}
}
this
.
doingBatchUpdate
=
false
;
this
.
doingBatchUpdate
=
false
;
}
}
...
...
src/webui/src/static/style/progress.scss
View file @
1e2a2e29
...
@@ -46,6 +46,9 @@
...
@@ -46,6 +46,9 @@
.description
{
.description
{
line-height
:
34px
;
line-height
:
34px
;
margin-left
:
6px
;
margin-left
:
6px
;
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment