-
Notifications
You must be signed in to change notification settings - Fork 189
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
add verbosity option for verdi commands #3896
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #3896 +/- ##
===========================================
- Coverage 79.36% 79.34% -0.02%
===========================================
Files 476 469 -7
Lines 34951 34812 -139
===========================================
- Hits 27736 27618 -118
+ Misses 7215 7194 -21
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
I am not sure if this is what the OP of #3864 had in mind (which is not to say that the changes here might not be useful). In their case they tried to setup manually and failed, but |
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.
Seems legit, thanks @ltalirz!
In conjunction with our discussions over in #3599, I think it would be better to call this --debug
instead of --verbose
, having it align better with the logging level as well.
However, if you simply want a more verbose version, I think this is fine if the logging level is then also changed. The two should match, otherwise, I am afraid setting the logging level may bleed into other actions unintentionally, showing unintended debug messages - if this is possible? I am not completely confident still in the intricacies of logging.
Didn't see this comment before reviewing. |
I agree that the level of logging provided here is not yet very extensive, but I think it is a reasonable start and it becomes easy to extend in the future if more details are desired.
I think you're right that the level of logging provided here can be considered "debug" level. However, let me propose an alternative solution instead:
The obvious benefit of this pattern is that it is always easy to ask for "more information" without having to learn the names of the particular log levels and their meaning. Since controlling the log level is something that should apply to verdi commands across the board, it would ideally be controlled at the So, as the next best thing, I propose that I will change the verbosity option to the form described above, make it available in the @sphuber @CasperWA Sounds good? One thing we would need to decide is the correspondence of flags and python VERBOSITY_LOG_LEVEL_MAP = {
-1: logging.ERROR, # only reachable via --vv=-1 . Could also start counting from 0 instead.
0: logging.WARNING,
1: logging.INFO,
2: logging.DEBUG,
} We should then also include a brief documentation of what those log levels mean in the AiiDA-core docs (see e.g. kubectl example). |
Let me know whether you agree and I will finish the PR |
I see the advantage of having a single consistently functioning option like the I just have two questions still.
|
Thanks, I simply overlooked this.
I agree that these two approaches will need to be married (in this PR) in the sense that the verbosity level should control whether As for eliminating one of the two approaches entirely - the |
6d1c2a3
to
428d3ae
Compare
428d3ae
to
14ccd4b
Compare
14ccd4b
to
5f9fa2b
Compare
@sphuber The PR now contains the approach we discussed in the issue (some minor things remain to be done, see to-do lists in the PR description). Would you mind giving a quick top-level look to check whether the general approach looks good to you? |
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 @ltalirz . Looking really good, I would continue in this direction. Shouldn't be far off now
04fc9d1
to
13d6f7c
Compare
@sphuber I've tried to address all remaining issues. Should be ready for review. |
62ee46f
to
e65fda5
Compare
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 @ltalirz , still have some comments and questions
|
||
node_pks_to_delete = [node.pk for node in nodes] | ||
|
||
delete_nodes(node_pks_to_delete, dry_run=dry_run, verbosity=verbosity, force=force, **kwargs) | ||
delete_nodes(node_pks_to_delete, dry_run=dry_run, force=force, **kwargs) |
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.
Don't we still need to forward the verbosity to this command? I know that the CLI levels do not map onto those that delete_nodes
understand, but now the verbosity option will simply be ignored. won't it?
# Invoke the runner | ||
run_api( | ||
hostname=hostname, | ||
port=port, | ||
config=config_dir, | ||
debug=debug, | ||
debug=VERDI_LOGGER.level <= LOG_LEVELS['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.
I wonder if we want to add some property or method on the VERDI_LOGGER
that makes this easier and does not require importing LOG_LEVELS
. Not sure if this would require some complex logic and in the end is not worth it. Just something to think about
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.
What about something like VERDI_LOGGER.includes('DEBUG')
or VERDI_LOGGER.is_logging('DEBUG')
?
@@ -625,28 +626,30 @@ def test_basics(self): | |||
""" | |||
from aiida.common.exceptions import NotExistent | |||
|
|||
node_delete = VERBOSITY()(cmd_node.node_delete) |
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 does this need to be added here? With the current setup, the subcommands won't have the verbosity option when calling the commands directly through the cli_runner
? Instead of hotfixing it like this, I think we would need to find a more rigorous global solution
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 does this need to be added here? With the current setup, the subcommands won't have the verbosity option when calling the commands directly through the
cli_runner
?
Correct.
Instead of hotfixing it like this, I think we would need to find a more rigorous global solution
Happy to hear your suggestions.
The thing is that the verdi group stuff does not seem to be executed by the cli runner - either you need to force it to run that or you need to find another way to add the option (logically, however, I think the group is the right place to add it).
@@ -25,9 +26,11 @@ def setUp(self): | |||
def test_run_restapi(self): | |||
"""Test `verdi restapi`.""" | |||
|
|||
options = ['--no-hookup', '--hostname', 'localhost', '--port', '6000', '--debug', '--wsgi-profile'] | |||
cmd = VERBOSITY()(restapi) |
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.
See comment on test_node.py
aiida/cmdline/commands/cmd_code.py
Outdated
verbosity = 0 | ||
elif verbose: | ||
verbosity = 2 | ||
VERDI_LOGGER.setLevel('CRITICAL') |
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.
Should force=True
be interpreted as suppress all logging?
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'm just replicating the previous behavior here...
aiida/cmdline/commands/cmd_code.py
Outdated
@@ -175,33 +175,29 @@ def show(code, verbose): | |||
table.append(['Prepend text', code.get_prepend_text()]) | |||
table.append(['Append text', code.get_append_text()]) | |||
|
|||
if verbose: | |||
if VERDI_LOGGER.level <= LOG_LEVELS['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.
Hmm, this is a downside of the new solution that I didn't consider. Here the old paradigm of having an on/off switch was clearly superior. Now, one would have to look at the implementation to figure out that when passing --verbosity DEBUG
one gets the number of calculations done with the code. That is not very intuitive. Is there a way we can improve this?
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.
While I agree that this makes the if condition a bit longer here, I would like to point out that this occurs only in cases where it is not possible to express the logging logic via individual .info
or .debug
calls (which is possible in most cases).
Now, one would have to look at the implementation to figure out that when passing --verbosity DEBUG one gets the number of calculations done with the code. That is not very intuitive. Is there a way we can improve this?
At least to me, --verbosity DEBUG
seems more intuitive than --verbose 2
. Are you referring to the fact that by no longer having a dedicated --verbose
option, the documentation of the specific behavior for this command is lost?
If that is the problem, we could simply add the logging behavior to the documentation of the command itself, i.e. adding a sentence like
Add `-v DEBUG` to get the number of calculations done with the code.
(or try to override the help string of the --verbosity
option, but I would prefer the former).
@ltalirz maybe this is in one of the resolved conversations, but why did you decide against this? |
The main argument, IIRC, is that since we are tying the implementation to the logging system, with its predefined logging levels, it makes more sense to have the interface reflect the same thing. Otherwise, one would need some translation table of what Of course that raises the question whether the implementation should affect the UI that much, but then the question really becomes whether Python's logging system should be used for the problem that is being tackled here. Not sure what the answer is to be honest. |
and also, as we (me an Leo) just discussed, how do you handle interfacing with functions that are in some sense independent of the CLI ( |
I feel that makes sense from a developer perspective, but not necessarily from a user one, i.e. the user should not have to care about the underlying implementation |
See my comment just before yours:
I definitely agree that we shouldn't tie UI to implementation for that reason, but here it was a question about two different UI's, both of which have their downsides. The advantage of the That being said:
I think this is the real problem with this PR. As I already commented during the review, the fact that now the |
@sphuber Regarding your last point, chris and me discussed that indeed I will fix this for code that is not specific to the cli. The only question is: how? There are a couple of possibilities
|
@chrisjsewell For the discussion of One of the drawbacks of the |
Your two solutions are assuming that the TLDR: |
In some places they use |
yeh this seems the way to go |
Perhaps this may be of interest: https://github.com/sphinx-doc/sphinx/blob/0476e1cea93b587e3c0ab295aa20b2b9f0f81a34/sphinx/util/logging.py#L59 |
How about something like: @options.VERBOSITY(loggers=(VERDI_LOGGER, EXPORT_LOGGER))
# or
@options.VERBOSITY(additional_loggers=(EXPORT_LOGGER,)) i.e. allowing for multiple loggers to be set up with the verbosity level |
Not sure, this way it is easy to miss some logger that might be called downstream. I think instead the I can make an example implementation later maybe |
yeh it will probably be clearer then. For the |
So far, the verdi cli has been using a number of variants of click.secho in order to write information to the command line (e.g. echo_info(), echo_warning(), echo_critical(), ...). This automatically adds colored indicators for info/warning/... levels but offers no way to control which level of information is printed. For example, it is often useful to print information for debugging purposes, and so it would be useful to be able to specify a verbosity level when running verdi commands. Here, we use python's logging module to build a custom handler that outputs log messages via click. We also add a click VERBOSITY option that is applied automatically to all verdi commands. Its default verbosity level can be controlled via the new logging.verdi_loglevel configuration option. Note: The code added here is inspired by the click_log package (but needed to be modified in order to fit the needs of AiiDA). Co-authored-by: Sebastiaan Huber <[email protected]>
9b8f62f
to
665f922
Compare
Configuring loggersPerhaps it's helpful to take a step back first and write down what we want. GoalI think we want the following:
Status quo (in this PR)There are a few loggers around:
How to get thereI think we can achieve the goals stated above if we:
@sphuber @chrisjsewell Do you agree? Edit: Finally, I propose to rename the verdi logger to |
Let CMDLINE_LOGGER inherit from AIIDA_LOGGER in order to be able to set the verbosity level globally.
It basically works, only that I'm currently still setting the the level of the If verdi output is routed through loggers, I think it makes sense to move the configuration of the loggers to an earlier point in the call graph. Just to be sure this does not result in slowing things down, I checked the speed of this function - it seems reasonable: In [1]: from aiida.common.log import configure_logging
In [2]: %timeit configure_logging()
1.31 ms ± 65 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) |
Here is a summary of a design meeting of August 16th 2021 with @ramirezfranciscof @chrisjsewell @ltalirz and yourstruly. We decided to start with the discussion on the implementation, since this would like influence the interface, even though typically directly tying a user interface to implementation details is ill-advised. ImplementationDesign considerationsThe control of the verbosity of output generated by CLI commands should not merely affect the output directly generated by the command itself, but also that of all output that is generated by the module code that it calls. This means that it should control the logging, which is the recommended way of outputting information for module code. It therefore seems most natural to use the same mechanism for the output produced directly by the CLI command, and so also have that go through the Logging and the
|
@chrisjsewell @ltalirz @ramirezfranciscof See the above comment with a summary of our discussion and decision. I am sure I may have forgotten some details. In that case, please report them below and I will update the post. At some point, we should probably refine it a bit more and put it in the documentation under the "Architecture" section as documentation of this design process. |
Superseded by #5085 |
fix #3864
fix #4330
So far, the verdi cli has been using a number of variants of
click.secho in order to write information to the command line
(e.g. echo_info(), echo_warning(), echo_critical(), ...).
This automatically adds colored indicators for info/warning/... levels
but offers no way to control which level of information is printed.
For example, it is often useful to print information for debugging
purposes, and so it would be useful to be able to specify a verbosity
level when running verdi commands.
Here, we use python's logging module to build a custom handler that
outputs log messages via click.
We also add a click VERBOSITY option that can be added to any command,
which allows to specify the verbosity of the logger.
Note: The code added here is inspired by the click_log package (but
needed to be modified in order to fit the needs of AiiDA).
Todo
verdi -v DEBUG profile list
vsverdi profile list -v DEBUG
)-v DEBUG
vs-v -v -v
etc.)echo_debug
function that simply usesCLI_LOGGER.debug
. Perhaps cleaner than mixing echo and direct logging (?)options.VERBOSE
andoptions.DEBUG
verdi
command already has a-v
option, namely-v/--version
. By adding the-v/--verbosity
option only at the subcommand level, we avoid clashes but there is a minor potential for confusion. I personally find it acceptable