Thursday, May 30, 2024

Enter Log Levels, Mike

I'm having to figure out how to handle weird situations in my app.

I have a singleton app state holder that doesn't really get its state until DOMContentLoaded. It gets its state from inline Javascript that takes time to execute. I can't just expect it to have taken effect as soon as my code comes alive. The inline Javascript in question attaches some values to the global window object, and the app state holder gets it from there. But it has to wait for DOMContentLoaded to do this.

This leads to small problems because other UI components in the app will register as subscribers to the app state holder before DOMContentLoaded has fired. They will even try to request state information, not knowing whether they have beaten DOMContentLoaded or not.

Thus, despite not being ready, the app state holder may get a request for information. What is this situation? Should I:

  • Throw an exception? This isn't really that level of an emergency. It's not a logic error. So no.
  • Resort to showing an alert to the user? No. I should handle this. It's not a burden on the user experience.
  • Log something at error level? No. This isn't an error.
  • Log something at trace level? No. This is more interesting than trace level information.
  • Log something at debug level? I chose this. This meant adding log levels to my singleton logger.

This also implied setting the log level to something higher than debug, because I'm normally not interested in hearing about this information. I don't even show the log console normally. Remember I'm on an iPad, so I don't have access to the Chrome console. I've built my own logger that renders to an absolutely-positioned div at the bottom of my web page's viewport.

I've never really had such a need for log levels until now. In the past, I've normally considered throttling logging when I'm investigating a problem. But this is like a small, inconvenient situation that I just want to keep an eye on. I'm not sure what to do with it. I think there is probably an organized way to prevent my UI components from asking for stuff from the app state holder until the holder is ready (DOMContentLoaded has passed). But I don't know what that solution is.

So log levels provide a way for me to monitor the issue for now.

When the app state holder encounters a subscriber request too early, besides logging at the debug level, it either returns null (if a return value is expected) or it returns early if it's a void function. Any interested UI components are assured of hearing about app state updates via their subscription.

This use of an app state singleton, and accompanying subscriptions, is an easy, old-school, lighweight alternative to Redux, and all of the additional programming that comes with actions and reducers.

This woke me up to other areas of improvement in my coding quality of life. I had many places where I was calling logging.info when really I should have been calling logging.error. This makes it easy for me to do debugging with logging.info calls, because when I need to do a search for where I've littered my code with temporary logging for problem-solving, I can search for the string logging.info and not see all of the permanent logging statements that are really for special, error-level information. The list returned in my text search is way shorter, and contains only the info logging I'm trying to clean up.

No comments:

Post a Comment