Unverified Commit 42eb04ef authored by liuzhe-lz's avatar liuzhe-lz Committed by GitHub
Browse files

Fix and improve nnictl warning message (#4430)

parent a6bed3cf
...@@ -262,7 +262,7 @@ def to_v2(v1): ...@@ -262,7 +262,7 @@ def to_v2(v1):
if v1_trial: if v1_trial:
_logger.error('trial config not fully converted: %s', v1_trial) _logger.error('trial config not fully converted: %s', v1_trial)
if v1: if v1:
_logger.error('config not fully converted: %s', v1) _logger.error('Config not fully converted: %s', v1)
return v2 return v2
def _move_field(v1, v2, v1_key, v2_key=None): def _move_field(v1, v2, v1_key, v2_key=None):
...@@ -275,7 +275,7 @@ def _move_field(v1, v2, v1_key, v2_key=None): ...@@ -275,7 +275,7 @@ def _move_field(v1, v2, v1_key, v2_key=None):
def _drop_field(v1, key): def _drop_field(v1, key):
if key in v1: if key in v1:
_logger.warning(f'Configuration field {key} is no longer supported and has been ignored') _logger.warning(f'Config field "{key}" is no longer supported and has been ignored')
v1.pop(key) v1.pop(key)
def _deprecate(v1, v2, key): def _deprecate(v1, v2, key):
......
...@@ -82,7 +82,7 @@ class Experiment: ...@@ -82,7 +82,7 @@ class Experiment:
... ...
def __init__(self, config=None, training_service=None): def __init__(self, config=None, training_service=None):
nni.runtime.log.init_logger_experiment() nni.runtime.log.init_logger_for_command_line()
self.config: Optional[ExperimentConfig] = None self.config: Optional[ExperimentConfig] = None
self.id: str = management.generate_experiment_id() self.id: str = management.generate_experiment_id()
......
...@@ -44,17 +44,21 @@ def init_logger() -> None: ...@@ -44,17 +44,21 @@ def init_logger() -> None:
logging.getLogger('filelock').setLevel(logging.WARNING) logging.getLogger('filelock').setLevel(logging.WARNING)
_exp_log_initialized = False _cli_log_initialized = False
def init_logger_experiment() -> None: def init_logger_for_command_line() -> None:
""" """
Initialize logger for `nni.experiment.Experiment`. Initialize logger for command line usage.
This means that NNI is used as "main function" rather than underlying library or background service,
so it should print log to stdout.
It is used by nnictl and `nni.experiment.Experiment`.
This function will get invoked after `init_logger()`. This function will get invoked after `init_logger()`.
""" """
global _exp_log_initialized global _cli_log_initialized
if not _exp_log_initialized: if not _cli_log_initialized:
_exp_log_initialized = True _cli_log_initialized = True
colorful_formatter = Formatter(log_format, time_format) colorful_formatter = Formatter(log_format, time_format)
colorful_formatter.format = _colorful_format colorful_formatter.format = _colorful_format
handlers['_default_'].setFormatter(colorful_formatter) handlers['_default_'].setFormatter(colorful_formatter)
...@@ -120,13 +124,17 @@ def _colorful_format(record): ...@@ -120,13 +124,17 @@ def _colorful_format(record):
return '[{}] ({}) {}'.format(time, record.name, record.msg % record.args) return '[{}] ({}) {}'.format(time, record.name, record.msg % record.args)
if record.levelno >= logging.ERROR: if record.levelno >= logging.ERROR:
color = colorama.Fore.RED color = colorama.Fore.RED
level = 'ERROR: '
elif record.levelno >= logging.WARNING: elif record.levelno >= logging.WARNING:
color = colorama.Fore.YELLOW color = colorama.Fore.YELLOW
level = 'WARNING: '
elif record.levelno >= logging.INFO: elif record.levelno >= logging.INFO:
color = colorama.Fore.GREEN color = colorama.Fore.GREEN
level = ''
else: else:
color = colorama.Fore.BLUE color = colorama.Fore.BLUE
msg = color + (record.msg % record.args) + colorama.Style.RESET_ALL level = ''
msg = color + level + (record.msg % record.args) + colorama.Style.RESET_ALL
if record.levelno < logging.INFO: if record.levelno < logging.INFO:
return '[{}] {}:{} {}'.format(time, record.threadName, record.name, msg) return '[{}] {}:{} {}'.format(time, record.threadName, record.name, msg)
else: else:
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# Licensed under the MIT license. # Licensed under the MIT license.
from getpass import getuser from getpass import getuser
import logging
from pathlib import Path from pathlib import Path
import tempfile import tempfile
...@@ -10,12 +11,15 @@ import yaml ...@@ -10,12 +11,15 @@ import yaml
from nni.experiment import Experiment, RunMode from nni.experiment import Experiment, RunMode
from nni.experiment.config import ExperimentConfig, convert, utils from nni.experiment.config import ExperimentConfig, convert, utils
from nni.runtime.log import init_logger_for_command_line
from nni.tools.annotation import expand_annotations, generate_search_space from nni.tools.annotation import expand_annotations, generate_search_space
# used for v1-only legacy setup, remove them later # used for v1-only legacy setup, remove them later
from nni.experiment.launcher import get_stopped_experiment_config_json from nni.experiment.launcher import get_stopped_experiment_config_json
from . import legacy_launcher from . import legacy_launcher
_logger = logging.getLogger(__name__)
def create_experiment(args): def create_experiment(args):
# to make it clear what are inside args # to make it clear what are inside args
config_file = Path(args.config) config_file = Path(args.config)
...@@ -24,8 +28,13 @@ def create_experiment(args): ...@@ -24,8 +28,13 @@ def create_experiment(args):
url_prefix = args.url_prefix url_prefix = args.url_prefix
foreground = args.foreground foreground = args.foreground
# it should finally be done in nnictl main function
# but for now don't break routines without logging support
init_logger_for_command_line()
logging.getLogger('nni').setLevel(logging.INFO)
if not config_file.is_file(): if not config_file.is_file():
print(Fore.RED + 'ERROR: "{config_file}" is not a valid file.' + Fore.RESET) _logger.error('"{config_file}" is not a valid file.')
exit(1) exit(1)
with config_file.open() as config: with config_file.open() as config:
...@@ -47,10 +56,14 @@ def create_experiment(args): ...@@ -47,10 +56,14 @@ def create_experiment(args):
try: try:
v2_config = convert.to_v2(config_content) v2_config = convert.to_v2(config_content)
except Exception: except Exception:
print(Fore.RED + 'ERROR: You are using legacy config file, please update it to latest format.' + Fore.RESET) _logger.error(
print(Fore.RED + 'Reference: https://nni.readthedocs.io/en/stable/reference/experiment_config.html' + Fore.RESET) 'You are using legacy config format with incorrect fields or values, '
'to get more accurate error message please update it to the new format.'
)
_logger.error('Reference: https://nni.readthedocs.io/en/stable/reference/experiment_config.html')
exit(1) exit(1)
print(Fore.YELLOW + f'WARNING: You are using legacy config file, please update it to latest format:' + Fore.RESET) _logger.warning(f'You are using legacy config file, please update it to latest format:')
# use `print` here because logging will add timestamp and make it hard to copy paste
print(Fore.YELLOW + '=' * 80 + Fore.RESET) print(Fore.YELLOW + '=' * 80 + Fore.RESET)
print(yaml.dump(v2_config, sort_keys=False).strip()) print(yaml.dump(v2_config, sort_keys=False).strip())
print(Fore.YELLOW + '=' * 80 + Fore.RESET) print(Fore.YELLOW + '=' * 80 + Fore.RESET)
...@@ -85,6 +98,9 @@ def resume_experiment(args): ...@@ -85,6 +98,9 @@ def resume_experiment(args):
foreground = args.foreground foreground = args.foreground
exp_dir = args.experiment_dir exp_dir = args.experiment_dir
init_logger_for_command_line()
logging.getLogger('nni').setLevel(logging.INFO)
config_json = get_stopped_experiment_config_json(exp_id, exp_dir) config_json = get_stopped_experiment_config_json(exp_id, exp_dir)
if config_json.get('trainingServicePlatform'): if config_json.get('trainingServicePlatform'):
legacy_launcher.resume_experiment(args) legacy_launcher.resume_experiment(args)
...@@ -99,6 +115,9 @@ def view_experiment(args): ...@@ -99,6 +115,9 @@ def view_experiment(args):
port = args.port port = args.port
exp_dir = args.experiment_dir exp_dir = args.experiment_dir
init_logger_for_command_line()
logging.getLogger('nni').setLevel(logging.INFO)
config_json = get_stopped_experiment_config_json(exp_id, exp_dir) config_json = get_stopped_experiment_config_json(exp_id, exp_dir)
if config_json.get('trainingServicePlatform'): if config_json.get('trainingServicePlatform'):
legacy_launcher.view_experiment(args) legacy_launcher.view_experiment(args)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment