
Boosters, the formal review of the Boost.Log library, written by Andrey Semashev, starts now and will run through March 17, 2010. The documentation for the current version is available at: http://boost-log.sourceforge.net The downloads are at: http://sourceforge.net/projects/boost-log Here are the important points: 1. All comments are appreciated. Even if you don't have the time for in-depth study of everything, comments on parts of the library are welcome. In particular, if you are already using logging in your applications and have specialized requirements, you might want to directly check how the proposed library handles them. 2. The reviews and all comments should be submitted to the developers list, boost@lists.boost.org and the email should have "[log]" prefix in the subject to make sure it's not missed. The deadline for reviews is 23:59, March 17, PST = 2:59, March 18, EST = 7:59 March 18, GMT = 10:59, March 18 MSK 3. Please explicitly state in your review whether the library should be accepted. 4. The general review checklist is provided below: - What is your evaluation of the design? - What is your evaluation of the implementation? - What is your evaluation of the documentation? - What is your evaluation of the potential usefulness of the library? - Did you try to use the library? With what compiler? Did you have any problems? - How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? - Are you knowledgeable about the problem domain? Thanks, Volodya

Zitat von Vladimir Prus <ghost@cs.msu.su>:
the formal review of the Boost.Log library, written by Andrey Semashev, starts now and will run through March 17, 2010.
Andrey, thanks for your contribution. I have a couple of questions for my review from reading the documentation. I'm sure there'll be more once I've used the library. could you please explain your design rationale for: - not using user-defined log record types. for example: logger << http_connection_requested("Connection from foreign host",host,port); with http_connection_requested being a user-defined class that models a defined concept so that the logging core is able to extract the attributes. - your use of shared_ptr. shared_ptrs are used in places where you'd expect return by reference(e.g. core::get()) or by value(e.g. result of Attribute::get_value()). why is a singleton managed by a shared_ptr? - why is the logging core a singleton? should you not be able to set up multiple logging systems within an application, each with its own filters and sinks? - for identifying attributes by runtime strings, instead of statically e.g. by attribute tags. - identifying channels by runtime strings - special handling of severity. why is it not just another attribute? - special handling of message. why is it not a string attribute? thanks!

On 03/08/2010 03:00 PM, strasser@uni-bremen.de wrote:
could you please explain your design rationale for:
- not using user-defined log record types.
for example:
logger << http_connection_requested("Connection from foreign host",host,port);
with http_connection_requested being a user-defined class that models a defined concept so that the logging core is able to extract the attributes.
That exact syntax is not possible because the streaming expression is executed after the record is constructed. Although the topic differs, the reason is the same as described here: http://tinyurl.com/ydlncuv As for the absence user-defined implementation of log records, there are two reasons: 1. I never thought about it, and thinking about it now I don't see a use case for it. 2. Log records are created by the logging core, and it cannot create a user-defined type now.
- your use of shared_ptr. shared_ptrs are used in places where you'd expect return by reference(e.g. core::get()) or by value(e.g. result of Attribute::get_value()). why is a singleton managed by a shared_ptr?
In case of singletons, this solves the problem of global objects destruction order. For example, all loggers store a shared_ptr to the core, so if you keep a logger object longer than the core life time, it will still be functional. In case of attributes, the pointer returned by get_value refers to a polymorphic object (in some cases - to the attribute itself). There is no way to return this object by value as its actual type is hidden behind the attribute_value interface.
- why is the logging core a singleton? should you not be able to set up multiple logging systems within an application, each with its own filters and sinks?
1. I don't see a use case for such a set up. 2. This would complicate the library usage considerably. For example, when constructing a logger one would have to specify a core instance to work with. There are other places which would require similar interface changes.
- for identifying attributes by runtime strings, instead of statically e.g. by attribute tags.
Well, strings looked simpler and more natural matter for a key type in attribute sets. A completely static solution is not viable because it would require templating the whole library on the attribute set type, which in turn would ruin modular architecture and increase compile times dramatically.
- identifying channels by runtime strings
Strings are just a default. You can use another type to identify channels.
- special handling of severity. why is it not just another attribute?
It is.
- special handling of message. why is it not a string attribute?
Because the message string is composed after all attribute values are acquired from the attributes. The link I gave above should give the answer.

Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
On 03/08/2010 03:00 PM, strasser@uni-bremen.de wrote:
- not using user-defined log record types.
That exact syntax is not possible because the streaming expression is executed after the record is constructed. Although the topic differs, the reason is the same as described here:
ok, but the issue there is not if the log record can have a user-defined type, but at what point the type and the attributes are specified so filtering can take place before the message is constructed. the reason I asked this question is because I think log records need to have (type) identity. especially for (but not limited to) reading back log records, as was discussed when the review was announced.
- why is the logging core a singleton? should you not be able to set up multiple logging systems within an application, each with its own filters and sinks?
1. I don't see a use case for such a set up.
you could think of setups that use multiple logging systems for regular activity logging, but for the use case of binary write-ahead-logging(WAL), which will be the focus of my review, it often is a requirement to maintain multiple independent logs in the same application.
- for identifying attributes by runtime strings, instead of statically e.g. by attribute tags.
Well, strings looked simpler and more natural matter for a key type in attribute sets. A completely static solution is not viable because it would require templating the whole library on the attribute set type, which in turn would ruin modular architecture and increase compile times dramatically.
I think(!) it wouldn't require templating the whole library on the attribute set, but the filtering etc. could be instantiated on the attributes passed to the logger. my focus here was again WAL. WAL records consist entirely of attributes that are dumped in binary form. I presume attributes are now stored in a std::map<std::string,Attribute> or similar. this is not an acceptable performance overhead for WAL.
- special handling of message. why is it not a string attribute?
Because the message string is composed after all attribute values are acquired from the attributes. The link I gave above should give the answer.
ok, I might have mixed up terminology here. I meant the message on the user's part, passed e.g. by rec.message() = "Hello world!"; I've asked before if binary logging is considered within the scope of the library. if it turns out that it's not, I can stop reviewing it from this angle at any time. Regards,

