I agree that allowing uninitialized use as well as multiple initialization are both problematic designs. The design of this logging API is vulnerable to exactly these problems and they are part of the reason I am arguing against this design!
These problems arise when a library exposes globally visible APIs rather than requiring explicit initialization of instances and it also requires initialization of some kind . The best libraries I have used avoid this kind of global state and use explicit instantiation instead before making their APIs available. This avoids the possibility of use before initialization and also avoids multiple initializations applicable to the same instance. This is the kind of design I am advocating for here.
I haven't seen your questions answered for the proposed logging API. How should it behave if someone requests a logger before bootstrap is called. Is it a trap or do they get a no-op logger or a logger with some default handler? What if bootstrap is called more than once? Does the application's handler get overwritten and every subsequent logger that is created get routed to the "wrong" handler (i.e. not the one the application bootstrapped with)?
My argument is precisely that we should not adopt a problematic design for this API because we think it will avoid trouble for other libraries. We should adopt a well-designed API with clean semantics and hope that other libraries doing the same will win out in our ecosystem.
For starters, see the questions Cory asked above which to my knowledge have not been answered for this library and particularly with regard to #2, I don't believe a satisfactory answer exists. As far as I can tell, as designed a library has the ability to stomp on an application's handler (as well as arbitrary application code that has no business messing with the handler). The same issues apply to mutating metadata, setting the log level, etc.
Can people ship functioning applications using designs that have semantics like this? Of course they can. Does that mean it's a good idea to design APIs with semantics like this? No it does not.
I am not arguing against the ability for applications to do things like this! Using the approach I have suggested, an application could trivially support a global makeDebugLogger()
function. All I am arguing against is the idea that we should impose this capability on all code that uses this logging API.
Are you really suggesting that we should make important semantic design choices of an ecosystem standard logging API based on the stated indifference about logging of an application developer "who doesn't care at all about logging"? Sure, they might grumble about having to pass a logger to a library but people grumble about all kinds of things and then move on.
My point is that there is no good design choice that can be made here. If you support dynamic reconfiguration then the application's handler can get overwritten. If you don't, code that expects to specify a handler is broken.