Skip to content
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

Merged
merged 17 commits into from
Oct 24, 2024
Merged

Conversation

Venefilyn
Copy link
Member

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

  • PR has been tested manually in a VM (either author or reviewer)
  • Jira issue has been made public if possible
  • [RHELC-] or [HMS-] is part of the PR title
  • GitHub label has been added to help with Release notes
  • PR title explains the change from the user's point of view
  • Code and tests are documented properly
  • The commits are squashed to as few commits as possible (without losing data)
  • When merged: Jira issue has been updated to Release Pending if relevant

convert2rhel/logger.py Fixed Show fixed Hide fixed
@@ -136,6 +136,7 @@ def main_locked():
initialize_file_logging("convert2rhel.log", logger_module.LOG_DIR)

try:
logger_module.ConversionStage.set_stage("prepare")
Copy link
Member

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

Copy link
Member Author

@Venefilyn Venefilyn Sep 12, 2024

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>

Copy link
Member

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.

Copy link
Member

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.

Copy link
Member Author

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

# 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"),)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ROLLBACK = (ConversionPhase(name="ROLLBACK", log_name="Rollback"),)
ROLLBACK = ConversionPhase(name="ROLLBACK", log_name="Rollback")

Copy link

codecov bot commented Sep 18, 2024

Codecov Report

Attention: Patch coverage is 79.72973% with 30 lines in your changes missing coverage. Please review.

Project coverage is 96.09%. Comparing base (d603f04) to head (943cec0).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
convert2rhel/phase.py 57.69% 18 Missing and 4 partials ⚠️
convert2rhel/main.py 82.35% 2 Missing and 4 partials ⚠️
convert2rhel/logger.py 66.66% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1373      +/-   ##
==========================================
- Coverage   96.59%   96.09%   -0.51%     
==========================================
  Files          71       72       +1     
  Lines        5113     5174      +61     
  Branches      883      896      +13     
==========================================
+ Hits         4939     4972      +33     
- Misses         98      119      +21     
- Partials       76       83       +7     
Flag Coverage Δ
centos-linux-7 91.61% <78.47%> (-0.46%) ⬇️
centos-linux-8 92.46% <79.16%> (-0.47%) ⬇️
centos-linux-9 92.59% <79.72%> (-0.46%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Venefilyn Venefilyn added the tests/sanity PR ready to run the sanity test suit. Equivalent to `/packit test --labels sanity`. label Sep 19, 2024
@has-bot
Copy link
Member

has-bot commented Sep 19, 2024

/packit test --labels sanity


Comment generated by an automation.

@Venefilyn
Copy link
Member Author

/packit test --labels sanity

2 similar comments
@Venefilyn
Copy link
Member Author

/packit test --labels sanity

@Venefilyn
Copy link
Member Author

/packit test --labels sanity

@Venefilyn Venefilyn force-pushed the refactor/logger-stages branch 2 times, most recently from 00ec140 to e7f77f1 Compare September 20, 2024 14:32
@Venefilyn
Copy link
Member Author

/packit test --labels sanity

@Venefilyn
Copy link
Member Author

/packit build

@Venefilyn
Copy link
Member Author

/packit test --labels sanity

@Venefilyn Venefilyn marked this pull request as ready for review September 23, 2024 09:31
@Venefilyn Venefilyn requested a review from a team as a code owner September 23, 2024 09:31
@Venefilyn
Copy link
Member Author

/packit test --labels sanity

"""

POST_CLI = ConversionPhase(name="POST_CLI")
PREPARE = ConversionPhase(name="PREPARE", log_name="Prepare")
Copy link
Member

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).

Copy link
Member Author

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

Copy link
Member

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

@hosekadam
Copy link
Member

/packit test --labels sanity

Copy link
Member

@hosekadam hosekadam left a 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.

@hosekadam
Copy link
Member

/packit test --labels sanity

@Venefilyn
Copy link
Member Author

/packit test

@Venefilyn Venefilyn requested a review from a team as a code owner October 19, 2024 18:12
@Venefilyn
Copy link
Member Author

/packit test

1 similar comment
@Venefilyn
Copy link
Member Author

/packit test

Copy link
Member

@SerCantus SerCantus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look great!
I see the integration tests are failing and some of them related to the expected messages, maybe something got messed up? I can't see it. For example in integration tests in CentOS7 it expects to see CUSTOM_REPOSITORIES_ARE_VALID::UNABLE_TO_ACCESS_REPOSITORIES but instead C2R fails with:

convert2rhel("-y --no-rhsm --enablerepo fake-rhel-8-for-x86_64-baseos-rpms --debug", unregister=True)

(ERROR) REMOVE_SPECIAL_PACKAGES::SPECIAL_PACKAGE_REMOVAL_FAILED - Failed to
remove some packages necessary for the conversion.
Description: The cause of this error is unknown, please look at the
diagnosis for more information.
Diagnosis: Couldn't download the centos-
release-7-9.2009.2.el7.centos.x86_64 package. This means we will not be able to
do a complete rollback and may put the system in a broken state.
Check to make sure that the CentOS Linux repositories are enabled and the
package is updated to its latest version.

@Venefilyn
Copy link
Member Author

The changes look great! I see the integration tests are failing and some of them related to the expected messages, maybe something got messed up? I can't see it. For example in integration tests in CentOS7 it expects to see CUSTOM_REPOSITORIES_ARE_VALID::UNABLE_TO_ACCESS_REPOSITORIES but instead C2R fails with:

convert2rhel("-y --no-rhsm --enablerepo fake-rhel-8-for-x86_64-baseos-rpms --debug", unregister=True)

(ERROR) REMOVE_SPECIAL_PACKAGES::SPECIAL_PACKAGE_REMOVAL_FAILED - Failed to
remove some packages necessary for the conversion.
Description: The cause of this error is unknown, please look at the
diagnosis for more information.
Diagnosis: Couldn't download the centos-
release-7-9.2009.2.el7.centos.x86_64 package. This means we will not be able to
do a complete rollback and may put the system in a broken state.
Check to make sure that the CentOS Linux repositories are enabled and the
package is updated to its latest version.

@SerCantus is it occurring in other PRs or in main?

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 <[email protected]>
Signed-off-by: Freya Gustavsson <[email protected]>
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 <[email protected]>
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 <[email protected]>
Signed-off-by: Freya Gustavsson <[email protected]>
Signed-off-by: Freya Gustavsson <[email protected]>
Signed-off-by: Freya Gustavsson <[email protected]>
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
@Venefilyn
Copy link
Member Author

/packit test

@SerCantus
Copy link
Member

SerCantus commented Oct 24, 2024

@SerCantus is it occurring in other PRs or in main?

@Venefilyn I commented after reviewing this PR checks but I see other PRs have similar failures so it might not be caused by this one. After discussing, it might be related to some infra.

@Venefilyn
Copy link
Member Author

Ack, feel free to approve and merge with squash

Copy link
Member

@danmyway danmyway left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test failures unrelated.
There is a regression caused by #1288 reported under RHELC-1753

@danmyway danmyway merged commit 261d533 into oamg:main Oct 24, 2024
45 of 53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/refactor merge-after-tests-ok tests/sanity PR ready to run the sanity test suit. Equivalent to `/packit test --labels sanity`.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants