-
Notifications
You must be signed in to change notification settings - Fork 1.3k
logger: Use a more _pythonic_ logging #1822
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
Conversation
tests/test_tag.py
Outdated
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.
Why couldn't self._caplog.at_level down below clear log by default?
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.
_caplog.at_level is only a context manager to set the level of a logger, and changing the level shouldn't affect the previous log, what caplog.clear() does is to remove all the LogRecord entries saved on caplog.records.
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.
@MrOutis yeah, but why would you use at_level and not use clear() before it? I'm not saying at_level should do that perse, but it feels like it would be convenient to have something that would reset it automatically when you are capturing log with with. What do you think?
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 guess at_level is to test logging specific info, for example, it is used in test_logger.py for logic that depends on the current level (outputting the traceback on an error only when --verbose is specified).
In this test, we were running the add command before, creating some unwanted logs for our test:
def test(self):
ret = main(["add", self.FOO])
self.assertEqual(ret, 0)That's why I do:
self._caplog.clear()Now, the at_level thing is because the previous test was asserting that the output should contain Warning: <message>, to maintain compatibility, I used _caplog.at_level to make sure the message didn't come from debug or info:
with self._caplog.at_level(logging.WARNING, logger="dvc"):
ret = main(["tag", "remove", "v1", "foo.dvc"])
self.assertEqual(ret, 0)
assert "tag 'v1' not found for 'foo'" in self._caplog.text
I don't think this is always the case, as sometimes we would be trying to test something logged by info. Also, I'd prefer to leave it as it is, you can read and write tests without having to know beforehand about a set_level_and_clear method, for example 😛
efiop
left a comment
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.
Looks great, @MrOutis ! Could you show us how dvc commands (e.g. dvc init) look like now? For example with asciinema.
pared
left a comment
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.
<3 especially for removing MockLoggerHandlers and ConsoleFontColorsRemover. Btw, I noticed that you did not remove those classes, maybe remove tests/utils/logger.py ?
just removed progress_aware :)
|
@MrOutis And what about tests/utils/logger.py? :) |
|
😅 missed that one, @pared , thanks! I'll remove it on the next commit |
ei-grad
left a comment
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'd like to replace all the
.format()things with the logger's own ability to do the message formatting. This is not so critical for the.exception()and.error(), but would really improve overall dvc performance if it would be replaced for.debug()calls. -
I think it could be better to make some explicitly named loggers like
cli_logger = logging.getLogger("dvc.cli")
remote_logger = logging.getLogger("dvc.remote")
repo_logger = logging.getLogger("dvc.repo")somewhere in dvc/logger.py instead of putting the logger = logging.getLogger(__name__) in each separate module. But now you should know better than me does it make sense at all and which loggers set could we need to improve the testing experience and make the logging configuration easier and more flexible.
dvc/command/commit.py
Outdated
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.
The string formatting routines shouldn't be used in the logger method invocations. This should be rewritten with:
"failed to commit%s", (" " + target) if target else ""
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.
totally, @ei-grad ; I delayed this change because the whole code base is currently using the brace style: "hello {}".format("world"), sadly, on 2.7 the logger doesn't support braces, but it does on 3.x maybe we should wait a little bit to embrace this change.
dvc/command/config.py
Outdated
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.
| logger.exception("failed to unset '{}'".format(self.args.name)) | |
| logger.exception("failed to unset %r", self.args.name) |
dvc/command/config.py
Outdated
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.
| logger.exception("failed to show '{}'".format(self.args.name)) | |
| logger.exception("failed to show %r", self.args.name) |
dvc/command/config.py
Outdated
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.
| "failed to set '{}.{}' to '{}'".format(section, opt, value) | |
| "failed to set '%s.%s' to %r", section, opt, value, |
|
Good work, btw! Thanks! Really like the dvc logging to go this way. |
@ei-grad , that's a great suggestion, a lot of projects use that approach. My thoughts are that having |
- Uses a formatter for coloring output - Move the `progress_aware` decorator logic to the logger itself - Refactor modules so each one uses their own instance of a logger Close #1753
ei-grand I'll open a new issue to keep track of this refactor
|
@efiop , ready ! 😃 |
efiop
left a comment
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.
🔥 Thank you!
progress_awaredecorator logic to the logger itselflogger.exceptionoverlogger.errorClose #1753