On 03/08/2010 03:58 PM, strasser@uni-bremen.de wrote:
Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
On 03/08/2010 03:00 PM, strasser@uni-bremen.de wrote:
- not using user-defined log record types.
That exact syntax is not possible because the streaming expression is executed after the record is constructed. Although the topic differs, the reason is the same as described here:
ok, but the issue there is not if the log record can have a user-defined type, but at what point the type and the attributes are specified so filtering can take place before the message is constructed.
As I said, the record now is constructed by the core, and it cannot construct a record of a user-defined type. The record, among other things, also holds some book-keeping data that is used by the library - the result of filtering in order to be able to feed the record to the sinks willing to accept it.
the reason I asked this question is because I think log records need to have (type) identity.
I'm still not sure I understand. What kind of identity do you mean and what purpose would it serve?
especially for (but not limited to) reading back log records, as was discussed when the review was announced.
Now that you mention it, I see the problem of constructing a valid record on the user's side. Yes, the problem is there, but I think it should not be difficult to solve it by separating the book-keeping data and the public data accessible from the record interface. However, I still don't see the need to create different record types on the user's side.
- why is the logging core a singleton? should you not be able to set up multiple logging systems within an application, each with its own filters and sinks?
1. I don't see a use case for such a set up.
you could think of setups that use multiple logging systems for regular activity logging, but for the use case of binary write-ahead-logging(WAL), which will be the focus of my review, it often is a requirement to maintain multiple independent logs in the same application.
The core doesn't limit the number of logs you can maintain. Just register as many sinks as you need and set up filtering accordingly.
- for identifying attributes by runtime strings, instead of statically e.g. by attribute tags.
Well, strings looked simpler and more natural matter for a key type in attribute sets. A completely static solution is not viable because it would require templating the whole library on the attribute set type, which in turn would ruin modular architecture and increase compile times dramatically.
I think(!) it wouldn't require templating the whole library on the attribute set, but the filtering etc. could be instantiated on the attributes passed to the logger.
Attribute sets are used in loggers and the core. I don't see how it would be possible not to template them if some kind of type erasure is not used (which brings us to the current solution). Further, the core constructs a view of attribute values out of the attribute sets, which is basically a map, like attribute sets. This view is then processed by filters, formatters and sinks, so they will be templated, too.
my focus here was again WAL. WAL records consist entirely of attributes that are dumped in binary form.
I guess, in terms of the library, these would be attribute values.
I presume attributes are now stored in a std::map<std::string,Attribute> or similar. this is not an acceptable performance overhead for WAL.
And what is your suggestion? Use fusion::map? Or std::map<std::type_info, Attribute>?
- special handling of message. why is it not a string attribute?
Because the message string is composed after all attribute values are acquired from the attributes. The link I gave above should give the answer.
ok, I might have mixed up terminology here. I meant the message on the user's part, passed e.g. by
rec.message() = "Hello world!";
Yes, that's the message I was talking about. It is not an attribute value for the outlined reasons.
I've asked before if binary logging is considered within the scope of the library. if it turns out that it's not, I can stop reviewing it from this angle at any time.
Yes, it has been considered. It is possible to create a binary sink that will serialize the attribute values and the message.

Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
I think(!) it wouldn't require templating the whole library on the attribute set, but the filtering etc. could be instantiated on the attributes passed to the logger.
Attribute sets are used in loggers and the core. I don't see how it would be possible not to template them if some kind of type erasure is not used (which brings us to the current solution). Further, the core constructs a view of attribute values out of the attribute sets, which is basically a map, like attribute sets. This view is then processed by filters, formatters and sinks, so they will be templated, too.
I presume attributes are now stored in a std::map<std::string,Attribute> or similar. this is not an acceptable performance overhead for WAL.
And what is your suggestion? Use fusion::map? Or std::map<std::type_info, Attribute>?
fusion::map, or not constructing a (dynamic) view of the attributes but passing it through. I don't think that would mean parametrizing the core by the whole attribute set of every attribute ever used throughout the application, but it probably does mean templating the core e.g. by the filters.
I've asked before if binary logging is considered within the scope of the library. if it turns out that it's not, I can stop reviewing it from this angle at any time.
Yes, it has been considered. It is possible to create a binary sink that will serialize the attribute values and the message.
I understand that you can write your own sink and store the information in whatever way, but with most use cases of binary logging come several requirements, e.g. performance-wise it should be similar to: http_connection_requested record(host,port); stream.sputc( get_record_identity(record) ); stream.sputn( &record, sizeof(record) ); (assuming that the record is bitwise-serializable) a lot of stuff that is now done at runtime, like creating a view of the attributes and filtering records based on that view, would have to be done at compile-time. so before I write a lengthy review from that angle, that would most likely result in a NO vote, let me know if this is beyond the scope of the library. this question is not only directed towards you but also towards other reviewers; if that use case is considered within the scope of a boost logging library.

strasser@uni-bremen.de wrote:
this question is not only directed towards you but also towards other reviewers; if that use case is considered within the scope of a boost logging library.
FWIW, I consider this library to be http://en.wikipedia.org/wiki/Data_logging and not the database/filesystem logging stuff, http://en.wikipedia.org/wiki/Write_ahead_logging In terms of the Linux filesystem hierarchy standard, I would expect the usual directory targeted by programs using this library to be /var/log, whereas WAL most probably resides in another directory, e.g., /var/lib. Cheers, Rutger

On 03/08/2010 05:12 PM, strasser@uni-bremen.de wrote:
Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
I think(!) it wouldn't require templating the whole library on the attribute set, but the filtering etc. could be instantiated on the attributes passed to the logger.
Attribute sets are used in loggers and the core. I don't see how it would be possible not to template them if some kind of type erasure is not used (which brings us to the current solution). Further, the core constructs a view of attribute values out of the attribute sets, which is basically a map, like attribute sets. This view is then processed by filters, formatters and sinks, so they will be templated, too.
I presume attributes are now stored in a std::map<std::string,Attribute> or similar. this is not an acceptable performance overhead for WAL.
And what is your suggestion? Use fusion::map? Or std::map<std::type_info, Attribute>?
fusion::map, or not constructing a (dynamic) view of the attributes but passing it through.
It looks like you're missing the difference between attributes and attribute values. Attributes do not represent any values, most of the time. For instance, a function that returns the current time stamp can be an attribute. Attribute values, on the other hand, do represent values (the concrete time readings in the example), and these values are processed by the most part of the library. So there is no way around constructing a view of attribute values. Also, dealing with a single view is much easier than with a number of distinct sets.
I don't think that would mean parametrizing the core by the whole attribute set of every attribute ever used throughout the application, but it probably does mean templating the core e.g. by the filters.
That approach doesn't look any better to me, since it has the same drawbacks I outlined earlier.
I understand that you can write your own sink and store the information in whatever way, but with most use cases of binary logging come several requirements, e.g. performance-wise it should be similar to:
http_connection_requested record(host,port);
stream.sputc( get_record_identity(record) ); stream.sputn( &record, sizeof(record) );
(assuming that the record is bitwise-serializable)
That assumption may be true in your particular case. But it's absolutely no go in a generic library, which Boost.Log is. In fact, even in more specialized cases I tend to reject such code.
a lot of stuff that is now done at runtime, like creating a view of the attributes and filtering records based on that view, would have to be done at compile-time.
The implications of such compile-time-biased approach look unacceptable to me.
so before I write a lengthy review from that angle, that would most likely result in a NO vote, let me know if this is beyond the scope of the library.
this question is not only directed towards you but also towards other reviewers; if that use case is considered within the scope of a boost logging library.
I said this before the review. This case was not considered as the main one. So currently, no, the library is not aimed for it. However, I consider it as a possible way for further improvement of the library.

Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
http_connection_requested record(host,port);
stream.sputc( get_record_identity(record) ); stream.sputn( &record, sizeof(record) );
(assuming that the record is bitwise-serializable)
That assumption may be true in your particular case. But it's absolutely no go in a generic library, which Boost.Log is. In fact, even in more specialized cases I tend to reject such code.
well, there are ways of serialization other than bitwise, this was example code only. my point was that for those use cases the logging sink must have access to the attribute _values_ without expensive intermediate steps like storing them in a dynamically allocated tree indexed by a string. but I realize that this is a very specialized case of logging, and I see no problem with handling it in a seperate library (most likely Boost.Transact). IF you wanted to support that case we should have incorporated it. I'll submit a review of your library without regard to this use case.

