-
Notifications
You must be signed in to change notification settings - Fork 84
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
refactor: Improved logger usage #1373
base: main
Are you sure you want to change the base?
Conversation
8d7ce2b
to
b48acf3
Compare
convert2rhel/main.py
Outdated
@@ -136,6 +136,7 @@ def main_locked(): | |||
initialize_file_logging("convert2rhel.log", logger_module.LOG_DIR) | |||
|
|||
try: | |||
logger_module.ConversionStage.set_stage("prepare") |
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 using ConversionPhase
for this? I think it could be really good to map the phases in that class to the ConversionStage
you created
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.
@r0x0d That's a good point. Though that made me dig down a rabbit hole of refactoring to be a bit nicer to use for more scenarios. What do you think of this?
class ConversionPhase:
"""Conversion phase to hold name and logging-friendly name.
"""
def __init__(self, name, log_name=None): # type: (str, str|None) -> None
self.name = name
self.log_name = log_name
def __str__(self):
return self.log_name
def __repr__(self):
return self.name
def __hash__(self) -> int:
return hash(self.name)
class ConversionPhases(dict):
"""During conversion we will be in different states depending on
where we are in the execution. This class establishes the different phases
that we have as well as what the current phase is set to.
"""
_phases = [
ConversionPhase(name="POST_CLI", log_name="Prepare"),
ConversionPhase(name="PRE_PONR_CHANGES", log_name="Prepare")
]
current_phase = None # type: ConversionPhase|None
def __getitem__(self, key): # type: (str) -> ConversionPhase|None
return next(phase for phase in self._phases if phase.name == key )
@classmethod
def set_stage(cls, phase): # type: (str) -> None
if phase is None or phase in cls._phases:
cls.current_phase = cls._phases[phase]
raise NotImplementedError("The stage {} is not implemented in the ConversionStage class".format(phase))
test = ConversionPhases()
print(test["POST_CLI"].__repr__)
$ python test.py
<bound method ConversionPhase.__repr__ of POST_CLI>
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.
Hmmm, this work as well, but it is easy to introduce an error if we miss the correct naming in other parts of the code or introduce a new phase and forget about it.
I was thinking in something more simple, like this:
class ConversionPhase:
POST_CLI = 1
# PONR means Point Of No Return
PRE_PONR_CHANGES = 2
# Phase to exit the Analyze SubCommand early
ANALYZE_EXIT = 3
POST_PONR_CHANGES = 4
class ConversionStage:
stages = {
ConversionPhase.PRE_PONR_CHANGES: "Prepare",
ConversionPhase.POST_PONR_CHANGES: "Final",
...
}
current = None # type: str|None
@classmethod
def set_stage(cls, stage): # type: (str) -> None
if stage == None or stage in cls.stages:
cls.current = cls.stages[stage]
raise NotImplementedError("The stage {} is not implemented in the ConversionStage class".format(stage))
Then, when we initialize the ConversionStage
, we could just simply:
logger_module.ConversionStage.set_stage(ConversionPhase.PRE_PONR_CHANGES)
And then we have it mapped everywhere that PRE_PONR_CHANGES
matches the Prepare
or something else. The interface will still look clean enough in the new class, and we will make sure that if someone changes the meaning for any of those phases, we will catch somewhere as well.
Since our use case is so small for now, I think that reusing the phases from ConversionPhase
should be good enough.
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 our ConversionPhase
class should hold the information where we are in the process at all times, being our source of truth for many different operations. It is true that logging phases may differ from execution phases, but if that's really the case, then we could come up with an intermediate class that will hold the logging phases for us, tied to the conversion phase if necessary.
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.
Ah I didn't see this as I got hyperfocused on overcomplicating the solution... but anyhow I did change it now to be a bit safer but in a way that means we still rely on strings. But given exceptions being raised we should catch it in tests if we do a mistake
b48acf3
to
8002f6a
Compare
8002f6a
to
034d54a
Compare
034d54a
to
ba181c1
Compare
convert2rhel/utils/phase.py
Outdated
# Phase to exit the Analyze SubCommand early | ||
ANALYZE_EXIT = ConversionPhase(name="ANALYZE_EXIT") | ||
POST_PONR_CHANGES = ConversionPhase(name="POST_PONR_CHANGES", log_name="Convert") | ||
ROLLBACK = (ConversionPhase(name="ROLLBACK", log_name="Rollback"),) |
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.
ROLLBACK = (ConversionPhase(name="ROLLBACK", log_name="Rollback"),) | |
ROLLBACK = ConversionPhase(name="ROLLBACK", log_name="Rollback") |
ba181c1
to
183d94a
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1373 +/- ##
==========================================
- Coverage 96.58% 96.07% -0.51%
==========================================
Files 71 72 +1
Lines 5090 5151 +61
Branches 880 893 +13
==========================================
+ Hits 4916 4949 +33
- Misses 98 119 +21
- Partials 76 83 +7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
e272c18
to
3c97895
Compare
/packit test --labels sanity |
2 similar comments
/packit test --labels sanity |
/packit test --labels sanity |
00ec140
to
e7f77f1
Compare
/packit test --labels sanity |
/packit build |
/packit test --labels sanity |
/packit test --labels sanity |
""" | ||
|
||
POST_CLI = ConversionPhase(name="POST_CLI") | ||
PREPARE = ConversionPhase(name="PREPARE", log_name="Prepare") |
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 just wonder, when we are changing the logging and the final is renamed to convert (which makes sense to me) - what about changing the Prepare
to Analysis
(or something like that)? I think it would be nice to have it matching the subcommands (analyze and convert).
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.
Agreed and I had that before, but I wanted minimal changes in this PR to the actual logs so wanted it to remain the same. We can change it in a follow-up PR but requires a bit more discussion IMO
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.
Okay. Maybe if we want minimal changes, then I would change the name of the post_conversion to the Final
to be consistent
/packit test --labels sanity |
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 good, just wait till the infrastructure problems are resolved and try the sanity tests.
/packit test --labels sanity |
Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
This refactors the logging stages that we output when we log in specific files depending on what we are doing. Meaning that any changes that has to do with preparing or rollback will now output the stage within the logger formatter rather than leaving it up to each class E.g. any logs with "Prepare: text" or "Rollback: text" will now be handled at the log-level Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
This removes all the different task log calls that include the stage it should be in and instead relies on the logger to take care of it e.g. `.task("Convert: ...")` will now have `Convert:` removed Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
ConversionPhases is now moved outside of utils module so that it doesn't cause a circular import with logger module Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
Signed-off-by: Freya Gustavsson <freya@spytec.se> Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
Signed-off-by: Freya Gustavsson <freya@venefilyn.se>
We didn't know what phase we were on before going into rollback. With this change it now keeps a (soft) linear history where each phase points to the previous one
dff0124
to
d791d5f
Compare
/packit test --labels sanity |
1 similar comment
/packit test --labels sanity |
/packit test --labels sanity |
1 similar comment
/packit test --labels sanity |
/packit test |
/packit test |
1 similar comment
/packit test |
This refactor of the usage of our logging is to get away from custom
functions that causes attribute errors in editors and IDEs. This will
also standarize the usage of logger and the loglevels.
In future PRs we can include changes to include prepare, rollback, and
final specific message styles.
Jira Issues:
Depends on
Checklist
[RHELC-]
or[HMS-]
is part of the PR titleRelease Pending
if relevant