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
Configure logging via TOML config #2483
Conversation
Pygments doesn't supports TOML by default https://gitlab.com/gitlab-org/gitlab-pygments-rb/commit/d460ba68716937e59498f95fd34709d98990dea3
Pygments doesn't supports TOML by default https://gitlab.com/gitlab-org/gitlab-pygments-rb/commit/d460ba68716937e59498f95fd34709d98990dea3
I'm in favor of this. I'll have to review another time though. :) |
Now all tests is fine :) |
Thank you for review :) All your advice applied, tests is passed. Do you have any other improvements? |
@Tarrasch, how is your review? ^^ |
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.
So cool to see that we're getting somewhere with improving the logging experience in luigi!
I just added a lot of comments on the code so that the code for this important core part of luigi keeps a high standard. I hope you can find time to address this stuff. I'm happy to merge (without more approval from me) once the issues are addressed.
Thanks!
5. logging_conf_file option | ||
6. ``logging`` section | ||
7. ``--log-level`` | ||
8. log_level option |
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.
Thanks for doing the deep-dive and finding these things out.
try: | ||
from ConfigParser import NoSectionError | ||
except ImportError: | ||
from configparser import NoSectionError |
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 recall this was a standard trick, can you link to some stack overflow thread or something?
Alternatively say # codepath for python < 2.7
something
luigi/setup_logging.py
Outdated
|
||
|
||
class DaemonLogging(BaseLogging): | ||
configured = False |
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.
Is this internal state? Make it _configured
maybe?
luigi/setup_logging.py
Outdated
|
||
class DaemonLogging(BaseLogging): | ||
configured = False | ||
log_format = "%(asctime)s %(name)s[%(process)s] %(levelname)s: %(message)s" |
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 you document if you can override this? If it's private do as commented above.
return configured | ||
|
||
|
||
class DaemonLogging(BaseLogging): |
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.
Maybe document this is to be used for luigid
return True | ||
|
||
@classmethod | ||
def _default(cls, opts): |
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.
add a more descriptive name please
InterfaceLogging.config = get_config() | ||
|
||
def _clean_config(self): | ||
DaemonLogging.config = LuigiTomlParser() |
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 weird. Where does toml come in in this generic context?
Should code like this be in a class TomlParserCmdlineTest(unittest.TestCase):
context or something??
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 is for creating minimal config for tests. It's here for old tests.
self.assertTrue(result) | ||
|
||
|
||
class PatchedLogging(InterfaceLogging): |
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.
Was it possible to mock one layer less?
|
||
@mock.patch("warnings.warn") | ||
@mock.patch("luigi.interface.setup_interface_logging") | ||
def test_cmdline_logger(self, setup_mock, warn): |
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's so much code that it's hard to review it all. But can you make sure that all tests you delete are added somewhere 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.
Yes, all logging well tested in test/setup_logging_test.py
result = self.cls._cli(opts) | ||
self.assertFalse(result) | ||
|
||
def test_section(self): |
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.
This test name setup_logging_test.TestDaemonLogging.test_section
could have more context if you rename test_section
to maybe test_section_returns_true_with_config
and another test test_section_returns_false_without_config
.
I know we don't follow this style at most places in this code base. But code testing improvements can start somewhere. If you want you can do this is too much you can do this as a follow up.
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's test all what we need test for _section
method
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 point is that test_section
is not saying much compared to test_section_returns_true_with_config
.
Added some @Tarrasch's improvements. Other requests commented |
CI is OK now. What about this PR? :) |
I'm good here. Have you been using this feature in production? All is good for your use? |
Now I'm in another team in the same company. I'll get actual feedback on this feature by next few days :) |
Congrats on your move @orsinium ! Appreciate the feedback |
I got feedback and have fixed example based on this:
I think, it will be better change So. now it is ready, I hope :) |
@dlstadther, @Tarrasch, what are we going to do with this Pull Request? |
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 things can be improved (as always). But anyway you've waited long already (sorry for my slow review), and this PR is actually a big improvement. Thanks!
'core', 'no_configure_logging', False): | ||
setup_interface_logging(logging_conf, env_params.log_level) | ||
|
||
InterfaceLogging.setup(env_params) |
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.
Oh nice you even cleaned up this part!
# | ||
""" | ||
This module contains helper classes for configuring logging for luigid and | ||
workers via command line arguments and options from config files. |
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.
Do these docs render nicely? Can you be explicit about if other's can use these methods or not?
return True | ||
|
||
@classmethod | ||
def _default(cls, opts): |
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.
(just a reminder to feel free to do this)
@@ -38,31 +36,7 @@ | |||
from luigi import worker | |||
from luigi import execution_summary | |||
from luigi.cmdline_parser import CmdlineParser | |||
|
|||
|
|||
def setup_interface_logging(conf_file='', level_name='DEBUG'): |
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.
A quick question. We call this method directly to set up logging. What is the equivalence now? Or it is not needed anymore?
Yeah, of course, we call InterfaceLogging instead of: Line 144 in 235edcc
|
Description
no_configure_logging
disable any logging configuring.Motivation and Context
Q. Why do you use same file for Luigi's config and logging config?
A. Because this is all project config. Also in future Pull Requests I plan to integrate in Luigi configs inheritance which allow also use separate file for logging, local settings or something else.
Q. Why do you do this? We already have support for
logging.conf
.A. Because logging via ini-file is ugly, since ini format doesn't support inherit dicts. But TOML (and YAML. JSON and other modern formats) can do it.
Q. Why do you change
no_configure_logging
behavior?A. Option
no_configure_logging
useful when you're configure logging in project bypass to Luigi. For example, when you want to use JSON or YAML configs for it. This is intuitive behavior for option with this name.Q. Why do you change code structure?
A. Old code structure is hard to test, explore and extend. Now it's beautiful :)
Have you tested this? If so, how?
And...
Thank you for best pipeline library. And best music streaming service too. All this things is amazing!