On 08.03.2010 21:22, strasser@uni-bremen.de wrote:
my point was that for those use cases the logging sink must have access to the attribute _values_ without expensive intermediate steps like storing them in a dynamically allocated tree indexed by a string.
Well, it's not that expensive as you may think. The view composition is a single memory allocation (not counting ones that may take place during attribute values acquisition) and no tree rebalancing or anything like that. There are also no memory allocations and copying for attribute names.

Andrey Semashev wrote:
On 08.03.2010 21:22, strasser@uni-bremen.de wrote:
my point was that for those use cases the logging sink must have access to the attribute _values_ without expensive intermediate steps like storing them in a dynamically allocated tree indexed by a string.
Well, it's not that expensive as you may think. The view composition is a single memory allocation (not counting ones that may take place during attribute values acquisition) and no tree rebalancing or anything like that. There are also no memory allocations and copying for attribute names.
Do you have any performance measurements to back up the above statement, and generally to give the idea of runtime performance, compiler performance and code size implications of using Boost.Log? - Volodya

On 03/10/2010 10:07 AM, Vladimir Prus wrote:
Andrey Semashev wrote:
Well, it's not that expensive as you may think. The view composition is a single memory allocation (not counting ones that may take place during attribute values acquisition) and no tree rebalancing or anything like that. There are also no memory allocations and copying for attribute names.
Do you have any performance measurements to back up the above statement, and generally to give the idea of runtime performance, compiler performance and code size implications of using Boost.Log?
Partially, that was discussed before the review. There is no document on performance comparisons, but there is a discussion thread [1] with testing results against log4cxx. The brief outcome is as follows: * When no or nearly no log records are dropped by filters, Boost.Log is faster by ratio around 0.95. * When most or all log records are dropped by filters or logging is completely disabled, Boost.Log is slower up to 2 times. * In multithreaded tests, having the similar settings, either both libraries tie, or Boost.Log is faster with ratio around 0.85. * In tests of formatting the main bottleneck is date/time formatting, which is done by Boost.DateTime. Up to 5.5 times slower than log4cxx in these cases. Without date/time (severity and message only) Boost.Log is faster (around 0.9). A few comments on these numbers. The figures are the ratio of execution times of Boost.Log and log4cxx. The measurements were done on a dual-core machine, under Windows Vista. MSVC 9 + STLPort was used. The tests did not produce any output, all log records were discarded. The performance depends greatly on the STL version being used, in case of Boost.Log, and the one being shipped with MSVC is not a good one if you seek for performance. Use STLPort instead. The performance drop for cases when nearly no log records pass filtering is not that significant, if absolute numbers are considered. My guess is that the most part of that difference is due to the call for the filter and its implementation (which includes an ad-hoc multimethod call). Considering the flexibility of attributes and filtering Boost.Log provides, I'd say it's a fair trade. The more considerable concern is the case when logging is disabled. In this case no filtering or attribute values view composition is done, yet the performance drop is there, and it's the most significant (it's those "2 times slower"). This needs closer investigation. But again, we're talking of a few CPU ticks here. The date/time formatting is the major slowdown. I have a few thoughts on optimizing Boost.DateTime, which I can implement when things around Boost.Log are settled. No tests identified that the attribute values view composition is the performance bottleneck. I think, it is optimized well enough, and in order to further improve performance, other parts of the library should be improved. I did not test other aspects that you mentioned, such as compile times or code size. But I didn't see any extraordinary code bloats in the library examples or other uses of the library. Compile times also stay reasonable, with more or less modern compilers. [1] http://tinyurl.com/ya85vwf

Andrey Semashev wrote:
It looks like you're missing the difference between attributes and attribute values. Attributes do not represent any values, most of the time. For instance, a function that returns the current time stamp can be an attribute. Attribute values, on the other hand, do represent values (the concrete time readings in the example), and these values are processed by the most part of the library. So there is no way around constructing a view of attribute values. Also, dealing with a single view is much easier than with a number of distinct sets.
Don't you think that using the word 'attribute' to mean 'function that computes attribute value' is bound to cause confusion? Is there some better name? - Volodya

On 03/10/2010 10:06 AM, Vladimir Prus wrote:
Don't you think that using the word 'attribute' to mean 'function that computes attribute value' is bound to cause confusion? Is there some better name?
In conjunction with the attribute semantics (e.g. "the current time stamp attribute" or "the current thread identifier attribute") the term makes sense to me. Do you have a better suggestion?

Andrey Semashev wrote:
On 03/10/2010 10:06 AM, Vladimir Prus wrote:
Don't you think that using the word 'attribute' to mean 'function that computes attribute value' is bound to cause confusion? Is there some better name?
In conjunction with the attribute semantics (e.g. "the current time stamp attribute" or "the current thread identifier attribute") the term makes sense to me. Do you have a better suggestion?
The documentation is pretty clear regarding attributes. I read it before experimenting and therefore did not have problems with the semantics. But I agree that "attribute" representing a function is not the most intuitive thing I've ever seen. For instance, the "current time stamp" is a value (THE current time stamp). I would thus not normally interpret "current time stamp attribute" as a function. Personally I'd go with any of attribute_function/attribute_provider/attribute_generator/attribute_computer and attribute_value Regards, Roland

strasser@uni-bremen.de wrote:
so before I write a lengthy review from that angle, that would most likely result in a NO vote, let me know if this is beyond the scope of the library.
this question is not only directed towards you but also towards other reviewers; if that use case is considered within the scope of a boost logging library.
Since you asked... I personally find your use case out of scope. michael -- ---------------------------------- Michael Caisse Object Modeling Designs www.objectmodelingdesigns.com

