-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use developer log level, protect logger defaults in test #473
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #473 +/- ##
===========================================
+ Coverage 90.43% 90.83% +0.39%
===========================================
Files 60 60
Lines 3837 3818 -19
===========================================
- Hits 3470 3468 -2
+ Misses 367 350 -17
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch! I have a couple of small nits for you, but otherwise LGTM!!
smartsim/log.py
Outdated
@@ -63,7 +63,7 @@ | |||
_PR = ParamSpec("_PR") | |||
|
|||
|
|||
def _get_log_level() -> str: | |||
def _translate_log_level(user_log_level: t.Optional[str] = "info") -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor typing nit: t.Optional[str]
implies that
_translate_log_level(user_log_level=None)
is a valid call. Did you mean
def _translate_log_level(user_log_level: t.Optional[str] = "info") -> str: | |
def _translate_log_level(user_log_level: str = "info") -> str: |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You know, I don't know. I think it's better as you say, as it is an internal function we should only call one way.
smartsim/log.py
Outdated
@@ -205,7 +204,7 @@ def get_logger( | |||
""" | |||
# if name is None, then logger is the root logger | |||
# if not root logger, get the name of file without prefix. | |||
user_log_level = _get_log_level() | |||
user_log_level = os.environ.get("SMARTSIM_LOG_LEVEL", "info") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding
user_log_level = os.environ.get("SMARTSIM_LOG_LEVEL", "info") | |
user_log_level = os.environ.get("SMARTSIM_LOG_LEVEL", "info").lower() |
otherwise
export SMARTSIM_LOG_LEVEL=QUIET
will default to "info"
which would technically be an API break
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, totally right
@@ -77,15 +77,14 @@ def _get_log_level() -> str: | |||
:returns: Log level for coloredlogs | |||
:rtype: str | |||
""" | |||
log_level = os.environ.get("SMARTSIM_LOG_LEVEL", "info").lower() | |||
if log_level == "quiet": | |||
if user_log_level == "quiet": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we shorten this to:
if user_log_level in ['quiet', 'info', 'debug','warning']:
return user_log_level
if user_log_level == "developer":
return "info"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you missed one case, but I got the point and modified implementation accordingly.
smartsim/log.py
Outdated
@@ -205,7 +204,7 @@ def get_logger( | |||
""" | |||
# if name is None, then logger is the root logger | |||
# if not root logger, get the name of file without prefix. | |||
user_log_level = _get_log_level() | |||
user_log_level = os.environ.get("SMARTSIM_LOG_LEVEL", "info") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder what you & @MattToast think about trying to move all os.environ['xyz']
calls into the smartsim._core.config.Config
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was already there...
"""Ensure that experiment loggers are added when context info exists""" | ||
monkeypatch.setenv("SMARTSIM_LOG_LEVEL", "developer") | ||
test_dir = pathlib.Path(test_dir) | ||
test_dir.mkdir(parents=True, exist_ok=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding direct unit test of new method:
@pytest.mark.parametrize(
"input_level,exp_level",
[
pytest.param("INFO", "info", id="lowercasing only, INFO"),
pytest.param("info", "info", id="input back, info"),
pytest.param("WARNING", "warning", id="lowercasing only, WARNING"),
pytest.param("warning", "warning", id="input back, warning"),
pytest.param("QUIET", "warning", id="lowercasing only, QUIET"),
pytest.param("quiet", "warning", id="translation back, quiet"),
pytest.param("DEVELOPER", "debug", id="lowercasing only, DEVELOPER"),
pytest.param("developer", "debug", id="translation back, developer"),
]
)
def test_translate_log_level(input_level: str, exp_level: str, turn_on_tm):
"""Ensure the correct logger type is instantiated"""
translated_level = smartsim.log._translate_log_level(input_level)
assert exp_level == translated_level
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I need turn_on_tm
, do I? @ankona
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, pending tests!!
The current
log.get_logger()
function has two issues._get_log_level()
to access the value ofSMARTSIM_LOG_LEVEL
, and uses its return value to define whether the logger name should just be SmartSim, or the user-provided one. The problem is that the user-provided one is used only when_get_log_level()
returnsdeveloper
, but that is never the case, asdeveloper
gets translated todebug
.get_logger(name="MY_LOGGER", log_level="INFO")
will always get the logger namedSmartSim
and set its level to info. When this is done in a test, then the log level will be set for all subsequent tests, no matter what the name is set to.I proposed to replace the
_get_log_level()
with_translate_log_level()
and use the return value to set the log level when log level is not set todeveloper
. To be honest, I think it is kind of weird that users can provide a name for the logger and that it gets thrown away 99.9% of the times, but I guess they could also use a different logger if they wanted something more flexible, and with the changes of this PR, the API is consistent with the docs.