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
290558c7
Unverified
Commit
290558c7
authored
May 12, 2021
by
liuzhe-lz
Committed by
GitHub
May 12, 2021
Browse files
Improve NNI manager logging (#3624)
Co-authored-by:
liuzhe
<
zhe.liu@microsoft.com
>
parent
60983149
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
115 additions
and
139 deletions
+115
-139
nni/tools/nnictl/launcher.py
nni/tools/nnictl/launcher.py
+1
-1
ts/nni_manager/common/log.ts
ts/nni_manager/common/log.ts
+101
-117
ts/nni_manager/common/utils.ts
ts/nni_manager/common/utils.ts
+0
-4
ts/nni_manager/core/nnimanager.ts
ts/nni_manager/core/nnimanager.ts
+2
-2
ts/nni_manager/main.ts
ts/nni_manager/main.ts
+11
-15
No files found.
nni/tools/nnictl/launcher.py
View file @
290558c7
...
@@ -368,7 +368,7 @@ def launch_experiment(args, experiment_config, mode, experiment_id, config_versi
...
@@ -368,7 +368,7 @@ def launch_experiment(args, experiment_config, mode, experiment_id, config_versi
log_dir
=
experiment_config
[
'logDir'
]
if
experiment_config
.
get
(
'logDir'
)
else
NNI_HOME_DIR
log_dir
=
experiment_config
[
'logDir'
]
if
experiment_config
.
get
(
'logDir'
)
else
NNI_HOME_DIR
else
:
else
:
log_dir
=
experiment_config
[
'experimentWorkingDirectory'
]
if
experiment_config
.
get
(
'experimentWorkingDirectory'
)
else
NNI_HOME_DIR
log_dir
=
experiment_config
[
'experimentWorkingDirectory'
]
if
experiment_config
.
get
(
'experimentWorkingDirectory'
)
else
NNI_HOME_DIR
log_level
=
experiment_config
[
'logLevel'
]
if
experiment_config
.
get
(
'logLevel'
)
else
None
log_level
=
experiment_config
[
'logLevel'
]
if
experiment_config
.
get
(
'logLevel'
)
else
'info'
#view experiment mode do not need debug function, when view an experiment, there will be no new logs created
#view experiment mode do not need debug function, when view an experiment, there will be no new logs created
foreground
=
False
foreground
=
False
if
mode
!=
'view'
:
if
mode
!=
'view'
:
...
...
ts/nni_manager/common/log.ts
View file @
290558c7
...
@@ -5,151 +5,135 @@
...
@@ -5,151 +5,135 @@
import
*
as
fs
from
'
fs
'
;
import
*
as
fs
from
'
fs
'
;
import
{
Writable
}
from
'
stream
'
;
import
{
Writable
}
from
'
stream
'
;
import
{
WritableStreamBuffer
}
from
'
stream-buffers
'
;
import
{
format
}
from
'
util
'
;
/* log level constants */
import
*
as
component
from
'
../common/component
'
;
import
{
getExperimentStartupInfo
,
isReadonly
}
from
'
./experimentStartupInfo
'
;
export
const
DEBUG
=
10
;
export
const
INFO
=
20
;
const
FATAL
:
number
=
1
;
export
const
WARNING
=
30
;
const
ERROR
:
number
=
2
;
export
const
ERROR
=
40
;
const
WARNING
:
number
=
3
;
export
const
CRITICAL
=
50
;
const
INFO
:
number
=
4
;
const
DEBUG
:
number
=
5
;
export
const
TRACE
=
1
;
const
TRACE
:
number
=
6
;
export
const
FATAL
=
50
;
const
l
ogL
evelName
Map
:
Map
<
string
,
number
>
=
new
Map
([
const
levelName
s
=
new
Map
<
number
,
string
>
([
[
'
fatal
'
,
FAT
AL
],
[
CRITICAL
,
'
CRITIC
AL
'
],
[
'
error
'
,
ERROR
],
[
ERROR
,
'
ERROR
'
],
[
'
warning
'
,
WARNING
],
[
WARNING
,
'
WARNING
'
],
[
'
info
'
,
INFO
],
[
INFO
,
'
INFO
'
],
[
'
debug
'
,
DEBUG
],
[
DEBUG
,
'
DEBUG
'
],
[
'
trace
'
,
TRACE
]
[
TRACE
,
'
TRACE
'
],
]);
]);
class
BufferSerialEmitter
{
/* global_ states */
private
buffer
:
Buffer
;
private
emitting
:
boolean
;
private
writable
:
Writable
;
constructor
(
writable
:
Writable
)
{
let
logFile
:
Writable
|
null
=
null
;
this
.
buffer
=
Buffer
.
alloc
(
0
);
let
logLevel
:
number
=
0
;
this
.
emitting
=
false
;
const
loggers
=
new
Map
<
string
,
Logger
>
();
this
.
writable
=
writable
;
}
public
feed
(
buffer
:
Buffer
):
void
{
/* major api */
this
.
buffer
=
Buffer
.
concat
([
this
.
buffer
,
buffer
]);
if
(
!
this
.
emitting
)
{
this
.
emit
();
}
}
private
emit
():
void
{
export
class
Logger
{
this
.
emitting
=
true
;
private
name
:
string
;
this
.
writable
.
write
(
this
.
buffer
,
()
=>
{
if
(
this
.
buffer
.
length
===
0
)
{
constructor
(
name
:
string
=
'
root
'
)
{
this
.
emitting
=
false
;
this
.
name
=
name
;
}
else
{
this
.
emit
();
}
});
this
.
buffer
=
Buffer
.
alloc
(
0
);
}
}
}
@
component
.
Singleton
public
trace
(...
args
:
any
[]):
void
{
class
Logger
{
this
.
log
(
TRACE
,
args
);
private
level
:
number
=
INFO
;
}
private
bufferSerialEmitter
?:
BufferSerialEmitter
;
private
writable
?:
Writable
;
private
readonly
:
boolean
=
false
;
constructor
(
fileName
?:
string
)
{
const
logFile
:
string
|
undefined
=
fileName
;
if
(
logFile
)
{
this
.
writable
=
fs
.
createWriteStream
(
logFile
,
{
flags
:
'
a+
'
,
encoding
:
'
utf8
'
,
autoClose
:
true
});
this
.
bufferSerialEmitter
=
new
BufferSerialEmitter
(
this
.
writable
);
}
const
logLevelName
:
string
=
getExperimentStartupInfo
()
public
debug
(...
args
:
any
[]):
void
{
.
getLogLevel
();
this
.
log
(
DEBUG
,
args
);
const
logLevel
:
number
|
undefined
=
logLevelNameMap
.
get
(
logLevelName
);
}
if
(
logLevel
!==
undefined
)
{
this
.
level
=
logLevel
;
}
this
.
readonly
=
isReadonly
();
public
info
(...
args
:
any
[]):
void
{
this
.
log
(
INFO
,
args
);
}
}
public
close
():
void
{
public
warning
(...
args
:
any
[]):
void
{
if
(
this
.
writable
)
{
this
.
log
(
WARNING
,
args
);
this
.
writable
.
destroy
();
}
}
}
public
trace
(...
param
:
any
[]):
void
{
public
error
(...
args
:
any
[]):
void
{
if
(
this
.
level
>=
TRACE
)
{
this
.
log
(
ERROR
,
args
);
this
.
log
(
'
TRACE
'
,
param
);
}
}
}
public
debug
(...
param
:
any
[]):
void
{
public
critical
(...
args
:
any
[]):
void
{
if
(
this
.
level
>=
DEBUG
)
{
this
.
log
(
CRITICAL
,
args
);
this
.
log
(
'
DEBUG
'
,
param
);
}
}
}
public
info
(...
param
:
any
[]):
void
{
public
fatal
(...
args
:
any
[]):
void
{
if
(
this
.
level
>=
INFO
)
{
this
.
log
(
FATAL
,
args
);
this
.
log
(
'
INFO
'
,
param
);
}
}
}
p
ublic
warning
(...
param
:
any
[]):
void
{
p
rivate
log
(
level
:
number
,
args
:
any
[]):
void
{
if
(
this
.
level
>=
WARNING
)
{
if
(
level
<
logLevel
||
logFile
===
null
)
{
this
.
log
(
'
WARNING
'
,
param
)
;
return
;
}
}
}
public
error
(...
param
:
any
[]):
void
{
// `time.toLocaleString('sv')` trick does not work for Windows
if
(
this
.
level
>=
ERROR
)
{
const
isoTime
=
new
Date
(
new
Date
().
toLocaleString
()
+
'
UTC
'
).
toISOString
();
this
.
log
(
'
ERROR
'
,
param
);
const
time
=
isoTime
.
slice
(
0
,
10
)
+
'
'
+
isoTime
.
slice
(
11
,
19
);
const
levelName
=
levelNames
.
has
(
level
)
?
levelNames
.
get
(
level
)
:
level
.
toString
();
const
words
=
[];
for
(
const
arg
of
args
)
{
if
(
arg
===
undefined
)
{
words
.
push
(
'
undefined
'
);
}
else
if
(
arg
===
null
)
{
words
.
push
(
'
null
'
);
}
else
if
(
typeof
arg
===
'
object
'
)
{
const
json
=
JSON
.
stringify
(
arg
);
words
.
push
(
json
===
undefined
?
arg
:
json
);
}
else
{
words
.
push
(
arg
);
}
}
}
const
message
=
words
.
join
(
'
'
);
const
record
=
`[
${
time
}
]
${
levelName
}
(
${
this
.
name
}
)
${
message
}
\n`
;
logFile
.
write
(
record
);
}
}
}
public
fatal
(...
param
:
any
[]):
void
{
export
function
getLogger
(
name
:
string
=
'
root
'
):
Logger
{
this
.
log
(
'
FATAL
'
,
param
);
let
logger
=
loggers
.
get
(
name
);
if
(
logger
===
undefined
)
{
logger
=
new
Logger
(
name
);
loggers
.
set
(
name
,
logger
);
}
}
return
logger
;
/**
}
* if the experiment is not in readonly mode, write log content to stream
* @param level log level
/* management functions */
* @param param the params to be written
*/
export
function
setLogLevel
(
levelName
:
string
):
void
{
private
log
(
level
:
string
,
param
:
any
[]):
void
{
if
(
levelName
)
{
if
(
!
this
.
readonly
)
{
const
level
=
module
.
exports
[
levelName
.
toUpperCase
()];
const
time
=
new
Date
();
if
(
typeof
level
===
'
number
'
)
{
const
localTime
=
new
Date
(
time
.
getTime
()
-
time
.
getTimezoneOffset
()
*
60000
);
logLevel
=
level
;
const
timeStr
=
localTime
.
toISOString
().
slice
(
0
,
-
5
).
replace
(
'
T
'
,
'
'
);
}
else
{
const
logContent
=
`[
${
timeStr
}
]
${
level
}
${
format
(
param
)}
\n`
;
console
.
log
(
'
[ERROR] Bad log level:
'
,
levelName
);
if
(
this
.
writable
&&
this
.
bufferSerialEmitter
)
{
getLogger
(
'
logging
'
).
error
(
'
Bad log level:
'
,
levelName
);
const
buffer
:
WritableStreamBuffer
=
new
WritableStreamBuffer
();
buffer
.
write
(
logContent
);
buffer
.
end
();
this
.
bufferSerialEmitter
.
feed
(
buffer
.
getContents
());
}
else
{
console
.
log
(
logContent
);
}
}
}
}
}
}
}
function
getLogger
():
Logger
{
export
function
startLogging
(
logPath
:
string
):
void
{
return
component
.
get
(
Logger
);
logFile
=
fs
.
createWriteStream
(
logPath
,
{
flags
:
'
a+
'
,
encoding
:
'
utf8
'
,
autoClose
:
true
});
}
}
export
{
Logger
,
getLogger
,
logLevelNameMap
};
export
function
stopLogging
():
void
{
if
(
logFile
!==
null
)
{
logFile
.
end
();
logFile
=
null
;
}
}
ts/nni_manager/common/utils.ts
View file @
290558c7
...
@@ -23,7 +23,6 @@ import { ExperimentStartupInfo, getExperimentStartupInfo, setExperimentStartupIn
...
@@ -23,7 +23,6 @@ import { ExperimentStartupInfo, getExperimentStartupInfo, setExperimentStartupIn
import
{
ExperimentConfig
,
Manager
}
from
'
./manager
'
;
import
{
ExperimentConfig
,
Manager
}
from
'
./manager
'
;
import
{
ExperimentManager
}
from
'
./experimentManager
'
;
import
{
ExperimentManager
}
from
'
./experimentManager
'
;
import
{
HyperParameters
,
TrainingService
,
TrialJobStatus
}
from
'
./trainingService
'
;
import
{
HyperParameters
,
TrainingService
,
TrialJobStatus
}
from
'
./trainingService
'
;
import
{
logLevelNameMap
}
from
'
./log
'
;
function
getExperimentRootDir
():
string
{
function
getExperimentRootDir
():
string
{
return
getExperimentStartupInfo
()
return
getExperimentStartupInfo
()
...
@@ -195,9 +194,6 @@ function prepareUnitTest(): void {
...
@@ -195,9 +194,6 @@ function prepareUnitTest(): void {
Container
.
snapshot
(
ExperimentManager
);
Container
.
snapshot
(
ExperimentManager
);
const
logLevel
:
string
=
parseArg
([
'
--log_level
'
,
'
-ll
'
]);
const
logLevel
:
string
=
parseArg
([
'
--log_level
'
,
'
-ll
'
]);
if
(
logLevel
.
length
>
0
&&
!
logLevelNameMap
.
has
(
logLevel
))
{
console
.
log
(
`FATAL: invalid log_level:
${
logLevel
}
`
);
}
setExperimentStartupInfo
(
true
,
'
unittest
'
,
8080
,
'
unittest
'
,
undefined
,
logLevel
);
setExperimentStartupInfo
(
true
,
'
unittest
'
,
8080
,
'
unittest
'
,
undefined
,
logLevel
);
mkDirPSync
(
getLogDir
());
mkDirPSync
(
getLogDir
());
...
...
ts/nni_manager/core/nnimanager.ts
View file @
290558c7
...
@@ -10,7 +10,7 @@ import * as component from '../common/component';
...
@@ -10,7 +10,7 @@ import * as component from '../common/component';
import
{
DataStore
,
MetricDataRecord
,
MetricType
,
TrialJobInfo
}
from
'
../common/datastore
'
;
import
{
DataStore
,
MetricDataRecord
,
MetricType
,
TrialJobInfo
}
from
'
../common/datastore
'
;
import
{
NNIError
}
from
'
../common/errors
'
;
import
{
NNIError
}
from
'
../common/errors
'
;
import
{
getExperimentId
,
getDispatcherPipe
}
from
'
../common/experimentStartupInfo
'
;
import
{
getExperimentId
,
getDispatcherPipe
}
from
'
../common/experimentStartupInfo
'
;
import
{
getLogger
,
Logg
er
}
from
'
../common/log
'
;
import
{
Logger
,
getLogger
,
stop
Logg
ing
}
from
'
../common/log
'
;
import
{
import
{
ExperimentProfile
,
Manager
,
ExperimentStatus
,
ExperimentProfile
,
Manager
,
ExperimentStatus
,
NNIManagerStatus
,
ProfileUpdateType
,
TrialJobStatistics
NNIManagerStatus
,
ProfileUpdateType
,
TrialJobStatistics
...
@@ -362,7 +362,7 @@ class NNIManager implements Manager {
...
@@ -362,7 +362,7 @@ class NNIManager implements Manager {
hasError
=
true
;
hasError
=
true
;
this
.
log
.
error
(
`
${
err
.
stack
}
`
);
this
.
log
.
error
(
`
${
err
.
stack
}
`
);
}
finally
{
}
finally
{
this
.
log
.
close
();
stopLogging
();
process
.
exit
(
hasError
?
1
:
0
);
process
.
exit
(
hasError
?
1
:
0
);
}
}
}
}
...
...
ts/nni_manager/main.ts
View file @
290558c7
...
@@ -10,7 +10,7 @@ import * as path from 'path';
...
@@ -10,7 +10,7 @@ import * as path from 'path';
import
*
as
component
from
'
./common/component
'
;
import
*
as
component
from
'
./common/component
'
;
import
{
Database
,
DataStore
}
from
'
./common/datastore
'
;
import
{
Database
,
DataStore
}
from
'
./common/datastore
'
;
import
{
setExperimentStartupInfo
}
from
'
./common/experimentStartupInfo
'
;
import
{
setExperimentStartupInfo
}
from
'
./common/experimentStartupInfo
'
;
import
{
getLogger
,
Logger
,
logLevelNameMap
}
from
'
./common/log
'
;
import
{
getLogger
,
setLogLevel
,
startLogging
}
from
'
./common/log
'
;
import
{
Manager
,
ExperimentStartUpMode
}
from
'
./common/manager
'
;
import
{
Manager
,
ExperimentStartUpMode
}
from
'
./common/manager
'
;
import
{
ExperimentManager
}
from
'
./common/experimentManager
'
;
import
{
ExperimentManager
}
from
'
./common/experimentManager
'
;
import
{
TensorboardManager
}
from
'
./common/tensorboardManager
'
;
import
{
TensorboardManager
}
from
'
./common/tensorboardManager
'
;
...
@@ -47,14 +47,15 @@ async function initContainer(foreground: boolean, platformMode: string, logFileN
...
@@ -47,14 +47,15 @@ async function initContainer(foreground: boolean, platformMode: string, logFileN
.
to
(
NNITensorboardManager
)
.
to
(
NNITensorboardManager
)
.
scope
(
Scope
.
Singleton
);
.
scope
(
Scope
.
Singleton
);
const
DEFAULT_LOGFILE
:
string
=
path
.
join
(
getLogDir
(),
'
nnimanager.log
'
);
const
DEFAULT_LOGFILE
:
string
=
path
.
join
(
getLogDir
(),
'
nnimanager.log
'
);
if
(
foreground
)
{
if
(
!
foreground
)
{
logFileName
=
undefined
;
if
(
logFileName
===
undefined
)
{
}
else
if
(
logFileName
===
undefined
)
{
startLogging
(
DEFAULT_LOGFILE
);
logFileName
=
DEFAULT_LOGFILE
;
}
else
{
startLogging
(
logFileName
);
}
// eslint-disable-next-line @typescript-eslint/no-use-before-define
setLogLevel
(
logLevel
);
}
}
Container
.
bind
(
Logger
).
provider
({
get
:
():
Logger
=>
new
Logger
(
logFileName
)
});
const
ds
:
DataStore
=
component
.
get
(
DataStore
);
const
ds
:
DataStore
=
component
.
get
(
DataStore
);
await
ds
.
init
();
await
ds
.
init
();
...
@@ -110,9 +111,6 @@ if (logDir.length > 0) {
...
@@ -110,9 +111,6 @@ if (logDir.length > 0) {
}
}
const
logLevel
:
string
=
parseArg
([
'
--log_level
'
,
'
-ll
'
]);
const
logLevel
:
string
=
parseArg
([
'
--log_level
'
,
'
-ll
'
]);
if
(
logLevel
.
length
>
0
&&
!
logLevelNameMap
.
has
(
logLevel
))
{
console
.
log
(
`FATAL: invalid log_level:
${
logLevel
}
`
);
}
const
readonlyArg
:
string
=
parseArg
([
'
--readonly
'
,
'
-r
'
]);
const
readonlyArg
:
string
=
parseArg
([
'
--readonly
'
,
'
-r
'
]);
if
(
!
(
'
true
'
||
'
false
'
).
includes
(
readonlyArg
.
toLowerCase
()))
{
if
(
!
(
'
true
'
||
'
false
'
).
includes
(
readonlyArg
.
toLowerCase
()))
{
...
@@ -132,11 +130,9 @@ mkDirP(getLogDir())
...
@@ -132,11 +130,9 @@ mkDirP(getLogDir())
await
initContainer
(
foreground
,
mode
);
await
initContainer
(
foreground
,
mode
);
const
restServer
:
NNIRestServer
=
component
.
get
(
NNIRestServer
);
const
restServer
:
NNIRestServer
=
component
.
get
(
NNIRestServer
);
await
restServer
.
start
();
await
restServer
.
start
();
const
log
:
Logger
=
getLogger
();
getLogger
(
'
main
'
).
info
(
`Rest server listening on:
${
restServer
.
endPoint
}
`
);
log
.
info
(
`Rest server listening on:
${
restServer
.
endPoint
}
`
);
}
catch
(
err
)
{
}
catch
(
err
)
{
const
log
:
Logger
=
getLogger
();
getLogger
(
'
main
'
).
error
(
`
${
err
.
stack
}
`
);
log
.
error
(
`
${
err
.
stack
}
`
);
throw
err
;
throw
err
;
}
}
})
})
...
...
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