Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
e1ae623f
Unverified
Commit
e1ae623f
authored
Mar 22, 2019
by
SparkSnail
Committed by
GitHub
Mar 22, 2019
Browse files
Merge pull request #147 from Microsoft/master
merge master
parents
f796c60b
63697ec5
Changes
41
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
879 additions
and
535 deletions
+879
-535
src/sdk/pynni/nni/multi_phase/multi_phase_dispatcher.py
src/sdk/pynni/nni/multi_phase/multi_phase_dispatcher.py
+1
-1
src/sdk/pynni/nni/protocol.py
src/sdk/pynni/nni/protocol.py
+3
-6
src/sdk/pynni/tests/test_assessor.py
src/sdk/pynni/tests/test_assessor.py
+7
-6
src/sdk/pynni/tests/test_tuner.py
src/sdk/pynni/tests/test_tuner.py
+6
-5
src/webui/src/components/Overview.tsx
src/webui/src/components/Overview.tsx
+4
-5
src/webui/src/components/SlideBar.tsx
src/webui/src/components/SlideBar.tsx
+1
-1
src/webui/src/components/TrialsDetail.tsx
src/webui/src/components/TrialsDetail.tsx
+134
-230
src/webui/src/components/overview/Title1.tsx
src/webui/src/components/overview/Title1.tsx
+1
-1
src/webui/src/components/trial-detail/DefaultMetricPoint.tsx
src/webui/src/components/trial-detail/DefaultMetricPoint.tsx
+139
-0
src/webui/src/components/trial-detail/Duration.tsx
src/webui/src/components/trial-detail/Duration.tsx
+41
-58
src/webui/src/components/trial-detail/Intermeidate.tsx
src/webui/src/components/trial-detail/Intermeidate.tsx
+291
-0
src/webui/src/components/trial-detail/Para.tsx
src/webui/src/components/trial-detail/Para.tsx
+163
-171
src/webui/src/components/trial-detail/TableList.tsx
src/webui/src/components/trial-detail/TableList.tsx
+9
-28
src/webui/src/static/interface.ts
src/webui/src/static/interface.ts
+18
-6
src/webui/src/static/style/overviewTitle.scss
src/webui/src/static/style/overviewTitle.scss
+13
-1
src/webui/src/static/style/para.scss
src/webui/src/static/style/para.scss
+27
-9
test/tuner_test.py
test/tuner_test.py
+2
-2
tools/nni_cmd/config_schema.py
tools/nni_cmd/config_schema.py
+2
-0
tools/nni_cmd/launcher.py
tools/nni_cmd/launcher.py
+2
-0
tools/nni_trial_tool/log_utils.py
tools/nni_trial_tool/log_utils.py
+15
-5
No files found.
src/sdk/pynni/nni/multi_phase/multi_phase_dispatcher.py
View file @
e1ae623f
...
...
@@ -75,7 +75,7 @@ def _pack_parameter(parameter_id, params, customized=False, trial_job_id=None, p
class
MultiPhaseMsgDispatcher
(
MsgDispatcherBase
):
def
__init__
(
self
,
tuner
,
assessor
=
None
):
super
()
super
(
MultiPhaseMsgDispatcher
,
self
).
__init__
(
)
self
.
tuner
=
tuner
self
.
assessor
=
assessor
if
assessor
is
None
:
...
...
src/sdk/pynni/nni/protocol.py
View file @
e1ae623f
...
...
@@ -42,11 +42,10 @@ class CommandType(Enum):
NoMoreTrialJobs
=
b
'NO'
KillTrialJob
=
b
'KI'
_lock
=
threading
.
Lock
()
try
:
_in_file
=
open
(
3
,
'rb'
)
_out_file
=
open
(
4
,
'wb'
)
_lock
=
threading
.
Lock
()
except
OSError
:
_msg
=
'IPC pipeline not exists, maybe you are importing tuner/assessor from trial code?'
import
logging
...
...
@@ -60,7 +59,6 @@ def send(command, data):
"""
global
_lock
try
:
if
multi_thread_enabled
():
_lock
.
acquire
()
data
=
data
.
encode
(
'utf8'
)
assert
len
(
data
)
<
1000000
,
'Command too long'
...
...
@@ -69,7 +67,6 @@ def send(command, data):
_out_file
.
write
(
msg
)
_out_file
.
flush
()
finally
:
if
multi_thread_enabled
():
_lock
.
release
()
...
...
src/sdk/pynni/tests/test_assessor.py
View file @
e1ae623f
...
...
@@ -73,9 +73,10 @@ class AssessorTestCase(TestCase):
assessor
=
NaiveAssessor
()
dispatcher
=
MsgDispatcher
(
None
,
assessor
)
try
:
nni
.
msg_dispatcher_base
.
_worker_fast_exit_on_terminate
=
False
dispatcher
.
run
()
e
xcept
E
xception
as
e
:
e
=
dispatcher
.
worker_e
xception
s
[
0
]
self
.
assertIs
(
type
(
e
),
AssertionError
)
self
.
assertEqual
(
e
.
args
[
0
],
'Unsupported command: CommandType.NewTrialJob'
)
...
...
src/sdk/pynni/tests/test_tuner.py
View file @
e1ae623f
...
...
@@ -88,9 +88,10 @@ class TunerTestCase(TestCase):
tuner
=
NaiveTuner
()
dispatcher
=
MsgDispatcher
(
tuner
)
try
:
nni
.
msg_dispatcher_base
.
_worker_fast_exit_on_terminate
=
False
dispatcher
.
run
()
e
xcept
E
xception
as
e
:
e
=
dispatcher
.
worker_e
xception
s
[
0
]
self
.
assertIs
(
type
(
e
),
AssertionError
)
self
.
assertEqual
(
e
.
args
[
0
],
'Unsupported command: CommandType.KillTrialJob'
)
...
...
src/webui/src/components/Overview.tsx
View file @
e1ae623f
...
...
@@ -2,10 +2,7 @@ import * as React from 'react';
import
axios
from
'
axios
'
;
import
{
Row
,
Col
}
from
'
antd
'
;
import
{
MANAGER_IP
}
from
'
../static/const
'
;
import
{
Experiment
,
TableObj
,
Parameters
,
TrialNumber
}
from
'
../static/interface
'
;
import
{
Experiment
,
TableObj
,
Parameters
,
TrialNumber
}
from
'
../static/interface
'
;
import
{
getFinal
}
from
'
../static/function
'
;
import
SuccessTable
from
'
./overview/SuccessTable
'
;
import
Title1
from
'
./overview/Title1
'
;
...
...
@@ -117,7 +114,9 @@ class Overview extends React.Component<{}, OverviewState> {
clusterMetaData
:
clusterMetaData
?
clusterMetaData
:
undefined
});
// search space format loguniform max and min
const
searchSpace
=
JSON
.
parse
(
sessionData
.
params
.
searchSpace
);
const
temp
=
sessionData
.
params
.
searchSpace
;
const
searchSpace
=
temp
!==
undefined
?
JSON
.
parse
(
temp
)
:
{};
Object
.
keys
(
searchSpace
).
map
(
item
=>
{
const
key
=
searchSpace
[
item
].
_type
;
let
value
=
searchSpace
[
item
].
_value
;
...
...
src/webui/src/components/SlideBar.tsx
View file @
e1ae623f
...
...
@@ -141,6 +141,7 @@ class SlideBar extends React.Component<{}, SliderState> {
}
});
}
getNNIversion
=
()
=>
{
axios
(
`
${
MANAGER_IP
}
/version`
,
{
method
:
'
GET
'
...
...
@@ -233,7 +234,6 @@ class SlideBar extends React.Component<{}, SliderState> {
</
a
>
<
span
className
=
"version"
>
Version:
{
version
}
</
span
>
</
Col
>
</
Row
>
);
}
...
...
src/webui/src/components/TrialsDetail.tsx
View file @
e1ae623f
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
{
MANAGER_IP
}
from
'
../static/const
'
;
import
{
Row
,
Col
,
Tabs
,
Input
,
Select
,
Button
}
from
'
antd
'
;
import
{
Row
,
Col
,
Tabs
,
Input
,
Select
,
Button
,
Icon
}
from
'
antd
'
;
const
Option
=
Select
.
Option
;
import
{
TableObj
,
Parameters
,
DetailAccurPoint
,
TooltipForAccuracy
}
from
'
../static/interface
'
;
import
{
getFinalResult
,
getFinal
}
from
'
../static/function
'
;
import
Accuracy
from
'
./overview/Accuracy
'
;
import
{
TableObj
,
Parameters
}
from
'
../static/interface
'
;
import
{
getFinal
}
from
'
../static/function
'
;
import
DefaultPoint
from
'
./trial-detail/DefaultMetricPoint
'
;
import
Duration
from
'
./trial-detail/Duration
'
;
import
Title1
from
'
./overview/Title1
'
;
import
Para
from
'
./trial-detail/Para
'
;
import
Intermediate
from
'
./trial-detail/Intermeidate
'
;
import
TableList
from
'
./trial-detail/TableList
'
;
const
TabPane
=
Tabs
.
TabPane
;
import
'
../static/style/trialsDetail.scss
'
;
...
...
@@ -22,6 +23,8 @@ interface TrialDetailState {
experimentStatus
:
string
;
entriesTable
:
number
;
experimentPlatform
:
string
;
searchSpace
:
string
;
defaultMetric
?:
Array
<
number
>
;
}
class
TrialsDetail
extends
React
.
Component
<
{},
TrialDetailState
>
{
...
...
@@ -33,6 +36,26 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
public
tableList
:
TableList
|
null
;
private
titleOfacc
=
(
<
Title1
text
=
"Default Metric"
icon
=
"3.png"
/>
);
private
titleOfhyper
=
(
<
Title1
text
=
"Hyper Parameter"
icon
=
"1.png"
/>
);
private
titleOfDuration
=
(
<
Title1
text
=
"Trial Duration"
icon
=
"2.png"
/>
);
private
titleOfIntermediate
=
(
// <Title1 text="Intermediate Result" icon="intermediate.png" />
<
div
className
=
"panelTitle"
>
<
Icon
type
=
"line-chart"
/>
<
span
>
Intermediate Result
</
span
>
</
div
>
);
constructor
(
props
:
{})
{
super
(
props
);
...
...
@@ -44,103 +67,29 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
experimentStatus
:
''
,
entriesTable
:
20
,
isHasSearch
:
false
,
experimentPlatform
:
''
experimentPlatform
:
''
,
searchSpace
:
''
,
defaultMetric
:
[
0
,
1
]
};
}
// trial accuracy graph
drawPointGraph
=
()
=>
{
axios
(
`
${
MANAGER_IP
}
/trial-jobs`
,
{
method
:
'
GET
'
})
.
then
(
res
=>
{
if
(
res
.
status
===
200
&&
this
.
_isMounted
)
{
const
accData
=
res
.
data
;
const
accSource
:
Array
<
DetailAccurPoint
>
=
[];
Object
.
keys
(
accData
).
map
(
item
=>
{
if
(
accData
[
item
].
status
===
'
SUCCEEDED
'
&&
accData
[
item
].
finalMetricData
)
{
let
searchSpace
:
object
=
{};
const
acc
=
getFinalResult
(
accData
[
item
].
finalMetricData
);
if
(
accData
[
item
].
hyperParameters
)
{
searchSpace
=
JSON
.
parse
(
accData
[
item
].
hyperParameters
).
parameters
;
}
accSource
.
push
({
acc
:
acc
,
index
:
accData
[
item
].
sequenceId
,
searchSpace
:
JSON
.
stringify
(
searchSpace
)
});
}
});
const
resultList
:
Array
<
number
|
string
>
[]
=
[];
Object
.
keys
(
accSource
).
map
(
item
=>
{
const
items
=
accSource
[
item
];
let
temp
:
Array
<
number
|
string
>
;
temp
=
[
items
.
index
,
items
.
acc
,
JSON
.
parse
(
items
.
searchSpace
)];
resultList
.
push
(
temp
);
});
const
allAcuracy
=
{
tooltip
:
{
trigger
:
'
item
'
,
enterable
:
true
,
position
:
function
(
point
:
Array
<
number
>
,
data
:
TooltipForAccuracy
)
{
if
(
data
.
data
[
0
]
<
resultList
.
length
/
2
)
{
return
[
point
[
0
],
80
];
}
else
{
return
[
point
[
0
]
-
300
,
80
];
}
},
formatter
:
function
(
data
:
TooltipForAccuracy
)
{
const
result
=
'
<div class="tooldetailAccuracy">
'
+
'
<div>Trial No:
'
+
data
.
data
[
0
]
+
'
</div>
'
+
'
<div>Default Metric:
'
+
data
.
data
[
1
]
+
'
</div>
'
+
'
<div>Parameters:
'
+
'
<pre>
'
+
JSON
.
stringify
(
data
.
data
[
2
],
null
,
4
)
+
'
</pre>
'
+
'
</div>
'
+
'
</div>
'
;
return
result
;
}
},
xAxis
:
{
name
:
'
Trial
'
,
type
:
'
category
'
,
},
yAxis
:
{
name
:
'
Default Metric
'
,
type
:
'
value
'
,
},
series
:
[{
symbolSize
:
6
,
type
:
'
scatter
'
,
data
:
resultList
}]
};
this
.
setState
({
accSource
:
allAcuracy
},
()
=>
{
if
(
resultList
.
length
===
0
)
{
this
.
setState
({
accNodata
:
'
No data
'
});
}
else
{
this
.
setState
({
accNodata
:
''
});
}
});
}
});
}
drawTableList
=
()
=>
{
getDetailSource
=
()
=>
{
this
.
isOffIntervals
();
axios
.
get
(
`
${
MANAGER_IP
}
/trial-jobs`
)
.
then
(
res
=>
{
axios
.
all
([
axios
.
get
(
`
${
MANAGER_IP
}
/trial-jobs`
),
axios
.
get
(
`
${
MANAGER_IP
}
/metric-data`
)
])
.
then
(
axios
.
spread
((
res
,
res1
)
=>
{
if
(
res
.
status
===
200
)
{
const
trialJobs
=
res
.
data
;
const
metricSource
=
res1
.
data
;
const
trialTable
:
Array
<
TableObj
>
=
[];
Object
.
keys
(
trialJobs
).
map
(
item
=>
{
// only succeeded trials have finalMetricData
let
desc
:
Parameters
=
{
parameters
:
{}
parameters
:
{},
intermediate
:
[]
};
let
duration
=
0
;
const
id
=
trialJobs
[
item
].
id
!==
undefined
...
...
@@ -171,7 +120,23 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
if
(
trialJobs
[
item
].
logPath
!==
undefined
)
{
desc
.
logPath
=
trialJobs
[
item
].
logPath
;
}
const
acc
=
getFinal
(
trialJobs
[
item
].
finalMetricData
);
// deal with intermediate result list
const
mediate
:
Array
<
number
>
=
[];
Object
.
keys
(
metricSource
).
map
(
key
=>
{
const
items
=
metricSource
[
key
];
if
(
items
.
trialJobId
===
id
)
{
// succeed trial, last intermediate result is final result
// final result format may be object
if
(
typeof
JSON
.
parse
(
items
.
data
)
===
'
object
'
)
{
mediate
.
push
(
JSON
.
parse
(
items
.
data
).
default
);
}
else
{
mediate
.
push
(
JSON
.
parse
(
items
.
data
));
}
}
});
desc
.
intermediate
=
mediate
;
trialTable
.
push
({
key
:
trialTable
.
length
,
sequenceId
:
trialJobs
[
item
].
sequenceId
,
...
...
@@ -182,7 +147,33 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
description
:
desc
});
});
// search part data
// get acc max and min for hyper-parameters graph color bar max and min
const
sortSource
=
JSON
.
parse
(
JSON
.
stringify
(
trialTable
));
sortSource
.
sort
((
a
:
TableObj
,
b
:
TableObj
)
=>
{
if
(
a
.
acc
!==
undefined
&&
b
.
acc
!==
undefined
)
{
return
JSON
.
parse
(
a
.
acc
.
default
)
-
JSON
.
parse
(
b
.
acc
.
default
);
}
else
{
return
NaN
;
}
});
if
(
this
.
_isMounted
&&
sortSource
!==
undefined
)
{
const
hyperMin
=
sortSource
[
0
].
acc
!==
undefined
?
sortSource
[
0
].
acc
.
default
:
'
0
'
;
const
max
=
sortSource
[
sortSource
.
length
-
1
].
acc
;
let
maxResult
=
'
1
'
;
if
(
max
!==
undefined
)
{
maxResult
=
max
.
default
;
}
this
.
setState
(()
=>
({
defaultMetric
:
[
JSON
.
parse
(
hyperMin
),
JSON
.
parse
(
maxResult
)]
}));
}
// update search data result
const
{
searchResultSource
}
=
this
.
state
;
if
(
searchResultSource
.
length
!==
0
)
{
const
temp
:
Array
<
number
>
=
[];
...
...
@@ -211,111 +202,29 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
}));
}
}
});
}
// update all data in table
drawAllTableList
=
()
=>
{
this
.
isOffIntervals
();
axios
.
get
(
`
${
MANAGER_IP
}
/trial-jobs`
)
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
const
trialJobs
=
res
.
data
;
const
trialTable
:
Array
<
TableObj
>
=
[];
Object
.
keys
(
trialJobs
).
map
(
item
=>
{
// only succeeded trials have finalMetricData
let
desc
:
Parameters
=
{
parameters
:
{}
};
let
duration
=
0
;
const
id
=
trialJobs
[
item
].
id
!==
undefined
?
trialJobs
[
item
].
id
:
''
;
const
status
=
trialJobs
[
item
].
status
!==
undefined
?
trialJobs
[
item
].
status
:
''
;
const
begin
=
trialJobs
[
item
].
startTime
;
const
end
=
trialJobs
[
item
].
endTime
;
if
(
begin
)
{
if
(
end
)
{
duration
=
(
end
-
begin
)
/
1000
;
}
else
{
duration
=
(
new
Date
().
getTime
()
-
begin
)
/
1000
;
}
}
if
(
trialJobs
[
item
].
hyperParameters
!==
undefined
)
{
const
getPara
=
JSON
.
parse
(
trialJobs
[
item
].
hyperParameters
[
0
]).
parameters
;
if
(
typeof
getPara
===
'
string
'
)
{
desc
.
parameters
=
JSON
.
parse
(
getPara
);
}
else
{
desc
.
parameters
=
getPara
;
}
}
else
{
desc
.
parameters
=
{
error
:
'
This trial
\'
s parameters are not available.
'
};
}
if
(
trialJobs
[
item
].
logPath
!==
undefined
)
{
desc
.
logPath
=
trialJobs
[
item
].
logPath
;
}
const
acc
=
getFinal
(
trialJobs
[
item
].
finalMetricData
);
trialTable
.
push
({
key
:
trialTable
.
length
,
sequenceId
:
trialJobs
[
item
].
sequenceId
,
id
:
id
,
status
:
status
,
duration
:
duration
,
acc
:
acc
,
description
:
desc
});
});
if
(
this
.
_isMounted
)
{
this
.
setState
(()
=>
({
tableListSource
:
trialTable
,
searchResultSource
:
trialTable
}));
}
}
});
}
callback
=
(
key
:
string
)
=>
{
switch
(
key
)
{
case
'
1
'
:
window
.
clearInterval
(
Para
.
intervalIDPara
);
window
.
clearInterval
(
Duration
.
intervalDuration
);
this
.
drawPointGraph
();
this
.
interAccuracy
=
window
.
setInterval
(
this
.
drawPointGraph
,
10000
);
break
;
case
'
2
'
:
this
.
isOffIntervals
();
window
.
clearInterval
(
this
.
interAccuracy
);
window
.
clearInterval
(
Duration
.
intervalDuration
);
break
;
case
'
3
'
:
this
.
isOffIntervals
();
window
.
clearInterval
(
this
.
interAccuracy
);
window
.
clearInterval
(
Para
.
intervalIDPara
);
break
;
default
:
}
}
// search a trial by trial No. & trial id
searchTrial
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
targetValue
=
event
.
target
.
value
;
if
(
targetValue
===
''
||
targetValue
===
'
'
)
{
this
.
drawAllTableList
();
this
.
interAllTableList
=
window
.
setInterval
(
this
.
drawAllTableList
,
10000
);
const
{
tableListSource
}
=
this
.
state
;
if
(
this
.
_isMounted
)
{
this
.
setState
(()
=>
({
isHasSearch
:
false
,
tableListSource
:
tableListSource
,
}));
}
}
else
{
window
.
clearInterval
(
this
.
interAllTableList
);
const
{
tableListSource
}
=
this
.
state
;
const
searchResultList
:
Array
<
TableObj
>
=
[];
Object
.
keys
(
tableListSource
).
map
(
key
=>
{
const
item
=
tableListSource
[
key
];
if
(
item
.
sequenceId
.
toString
()
===
targetValue
||
item
.
id
.
includes
(
targetValue
))
{
if
(
item
.
sequenceId
.
toString
()
===
targetValue
||
item
.
id
.
includes
(
targetValue
)
||
item
.
status
.
includes
(
targetValue
)
)
{
searchResultList
.
push
(
item
);
}
});
...
...
@@ -328,6 +237,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
}
}
// close timer
isOffIntervals
=
()
=>
{
axios
(
`
${
MANAGER_IP
}
/check-status`
,
{
method
:
'
GET
'
...
...
@@ -338,11 +248,7 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
case
'
DONE
'
:
case
'
ERROR
'
:
case
'
STOPPED
'
:
window
.
clearInterval
(
this
.
interAccuracy
);
window
.
clearInterval
(
this
.
interTableList
);
window
.
clearInterval
(
Duration
.
intervalDuration
);
window
.
clearInterval
(
Para
.
intervalIDPara
);
window
.
clearInterval
(
this
.
interAllTableList
);
break
;
default
:
}
...
...
@@ -362,7 +268,8 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
this
.
setState
(()
=>
({
entriesTable
:
100
}));
break
;
case
'
all
'
:
this
.
setState
(()
=>
({
entriesTable
:
100000
}));
const
{
tableListSource
}
=
this
.
state
;
this
.
setState
(()
=>
({
entriesTable
:
tableListSource
.
length
}));
break
;
default
:
}
...
...
@@ -385,7 +292,8 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
''
;
if
(
this
.
_isMounted
)
{
this
.
setState
({
experimentPlatform
:
trainingPlatform
experimentPlatform
:
trainingPlatform
,
searchSpace
:
res
.
data
.
params
.
searchSpace
});
}
}
...
...
@@ -395,56 +303,55 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
componentDidMount
()
{
this
.
_isMounted
=
true
;
this
.
drawTableList
();
this
.
drawPointGraph
();
this
.
interTableList
=
window
.
setInterval
(
this
.
drawTableList
,
10000
);
this
.
interAccuracy
=
window
.
setInterval
(
this
.
drawPointGraph
,
10000
);
this
.
getDetailSource
();
this
.
interTableList
=
window
.
setInterval
(
this
.
getDetailSource
,
10000
);
this
.
checkExperimentPlatform
();
}
componentWillUnmount
()
{
this
.
_isMounted
=
false
;
window
.
clearInterval
(
this
.
interTableList
);
window
.
clearInterval
(
this
.
interAccuracy
);
}
render
()
{
const
{
accSource
,
accNodata
,
tableListSource
,
entriesTable
,
searchResultSource
,
isHasSearch
,
experimentPlatform
const
{
tableListSource
,
searchResultSource
,
isHasSearch
,
entriesTable
,
experimentPlatform
,
searchSpace
,
defaultMetric
}
=
this
.
state
;
const
titleOfacc
=
(
<
Title1
text
=
"Default Metric"
icon
=
"3.png"
/>
);
const
titleOfhyper
=
(
<
Title1
text
=
"Hyper Parameter"
icon
=
"1.png"
/>
);
const
titleOfDuration
=
(
<
Title1
text
=
"Trial Duration"
icon
=
"2.png"
/>
);
const
source
=
isHasSearch
?
searchResultSource
:
tableListSource
;
return
(
<
div
>
<
div
className
=
"trial"
id
=
"tabsty"
>
<
Tabs
onChange
=
{
this
.
callback
}
type
=
"card"
>
<
TabPane
tab
=
{
titleOfacc
}
key
=
"1"
>
<
Tabs
type
=
"card"
>
<
TabPane
tab
=
{
this
.
titleOfacc
}
key
=
"1"
>
<
Row
className
=
"graph"
>
<
Accuracy
<
DefaultPoint
height
=
{
432
}
accuracyData
=
{
accSource
}
accNodata
=
{
accNodata
}
showSource
=
{
source
}
/>
</
Row
>
</
TabPane
>
<
TabPane
tab
=
{
this
.
titleOfhyper
}
key
=
"2"
>
<
Row
className
=
"graph"
>
<
Para
dataSource
=
{
source
}
expSearchSpace
=
{
searchSpace
}
defaultMetric
=
{
defaultMetric
}
/>
</
Row
>
</
TabPane
>
<
TabPane
tab
=
{
titleOf
hyper
}
key
=
"
2
"
>
<
Row
className
=
"graph"
><
Para
/></
Row
>
<
TabPane
tab
=
{
this
.
titleOf
Duration
}
key
=
"
3
"
>
<
Duration
source
=
{
source
}
/
>
</
TabPane
>
<
TabPane
tab
=
{
titleOf
Duration
}
key
=
"
3
"
>
<
Duration
/>
<
TabPane
tab
=
{
this
.
titleOf
Intermediate
}
key
=
"
4
"
>
<
Intermediate
source
=
{
source
}
/>
</
TabPane
>
</
Tabs
>
</
div
>
{
/* trial table list */
}
<
Title1
text
=
"
All
Trials"
icon
=
"6.png"
/>
<
Title1
text
=
"Trial
Job
s"
icon
=
"6.png"
/>
<
Row
className
=
"allList"
>
<
Col
span
=
{
12
}
>
<
span
>
show
</
span
>
...
...
@@ -472,12 +379,11 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
</
Button
>
</
Col
>
<
Col
span
=
{
12
}
>
{
/* <span>Search:</span> */
}
<
Input
type
=
"text"
placeholder
=
"search by Trial No.
and id
"
placeholder
=
"search by
Id,
Trial No.
or Status
"
onChange
=
{
this
.
searchTrial
}
style
=
{
{
width
:
2
0
0
,
marginLeft
:
6
}
}
style
=
{
{
width
:
2
3
0
,
marginLeft
:
6
}
}
/>
</
Col
>
</
Row
>
...
...
@@ -485,10 +391,8 @@ class TrialsDetail extends React.Component<{}, TrialDetailState> {
</
Row
>
<
TableList
entries
=
{
entriesTable
}
tableSource
=
{
tableListSource
}
updateList
=
{
this
.
drawTableList
}
searchResult
=
{
searchResultSource
}
isHasSearch
=
{
isHasSearch
}
tableSource
=
{
source
}
updateList
=
{
this
.
getDetailSource
}
platform
=
{
experimentPlatform
}
ref
=
{
(
tabList
)
=>
this
.
tableList
=
tabList
}
/>
...
...
src/webui/src/components/overview/Title1.tsx
View file @
e1ae623f
...
...
@@ -2,7 +2,7 @@ import * as React from 'react';
interface
Title1Props
{
text
:
string
;
icon
:
string
;
icon
?
:
string
;
bgcolor
?:
string
;
}
...
...
src/webui/src/components/trial-detail/DefaultMetricPoint.tsx
0 → 100644
View file @
e1ae623f
import
*
as
React
from
'
react
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
{
TableObj
,
DetailAccurPoint
,
TooltipForAccuracy
}
from
'
../../static/interface
'
;
require
(
'
echarts/lib/chart/scatter
'
);
require
(
'
echarts/lib/component/tooltip
'
);
require
(
'
echarts/lib/component/title
'
);
interface
DefaultPointProps
{
showSource
:
Array
<
TableObj
>
;
height
:
number
;
}
interface
DefaultPointState
{
defaultSource
:
object
;
accNodata
:
string
;
}
class
DefaultPoint
extends
React
.
Component
<
DefaultPointProps
,
DefaultPointState
>
{
public
_isMounted
=
false
;
constructor
(
props
:
DefaultPointProps
)
{
super
(
props
);
this
.
state
=
{
defaultSource
:
{},
accNodata
:
'
No data
'
};
}
defaultMetric
=
(
showSource
:
Array
<
TableObj
>
)
=>
{
const
accSource
:
Array
<
DetailAccurPoint
>
=
[];
Object
.
keys
(
showSource
).
map
(
item
=>
{
const
temp
=
showSource
[
item
];
if
(
temp
.
status
===
'
SUCCEEDED
'
&&
temp
.
acc
.
default
!==
undefined
)
{
const
searchSpace
=
temp
.
description
.
parameters
;
accSource
.
push
({
acc
:
temp
.
acc
.
default
,
index
:
temp
.
sequenceId
,
searchSpace
:
JSON
.
stringify
(
searchSpace
)
});
}
});
const
resultList
:
Array
<
number
|
string
>
[]
=
[];
Object
.
keys
(
accSource
).
map
(
item
=>
{
const
items
=
accSource
[
item
];
let
temp
:
Array
<
number
|
string
>
;
temp
=
[
items
.
index
,
items
.
acc
,
JSON
.
parse
(
items
.
searchSpace
)];
resultList
.
push
(
temp
);
});
const
allAcuracy
=
{
grid
:
{
left
:
'
8%
'
},
tooltip
:
{
trigger
:
'
item
'
,
enterable
:
true
,
position
:
function
(
point
:
Array
<
number
>
,
data
:
TooltipForAccuracy
)
{
if
(
data
.
data
[
0
]
<
resultList
.
length
/
2
)
{
return
[
point
[
0
],
80
];
}
else
{
return
[
point
[
0
]
-
300
,
80
];
}
},
formatter
:
function
(
data
:
TooltipForAccuracy
)
{
const
result
=
'
<div class="tooldetailAccuracy">
'
+
'
<div>Trial No:
'
+
data
.
data
[
0
]
+
'
</div>
'
+
'
<div>Default Metric:
'
+
data
.
data
[
1
]
+
'
</div>
'
+
'
<div>Parameters:
'
+
'
<pre>
'
+
JSON
.
stringify
(
data
.
data
[
2
],
null
,
4
)
+
'
</pre>
'
+
'
</div>
'
+
'
</div>
'
;
return
result
;
}
},
xAxis
:
{
name
:
'
Trial
'
,
type
:
'
category
'
,
},
yAxis
:
{
name
:
'
Default Metric
'
,
type
:
'
value
'
,
},
series
:
[{
symbolSize
:
6
,
type
:
'
scatter
'
,
data
:
resultList
}]
};
if
(
this
.
_isMounted
===
true
)
{
this
.
setState
({
defaultSource
:
allAcuracy
},
()
=>
{
if
(
resultList
.
length
===
0
)
{
this
.
setState
({
accNodata
:
'
No data
'
});
}
else
{
this
.
setState
({
accNodata
:
''
});
}
});
}
}
// update parent component state
componentWillReceiveProps
(
nextProps
:
DefaultPointProps
)
{
const
showSource
=
nextProps
.
showSource
;
this
.
defaultMetric
(
showSource
);
}
componentDidMount
()
{
this
.
_isMounted
=
true
;
}
componentWillUnmount
()
{
this
.
_isMounted
=
false
;
}
render
()
{
const
{
height
}
=
this
.
props
;
const
{
defaultSource
,
accNodata
}
=
this
.
state
;
return
(
<
div
>
<
ReactEcharts
option
=
{
defaultSource
}
style
=
{
{
width
:
'
100%
'
,
height
:
height
,
margin
:
'
0 auto
'
,
}
}
theme
=
"my_theme"
notMerge
=
{
true
}
// update now
/>
<
div
className
=
"showMess"
>
{
accNodata
}
</
div
>
</
div
>
);
}
}
export
default
DefaultPoint
;
\ No newline at end of file
src/webui/src/components/trial-detail/Duration.tsx
View file @
e1ae623f
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
{
MANAGER_IP
}
from
'
../../static/const
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
const
echarts
=
require
(
'
echarts/lib/echarts
'
)
;
import
{
TableObj
}
from
'
src/static/interface
'
;
require
(
'
echarts/lib/chart/bar
'
);
require
(
'
echarts/lib/component/tooltip
'
);
require
(
'
echarts/lib/component/title
'
);
echarts
.
registerTheme
(
'
my_theme
'
,
{
color
:
'
#3c8dbc
'
});
interface
Runtrial
{
trialId
:
Array
<
string
>
;
trialTime
:
Array
<
number
>
;
}
interface
DurationProps
{
source
:
Array
<
TableObj
>
;
}
interface
DurationState
{
durationSource
:
{};
}
class
Duration
extends
React
.
Component
<
{}
,
DurationState
>
{
class
Duration
extends
React
.
Component
<
DurationProps
,
DurationState
>
{
static
intervalDuration
=
1
;
public
_isMounted
=
false
;
constructor
(
props
:
{})
{
super
(
props
);
constructor
(
props
:
DurationProps
)
{
super
(
props
);
this
.
state
=
{
durationSource
:
{}
};
}
getOption
=
(
dataObj
:
Runtrial
)
=>
{
let
xAxis
=
dataObj
.
trialTime
;
let
yAxis
=
dataObj
.
trialId
;
let
option
=
{
return
{
tooltip
:
{
trigger
:
'
axis
'
,
axisPointer
:
{
...
...
@@ -50,6 +45,7 @@ class Duration extends React.Component<{}, DurationState> {
left
:
'
1%
'
,
right
:
'
4%
'
},
dataZoom
:
[{
type
:
'
slider
'
,
name
:
'
trial
'
,
...
...
@@ -69,65 +65,52 @@ class Duration extends React.Component<{}, DurationState> {
yAxis
:
{
name
:
'
Trial
'
,
type
:
'
category
'
,
data
:
yAxis
data
:
dataObj
.
trialId
},
series
:
[{
type
:
'
bar
'
,
data
:
xAxis
data
:
dataObj
.
trialTime
}]
};
return
option
;
}
draw
Ru
nGraph
=
()
=>
{
draw
Duratio
nGraph
=
(
trialJobs
:
Array
<
TableObj
>
)
=>
{
axios
(
`
${
MANAGER_IP
}
/trial-jobs`
,
{
method
:
'
GET
'
})
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
const
trialJobs
=
res
.
data
;
const
trialId
:
Array
<
string
>
=
[];
const
trialTime
:
Array
<
number
>
=
[];
const
trialRun
:
Array
<
Runtrial
>
=
[];
Object
.
keys
(
trialJobs
).
map
(
item
=>
{
if
(
trialJobs
[
item
].
status
!==
'
WAITING
'
)
{
let
duration
:
number
=
0
;
const
end
=
trialJobs
[
item
].
endTime
;
const
start
=
trialJobs
[
item
].
startTime
;
if
(
start
&&
end
)
{
duration
=
(
end
-
start
)
/
1000
;
}
else
{
duration
=
(
new
Date
().
getTime
()
-
start
)
/
1000
;
}
trialId
.
push
(
trialJobs
[
item
].
sequenceId
);
trialTime
.
push
(
duration
);
const
temp
=
trialJobs
[
item
];
if
(
temp
.
status
!==
'
WAITING
'
)
{
trialId
.
push
(
temp
.
sequenceId
);
trialTime
.
push
(
temp
.
duration
);
}
});
trialRun
.
push
({
trialId
:
trialId
,
trialTime
:
trialTime
});
if
(
this
.
_isMounted
&&
res
.
status
===
200
)
{
if
(
this
.
_isMounted
)
{
this
.
setState
({
durationSource
:
this
.
getOption
(
trialRun
[
0
])
});
}
}
});
componentWillReceiveProps
(
nextProps
:
DurationProps
)
{
const
trialJobs
=
nextProps
.
source
;
this
.
drawDurationGraph
(
trialJobs
);
}
componentDidMount
()
{
this
.
_isMounted
=
true
;
this
.
drawRunGraph
();
Duration
.
intervalDuration
=
window
.
setInterval
(
this
.
drawRunGraph
,
10000
);
// init: user don't search
const
{
source
}
=
this
.
props
;
this
.
drawDurationGraph
(
source
);
}
componentWillUnmount
()
{
this
.
_isMounted
=
false
;
window
.
clearInterval
(
Duration
.
intervalDuration
);
}
render
()
{
...
...
@@ -136,7 +119,7 @@ class Duration extends React.Component<{}, DurationState> {
<
div
>
<
ReactEcharts
option
=
{
durationSource
}
style
=
{
{
width
:
'
100
%
'
,
height
:
412
,
margin
:
'
0 auto
'
}
}
style
=
{
{
width
:
'
95
%
'
,
height
:
412
,
margin
:
'
0 auto
'
}
}
theme
=
"my_theme"
/>
</
div
>
...
...
src/webui/src/components/trial-detail/Intermeidate.tsx
0 → 100644
View file @
e1ae623f
import
*
as
React
from
'
react
'
;
import
{
Row
,
Col
,
Button
,
Switch
}
from
'
antd
'
;
import
{
TooltipForIntermediate
,
TableObj
}
from
'
../../static/interface
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
require
(
'
echarts/lib/component/tooltip
'
);
require
(
'
echarts/lib/component/title
'
);
interface
Intermedia
{
name
:
string
;
// id
type
:
string
;
data
:
Array
<
number
|
object
>
;
// intermediate data
hyperPara
:
object
;
// each trial hyperpara value
}
interface
IntermediateState
{
interSource
:
object
;
filterSource
:
Array
<
TableObj
>
;
eachIntermediateNum
:
number
;
// trial's intermediate number count
isLoadconfirmBtn
:
boolean
;
isFilter
:
boolean
;
}
interface
IntermediateProps
{
source
:
Array
<
TableObj
>
;
}
class
Intermediate
extends
React
.
Component
<
IntermediateProps
,
IntermediateState
>
{
static
intervalMediate
=
1
;
public
_isMounted
=
false
;
public
pointInput
:
HTMLInputElement
|
null
;
public
minValInput
:
HTMLInputElement
|
null
;
public
maxValInput
:
HTMLInputElement
|
null
;
constructor
(
props
:
IntermediateProps
)
{
super
(
props
);
this
.
state
=
{
interSource
:
{},
filterSource
:
[],
eachIntermediateNum
:
1
,
isLoadconfirmBtn
:
false
,
isFilter
:
false
};
}
initMediate
=
()
=>
{
const
option
=
{
grid
:
{
left
:
'
5%
'
,
top
:
40
,
containLabel
:
true
},
xAxis
:
{
type
:
'
category
'
,
boundaryGap
:
false
,
},
yAxis
:
{
type
:
'
value
'
,
name
:
'
Scape
'
}
};
if
(
this
.
_isMounted
)
{
this
.
setState
(()
=>
({
interSource
:
option
}));
}
}
drawIntermediate
=
(
source
:
Array
<
TableObj
>
)
=>
{
if
(
source
.
length
>
0
)
{
const
trialIntermediate
:
Array
<
Intermedia
>
=
[];
Object
.
keys
(
source
).
map
(
item
=>
{
const
temp
=
source
[
item
];
trialIntermediate
.
push
({
name
:
temp
.
id
,
data
:
temp
.
description
.
intermediate
,
type
:
'
line
'
,
hyperPara
:
temp
.
description
.
parameters
});
});
// find max intermediate number
trialIntermediate
.
sort
((
a
,
b
)
=>
{
return
(
b
.
data
.
length
-
a
.
data
.
length
);
});
const
legend
:
Array
<
string
>
=
[];
// max length
const
length
=
trialIntermediate
[
0
].
data
.
length
;
const
xAxis
:
Array
<
number
>
=
[];
Object
.
keys
(
trialIntermediate
).
map
(
item
=>
{
const
temp
=
trialIntermediate
[
item
];
legend
.
push
(
temp
.
name
);
});
for
(
let
i
=
1
;
i
<=
length
;
i
++
)
{
xAxis
.
push
(
i
);
}
const
option
=
{
tooltip
:
{
trigger
:
'
item
'
,
enterable
:
true
,
position
:
function
(
point
:
Array
<
number
>
,
data
:
TooltipForIntermediate
)
{
if
(
data
.
dataIndex
<
length
/
2
)
{
return
[
point
[
0
],
80
];
}
else
{
return
[
point
[
0
]
-
300
,
80
];
}
},
formatter
:
function
(
data
:
TooltipForIntermediate
)
{
const
trialId
=
data
.
seriesName
;
let
obj
=
{};
const
temp
=
trialIntermediate
.
find
(
key
=>
key
.
name
===
trialId
);
if
(
temp
!==
undefined
)
{
obj
=
temp
.
hyperPara
;
}
return
'
<div class="tooldetailAccuracy">
'
+
'
<div>Trial Id:
'
+
trialId
+
'
</div>
'
+
'
<div>Intermediate:
'
+
data
.
data
+
'
</div>
'
+
'
<div>Parameters:
'
+
'
<pre>
'
+
JSON
.
stringify
(
obj
,
null
,
4
)
+
'
</pre>
'
+
'
</div>
'
+
'
</div>
'
;
}
},
grid
:
{
left
:
'
5%
'
,
top
:
40
,
containLabel
:
true
},
xAxis
:
{
type
:
'
category
'
,
name
:
'
Scape
'
,
boundaryGap
:
false
,
data
:
xAxis
},
yAxis
:
{
type
:
'
value
'
,
name
:
'
Intermediate
'
},
series
:
trialIntermediate
};
if
(
this
.
_isMounted
)
{
this
.
setState
(()
=>
({
interSource
:
option
}));
}
}
else
{
this
.
initMediate
();
}
}
// confirm btn function [filter data]
filterLines
=
()
=>
{
if
(
this
.
_isMounted
)
{
const
filterSource
:
Array
<
TableObj
>
=
[];
this
.
setState
({
isLoadconfirmBtn
:
true
},
()
=>
{
const
{
source
}
=
this
.
props
;
// get input value
const
pointVal
=
this
.
pointInput
!==
null
?
this
.
pointInput
.
value
:
''
;
const
minVal
=
this
.
minValInput
!==
null
?
this
.
minValInput
.
value
:
''
;
const
maxVal
=
this
.
maxValInput
!==
null
?
this
.
maxValInput
.
value
:
''
;
// user not input message
if
(
pointVal
===
''
||
minVal
===
''
)
{
alert
(
'
Please input filter message
'
);
}
else
{
// user not input max value
const
position
=
JSON
.
parse
(
pointVal
);
const
min
=
JSON
.
parse
(
minVal
);
if
(
maxVal
===
''
)
{
Object
.
keys
(
source
).
map
(
item
=>
{
const
temp
=
source
[
item
];
const
val
=
temp
.
description
.
intermediate
[
position
-
1
];
if
(
val
>=
min
)
{
filterSource
.
push
(
temp
);
}
});
}
else
{
const
max
=
JSON
.
parse
(
maxVal
);
Object
.
keys
(
source
).
map
(
item
=>
{
const
temp
=
source
[
item
];
const
val
=
temp
.
description
.
intermediate
[
position
-
1
];
if
(
val
>=
min
&&
val
<=
max
)
{
filterSource
.
push
(
temp
);
}
});
}
if
(
this
.
_isMounted
)
{
this
.
setState
({
filterSource
:
filterSource
});
}
this
.
drawIntermediate
(
filterSource
);
}
this
.
setState
({
isLoadconfirmBtn
:
false
});
});
}
}
switchTurn
=
(
checked
:
boolean
)
=>
{
if
(
this
.
_isMounted
)
{
this
.
setState
({
isFilter
:
checked
});
}
if
(
checked
===
false
)
{
this
.
drawIntermediate
(
this
.
props
.
source
);
}
}
componentDidMount
()
{
this
.
_isMounted
=
true
;
const
{
source
}
=
this
.
props
;
this
.
drawIntermediate
(
source
);
}
componentWillReceiveProps
(
nextProps
:
IntermediateProps
)
{
const
{
isFilter
,
filterSource
}
=
this
.
state
;
if
(
isFilter
===
true
)
{
const
pointVal
=
this
.
pointInput
!==
null
?
this
.
pointInput
.
value
:
''
;
const
minVal
=
this
.
minValInput
!==
null
?
this
.
minValInput
.
value
:
''
;
if
(
pointVal
===
''
&&
minVal
===
''
)
{
this
.
drawIntermediate
(
nextProps
.
source
);
}
else
{
this
.
drawIntermediate
(
filterSource
);
}
}
else
{
this
.
drawIntermediate
(
nextProps
.
source
);
}
}
componentWillUnmount
()
{
this
.
_isMounted
=
false
;
}
render
()
{
const
{
interSource
,
isLoadconfirmBtn
,
isFilter
}
=
this
.
state
;
return
(
<
div
>
{
/* style in para.scss */
}
<
Row
className
=
"meline intermediate"
>
<
Col
span
=
{
8
}
/>
<
Col
span
=
{
3
}
style
=
{
{
height
:
34
}
}
>
{
/* filter message */
}
<
span
>
filter
</
span
>
<
Switch
defaultChecked
=
{
false
}
onChange
=
{
this
.
switchTurn
}
/>
</
Col
>
{
isFilter
?
<
div
>
<
Col
span
=
{
3
}
>
<
span
>
Scape
</
span
>
<
input
placeholder
=
"point"
ref
=
{
input
=>
this
.
pointInput
=
input
}
className
=
"strange"
/>
</
Col
>
<
Col
className
=
"range"
span
=
{
10
}
>
<
span
>
Intermediate Result
</
span
>
<
input
placeholder
=
"number"
ref
=
{
input
=>
this
.
minValInput
=
input
}
/>
<
span
className
=
"heng"
>
-
</
span
>
<
input
placeholder
=
"number"
ref
=
{
input
=>
this
.
maxValInput
=
input
}
/>
<
Button
type
=
"primary"
className
=
"changeBtu tableButton"
onClick
=
{
this
.
filterLines
}
disabled
=
{
isLoadconfirmBtn
}
>
Confirm
</
Button
>
</
Col
>
</
div
>
:
<
Col
/>
}
</
Row
>
<
Row
>
<
ReactEcharts
option
=
{
interSource
}
style
=
{
{
width
:
'
100%
'
,
height
:
418
,
margin
:
'
0 auto
'
}
}
notMerge
=
{
true
}
// update now
/>
</
Row
>
</
div
>
);
}
}
export
default
Intermediate
;
\ No newline at end of file
src/webui/src/components/trial-detail/Para.tsx
View file @
e1ae623f
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
{
MANAGER_IP
}
from
'
../../static/const
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
{
Row
,
Col
,
Select
,
Button
,
message
}
from
'
antd
'
;
import
{
ParaObj
,
VisualMapValue
,
Dimobj
}
from
'
../../static/interface
'
;
import
{
getFinalResult
}
from
'
../../static/function
'
;
import
{
ParaObj
,
Dimobj
,
TableObj
,
SearchSpace
}
from
'
../../static/interface
'
;
const
Option
=
Select
.
Option
;
require
(
'
echarts/lib/chart/parallel
'
);
require
(
'
echarts/lib/component/tooltip
'
);
...
...
@@ -20,12 +17,14 @@ interface ParaState {
swapAxisArr
:
Array
<
string
>
;
percent
:
number
;
paraNodata
:
string
;
visualValue
:
VisualMapValue
;
barColorMax
:
number
;
barColorMin
:
number
;
}
interface
SearchSpace
{
_value
:
Array
<
number
|
string
>
;
_type
:
string
;
interface
ParaProps
{
dataSource
:
Array
<
TableObj
>
;
expSearchSpace
:
string
;
defaultMetric
:
Array
<
number
>
|
undefined
;
}
message
.
config
({
...
...
@@ -33,12 +32,18 @@ message.config({
duration
:
2
,
});
class
Para
extends
React
.
Component
<
{}
,
ParaState
>
{
class
Para
extends
React
.
Component
<
ParaProps
,
ParaState
>
{
static
intervalIDPara
=
4
;
public
_isMounted
=
false
;
constructor
(
props
:
{})
{
private
chartMulineStyle
=
{
width
:
'
100%
'
,
height
:
392
,
margin
:
'
0 auto
'
,
padding
:
'
0 15 10 15
'
};
constructor
(
props
:
ParaProps
)
{
super
(
props
);
this
.
state
=
{
option
:
{},
...
...
@@ -53,28 +58,37 @@ class Para extends React.Component<{}, ParaState> {
swapAxisArr
:
[],
percent
:
0
,
paraNodata
:
''
,
visualValue
:
{
minAccuracy
:
0
,
maxAccuracy
:
1
}
barColorMax
:
this
.
props
.
defaultMetric
!==
undefined
?
this
.
props
.
defaultMetric
[
1
]
:
1
,
barColorMin
:
this
.
props
.
defaultMetric
!==
undefined
?
this
.
props
.
defaultMetric
[
0
]
:
1
};
}
componentDidMount
()
{
this
.
_isMounted
=
true
;
this
.
reInit
();
}
getParallelAxis
=
(
dimName
:
Array
<
string
>
,
searchRange
:
SearchSpace
,
parallelAxis
:
Array
<
Dimobj
>
,
accPara
:
Array
<
number
>
,
accPara
:
Array
<
number
>
,
eachTrialParams
:
Array
<
string
>
,
paraYdata
:
number
[][]
)
=>
{
if
(
this
.
_isMounted
)
{
this
.
setState
(()
=>
({
dimName
:
dimName
,
visualValue
:
{
minAccuracy
:
accPara
.
length
!==
0
?
Math
.
min
(...
accPara
)
:
0
,
maxAccuracy
:
accPara
.
length
!==
0
?
Math
.
max
(...
accPara
)
:
1
}
dimName
:
dimName
}));
}
const
parallelAxis
:
Array
<
Dimobj
>
=
[];
// search space range and specific value [only number]
for
(
let
i
=
0
;
i
<
dimName
.
length
;
i
++
)
{
const
searchKey
=
searchRange
[
dimName
[
i
]];
...
...
@@ -107,7 +121,24 @@ class Para extends React.Component<{}, ParaState> {
dim
:
i
,
name
:
dimName
[
i
],
type
:
'
category
'
,
data
:
data
data
:
data
,
boundaryGap
:
true
,
axisLine
:
{
lineStyle
:
{
type
:
'
dotted
'
,
// axis type,solid,dashed,dotted
width
:
1
}
},
axisTick
:
{
show
:
true
,
interval
:
0
,
alignWithLabel
:
true
,
},
axisLabel
:
{
show
:
true
,
interval
:
0
,
// rotate: 30
},
});
break
;
// support log distribute
...
...
@@ -143,100 +174,70 @@ class Para extends React.Component<{}, ParaState> {
}
paraYdata
.
push
(
temp
);
});
}
hyperParaPic
=
()
=>
{
axios
.
all
([
axios
.
get
(
`
${
MANAGER_IP
}
/trial-jobs`
),
axios
.
get
(
`
${
MANAGER_IP
}
/experiment`
)
])
.
then
(
axios
.
spread
((
res
,
res1
)
=>
{
if
(
res
.
status
===
200
&&
res1
.
status
===
200
)
{
if
(
res
.
data
.
length
!==
0
)
{
const
accParaData
=
res
.
data
;
const
accPara
:
Array
<
number
>
=
[];
// specific value array
const
eachTrialParams
:
Array
<
string
>
=
[];
const
parallelAxis
:
Array
<
Dimobj
>
=
[];
const
paraYdata
:
number
[][]
=
[];
// experiment interface search space obj
const
searchRange
=
JSON
.
parse
(
res1
.
data
.
params
.
searchSpace
);
const
reallySearchKeys
=
Object
.
keys
(
searchRange
);
// trial-jobs interface list
Object
.
keys
(
accParaData
).
map
(
item
=>
{
if
(
accParaData
[
item
].
status
===
'
SUCCEEDED
'
)
{
const
finalData
=
accParaData
[
item
].
finalMetricData
;
if
(
finalData
&&
accParaData
[
item
].
hyperParameters
)
{
const
result
=
getFinalResult
(
finalData
);
accPara
.
push
(
result
);
// get dim and every line specific number
const
temp
=
JSON
.
parse
(
accParaData
[
item
].
hyperParameters
).
parameters
;
eachTrialParams
.
push
(
temp
);
}
}
});
const
dimName
=
reallySearchKeys
;
this
.
getParallelAxis
(
dimName
,
searchRange
,
parallelAxis
,
accPara
,
eachTrialParams
,
paraYdata
);
// add acc
Object
.
keys
(
paraYdata
).
map
(
item
=>
{
paraYdata
[
item
].
push
(
accPara
[
item
]);
});
// according acc to sort ydata
if
(
paraYdata
.
length
!==
0
)
{
const
len
=
paraYdata
[
0
].
length
-
1
;
paraYdata
.
sort
((
a
,
b
)
=>
b
[
len
]
-
a
[
len
]);
}
if
(
this
.
_isMounted
)
{
this
.
setState
(()
=>
({
paraBack
:
{
const
paraData
=
{
parallelAxis
:
parallelAxis
,
data
:
paraYdata
}
}));
}
const
{
percent
,
swapAxisArr
,
paraBack
}
=
this
.
state
;
};
const
{
percent
,
swapAxisArr
}
=
this
.
state
;
// need to cut down the data
if
(
percent
!==
0
)
{
const
linesNum
=
para
Back
.
data
.
length
;
const
linesNum
=
para
Data
.
data
.
length
;
const
len
=
Math
.
floor
(
linesNum
*
percent
);
paraBack
.
data
.
length
=
len
;
paraData
.
data
.
length
=
len
;
}
// need to swap the yAxis
if
(
swapAxisArr
.
length
>=
2
)
{
this
.
swapGraph
(
para
Back
,
swapAxisArr
);
this
.
swapGraph
(
para
Data
,
swapAxisArr
);
}
this
.
getOption
(
para
Back
);
this
.
getOption
(
para
Data
);
}
hyperParaPic
=
(
dataSource
:
Array
<
TableObj
>
,
searchSpace
:
string
)
=>
{
const
accPara
:
Array
<
number
>
=
[];
// specific value array
const
eachTrialParams
:
Array
<
string
>
=
[];
const
paraYdata
:
number
[][]
=
[];
// experiment interface search space obj
const
searchRange
=
JSON
.
parse
(
searchSpace
);
const
dimName
=
Object
.
keys
(
searchRange
);
// trial-jobs interface list
Object
.
keys
(
dataSource
).
map
(
item
=>
{
const
temp
=
dataSource
[
item
];
if
(
temp
.
status
===
'
SUCCEEDED
'
)
{
accPara
.
push
(
temp
.
acc
.
default
);
eachTrialParams
.
push
(
temp
.
description
.
parameters
);
}
}));
});
this
.
getParallelAxis
(
dimName
,
searchRange
,
accPara
,
eachTrialParams
,
paraYdata
);
}
// get percent value number
percentNum
=
(
value
:
string
)
=>
{
window
.
clearInterval
(
Para
.
intervalIDPara
);
let
vals
=
parseFloat
(
value
);
if
(
this
.
_isMounted
)
{
this
.
setState
(()
=>
(
{
percent
:
vals
})
)
;
this
.
setState
(
{
percent
:
vals
},
()
=>
{
this
.
reInit
();
});
}
this
.
hyperParaPic
();
Para
.
intervalIDPara
=
window
.
setInterval
(
this
.
hyperParaPic
,
10000
);
}
// deal with response data into pic data
getOption
=
(
dataObj
:
ParaObj
)
=>
{
const
{
visualValue
}
=
this
.
state
;
const
{
barColorMax
,
barColorMin
}
=
this
.
state
;
let
parallelAxis
=
dataObj
.
parallelAxis
;
let
paralleData
=
dataObj
.
data
;
const
maxAccuracy
=
visualValue
.
maxAccuracy
;
const
minAccuracy
=
visualValue
.
minAccuracy
;
let
visualMapObj
=
{};
if
(
maxAccuracy
===
minAccuracy
)
{
if
(
barColorMax
===
barColorMin
)
{
visualMapObj
=
{
type
:
'
continuous
'
,
precision
:
3
,
...
...
@@ -247,10 +248,9 @@ class Para extends React.Component<{}, ParaState> {
bottom
:
'
20px
'
,
type
:
'
continuous
'
,
precision
:
3
,
min
:
visualValue
.
minAccuracy
,
max
:
visualValue
.
maxAccuracy
,
color
:
[
'
#CA0000
'
,
'
#FFC400
'
,
'
#90EE90
'
],
calculable
:
true
min
:
barColorMin
,
max
:
barColorMax
,
color
:
[
'
#CA0000
'
,
'
#FFC400
'
,
'
#90EE90
'
]
};
}
let
optionown
=
{
...
...
@@ -317,11 +317,9 @@ class Para extends React.Component<{}, ParaState> {
}
}
swapBtn
=
()
=>
{
window
.
clearInterval
(
Para
.
intervalIDPara
);
this
.
hyperParaPic
();
Para
.
intervalIDPara
=
window
.
setInterval
(
this
.
hyperParaPic
,
10000
);
reInit
=
()
=>
{
const
{
dataSource
,
expSearchSpace
}
=
this
.
props
;
this
.
hyperParaPic
(
dataSource
,
expSearchSpace
);
}
sortDimY
=
(
a
:
Dimobj
,
b
:
Dimobj
)
=>
{
...
...
@@ -330,8 +328,6 @@ class Para extends React.Component<{}, ParaState> {
// deal with after swap data into pic
swapGraph
=
(
paraBack
:
ParaObj
,
swapAxisArr
:
string
[])
=>
{
if
(
swapAxisArr
.
length
>=
2
)
{
const
paralDim
=
paraBack
.
parallelAxis
;
const
paraData
=
paraBack
.
data
;
let
temp
:
number
;
...
...
@@ -362,10 +358,10 @@ class Para extends React.Component<{}, ParaState> {
// swap dim's number
Object
.
keys
(
paralDim
).
map
(
item
=>
{
if
(
bool3
)
{
if
(
paralDim
[
item
].
name
===
this
.
state
.
swapAxisArr
[
0
])
{
if
(
paralDim
[
item
].
name
===
swapAxisArr
[
0
])
{
paralDim
[
item
].
dim
=
dim2
;
}
if
(
paralDim
[
item
].
name
===
this
.
state
.
swapAxisArr
[
1
])
{
if
(
paralDim
[
item
].
name
===
swapAxisArr
[
1
])
{
paralDim
[
item
].
dim
=
dim1
;
}
}
...
...
@@ -379,30 +375,26 @@ class Para extends React.Component<{}, ParaState> {
paraData
[
paraItem
][
dim2
]
=
temp
;
});
}
}
componentDidMount
()
{
componentWillReceiveProps
(
nextProps
:
ParaProps
)
{
const
dataSource
=
nextProps
.
dataSource
;
const
expSearchSpace
=
nextProps
.
expSearchSpace
;
const
metricMax
=
nextProps
.
defaultMetric
!==
undefined
?
nextProps
.
defaultMetric
[
1
]
:
1
;
this
.
setState
({
barColorMax
:
metricMax
});
this
.
hyperParaPic
(
dataSource
,
expSearchSpace
);
this
.
_isMounted
=
true
;
// default draw all data pic
this
.
hyperParaPic
();
Para
.
intervalIDPara
=
window
.
setInterval
(
this
.
hyperParaPic
,
10000
);
}
componentWillUnmount
()
{
this
.
_isMounted
=
false
;
window
.
clearInterval
(
Para
.
intervalIDPara
);
}
render
()
{
const
{
option
,
paraNodata
,
dimName
}
=
this
.
state
;
const
chartMulineStyle
=
{
width
:
'
100%
'
,
height
:
392
,
margin
:
'
0 auto
'
,
padding
:
'
0 15 10 15
'
};
return
(
<
Row
className
=
"parameter"
>
<
Row
>
...
...
@@ -439,7 +431,7 @@ class Para extends React.Component<{}, ParaState> {
<
Button
type
=
"primary"
className
=
"changeBtu tableButton"
onClick
=
{
this
.
swapBtn
}
onClick
=
{
this
.
reInit
}
>
Confirm
</
Button
>
...
...
@@ -449,8 +441,8 @@ class Para extends React.Component<{}, ParaState> {
<
Row
className
=
"searcHyper"
>
<
ReactEcharts
option
=
{
option
}
style
=
{
chartMulineStyle
}
//
lazyUpdate={true}
style
=
{
this
.
chartMulineStyle
}
lazyUpdate
=
{
true
}
notMerge
=
{
true
}
// update now
/>
<
div
className
=
"noneData"
>
{
paraNodata
}
</
div
>
...
...
src/webui/src/components/trial-detail/TableList.tsx
View file @
e1ae623f
...
...
@@ -2,9 +2,8 @@ import * as React from 'react';
import
axios
from
'
axios
'
;
import
ReactEcharts
from
'
echarts-for-react
'
;
import
{
Row
,
Input
,
Table
,
Button
,
Popconfirm
,
Modal
,
Checkbox
Row
,
Table
,
Button
,
Popconfirm
,
Modal
,
Checkbox
}
from
'
antd
'
;
const
{
TextArea
}
=
Input
;
const
CheckboxGroup
=
Checkbox
.
Group
;
import
{
MANAGER_IP
,
DOWNLOAD_IP
,
trialJobStatus
,
COLUMN
,
COLUMN_INDEX
}
from
'
../../static/const
'
;
import
{
convertDuration
,
intermediateGraphOption
,
killJob
}
from
'
../../static/function
'
;
...
...
@@ -29,9 +28,7 @@ echarts.registerTheme('my_theme', {
interface
TableListProps
{
entries
:
number
;
tableSource
:
Array
<
TableObj
>
;
searchResult
:
Array
<
TableObj
>
;
updateList
:
Function
;
isHasSearch
:
boolean
;
platform
:
string
;
}
...
...
@@ -78,6 +75,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
const
intermediateArr
:
number
[]
=
[];
// support intermediate result is dict
Object
.
keys
(
res
.
data
).
map
(
item
=>
{
const
temp
=
JSON
.
parse
(
res
.
data
[
item
].
data
);
if
(
typeof
temp
===
'
object
'
)
{
...
...
@@ -244,10 +242,8 @@ class TableList extends React.Component<TableListProps, TableListState> {
render
()
{
const
{
entries
,
tableSource
,
searchResult
,
isHasSearch
,
updateList
}
=
this
.
props
;
const
{
intermediateOption
,
modalVisible
,
isShowColumn
,
columnSelected
,
logMessage
,
logModal
}
=
this
.
state
;
const
{
entries
,
tableSource
,
updateList
}
=
this
.
props
;
const
{
intermediateOption
,
modalVisible
,
isShowColumn
,
columnSelected
}
=
this
.
state
;
let
showTitle
=
COLUMN
;
let
bgColor
=
''
;
const
trialJob
:
Array
<
TrialJob
>
=
[];
...
...
@@ -340,7 +336,10 @@ class TableList extends React.Component<TableListProps, TableListState> {
);
},
filters
:
trialJob
,
onFilter
:
(
value
:
string
,
record
:
TableObj
)
=>
record
.
status
.
indexOf
(
value
)
===
0
,
onFilter
:
(
value
:
string
,
record
:
TableObj
)
=>
{
return
record
.
status
.
indexOf
(
value
)
===
0
;
},
// onFilter: (value: string, record: TableObj) => record.status.indexOf(value) === 0,
sorter
:
(
a
:
TableObj
,
b
:
TableObj
):
number
=>
a
.
status
.
localeCompare
(
b
.
status
)
});
break
;
...
...
@@ -453,7 +452,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
<
Table
columns
=
{
showColumn
}
expandedRowRender
=
{
this
.
openRow
}
dataSource
=
{
isHasSearch
?
searchResult
:
tableSource
}
dataSource
=
{
tableSource
}
className
=
"commonTableStyle"
pagination
=
{
{
pageSize
:
entries
}
}
/>
...
...
@@ -475,24 +474,6 @@ class TableList extends React.Component<TableListProps, TableListState> {
theme
=
"my_theme"
/>
</
Modal
>
{
/* trial log modal */
}
<
Modal
title
=
"trial log"
visible
=
{
logModal
}
onCancel
=
{
this
.
hideLogModal
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
width
=
"80%"
>
<
div
id
=
"trialLogContent"
style
=
{
{
height
:
window
.
innerHeight
*
0.6
}
}
>
<
TextArea
value
=
{
logMessage
}
disabled
=
{
true
}
className
=
"logcontent"
/>
</
div
>
</
Modal
>
</
div
>
{
/* Add Column Modal */
}
<
Modal
...
...
src/webui/src/static/interface.ts
View file @
e1ae623f
...
...
@@ -10,6 +10,11 @@ interface TableObj {
color
?:
string
;
}
interface
SearchSpace
{
_value
:
Array
<
number
|
string
>
;
_type
:
string
;
}
interface
FinalType
{
default
:
string
;
}
...
...
@@ -21,6 +26,7 @@ interface ErrorParameter {
interface
Parameters
{
parameters
:
ErrorParameter
;
logPath
?:
string
;
intermediate
?:
Array
<
number
>
;
}
interface
Experiment
{
...
...
@@ -54,6 +60,12 @@ interface DetailAccurPoint {
searchSpace
:
string
;
}
interface
TooltipForIntermediate
{
data
:
string
;
seriesName
:
string
;
dataIndex
:
number
;
}
interface
TooltipForAccuracy
{
data
:
Array
<
number
|
object
>
;
}
...
...
@@ -80,6 +92,10 @@ interface Dimobj {
min
?:
number
;
type
?:
string
;
data
?:
string
[];
boundaryGap
?:
boolean
;
axisTick
?:
object
;
axisLabel
?:
object
;
axisLine
?:
object
;
}
interface
ParaObj
{
...
...
@@ -87,11 +103,6 @@ interface ParaObj {
parallelAxis
:
Array
<
Dimobj
>
;
}
interface
VisualMapValue
{
maxAccuracy
:
number
;
minAccuracy
:
number
;
}
interface
FinalResult
{
data
:
string
;
}
...
...
@@ -100,5 +111,6 @@ export {
TableObj
,
Parameters
,
Experiment
,
AccurPoint
,
TrialNumber
,
TrialJob
,
DetailAccurPoint
,
TooltipForAccuracy
,
ParaObj
,
VisualMapValue
,
Dimobj
,
FinalResult
,
FinalType
ParaObj
,
Dimobj
,
FinalResult
,
FinalType
,
TooltipForIntermediate
,
SearchSpace
};
src/webui/src/static/style/overviewTitle.scss
View file @
e1ae623f
...
...
@@ -13,7 +13,6 @@ $titleBgcolor: #b3b3b3;
height
:
22px
;
margin-top
:
-8px
;
padding-left
:
14px
;
padding-right
:
14px
;
}
span
{
...
...
@@ -22,9 +21,22 @@ $titleBgcolor: #b3b3b3;
font-family
:
'Segoe'
;
color
:
#333
;
line-height
:
38px
;
margin-left
:
14px
;
}
i
{
font-size
:
24px
;
margin-left
:
14px
;
color
:
#545454
;
position
:
relative
;
top
:
2px
;
}
}
/* antd icon margin intermediate result style*/
#tabsty
.anticon
{
margin-right
:
0
;
}
.top10bg
{
background-color
:
$titleBgcolor
;
...
...
src/webui/src/static/style/para.scss
View file @
e1ae623f
.parameter
{
height
:
100%
;
}
.meline
{
.meline
{
margin-top
:
15px
;
span
{
font-size
:
14px
;
margin-right
:
6px
;
}
}
}
.searcHyper
{
...
...
@@ -25,3 +24,22 @@
color
:
#999
;
}
}
/* Intermediate Result Style */
.intermediate
{
/* border: 1px solid blue; */
input
{
width
:
80px
;
height
:
32px
;
padding-left
:
8px
;
}
.strange
{
margin-top
:
2px
;
}
.range
{
.heng
{
margin-left
:
6px
;
margin-right
:
6px
;
}
}
}
test/tuner_test.py
View file @
e1ae623f
...
...
@@ -76,8 +76,8 @@ def run(dispatch_type):
dipsatcher_list
=
TUNER_LIST
if
dispatch_type
==
'Tuner'
else
ASSESSOR_LIST
for
dispatcher_name
in
dipsatcher_list
:
try
:
#
s
leep
5 seconds
here
,
to make sure previous stopped exp has enough time to exit to avoid port conflict
time
.
sleep
(
5
)
#
S
leep here to make sure previous stopped exp has enough time to exit to avoid port conflict
time
.
sleep
(
6
)
test_builtin_dispatcher
(
dispatch_type
,
dispatcher_name
)
print
(
GREEN
+
'Test %s %s: TEST PASS'
%
(
dispatcher_name
,
dispatch_type
)
+
CLEAR
)
except
Exception
as
error
:
...
...
tools/nni_cmd/config_schema.py
View file @
e1ae623f
...
...
@@ -36,6 +36,7 @@ Optional('nniManagerIp'): str,
Optional
(
'logDir'
):
os
.
path
.
isdir
,
Optional
(
'debug'
):
bool
,
Optional
(
'logLevel'
):
Or
(
'trace'
,
'debug'
,
'info'
,
'warning'
,
'error'
,
'fatal'
),
Optional
(
'logCollection'
):
Or
(
'http'
,
'none'
),
'useAnnotation'
:
bool
,
Optional
(
'advisor'
):
Or
({
'builtinAdvisorName'
:
Or
(
'Hyperband'
),
...
...
@@ -57,6 +58,7 @@ Optional('tuner'): Or({
Optional
(
'classArgs'
):
{
'optimize_mode'
:
Or
(
'maximize'
,
'minimize'
)
},
Optional
(
'includeIntermediateResults'
):
bool
,
Optional
(
'gpuNum'
):
And
(
int
,
lambda
x
:
0
<=
x
<=
99999
),
},{
'builtinTunerName'
:
Or
(
'BatchTuner'
,
'GridSearch'
),
...
...
tools/nni_cmd/launcher.py
View file @
e1ae623f
...
...
@@ -274,6 +274,8 @@ def set_experiment(experiment_config, mode, port, config_file_name):
#debug mode should disable version check
if
experiment_config
.
get
(
'debug'
)
is
not
None
:
request_data
[
'versionCheck'
]
=
not
experiment_config
.
get
(
'debug'
)
if
experiment_config
.
get
(
'logCollection'
):
request_data
[
'logCollection'
]
=
experiment_config
.
get
(
'logCollection'
)
request_data
[
'clusterMetaData'
]
=
[]
if
experiment_config
[
'trainingServicePlatform'
]
==
'local'
:
...
...
tools/nni_trial_tool/log_utils.py
View file @
e1ae623f
...
...
@@ -25,6 +25,7 @@ import logging
import
logging.handlers
import
time
import
threading
import
re
from
datetime
import
datetime
from
enum
import
Enum
,
unique
...
...
@@ -81,7 +82,7 @@ class RemoteLogger(object):
"""
NNI remote logger
"""
def
__init__
(
self
,
syslog_host
,
syslog_port
,
tag
,
std_output_type
,
log_level
=
logging
.
INFO
):
def
__init__
(
self
,
syslog_host
,
syslog_port
,
tag
,
std_output_type
,
log_collection
,
log_level
=
logging
.
INFO
):
'''
constructor
'''
...
...
@@ -94,12 +95,13 @@ class RemoteLogger(object):
self
.
orig_stdout
=
sys
.
__stdout__
else
:
self
.
orig_stdout
=
sys
.
__stderr__
self
.
log_collection
=
log_collection
def
get_pipelog_reader
(
self
):
'''
Get pipe for remote logger
'''
return
PipeLogReader
(
self
.
logger
,
logging
.
INFO
)
return
PipeLogReader
(
self
.
logger
,
self
.
log_collection
,
logging
.
INFO
)
def
write
(
self
,
buf
):
'''
...
...
@@ -117,7 +119,7 @@ class PipeLogReader(threading.Thread):
"""
The reader thread reads log data from pipe
"""
def
__init__
(
self
,
logger
,
log_level
=
logging
.
INFO
):
def
__init__
(
self
,
logger
,
log_collection
,
log_level
=
logging
.
INFO
):
"""Setup the object with a logger and a loglevel
and start the thread
"""
...
...
@@ -131,6 +133,8 @@ class PipeLogReader(threading.Thread):
self
.
orig_stdout
=
sys
.
__stdout__
self
.
_is_read_completed
=
False
self
.
process_exit
=
False
self
.
log_collection
=
log_collection
self
.
log_pattern
=
re
.
compile
(
r
'^NNISDK_MEb\'.*\'$'
)
def
_populateQueue
(
stream
,
queue
):
'''
...
...
@@ -143,8 +147,6 @@ class PipeLogReader(threading.Thread):
line
=
self
.
queue
.
get
(
True
,
5
)
try
:
self
.
logger
.
log
(
self
.
log_level
,
line
.
rstrip
())
self
.
orig_stdout
.
write
(
line
.
rstrip
()
+
'
\n
'
)
self
.
orig_stdout
.
flush
()
except
Exception
as
e
:
pass
except
Exception
as
e
:
...
...
@@ -165,9 +167,17 @@ class PipeLogReader(threading.Thread):
def
run
(
self
):
"""Run the thread, logging everything.
If the log_collection is 'none', the log content will not be enqueued
"""
for
line
in
iter
(
self
.
pipeReader
.
readline
,
''
):
self
.
orig_stdout
.
write
(
line
.
rstrip
()
+
'
\n
'
)
self
.
orig_stdout
.
flush
()
if
self
.
log_collection
==
'none'
:
# If not match metrics, do not put the line into queue
if
not
self
.
log_pattern
.
match
(
line
):
continue
self
.
queue
.
put
(
line
)
self
.
pipeReader
.
close
()
def
close
(
self
):
...
...
Prev
1
2
3
Next
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