Boost logo

Boost :

Subject: Re: [boost] [Log] Review Results
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2010-03-10 16:24:02


On 03/10/2010 08:52 PM, Roland Bock wrote:
>
> Missing Features:
> =================
> Maybe I overlooked it, but I did not find the following:
> - Have several sinks share a formatter: The programs in my company
> typically produce several log files:
> - debug: Contains everything
> - warn: Contains everything which is at least a warning
> - error: Contains everything which is error or fatal
> Messages in all files are formatted in the same way. I understand
> that I could create several file sinks and each is given its
> own formatter. But that would mean that the same formatting is
> done several times.
> Is there a way to have several sinks with different filter but
> sharing the log records?

That's an interesting idea, not very simple to implement though. The
problem is that some records can pass filtering for some of the sinks
and not the others, while the sinks may share the formatter. Further on,
formatting of the same log record for different sinks may occur in
different threads. I'll add this feature to the TODO list, I need some
time to think about it.

> Compiling:
> ==========
> - Library Code:
> As mentioned in an earlier mail, it takes awfully long to compile
> the library, which is due to one file:
>
> formatter_parser.cpp
>
> The parsing is based on Boost.Spirit (classic) and takes 20 minutes
> to compile on my maschine (Ubuntu-8.04 64bit, gcc-4.2.4, Intel Quad
> Core, 2.5GHz)

I suppose, it's because of the old compiler. On my setup (GCC 4.4, Intel
dual core, 3GHz) the whole library builds in about 1.5 minutes, in a
single thread. I'll see what I can do about it. Hopefully, the switch to
Spirit 2 will help.

> I don't know how much can be gained by switching to Spirit 2.1.
> But I am sure a way has to be found to accelerate the compilation.
> Otherwise, users will do what I did: Get nervous about the long
> compilation time and tend to press Ctrl-C before the work is done.

You can reduce build times and the binary size by disabling parts of the
library you don't use. See here:

http://tinyurl.com/yjq622b

The particular options you might be interested in are BOOST_LOG_USE_CHAR
and BOOST_LOG_NO_SETTINGS_PARSERS_SUPPORT.

> We strive for code that compiles without warnings, but with
> boost.log, I get tons of warnings. What I have seen so far should
> be easy to get rid of. But I will not be able to use the
> boost.log library unless the warnings are taken care of.

I'm using GCC 4.4 and don't get any warnings. Could you send your build
log? Perhaps, off list, if it's too heavy.

> Debugging:
> ==========
> - I tried to add a timestamp to each written record.
> This compiled, but when I ran my program, I got an exception message
> which did not really tell what was wrong:
> -----------------
> terminate called after throwing an instance of
> 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::log_mt_posix::missing_value>
> >'
> what(): Requested attribute value not found
> -----------------
> I think, at least it should tell which attribute value was not
> found. But the real reason for the exception was that
> the types of the attribute and the attribute value did not match.

I will make error messages more telling. The reason I didn't do that
earlier is that character conversion may fail and throw itself.

> - Is there a way to get to these exceptions earlier? As of now, in the
> example above, the exception is thrown when a logger is used. This
> is much too late. I need to initialize logging and then be sure
> that logging will work for the components that use it (within
> limits of course, e.g. filesystem being full).
> But mis-configurations like above must be detected before the
> real work is done in the components using the log system. For
> instance when constructing the logger.
> - Of course, best would be to prevent such stuff at compile time
> (no idea how, though)

I can't see a way to detect such errors on an earlier stage, because
filters, formatters and loggers are unrelated. Also, it's difficult to
perform this kind of check because the setup may still be valid even if
not all attributes are present in the core and/or loggers. One can use
scoped attributes to temporarily add attributes. Moreover, some
attributes may be required by particular sinks.

If you don't want exceptions to be thrown, you can use things like
flt::has_attr, std::nothrow in filters/formatters and exception handlers.

