The other idea I would throw in there is to make the logging implementation a plug-in.
In my own spin on this, I have a unified Logger class where each call to log includes an identifier of which Component it is e.g. I log like this:
Logger.log(LoggingLevel.DEBUG, 'My Component', 'A message');
And then I have a custom metadata record which sets the logging level and implementation per component e.g. 'My Component' might be set at
System.debug as the implementation. While 'My Integration' might use Platform Events.
The different implementations may be more appropriate for different circumstances e.g. in a unit test,
System.debug is really nice and simple because you can see it right there in the log with no extra work. At run-time in production, Platform Events are great.
Also, if you're installing into unknown environments, you can use a plug-in to make it fit e.g. We are a consultancy, and maybe our customer already has a
Log__e object. No problem, we write a plugin just for them which fits in with their existing code/config.