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

Improve logger class #112

Merged
merged 33 commits into from
Jan 29, 2025
Merged

Improve logger class #112

merged 33 commits into from
Jan 29, 2025

Conversation

blakejameson
Copy link
Contributor

I removed the error_print() calls that were previously in pysquared.py. Error_count became a property of the Logger object. With the move to the Logger, it still remained as an nvm Counter object.

I added 2 new fields to the config.json, log_level and log_mode; I removed the debug field

I removed the debug parameter from Face, AllFaces, and Field. Being that the debut property or rather now the 'log_level' state is managed by the logger, there is no need for those classes to have a debug property and check for 'if debug', as that functionality is provided by the Logger

I can confirm I ran the code on a v4b board and saw similar output to what is currently in main, the only difference being the improved Logger error calls with cleaner output than previous.

@blakejameson blakejameson requested review from nateinaction and a team January 26, 2025 21:45
@blakejameson blakejameson linked an issue Jan 26, 2025 that may be closed by this pull request
2 tasks
@Mikefly123
Copy link
Member

Hey Blake! These changes look solid to me. I noticed that the new SonarCloud check is failing though, and I believe it's on a part of the code on main that was brought in by @dbgen1 in #96.

image

Seems to be a pretty straightforward fix to me. Not sure if we want to capture it in this PR or make a unique patch for it on main.

@blakejameson
Copy link
Contributor Author

Hey Blake! These changes look solid to me. I noticed that the new SonarCloud check is failing though, and I believe it's on a part of the code on main that was brought in by @dbgen1 in #96.

image

Seems to be a pretty straightforward fix to me. Not sure if we want to capture it in this PR or make a unique patch for it on main.

Appreciate you taking the time to look things over Michael

With the earlier commit, some pytests were failing due to me not using a mock for the byte array. With @nateinaction 's help, he guided me to steps I needed to take to address the pytest errors. Now the tests are passing,
but it turns out the adding self to line 67 wasn't sufficient for the SonarCloud analysis, as it now shows 6 resulting errors from my change. I will need to explore how to address this

@blakejameson
Copy link
Contributor Author

Hey Blake! These changes look solid to me. I noticed that the new SonarCloud check is failing though, and I believe it's on a part of the code on main that was brought in by @dbgen1 in #96.
image
Seems to be a pretty straightforward fix to me. Not sure if we want to capture it in this PR or make a unique patch for it on main.

Appreciate you taking the time to look things over Michael

With the earlier commit, some pytests were failing due to me not using a mock for the byte array. With @nateinaction 's help, he guided me to steps I needed to take to address the pytest errors. Now the tests are passing, but it turns out the adding self to line 67 wasn't sufficient for the SonarCloud analysis, as it now shows 6 resulting errors from my change. I will need to explore how to address this

@Mikefly123 @nateinaction
I was just now able to get things passing the Sonar check just now by putting '@ staticmethod' above the safe_init function definition

@blakejameson blakejameson self-assigned this Jan 27, 2025
@blakejameson blakejameson added the enhancement New feature or request label Jan 27, 2025
@blakejameson
Copy link
Contributor Author

@nateinaction after rebasing 10 minutes ago, I tried running the code again on the board just to verify things still worked.

Screenshot 2025-01-28 at 12 53 12 PM

I got hit with the error above. Adding static_method above the safe_init function is how I resolved the Sonar errors a few days back.

I tested the code on the FC board after adding static_method 2 days ago, but now I realize I obviously messed up by either dragging an older version of pysquared.py or being on the wrong branch. Anyways, dealing with the Sonar errors for this safe_init function will likely take some refactoring of the safe_init functions because using the 'self' or 'cls' keyword didn't fix things.

I am curious to know if you'd be open to reviewing this PR (with Sonar errors) and allowing the changes to be merged in on potential approval and if we could dedicate another issue towards fixing the Sonar errors resulting from the safe_init functions. Let me know what your thoughts are

@blakejameson
Copy link
Contributor Author

blakejameson commented Jan 28, 2025

@nateinaction Apologies if this whole sequence is a lot to read through, but I went ahead and put back a parameter in the safe_init function of 'error_severity'. During my PR initially, I removed this parameter because it isn't needed. The logger outputs the severity so this string is unnecessary. However, for whatever reason, having this parameter in the function allows for no Sonar errors, though it marks it as an issue.

All that being said, I confirm I ran the code on an v4b FC board and the output is similar to main branch
The code is ready for review

@Mikefly123
Copy link
Member

@blakejameson what if we just passed self in the safe_init() definition? That was one of the recommendations SonarCloud was giving to fix the issue, and it feels better than putting an unused parameter there.

@dbgen1
Copy link
Contributor

dbgen1 commented Jan 28, 2025

Hi there, if you want to remove the error severity, there is actually no need for an additional layer to the decorator. The decorator currently consist of:

  • a inner function "wrapper" which wraps the hardware initialization function
  • a "decorator" which allows the wrapper to be applied to any function with the @ symbol,
  • and a "decorator factory" (safe_init). The only purpose of the decorator factory is to allow arguments in a decorator, so if there is no error severity, this layer is not needed.

Theoretically, all the problems can be solved by simply removing the outer layer and renaming decorator to safe_init. Feel free to try it yourself, or if you are okay with it, I can commit a fix for this to this branch in a few hours!

@blakejameson
Copy link
Contributor Author

@Mikefly123 I am unable to see the Sonar reports before the most recent, but when I followed the recommendation of putting 'self', it resulted in 6 errors for the functions that used the decorator. I commented about it higher up in this thread

