
Vladimir Batov wrote:
Hmm, I honestly think that having "loggers as class members" is a bad idea.
And I find it extremely useful. In fact, I tend to avoid making loggers irrelevant to some sensible entity in the program. For example, if I have a class that implements a network connection, I would most likely make logger a member of this class. This allows to seemlessly embed information related to this connection into log records. In consequence, this allows to apply filtering based on this information.
Yes, I understand and I am not trying to convert you or anything. Just expressing my view which you might or might not take into account.
That's ok, I'm not trying to persuade you either. I'm just sharing my view on these things, as well as answering questions. :)
Design-wise I do not believe a logger should be part of a class. That inclusion of convenience that you describe is unlikely to happen in a more structured development environment (where design is evaluated and approved separately and might be even done by different people). I feel that inclusion certainly goes against the design trend of making classes as clean/small as possible.
I'd say I can both agree and disagree with your point, depending on the situation. For classes that play active role in an application, such as the aforementioned network connection class, I think it is perfectly reasonable to store a logger in it as a member. It doesn't violate the design because writing logs is actually a part of functionality of such classes. I can say more, I had cases when such approach was essentially mandated by the requirements on the project management level, because such practice proved to be useful. If your classes play passive role in the application, for instance, classes that represent dictionary entries, I totally agree with you. Such classes do tend to have many instances and size overhead can be significant, while there is no obvious benefit from having a logger inside each of them.
Implementation-wise, you do not mention if you "make logger a member of this class" as a static member. If it is not static, then the associated overhead is not acceptable (I have about 30,000 objects). As a static member it is not greatly different from a file-scope static.
I agree, there is no point of having a static member logger. Unless you want to restrict access to it in such way.
I have not got that impression that your BOOST_LOG_DECLARE_GLOBAL_LOGGER-based "example above does just that". To start with, I (I'll use "I", "you" for convenience. nothing personal) simply create a logger instance on the spot when I need it. You insist I *declare* first with some hairy :-) macro "in some common header". Then, to actually get the logger, I need "src::severity_logger_mt< >& lg = my_logger::get();".
Sorry, I don't see much difference between logger lg(name); and logger& lg = name::get(); The latter looks more descriptive to me. If you like your syntax more, you can write a trivial wrapper around "get()" or use flyweight. However, after getting a quick look at flyweight docs, it doesn't seem to provide inter-module facilities.
I do not mind you do it the way you do it. However, I insist that "my" way is very incremental. I can start the most basic:
boost::log() << "Hello";
and then incorporate streams, filters, formatters, etc. when the need arises. I do not have the feeling you do "just that".
Yet again, you can create loggers at your will, so your case is covered by the library. The only thing you have to do besides creating a logger is to provide a sink, where to store logs. For instance, to put logs into a file you have to call init_log_to_file("file.log"); somewhere in the beginning of your main(). I think you'll have to do it with any approach, be that my library or a different one.
IMHO the incremental deployment nature is extremely important for a logging library. Probably your library can do all that. What I feel is that the user's exposure to the library complexity might be looked at.
I fact, the Tutorial in the docs was written with respect to increasing complexity. The first two steps (about sinks and loggers) describe the basics to get things started. The rest of the steps go deeper and introduce filtering and formatting.