Add a Logger class to centralize Log Management#95
Conversation
This error logger will be used to report all errors, warnings, info, etc. This is useful becasue it standardizes how information is reported to the output console and will allow error messages to be labled and ranked on importance.
All print statements in the project have been made to be more useful and more organized by using the Logger class.
HirdayGupta
left a comment
There was a problem hiding this comment.
Hey! Sorry for the delayed response, great job adding in the new class and calling it instead of all of our (overly generous) uses of the print statement! I think I agree with your ErrorType classifications on most of the print statements you replaced.
Leaving some requested changes that are mainly aesthetic in nature. Great work otherwise!
| } | ||
|
|
||
| class Logger { | ||
| static let shared = Logger() |
There was a problem hiding this comment.
@kamalca @ayush-patel Do you foresee the Logger class ever having a state of its own? (I.e. its own private data). It doesn't right now, and if that isn't something that we foresee, then we can change this from a Singleton class to just a class with static functions. (UPDATE: I don't think its ever going to have a state of its own in the foreseeable future, so go with the static approach please)
That change would involve changing all the (one) functions to static and removing the static let shared singleton (because all function calls would be through a static function).
This means that all calls to this class will now look like this: Logger.handle(type: message:)
|
|
||
| private init() { } | ||
|
|
||
| func handle(type:ErrorType, message:String) { |
There was a problem hiding this comment.
Suggest changing the method name & using function argument labels to modify the function signature to the following: (and using static to abide by the previous suggestion)
static func log(message: String, ofType type: ErrorType)This and the switch from singleton to static would mean that calls to this function would now look like:
Logger.log(message: "Hi! I'm an error!", ofType: .error)An alternate is dropping the label for message entirely, so the function definition would look like this:
static func log(_ message: String, withType type: ErrorType)Now, this change and the switch from singleton to static would mean that calls to this function would now look like:
Logger.log("Hi! I'm an error!", withType: .error)I'm in favor of the second one because the function name log, implies the verb, and hence, the label message for the first argument is kind of implied, because what else would you be logging lol. (EDIT: @kamalca let me know which alternative you prefer, and if you agree with the second one, go ahead and implement it!)
Side note: This may seem trivial, but think about it this way - the interface you are designing now is going to be used across the app for many more versions to come. Plus, our code could do with some beauty 😄
| @@ -0,0 +1,37 @@ | |||
| // | |||
| // ErrorLogger.swift | |||
There was a problem hiding this comment.
Rename the file to LogManager.swift and move it from the Models folder to a new folder called Managers.
|
|
||
| import Foundation | ||
|
|
||
| enum ErrorType: String { |
There was a problem hiding this comment.
Rename this to LogLevel (because names like ErrorType should be reserved for our Centralised Error Handling mechanism, whenever we get to it).
When you do make this change, you should also replace the word 'type' from the argument name and labels in the handle function to 'level'.
|
|
||
| func handle(type:ErrorType, message:String) { | ||
|
|
||
| if(message == "") |
| let results = try JSONDecoder().decode(MatchRequestData.self, from: response.data) | ||
| let jsonData = JSON(response.data) | ||
| print(jsonData) | ||
| Logger.shared.handle(type: .debug, message: "matchUser JSON data: \(jsonData)") |
There was a problem hiding this comment.
Good precedent for the .debug type!
| Logger.shared.handle(type: .error, message: "matchUser: \(err)") | ||
| } | ||
| print("Successfully Sent match") | ||
| Logger.shared.handle(type: .verbose, message: "Successfully Sent match") |
| self.topBar.timeSelected("Night") | ||
| default: | ||
| print("Current Meal Period could not be determined") | ||
| Logger.shared.handle(type: .error, message: "Current Meal Period could not be determined") |
There was a problem hiding this comment.
Can you reconfirm if this needs to be .error or if we can change it to .warning (read the aforementioned descriptions for the intention of each type, basically, if the meal period not being determined breaks things in a very noticeable fashion then leave it as .error but if not, and its a minor inconvenience, then change to warning)
There was a problem hiding this comment.
I believe this wold result in the behavior we were seeing last year where the menu would not load until you clicked on a different time. However, this switch statement covers all possible values of hour from zero (inclusive) to 24 (exclusive). Therefore the error is more of a formality. I can switch it to warning though.
| } | ||
| } else { | ||
| print("No meal period selected") | ||
| Logger.shared.handle(type: .warning, message: "No meal period selected") |
There was a problem hiding this comment.
Confirm if this needs to be .error or can stay as a .warning
There was a problem hiding this comment.
This warning/error occurs when someone tries to select a time before selecting a meal period. The resulting behavior is simply a popup that is not populated with times. I would not consider it a fatal error by any means. I suggest keeping it a warning and later alerting the user to this error when they attempt to put in a time before the meal period.
|
@kamalca When there are many requested changes, Github hides some of the requested changes by default, so be sure to click the |
Carried out the changes requested by @HirdayGupta -- • Static functions instead of a singleton • Changed parameter names and function name from handle to log • Changed file from ErrorLogger to LogManager • Changed enumeration name from ErrorType to LogLevel • Removed raw values from enumeration and added a function to determine the header • Added documentation to enumeration • Revised some log messages and log levels
| print("Device Token: \(token)") | ||
| print(token) | ||
| Logger.log("Device Token: \(token)", withLevel: .debug) | ||
| Logger.log(token, withLevel: .debug) |
There was a problem hiding this comment.
Should be safe to remove Line 90 because its a repeat.
|
|
||
| class Logger { | ||
|
|
||
| private init() { } |
There was a problem hiding this comment.
Can remove the private initializer because an initialized Logger class has no use if all its functions are static (so even if a dev was to initialize a Logger object, it would be useless).
HirdayGupta
left a comment
There was a problem hiding this comment.
Whoops, left this out of my previous review.
|
@kamalca Any progress on this Pull Request? |
HirdayGupta
left a comment
There was a problem hiding this comment.
Looks good, thanks for putting in the effort @kamalca! 😄
All print statements now use a centralized class to report errors, warnings, and other information.
Note: Some messaged from pods or from UI elements still do not use the error class because I did not want to edit any of the locked files that are in charge of printing these messages.
I did my best to clean up the error reporting so that any error could be traced back to the code that produced them.
As for reporting what view controller they came from, the error itself should be good enough to track which code the error came from. However, something that I I looked into and may be useful is reporting which ViewController is open when the error was reported. This feature could be added upon request.