@blakejameson
Copy link
Contributor Author

@dbgen1 Thank you for explaining Davit.
And if it's alright, I will let you commit the fix in a few hours. The world of decorators and wrappers is something I honestly haven't learned yet, so I am going to hold off in fear of still messing things up despite your excellent instructions

@dbgen1
Copy link
Contributor

dbgen1 commented Jan 28, 2025

@blakejameson Ready to go!

@blakejameson
Copy link
Contributor Author

@dbgen1 Thank you so much for the fix!!

I just ran the code on a v4b board and things worked normal

@nateinaction After Davit's help in fixing the Sonar errors with safe_init, I can now hopefully say for the last time that the code is now ready for review

lib/pysquared/logger.py Outdated Show resolved Hide resolved
main.py Outdated Show resolved Hide resolved
lib/pysquared/logger.py Outdated Show resolved Hide resolved
@@ -3,15 +3,51 @@
Logs can be output to standard output or saved to a file (functionality to be implemented).
"""

# NVM register number
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
# NVM register number

lib/pysquared/pysquared.py Outdated Show resolved Hide resolved
lib/pysquared/logger.py Outdated Show resolved Hide resolved
self.logToStandardOut: bool = True
self.error_count: Counter = Counter(index=ERRORCNT, datastore=self.datastore)
Copy link
Member

Choose a reason for hiding this comment

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

Ok, looking at this now. I think I might have given bad advice. Instantiating this class inside the logger constructor doesn't feel right and violates our desired state of having a dependency injection framework. I think the logger interface in main and repl might instead be better off looking like:

logger: Logger = Logger(
    counter=Counter(index=ERRORCNT, datastore=self.datastore)
)

What do you think about trying to implement it that way?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am down for that!

Copy link
Member

Choose a reason for hiding this comment

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

I don't have a finger on the scale in terms of design here, so up to you guys how to implement this! I did want to comment just to say this was the first time I had heard of a dependency injection framework, so I had to educate myself about it real quick.

I can definitely see the merits and how this is building toward's Nate's vision of having much more modular code vs the doom stack that pysquared.py and its children have been. I think there's perhaps an interesting paper here to write about how flight software gets written when your team isn't traditionally trained in embedded software engineering. It feels like the approaches are going to end up being quite a bit different!

Copy link
Member

Choose a reason for hiding this comment

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

@Mikefly123 Isn't that a cool idea? Maybe not so surprisingly that's exactly what FPrime does. In addition to many other cool things, it's is a dependency injection framework building all objects it will ever need on start.

@@ -24,35 +60,39 @@ def _log(self, level: str, message: str, **kwargs) -> None:

json_output = json.dumps(kwargs)

if self.logToStandardOut:
if self.logToStandardOut and self.can_print_this_level(level_value):
print(json_output)
Copy link
Member

Choose a reason for hiding this comment

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

If we so fancied we could return the debug color stuff here haha. Maybe something for a future PR

Copy link
Member

Choose a reason for hiding this comment

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

Yeah! We talked about using the color interface from loguru as a guide for how we might reimplement it in our new logger. 🚀

@@ -16,20 +16,20 @@
from lib.pysquared.config import Config
from lib.pysquared.logger import Logger

logger = Logger()

logger: Logger = Logger(microcontroller.nvm)
logger.info("Booting", software_version="2.0.0", published_date="November 19, 2024")
Copy link
Member

Choose a reason for hiding this comment

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

This statement should actually probably be updated in each new PR to reflect this week's latest software version and the date that the PR was made ready for review. I think it's handy so users have an idea of what software they're running.

For this PR the version would be for V2.0.0-alpha-25w05 Pre-Release.

Copy link
Member

@nateinaction nateinaction Jan 29, 2025

Choose a reason for hiding this comment

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

I think I can solve for versioning in the build step soon!

Copy link
Member

Choose a reason for hiding this comment

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

Will be very excited to see that come in!

lib/pysquared/logger.py Outdated Show resolved Hide resolved
Comment on lines 12 to 15
class LogMode:
PRINT = 1
FILE = 2
BOTH = 3
Copy link
Member

Choose a reason for hiding this comment

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

Since LogMode is not fully implemented do you want to remove references to it in this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

great idea

Comment on lines 34 to 37
self.log_to_standard_out: bool = True
self.error_counter: Counter = error_counter
self.log_level: int = log_level
self.log_mode: int = log_mode
Copy link
Member

Choose a reason for hiding this comment

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

Since we don't want users to be able to modify these class member vars after they are set by the constructor, let's mark them as private by prefixing them with _.

Also ref the comment above about implementing log mode in a later PR we could remove self.log_to_standard_out and self.log_mode for this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for this call out

Comment on lines 89 to 90
def get_error_count(self) -> int:
return self.error_counter.get()
Copy link
Member

Choose a reason for hiding this comment

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

It looks like this isn't used anywhere but if we make the class member vars private then we will need this getter.

…d, AllFaces, Faces, and other places. As the debug mode functionality is now originating in the Logger class, there is no need for extra debug variables. All debug or rather logmode and log levels will stem from the Logger
lib/pysquared/logger.py Outdated Show resolved Hide resolved
lib/pysquared/logger.py Outdated Show resolved Hide resolved
@blakejameson blakejameson merged commit ddb2f51 into main Jan 29, 2025
4 checks passed
@blakejameson blakejameson deleted the improve-logger-class branch January 29, 2025 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve Logger class
5 participants