Create the Logging and Output guidelines#4935
Conversation
There was a problem hiding this comment.
Code Review
This pull request adds a new 'Logging and Output' section to the contribution documentation (docs/contribute.rst) to clarify the distinction between logging (stderr) and output (stdout), and to define verbosity and debug levels. Feedback recommends formatting the logging method names as inline literals for consistent rendering, and adding a note to clarify that using the level parameter with info() is a planned target state, as the current implementation requires using verbose() instead.
| * ``info()`` / level 0 — key output: plan names, step names, | ||
| phase summary, overall summaries | ||
| * ``info(level=1)`` — specific info: individual test names in | ||
| ``discover`` and ``execute`` |
There was a problem hiding this comment.
The separation between these 2 is still vague in the wording. I don't feel like I can answer yet when a potentially loggable output should be:
- info0
- info1
- moved to debug
- not logged at all
Let me give a concrete snippet
tmt/tmt/steps/prepare/artifact/providers/repository.py
Lines 82 to 83 in bae12b9
There was a problem hiding this comment.
The two levels are actually described using the current tmt run behavior. Overal summaries versus listing individual tests. If you have more tangible examples at hand, please suggest them.
There was a problem hiding this comment.
If you have more tangible examples at hand, please suggest them.
What is wrong with the example snippet given above?
There was a problem hiding this comment.
I mean, example of how to better write the summary, for those two levels.
There was a problem hiding this comment.
Well, first is the question of what to do in that example case. Because I do not know how it should be handled and as such I don't know what info0 and info1 should have
There was a problem hiding this comment.
After reading the level summaries...
self.logger.info(f"Reading repository file from local path: {parsed_path}")
seems like this one should be log level 1
self.logger.debug(f"Absolute path of the repository file: '{parsed_path.resolve()}'")
This one should be debug level 2
If those choices seem wrong, then maybe the summary for those two levels could be changed 😆
There was a problem hiding this comment.
@LecrisUT, do you mean adding some user guidance like the following?
When deciding where to place a new message, ask from the user's perspective:
- Would a user running plain
tmt runneed this to understand what is happening? ...info()(level 0) - Is it useful when the user wants more detail about individual items (tests, guests, packages, plugins)? ...
info(level=1) - Does it help investigating results after the run (log paths, guest facts)? ...
info(level=2) - Is it full command or test output? ...
info(level=3) - Would only a tmt developer care? ...
debug()
For the two examples above I would probably use this:
self.logger.info(f"Reading repository file from local path: {parsed_path}", level=2)
self.logger.debug(f"Absolute path of the repository file: '{parsed_path.resolve()}'", level=3) There was a problem hiding this comment.
Thanks for adding that section LGTM
There was a problem hiding this comment.
For the two examples above I would probably use this:
self.logger.info(f"Reading repository file from local path: {parsed_path}", level=2) self.logger.debug(f"Absolute path of the repository file: '{parsed_path.resolve()}'", level=3)
Well, that confuses me more. My reading of the info2 was that, "here is where you can find more logs" and info3 "here is the contents that you would find in that log". I liked how those 2 were very narrow in their definition.
Now the usage of info2 in the snippet above does not make sense in that scope anymore. The word "path" is there, but it is not an extra path where you can find more info, it is an input. Does not even fit into
- Does it help investigating results after the run (log paths, guest facts)? ...
info(level=2)
To me this should either be
info("repository path", parsed_path, level=1)or dropped altogether as it is already stating what is in the provide key.
My issue with the current guideline is:
- We are not strict on what is a useful output for the user. The first question we should be asking is does it even belong to
info - We are too loose on the format we use. If the info cannot be formatted in the prescribed format, we should be reconsidering if we should even be logging it.
- The difference between info0 and info1 is still to vague, anything can be either "more detail" or something that "user needs"
- If we open the gate for info2 to be broad beyond the logs, we will have the same issues as above. Right now it is very narrow "logs" (and "guest facts", sure why not)
- Giving a name to the grouping I don't think it helps as these are too vague in what they can contain. It is fine to have it, but that is not helping with the disambiguation of what should be where.
- Whatever is in the current info/verbosity levels should not be guiding how we define these groups. If we cannot make a clear grouping definition, then I do not think the grouping were defined well in the first place and we should try another angle
Here is my shot at a grouping
- info3: command outputs, rendered script, other constructed input
- info2: log paths, links, external sources
- info1: phase inputs (static and dynamic ones), guest facts, phase outputs
- info0: current state progress of step and phase, and their summaries
The difference in the examples you have there is guest facts can either be an info1 or info2, I am fine with either. Everything else fits in the same place, e.g. tests that are run are the output of discover and input of execute.
For the Reading repository file from local path: {parsed_path} example, this can be converted to a format of dynamic input of the artifact provider (not a phase), or moved to debug
6f280e7 to
5c2880e
Compare
e2aa8e1 to
c31c597
Compare
| * ``info()`` / level 0 — key output: plan names, step names, | ||
| phase summary, overall summaries | ||
| * ``info(level=1)`` — specific info: individual test names in | ||
| ``discover`` and ``execute`` |
There was a problem hiding this comment.
Well, first is the question of what to do in that example case. Because I do not know how it should be handled and as such I don't know what info0 and info1 should have
Add a new section defining the individual output types and individual verbosity levels. Describes the target state to which we want to get.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Cristian Le <github@lecris.me>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
c31c597 to
fdf4cb0
Compare
Add a new section defining the individual output types and individual verbosity levels. Describes the target state to which we want to get.
Fix #4814.
Pull Request Checklist