On Mon, 08 Mar 2010 09:37:38 +0100, Vladimir Prus <ghost@cs.msu.su> wrote:
[...]3. Please explicitly state in your review whether the library should be accepted.
The library should be accepted (acceptance is overdue :).
4. The general review checklist is provided below:
- What is your evaluation of the design?
The design makes perfectly sense to me. The library is neither too complicated nor is it just another simple stream class. If you think the evaluation is a bit short: I've used John Torjo's library for about a year before I switched to Andrey's library. That was beginning of 2009 I think. That said I evaluated the libraries quite some time ago and don't really remember all the details. However I do remember that I liked Andrey's library better than John's (which hasn't been updated for years anyway).
- What is your evaluation of the implementation?
Didn't look at the implementation.
- What is your evaluation of the documentation?
The documentation is really good and in my opinion one of the better ones of the Boost libraries.
- What is your evaluation of the potential usefulness of the library?
It's a logging library and useful by definition. :)
- Did you try to use the library? With what compiler? Did you have any problems?
I started to use Andrey's library about a year ago (if I remember correctly). I tried it with VC++ on Windows and g++ on Linux. I had some questions and requests but that's all long ago (eg. there was only a syslog backend in the beginning; now there is support for the Windows NT event log, too).
- How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
I thoroughly evaluated Andrey's library in 2009 - especially as I had used John Torjo's library before and wanted to know whether I should switch.
- Are you knowledgeable about the problem domain?
I'm not a logging expert but had compared both Boost.Log candidates from John and Andrey very thoroughly. Boris

Hi Andrey, Boost.Log is not header only, and uses Boost libraries which are not header only.
The logging library also uses several Boost libraries that need building too. These are Boost.Filesystem, Boost.System, Boost.DateTime, Boost.Thread and Boost.Regex
Is it possible to use Boost.Log in header-only mode, assuming a simple use case without threads and separate DLLs? Thanks, Barend

On 03/11/2010 01:28 PM, Barend Gehrels wrote:
Hi Andrey,
Boost.Log is not header only, and uses Boost libraries which are not header only.
The logging library also uses several Boost libraries that need building too. These are Boost.Filesystem, Boost.System, Boost.DateTime, Boost.Thread and Boost.Regex
Is it possible to use Boost.Log in header-only mode, assuming a simple use case without threads and separate DLLs?
No, the library has to be compiled anyway. However, if your application is a single .exe module, you can link statically with Boost.Log and other libraries.

Andrey Semashev wrote:
On 03/11/2010 01:28 PM, Barend Gehrels wrote:
Hi Andrey,
Boost.Log is not header only, and uses Boost libraries which are not header only.
The logging library also uses several Boost libraries that need building too. These are Boost.Filesystem, Boost.System, Boost.DateTime, Boost.Thread and Boost.Regex
Is it possible to use Boost.Log in header-only mode, assuming a simple use case without threads and separate DLLs?
No, the library has to be compiled anyway. However, if your application is a single .exe module, you can link statically with Boost.Log and other libraries.
OK, I must say that I'm not so happy with that. What is the reason for the need to compile? Logging is very useful, but to statically link only because of logging is in many cases not convenient. Would it be possible (technically or otherwise) to adapt it to be header only, as a whole or just the core part? Barend

Barend Gehrels wrote:
Andrey Semashev wrote:
No, the library has to be compiled anyway. However, if your application is a single .exe module, you can link statically with Boost.Log and other libraries.
OK, I must say that I'm not so happy with that. What is the reason for the need to compile? Logging is very useful, but to statically link only because of logging is in many cases not convenient.
There was a report that it had taken about 20 minutes to compile the lib. Do you really want to spend 20 minutes each time you compile an application which uses the lib? Or would you rather compile the lib once and then link against it?
Would it be possible (technically or otherwise) to adapt it to be header only, as a whole or just the core part?
Barend
BR, Dmitry

Dmitry Goncharov wrote:
Barend Gehrels wrote:
Andrey Semashev wrote:
No, the library has to be compiled anyway. However, if your application is a single .exe module, you can link statically with Boost.Log and other libraries.
OK, I must say that I'm not so happy with that. What is the reason for the need to compile? Logging is very useful, but to statically link only because of logging is in many cases not convenient.
There was a report that it had taken about 20 minutes to compile the lib. Do you really want to spend 20 minutes each time you compile an application which uses the lib? Or would you rather compile the lib once and then link against it?
That also sounds not good. However, what might happen is that if there is an attractive logging library, Boost library writers start to use it, of course. All libraries using the logging functionality will need compilation. I normally use only header only libraries from Boost (sometimes making an exception). So this scenario might cause me stopping using Boost... There are much more people using only header-only Boost headers. It might be even worse. If *existing* libraries will start using Boost.Log in an update (because it is really useful), existing project files and solutions will be broken. And finally for me the worst case scenario: if *existing *libraries *used in Boost.Geometry* will start using Boost.Log in an update, our Boost.Geometry library is broken and not header only anymore. That is the reason that I'm really not happy with this, and I think it should be fixed. Regards, Barend

Barend Gehrels wrote:
Dmitry Goncharov wrote:
There was a report that it had taken about 20 minutes to compile the lib. Do you really want to spend 20 minutes each time you compile an application which uses the lib? Or would you rather compile the lib once and then link against it? That also sounds not good.
However, what might happen is that if there is an attractive logging library, Boost library writers start to use it, of course. All libraries using the logging functionality will need compilation. I normally use only header only libraries from Boost (sometimes making an exception). So this scenario might cause me stopping using Boost...
Here, i cannot really see reasons not to use a library which requires linking.
There are much more people using only header-only Boost headers. The same as above.
It might be even worse. If *existing* libraries will start using Boost.Log in an update (because it is really useful), existing project files and solutions will be broken. If an existing header-only library starts using the Boost.Log library we'll need to update the makefiles. This is a reasonable cost. In reward we won't need to compile the Boost.Log lib over and over again.
And finally for me the worst case scenario: if *existing *libraries *used in Boost.Geometry* will start using Boost.Log in an update, our Boost.Geometry library is broken and not header only anymore.
The same as above.
That is the reason that I'm really not happy with this, and I think it should be fixed.
BR, Dmitry

Here, i cannot really see reasons not to use a library which requires linking.
There are much more people using only header-only Boost headers. The same as above.
It might be even worse. If *existing* libraries will start using Boost.Log in an update (because it is really useful), existing project files and solutions will be broken. If an existing header-only library starts using the Boost.Log library we'll need to update the makefiles. This is a reasonable cost. In reward we won't need to compile the Boost.Log lib over and over again.
All your statements are based on your opinion that linking is no problem, whereas all my statements are based on my opinion that linking is a problem... So I think we stay keeping different opinions here. Regards, Barend

Barend Gehrels wrote: [snip]
However, what might happen is that if there is an attractive logging library, Boost library writers start to use it, of course. All libraries
Why would they? I'd say logging is done by an application, not by generic libraries. Because logging is also useful in libraries, and there is no Boost Police preventing this being done in existing libraries.
Regards, Barend

Roland Bock wrote:
However, what might happen is that if there is an attractive logging library, Boost library writers start to use it, of course. All
Barend Gehrels wrote: [snip] libraries
Why would they? I'd say logging is done by an application, not by generic libraries.
This is an excellent point. As a remark a bit offtopic for the review of a logging library, I think the following can be said about libraries: Libraries have to communicate "errors", "warnings" and "informations" back to their "client": * The communication of "errors" is easy, just throw an exception. * The communication of "warnings" is more challenging, since the library has to continue its work. So "warnings" must be "aggregated" as they arise and reported back when the library has finished its work. The "aggregation" means among others, that certain "warnings" are only reported and stored once (take "somebody included a deprecated header" warning of gcc as an example). * The communication of "information" is not necessarily challenging, but leads to the question which "information" is really interesting and should be reported. This is most closely related to the task of a logging library. This is also a broad domain, as there is such diverse "information" as "progress report", "work summary" and "???". What this information has in common is that it is not really important for the program logic, so it can be switched on and off via some sort of "verbose" flag. Regards, Thomas

Thomas Klimpel wrote:
Roland Bock wrote:
Barend Gehrels wrote: [snip]
However, what might happen is that if there is an attractive logging library, Boost library writers start to use it, of course.
Why would they? I'd say logging is done by an application, not by generic libraries.
This is an excellent point.
While I agree with Barend's intent, a generic or standard library should not impose its own notion of logging on the application using it, even if there is a reasonably standard logging library. If a library must communicate, as if logging, then it must provide a communication mechanism that can be hooked into the logging mechanism used by the application using it.
As a remark a bit offtopic for the review of a logging library, I think the following can be said about libraries: Libraries have to communicate "errors", "warnings" and "informations" back to their "client":
* The communication of "errors" is easy, just throw an exception.
Yes or, of course, return an error code or use the likes of Boost.System. However, it is also common to log such conditions prior to throwing the exception, etc.
* The communication of "warnings" is more challenging, since the library has to continue its work. So "warnings" must be "aggregated" as they arise and reported back when the library has finished its work. The "aggregation" means among others, that certain "warnings" are only reported and stored once (take "somebody included a deprecated header" warning of gcc as an example).
I disagree with the idea of aggregating warning information. Often the output must appear on the output device as it occurs.
* The communication of "information" is not necessarily challenging, but leads to the question which "information" is really interesting and should be reported. This is most closely related to the task of a logging library. This is also a broad domain, as there is such diverse "information" as "progress report", "work summary" and "???". What this information has in common is that it is not really important for the program logic, so it can be switched on and off via some sort of "verbose" flag.
The solution is for libraries that wish to communicate such information -- which would otherwise be logged by the library -- via a callback API. Such an API is reasonably within the scope of Boost.Log (even if that turns out to not be Andrey's library). IOW, Boost.Log can define an API and some functionality to standardize the mechanism for reporting information that would be logged, such that an application can tie that reporting into any logging system. Thus, Boost libraries should not log via Boost.Log but should report loggable information via a Boost.Log-provided callback API that can be connected to Boost.Log or any other logging library of the application's choice. Then, all Boost libraries that wish to report loggable information use one API for reporting and an application makes just one call to connect them all to its preferred logging library. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On Mar 12, 2010, at 6:53 AM, Stewart, Robert wrote:
The solution is for libraries that wish to communicate such information -- which would otherwise be logged by the library -- via a callback API. Such an API is reasonably within the scope of Boost.Log (even if that turns out to not be Andrey's library). IOW, Boost.Log can define an API and some functionality to standardize the mechanism for reporting information that would be logged, such that an application can tie that reporting into any logging system.
Thus, Boost libraries should not log via Boost.Log but should report loggable information via a Boost.Log-provided callback API that can be connected to Boost.Log or any other logging library of the application's choice. Then, all Boost libraries that wish to report loggable information use one API for reporting and an application makes just one call to connect them all to its preferred logging library.
This is how I designed our own internal logging system. Components that wish to log emit a signal that the logging service can connect to. The critical part of such a system is the ability to determine whether anyone is listening before incurring the expense of calculating/formatting/serializing data for the log. Signals are my preferred callback mechanism because it allows multiple logging services to be running. Of course all signals are exposed via RPC so a logging service can connect over the network.

On 03/12/2010 02:53 PM, Stewart, Robert wrote:
The solution is for libraries that wish to communicate such information -- which would otherwise be logged by the library -- via a callback API. Such an API is reasonably within the scope of Boost.Log (even if that turns out to not be Andrey's library). IOW, Boost.Log can define an API and some functionality to standardize the mechanism for reporting information that would be logged, such that an application can tie that reporting into any logging system.
Thus, Boost libraries should not log via Boost.Log but should report loggable information via a Boost.Log-provided callback API that can be connected to Boost.Log or any other logging library of the application's choice. Then, all Boost libraries that wish to report loggable information use one API for reporting and an application makes just one call to connect them all to its preferred logging library.
You may be right. I just wanted to make it clear that the proposed library is not a proposal of such API.

Thomas Klimpel wrote:
Roland Bock wrote:
However, what might happen is that if there is an attractive logging library, Boost library writers start to use it, of course. All
Barend Gehrels wrote: [snip] libraries
Why would they? I'd say logging is done by an application, not by generic libraries.
This is an excellent point.
As a remark a bit offtopic for the review of a logging library, I think the following can be said about libraries: Libraries have to communicate "errors", "warnings" and "informations" back to their "client":
* The communication of "errors" is easy, just throw an exception.
* The communication of "warnings" is more challenging, since the library has to continue its work. So "warnings" must be "aggregated" as they arise and reported back when the library has finished its work. The "aggregation" means among others, that certain "warnings" are only reported and stored once (take "somebody included a deprecated header" warning of gcc as an example).
* The communication of "information" is not necessarily challenging, but leads to the question which "information" is really interesting and should be reported. This is most closely related to the task of a logging library. This is also a broad domain, as there is such diverse "information" as "progress report", "work summary" and "???". What this information has in common is that it is not really important for the program logic, so it can be switched on and off via some sort of "verbose" flag.
Personally, I'd say that "information" should only be given upon request from the client by some get_xy_info() method. About warnings, I am not sure. When would a generic library (like the ones found in boost) issue a warning? Anyway: If there really is an urge for a library to actively report some information, I'd agree with Rob Stewart: The client could to provide the library with a callback. Although, I'd say that this should be a rather simple callback (e.g. void (const string&)) which should not require Boost.Log. Just my 2c. Regards, Roland

Roland Bock wrote:
If there really is an urge for a library to actively report some information, I'd agree with Rob Stewart: The client could to provide the library with a callback. Although, I'd say that this should be a rather simple callback (e.g. void (const string&)) which should not require Boost.Log.
I don't think that's sufficient. The callback API should provide a means to discover whether logging at a certain severity is enabled, for example, before the message content is formatted. Otherwise, the library will waste time producing a string that won't be used. Furthermore, any other attributes that might be reasonable to characterize the source of the information, the library name perhaps, might be split from the string if the application's logging API allows it. I haven't thought through how what I'm describing might be done in an efficient and flexible manner. Maybe I'm really just saying that Boost.Log should provide a really lightweight path to an easily customized adapter that directs the logging output to the application's logging mechanism. What I don't want is for such a path to trigger the creation of threads or otherwise impose on the application much more than just a simple redirection to the application's preferred logging API. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert wrote:
Roland Bock wrote:
If there really is an urge for a library to actively report some information, I'd agree with Rob Stewart: The client could to provide the library with a callback. Although, I'd say that this should be a rather simple callback (e.g. void (const string&)) which should not require Boost.Log.
I don't think that's sufficient. The callback API should provide a means to discover whether logging at a certain severity is enabled, for example, before the message content is formatted. Otherwise, the library will waste time producing a string that won't be used. Furthermore, any other attributes that might be reasonable to characterize the source of the information, the library name perhaps, might be split from the string if the application's logging API allows it.
Hmm. This is getting complex and (from my perspective) a bit theoretical. Until now, I cannot think of a generic library having the need to give information at all. And for specific libraries, e.g. a network monitoring library which detects unusual activities, I'd say the interface should be discussed with the developers/users of those specific libraries.

Roland Bock wrote:
Stewart, Robert wrote:
Roland Bock wrote:
If there really is an urge for a library to actively report some information, I'd agree with Rob Stewart: The client could to provide the library with a callback. Although, I'd say that this should be a rather simple callback (e.g. void (const string&)) which should not require Boost.Log.
I don't think that's sufficient. The callback API should provide a means to discover whether logging at a certain severity is enabled, for example, before the message content is formatted. Otherwise, the library will waste time producing a string that won't be used. Furthermore, any other attributes that might be reasonable to characterize the source of the information, the library name perhaps, might be split from the string if the application's logging API allows it.
Hmm. This is getting complex and (from my perspective) a bit theoretical. Until now, I cannot think of a generic library having the need to give information at all.
It is theoretical as we don't yet know what any Boost library (or other generic library) might wish to log. Barend raised the issue, presumably because he was interested in logging from his library. I know that we log a good deal from our internal libraries, but they aren't libraries like those in Boost. What would prove unacceptable is for each Boost library wishing to log something to create its own API for doing so, unless the number of such libraries is close to one.
And for specific libraries, e.g. a network monitoring library which detects unusual activities, I'd say the interface should be discussed with the developers/users of those specific libraries.
Discussing it on this list is discussing it with the developers and many users. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert wrote:
It is theoretical as we don't yet know what any Boost library (or other generic library) might wish to log. Barend raised the issue, presumably because he was interested in logging from his library. I know that we log a good deal from our internal libraries, but they aren't libraries like those in Boost. What would prove unacceptable is for each Boost library wishing to log something to create its own API for doing so, unless the number of such libraries is close to one.
I certainly agree that IF any boost library would want to log, we should discuss in which way to do it. It is just that I fail to see which one would actually want that.

Roland Bock wrote:
Stewart, Robert wrote:
It is theoretical as we don't yet know what any Boost library (or other generic library) might wish to log. Barend raised the issue, presumably because he was interested in logging from his library. I know that we log a good deal from our internal libraries, but they aren't libraries like those in Boost. What would prove unacceptable is for each Boost library wishing to log something to create its own API for doing so, unless the number of such libraries is close to one.
I certainly agree that IF any boost library would want to log, we should discuss in which way to do it. It is just that I fail to see which one would actually want that. Yes, it is because I'm interested in logging from our library.
I'm writing libraries since many years and always log, or have the need to log. But I'm not the only one. Accepted Boost libraries: Look e.g. in Boost.Geometry and you will find many places (this is our library) Look e.g. in Boost.Polygon and you will find 15 files writing to std::cout (= need to log) Long time Boost Libraries in Trunk: Boost.DateTime: 6 files writing to std::cout Boost.Math: writing to std::cout (#ifdef BOOST_INSTRUMENT) Boost.Spirit: has file debug.hpp I didn't look in more of the sandbox but I'm sure there is more need for this. Therefore I advocate a (as Rob states it nicely) *lightweight* logging utility and I had hoped that Boost.Log would fulfil this need. If it does not, it does not mean that Boost.Log is not good or not useful, of course. And maybe I would use it for my own programs. But it is not the library I'm looking for as a library writer. Regards, Barend

Barend Gehrels wrote:
I certainly agree that IF any boost library would want to log, we should discuss in which way to do it. It is just that I fail to see which one would actually want that. Yes, it is because I'm interested in logging from our library.
I'm writing libraries since many years and always log, or have the need to log.
But I'm not the only one.
Accepted Boost libraries: Look e.g. in Boost.Geometry and you will find many places (this is our library) Look e.g. in Boost.Polygon and you will find 15 files writing to std::cout (= need to log)
Long time Boost Libraries in Trunk: Boost.DateTime: 6 files writing to std::cout Boost.Math: writing to std::cout (#ifdef BOOST_INSTRUMENT) Boost.Spirit: has file debug.hpp
I didn't look in more of the sandbox but I'm sure there is more need for this.
Therefore I advocate a (as Rob states it nicely) *lightweight* logging utility and I had hoped that Boost.Log would fulfil this need. If it does not, it does not mean that Boost.Log is not good or not useful, of course. And maybe I would use it for my own programs. But it is not the library I'm looking for as a library writer.
Thanks :-) I was not aware of that. My impression is that Boost.Log is too heavyweight for this job (and as Daniel pointed out, it might restrict to too few platforms).

On 12 March 2010 09:00, Roland Bock <rbock@eudoxos.de> wrote:
Barend Gehrels wrote:
I certainly agree that IF any boost library would want to log, we should
discuss in which way to do it. It is just that I fail to see which one would actually want that.
Yes, it is because I'm interested in logging from our library.
I'm writing libraries since many years and always log, or have the need to log.
But I'm not the only one.
Accepted Boost libraries: Look e.g. in Boost.Geometry and you will find many places (this is our library) Look e.g. in Boost.Polygon and you will find 15 files writing to std::cout (= need to log)
Long time Boost Libraries in Trunk: Boost.DateTime: 6 files writing to std::cout Boost.Math: writing to std::cout (#ifdef BOOST_INSTRUMENT) Boost.Spirit: has file debug.hpp
I didn't look in more of the sandbox but I'm sure there is more need for this.
Therefore I advocate a (as Rob states it nicely) *lightweight* logging utility and I had hoped that Boost.Log would fulfil this need. If it does not, it does not mean that Boost.Log is not good or not useful, of course. And maybe I would use it for my own programs. But it is not the library I'm looking for as a library writer.
I think that any reasonable log library must be compiled to it's own lib due to the intermodule singleton requirement. If some developers here think it's not an important feature or that programmers are better off without separate modules, please consider that users of your generic libraries may not be in the more trivial scenario with only one statically built .exe. / christian

On 12 March 2010 22:48, Christian Holmquist <c.holmquist@gmail.com> wrote:
Barend Gehrels wrote:
Therefore I advocate a (as Rob states it nicely) *lightweight* logging utility and I had hoped that Boost.Log would fulfil this need. If it does not, it does not mean that Boost.Log is not good or not useful, of course. And maybe I would use it for my own programs. But it is not the library I'm looking for as a library writer.
I think that any reasonable log library must be compiled to it's own lib due to the intermodule singleton requirement. If some developers here think it's not an important feature or that programmers are better off without separate modules, please consider that users of your generic libraries may not be in the more trivial scenario with only one statically built .exe.
The suggestion is to have a lightweight logging library that can use different backends, so all you'd have to do is use a backend which meets your needs. Daniel

On 03/13/2010 07:14 PM, Daniel James wrote:
On 12 March 2010 22:48, Christian Holmquist<c.holmquist@gmail.com> wrote:
Barend Gehrels wrote:
Therefore I advocate a (as Rob states it nicely) *lightweight* logging utility and I had hoped that Boost.Log would fulfil this need. If it does not, it does not mean that Boost.Log is not good or not useful, of course. And maybe I would use it for my own programs. But it is not the library I'm looking for as a library writer.
I think that any reasonable log library must be compiled to it's own lib due to the intermodule singleton requirement. If some developers here think it's not an important feature or that programmers are better off without separate modules, please consider that users of your generic libraries may not be in the more trivial scenario with only one statically built .exe.
The suggestion is to have a lightweight logging library that can use different backends, so all you'd have to do is use a backend which meets your needs.
I wouldn't call that a "logging library" since it doesn't actually write logs. It's more like a binding or a wrapper.

On 13 March 2010 19:18, Andrey Semashev <andrey.semashev@gmail.com> wrote:
I wouldn't call that a "logging library" since it doesn't actually write logs. It's more like a binding or a wrapper.
Call it whatever you wish. I assume it'd include a simple backend for basic tasks (which might just write to a stream or something), although by default it'd do nothing. Daniel

On 12.03.2010 17:27, Barend Gehrels wrote:
Accepted Boost libraries: Look e.g. in Boost.Geometry and you will find many places (this is our library) Look e.g. in Boost.Polygon and you will find 15 files writing to std::cout (= need to log)
Long time Boost Libraries in Trunk: Boost.DateTime: 6 files writing to std::cout Boost.Math: writing to std::cout (#ifdef BOOST_INSTRUMENT) Boost.Spirit: has file debug.hpp
I didn't look in more of the sandbox but I'm sure there is more need for this.
If we have a list of places in Boost where logging may be applied, perhaps we could compile a set of requirements for such a lightweight wrapper. When we have it, it would be easier to tell, whether Boost.Log fits the role or not, or whether the wrapper should be part of it or a separate submission. I'd be interested to hear from the library authors on this topic.

On 12 March 2010 12:37, Stewart, Robert <Robert.Stewart@sig.com> wrote:
I haven't thought through how what I'm describing might be done in an efficient and flexible manner. Maybe I'm really just saying that Boost.Log should provide a really lightweight path to an easily customized adapter that directs the logging output to the application's logging mechanism. What I don't want is for such a path to trigger the creation of threads or otherwise impose on the application much more than just a simple redirection to the application's preferred logging API.
That's not a bad idea, but it sounds to me like it should be separate from Boost.Log. If we ever manage to modularize boost, then you wouldn't want everything that depends on this lightweight logging header to depend on Boost.Log. Daniel

Daniel James wrote:
On 12 March 2010 12:37, Stewart, Robert <Robert.Stewart@sig.com> wrote:
I haven't thought through how what I'm describing might be done in an efficient and flexible manner. Maybe I'm really just saying that Boost.Log should provide a really lightweight path to an easily customized adapter that directs the logging output to the application's logging mechanism. What I don't want is for such a path to trigger the creation of threads or otherwise impose on the application much more than just a simple redirection to the application's preferred logging API.
That's not a bad idea, but it sounds to me like it should be separate from Boost.Log. If we ever manage to modularize boost, then you wouldn't want everything that depends on this lightweight logging header to depend on Boost.Log.
I was presuming that such a mechanism would reuse parts of Boost.Log and that those looking for such an adapter would look at Boost.Log first. Provided that mechanism is header only, I don't see why it can't be part of Boost.Log. That would require that Boost.Log be in the Boost installation, but it wouldn't require building Boost.Log. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 12 March 2010 13:38, Stewart, Robert <Robert.Stewart@sig.com> wrote:
I was presuming that such a mechanism would reuse parts of Boost.Log
Then it probably wouldn't be lightweight enough and it would make other logging libraries second class backends. It also wouldn't be usable from anything which is more portable than Boost.Log. Daniel

Roland Bock wrote:
About warnings, I am not sure. When would a generic library (like the ones found in boost) issue a warning?
I just know that the need to report warnings arises quite often in my experience. From "deprecation warnings" to "inaccurate results" caused by "extremely coarse" user supplied numerical parameters (or excessive computation time due to "extremely fine" user supplied numerical parameters). Same goes for "information" reporting, especially "progress information" for such things as "progress bars". I don't believe that "generic libraries" are free from these issues. Why "generic" by the way? Is there really a difference with respect to warnings for "libraries" versus "generic libraries"? Regards, Thomas

On Friday 12 March 2010 13:00:31 Barend Gehrels wrote:
Dmitry Goncharov wrote:
Barend Gehrels wrote:
Andrey Semashev wrote:
No, the library has to be compiled anyway. However, if your application is a single .exe module, you can link statically with Boost.Log and other libraries.
OK, I must say that I'm not so happy with that. What is the reason for the need to compile? Logging is very useful, but to statically link only because of logging is in many cases not convenient.
There was a report that it had taken about 20 minutes to compile the lib. Do you really want to spend 20 minutes each time you compile an application which uses the lib? Or would you rather compile the lib once and then link against it?
That also sounds not good.
However, what might happen is that if there is an attractive logging library, Boost library writers start to use it, of course. All libraries using the logging functionality will need compilation. I normally use only header only libraries from Boost (sometimes making an exception). So this scenario might cause me stopping using Boost... There are much more people using only header-only Boost headers.
It might be even worse. If *existing* libraries will start using Boost.Log in an update (because it is really useful), existing project files and solutions will be broken.
And finally for me the worst case scenario: if *existing *libraries *used in Boost.Geometry* will start using Boost.Log in an update, our Boost.Geometry library is broken and not header only anymore.
That is the reason that I'm really not happy with this, and I think it should be fixed.
I believe that discussions about header-onlyness and relative merits thereof happened on this list before, and probably more than once, and it's safe to assume that no conclusion can ever be reached. Which probably means that the decision is with the author(s) of each individual library. - Volodya

On 03/12/2010 01:52 PM, Vladimir Prus wrote:
I believe that discussions about header-onlyness and relative merits thereof happened on this list before, and probably more than once, and it's safe to assume that no conclusion can ever be reached. Which probably means that the decision is with the author(s) of each individual library.
Agreed.

On 03/12/2010 01:00 PM, Barend Gehrels wrote:
However, what might happen is that if there is an attractive logging library, Boost library writers start to use it, of course. All libraries using the logging functionality will need compilation. I normally use only header only libraries from Boost (sometimes making an exception). So this scenario might cause me stopping using Boost... There are much more people using only header-only Boost headers.
I think, you're exaggerating things. I agree that linking with a library is a bit more complicated than including a header, but it's hardly a showstopper. If it is, you should really revise your build system, and it's not Boost's concern, IMHO.
It might be even worse. If *existing* libraries will start using Boost.Log in an update (because it is really useful), existing project files and solutions will be broken.
And finally for me the worst case scenario: if *existing *libraries *used in Boost.Geometry* will start using Boost.Log in an update, our Boost.Geometry library is broken and not header only anymore.
If you're speaking of libraries in the broader meaning than Boost, then I see no problem in using Boost.Log in them. In fact, I think Boost.Log is suited quite well for this scenario. That actually is also true for the compiled libraries in Boost. As for header-only libraries, I think, the most reasonable solution would be to provide a configuration option for these libraries, so that the user is able to decide, whether he wants logging or not. After all, if the user already employs Boost.Log in his application, there's no downside if headers of Boost libraries also use Boost.Log to provide more information. If the user strives for header-onlyness, he would be able to remove references to Boost.Log.

Hi Andrey, If you're speaking of libraries in the broader meaning than Boost, then I see no problem in using Boost.Log in them. In fact, I think Boost.Log is suited quite well for this scenario. That actually is also true for the compiled libraries in Boost. Sure, for non-Boost libraries I don't see problems and Boost.Log will be useful. As for header-only libraries, I think, the most reasonable solution would be to provide a configuration option for these libraries, so that the user is able to decide, whether he wants logging or not. After all, if the user already employs Boost.Log in his application, there's no downside if headers of Boost libraries also use Boost.Log to provide more information. If the user strives for header-onlyness, he would be able to remove references to Boost.Log. This sounds as a reasonable 'solution' indeed. Logging in libraries is in many situations done for the library writer, just as a debugging utility. It's probably always optional then. The cases where it's broader than debugging, it should also be optional and I hope library writers (especially the ones Boost.Geometry depends on) will do that. So I state 'solution' because there is nothing to 'force' a library writer. However, most header-only library writers will probably not convert their library to non-header-only, only for logging. I've seen that you also refer to the possibility to make Boost.Log header only in your TODO list. Thanks, Barend

On 03/12/2010 12:40 PM, Barend Gehrels wrote:
Is it possible to use Boost.Log in header-only mode, assuming a simple use case without threads and separate DLLs?
No, the library has to be compiled anyway. However, if your application is a single .exe module, you can link statically with Boost.Log and other libraries.
OK, I must say that I'm not so happy with that. What is the reason for the need to compile? Logging is very useful, but to statically link only because of logging is in many cases not convenient.
You do link anyway, do you? :) What is the problem of adding a library to the linker command line?
Would it be possible (technically or otherwise) to adapt it to be header only, as a whole or just the core part?
Not right now. The library relies on process-scope singletons in several places. Also, the implementation itself is heavy enough. Another alternative I might suggest is to compile the library sources along with your project.

On Mar 8, 2010, at 1:37 AM, Vladimir Prus wrote:
The downloads are at:
Hi, I was thinking of submitting a review, tried to build the library with gcc-4.2.4, and ran into this error. I apologize in advance if this has already been discussed / resolved, I haven't been following the discussion. ../../../boost/intrusive/detail/is_stateful_value_traits.hpp:38: error: ‘& boost::intrusive::derivation_value_traits<T, NodeTraits, LinkMode>::to_node_ptr [with T = boost::log_st::basic_attribute_set<wchar_t>::implementation::node, NodeTraits = boost::log_st::<unnamed>::ordered_list<boost::log_st::basic_attribute_se t<wchar_t>::implementation::node, boost::log_st::basic_attribute_set<wchar_t>::node_base>::node_traits, boost::intrusive::link_mode_type LinkMode = safe_link]’ is not a valid template argument for type ‘boost::log_st::basic_attribute_set<wchar_t>::node_base* (*) (boost::log_st::basic_attribute_set<wchar_t>::implementation::node&)’ because function ‘static typename NodeTraits::node_ptr boost::intrusive::derivation_value_traits<T, NodeTraits, LinkMode>::to_node_ptr(typename std::iterator_traits<typename boost::pointer_to_other<typename NodeTraits::node_ptr, T>::type>::reference) [with T = boost::log_st::basic_attribute_set<wchar_t>::implementation::node, NodeTraits = boost::log_st::<unnamed>::ordered_list<boost::log_st::basic_attribute_se t<wchar_t>::implementation::node, boost::log_st::basic_attribute_set<wchar_t>::node_base>::node_traits, boost::intrusive::link_mode_type LinkMode = safe_link]’ has not external linkage "g++" -ftemplate-depth-128 -O0 -fno-inline -Wall -g -fno-strict- aliasing -DBOOST_ALL_NO_LIB=1 -DBOOST_LOG_BUILDING_THE_LIB=1 - DBOOST_LOG_NO_THREADS -DBOOST_LOG_USE_NATIVE_SYSLOG=1 - DBOOST_SYSTEM_STATIC_LINK=1 -DDATE_TIME_INLINE -I"../../.." -c -o "../../../bin.v2/libs/log/build/gcc-4.2.4/debug/link-static/ attribute_set.o" "../../../libs/log/src/attribute_set.cpp" The tar ball was named RC4 and was laid down over Boost trunk in case that matters. -- Noel Here's the program I was trying to compile. #include <iostream> #include <stdexcept> #include "mpi.h" #include <boost/log/core.hpp> #include <boost/log/trivial.hpp> int main (int argc, char *argv[]) { try { boost::log::sources::logger lg; MPI_Init(&argc, &argv); int rank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &rank); BOOST_LOG(lg) << "hello from processor " << rank << "\n"; MPI_Finalize(); } catch (std::exception& e) { std::cout << e.what() << std::endl; } catch (...) { } return 0; }

On 03/15/2010 10:07 PM, K. Noel Belcourt wrote:
On Mar 8, 2010, at 1:37 AM, Vladimir Prus wrote:
The downloads are at:
Hi,
I was thinking of submitting a review, tried to build the library with gcc-4.2.4, and ran into this error. I apologize in advance if this has already been discussed / resolved, I haven't been following the discussion.
The issue with GCC 4.2 was fixed in SVN trunk after RC4 was released. Checkout as described here: https://sourceforge.net/scm/?type=svn&group_id=199644
participants (16)
-
Andrey Semashev
-
barend
-
Barend Gehrels
-
Boris Schaeling
-
Christian Holmquist
-
Daniel James
-
Daniel Larimer
-
Dmitry Goncharov
-
K. Noel Belcourt
-
Michael Caisse
-
Roland Bock
-
Rutger ter Borg
-
Stewart, Robert
-
strasser@uni-bremen.de
-
Thomas Klimpel
-
Vladimir Prus