> - Flexibility: To be honest, in some aspects, I would have preferred
> to see less flexibility, for two reasons:
> a) the documentation effort rises and I suspect that the missing
> completeness of the documentation is partly a result of
> over-flexibility
> b) the testing effort rises (I guess). It will be hard to make sure
> that everything works as expected.

It's never too flexible. :) Really, there will always be someone who
wants that little thing work a bit differently.

> An example is log record formatting via Boost.Lamda, Boost.Format,
> String Templates, Custom-Formatting, which is all shown by example
> in the tutorial, but the detailed description of Formatters does not
> even mention String Templates or Custom Formatting.

String templates are described here:

http://tinyurl.com/ylxeblv

But I'll add a reference in the section about formatters.

Regarding Custom formatting, do you mean user-defined functions as
formatters? If so, what can be said on that topic?

> - Names:
> - namespace trivial: I admit that I don't like that, especially
> since its content is not exactly trivial. Easy, basic or default
> maybe, I don't know. But not trivial :-)

Trivial is the usage pattern, the implementation may not be trivial
(although, it is quite simple, as for me).

> Documentation:
> ==============
>
> I admit that I got lost on the last few pages, but was probably due to
> me not actually experimenting with all of it.

Can you point me to the particular sections that were difficult to read?

> Build process:
> - it would be nice, if the default build configuration were documented

By default the "all included" version is built. This comes from the
Installation section that I mentioned earlier. I'll spell it out explicitly.

> - I wonder which build configuration will be used when the library is
> included in boost?

I don't plan to change the configuration mechanism upon inclusion.

> Tutorial:
> - Trivial logging with filters: The "Tip" that streaming expressions
> are not evaluated if the message is filtered should probably be a
> warning of potential hazard. It is certainly a good feature, but
> the semantics of the macros are not immediately obvious so I would
> give the "Tip" a more critical nature.

Ok.

> - none of the code examples is complete. They are missing the
> namespace declarations documented in the introduction, at least.
> While brevity is good, it would be very helpful to have complete,
> compiling examples in the tutorial

I don't think adding namespaces and includes to examples in the readable
documentation is a good idea. As you noted, these examples should be
brief and free of such noise. However, I will reorganize the docs, so
that the code samples will be taken from compilable external files.

> Missing Documentation:
> - Not all include files are mentioned. This makes it unnecessarily
> tough to follow the examples.
> For instance, boost/log/utility/empty_deleter.hpp is required to
> use logging::empty_deleter. I could not find this information in
> all of the turorial and details.
> Another, maybe even more critical example: The BOOST_LOG macro
> is defined in boost/log/sources/record_ostream.hpp
> Again I did not find that information in the tutorial.

Yes, these small bits fell out of my scope. If only it was possible to
generate the reference both header-based (like it is now) and
content-based...

> - I understand that I can use my own set of severity levels. It is
> well documented how to filter messages using these severity levels.
> But I have no idea how to format messages with these severity
> levels? I do not want the number, I'd like a string, of course.
> I looked it up in the trivial.hpp, but it should be part of
> the documentation.

It is described in the formatters section:

http://tinyurl.com/yh3r7ue

All you have to do is to define operator<<. The approach is also
demonstrated in examples.

> - Maybe I missed it, but I did not find an overview of the log
> rotation options, including a description of the placeholders in
> strings.

http://tinyurl.com/ygpxtgc

> Specific question: Can I tell the log rotation to take place at
> midnight (regardless of the amount of data which is being logged)?

No, you currently cannot specify a specific time point of rotation, but
you can specify the rotation period. I've been requested to support time
point rotation, so I'll implement it some time.

> I would like to stress this last item one more time: The examples are
> excellent, but they should be accompanied by more formal tables which
> show the complete set of options, e.g. which placeholders can be used in
> a filename format or a list of public (protected?) member functions of a
> logger. For instance, I found the logger::strm() member in examples only.

The functions and their arguments (including named ones) are described
in the Reference section. That is the formal interface description. The
more expanded description with code samples in the Detailed features
description. If you found inconsistencies or something missing in
particular, I'll be glad to fix it.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk