[log] Questions for Andrey

I've been converting a program from John's logging library to Andrey's logging library. I have to continue playing around with Andrey's library but in the moment I prefer it over John's library. I can't say really that this or that is better - it's more the overall handling of Andrey's logging library which feels more natural for me. Maybe it's also Andrey's documentation which is rather good (the definitions and design overview really help to understand the big picture before you dive into all the details). I've some questions though for Andrey: * Where is the connection between a source and a sink? In the basic_usage example there are two sinks registered (console and file). There is then one source created which is used to log a message. The message is then sent to both the console and the file. But what if I want to use for example two sources and want messages from each source to be sent to a different sink? Do I understand correctly that I need to use attributes somehow and filter records based on attribute values? I guess I would need to add an attribute to each source and set a filter in each sink to make sure only messages with a certain attribute are written? * If I want to format a message and add a timestamp why do I need to write boost::log::formatters::date_time("TimeStamp") and can't write boost::log::formatters::attr("TimeStamp")? Doesn't the attribute value know how to be serialized (or isn't it written to a std::ostream)? If I use boost::log::formatters::attr("TimeStamp") nothing is written to the log file. It's not a problem to use boost::log::formatters::date_time("TimeStamp") of course. But I still wonder why the library can't figure out to write the timestamp if I use boost::log::formatters::attr("TimeStamp"). * I've been reading http://boost-log.sourceforge.net/libs/log/doc/html/advanced/advanced.html#ad... a few times but still don't understand why I can't (or shouldn't) instantiate a global logger with "boost::log::sources::logger logger;". I actually did this and everything works (or at least seems to work :). Must the macro BOOST_LOG_DECLARE_GLOBAL_LOGGER really be used when a global logger is created? Maybe I better understand if I ask differently: What is so special about a logger that I need to use a macro to define it globally while I can create for example a global std::string instance without a macro? * By default there is a newline appended to every message written? By the way, looking at the TODO list: I would be very much interested in Windows NT event log support. I'm sure it would also convince more developers to use a logging library as writing texts to files in some fancy ways can also be done without a logging library. :) Boris

Boris wrote:
I've been converting a program from John's logging library to Andrey's logging library. I have to continue playing around with Andrey's library but in the moment I prefer it over John's library. I can't say really that this or that is better - it's more the overall handling of Andrey's logging library which feels more natural for me. Maybe it's also Andrey's documentation which is rather good (the definitions and design overview really help to understand the big picture before you dive into all the details).
I've some questions though for Andrey:
* Where is the connection between a source and a sink? In the basic_usage example there are two sinks registered (console and file). There is then one source created which is used to log a message. The message is then sent to both the console and the file. But what if I want to use for example two sources and want messages from each source to be sent to a different sink? Do I understand correctly that I need to use attributes somehow and filter records based on attribute values? I guess I would need to add an attribute to each source and set a filter in each sink to make sure only messages with a certain attribute are written?
Correct. There is no direct connection between sources and sinks, so that records from any source may go to any sink. Which sink will finally process a record is totally defined by filtering. If you want to relate your loggers and sinks, the simpliest way to do so is to use channel_logger and set up filters in your sinks that will pass through only records from needed channels.
* If I want to format a message and add a timestamp why do I need to write boost::log::formatters::date_time("TimeStamp") and can't write boost::log::formatters::attr("TimeStamp")? Doesn't the attribute value know how to be serialized (or isn't it written to a std::ostream)?
The attr formatter should work too. The date_time formatter provides additional formatting facilities, while attr always simply puts the attribute value to a stream.
If I use boost::log::formatters::attr("TimeStamp") nothing is written to the log file.
That's odd. Could you send a short code sample that shows the problem?
* I've been reading http://boost-log.sourceforge.net/libs/log/doc/html/advanced/advanced.html#ad... a few times but still don't understand why I can't (or shouldn't) instantiate a global logger with "boost::log::sources::logger logger;". I actually did this and everything works (or at least seems to work :). Must the macro BOOST_LOG_DECLARE_GLOBAL_LOGGER really be used when a global logger is created? Maybe I better understand if I ask differently: What is so special about a logger that I need to use a macro to define it globally while I can create for example a global std::string instance without a macro?
There's nothing in loggers that prevent you from creating them globally. There are several significant differences, though, between using the macro and a global logger: 1. In general, having global non-POD variables (not necessarily a logger) is not thread-safe. If there are multiple threads running while global variables are initialized, you may end up executing one object's constructor multiple times concurrently. The macro is thread safe in this respect. 2. The macro defines a logger that will be truly global throughout the application, even if the application consists of multiple modules. By doing so, it doesn't introduce any additional linking dependences. Global variables, depending on their definition, are visible either in a single translation unit, or a single module. You will notice the difference when you try to manage attributes of the global logger. 3. The loggers defined with the macro are lazily constructed, while global variables tend to be constructed on the application startup. As a side effect of the macro implementation, it is significantly easier to use the macro to declare loggers in header-only components. In order to achieve this with global variables you would have to resort to various tricks to avoid linking failures.
* By default there is a newline appended to every message written?
Yes, the text ostream sink adds a newline after each log record.
By the way, looking at the TODO list: I would be very much interested in Windows NT event log support. I'm sure it would also convince more developers to use a logging library as writing texts to files in some fancy ways can also be done without a logging library. :)
That's why it's in TODO. :) However, I'm not sure this functionality is a must for the first release.

On Wed, 20 Aug 2008 18:27:39 +0200, Andrey Semashev <andrey.semashev@gmail.com> wrote: Hi Andrey,
[...]
If I use boost::log::formatters::attr("TimeStamp") nothing is written to the log file.
That's odd. Could you send a short code sample that shows the problem?
here's the entire program: ---------- #include <boost/log/sources/severity_logger.hpp> #include <boost/log/logging_core.hpp> #include <boost/log/utility/init/to_file.hpp> #include <boost/log/utility/init/common_attributes.hpp> #include <boost/log/formatters/format.hpp> #include <boost/log/formatters/attr.hpp> #include <boost/log/formatters/message.hpp> #include <boost/shared_ptr.hpp> boost::log::sources::severity_logger logger; int main() { boost::log::add_common_attributes(); boost::shared_ptr<boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend>> sink = boost::log::init_log_to_file("test.txt"); sink->locked_backend()->set_formatter(boost::log::formatters::format("[%1%] %2%") % boost::log::formatters::attr("TimeStamp") % boost::log::formatters::message()); sink->locked_backend()->auto_flush(true); BOOST_LOG(logger) << "message"; } ---------- If I build it with VC++ 9.0 SP1 the file test.txt contains afterwards: [] message Only if I use boost::log::formatters::date_time("TimeStamp") the timestamp is written. Boris
[...]

Boris wrote:
On Wed, 20 Aug 2008 18:27:39 +0200, Andrey Semashev <andrey.semashev@gmail.com> wrote:
Hi Andrey,
[...]
If I use boost::log::formatters::attr("TimeStamp") nothing is written to the log file.
That's odd. Could you send a short code sample that shows the problem?
here's the entire program:
---------- #include <boost/log/sources/severity_logger.hpp> #include <boost/log/logging_core.hpp> #include <boost/log/utility/init/to_file.hpp> #include <boost/log/utility/init/common_attributes.hpp> #include <boost/log/formatters/format.hpp> #include <boost/log/formatters/attr.hpp> #include <boost/log/formatters/message.hpp> #include <boost/shared_ptr.hpp>
boost::log::sources::severity_logger logger;
int main() { boost::log::add_common_attributes();
boost::shared_ptr<boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend>> sink = boost::log::init_log_to_file("test.txt");
sink->locked_backend()->set_formatter(boost::log::formatters::format("[%1%] %2%") % boost::log::formatters::attr("TimeStamp") % boost::log::formatters::message());
sink->locked_backend()->auto_flush(true);
BOOST_LOG(logger) << "message"; } ----------
If I build it with VC++ 9.0 SP1 the file test.txt contains afterwards:
[] message
Only if I use boost::log::formatters::date_time("TimeStamp") the timestamp is written.
This is not a bug. The problem is that you used attr formatter without specifying date type. The attr formatter by default supports most fundamental types and strings. For other types the attribute value type (or set of types) must be specified explicitly: boost::log::formatters::attr< boost::posix_time::ptime >("TimeStamp") As for the date_time formatter, it implicitly supports all date and time types defined in the library documentation, which includes ptime. That's why it worked right away.

On Wed, 20 Aug 2008 20:36:47 +0200, Andrey Semashev <andrey.semashev@gmail.com> wrote:
[...]
If I build it with VC++ 9.0 SP1 the file test.txt contains afterwards:
[] message
Only if I use boost::log::formatters::date_time("TimeStamp") the timestamp is written.
This is not a bug. The problem is that you used attr formatter without specifying date type. The attr formatter by default supports most fundamental types and strings. For other types the attribute value type (or set of types) must be specified explicitly:
boost::log::formatters::attr< boost::posix_time::ptime >("TimeStamp")
As for the date_time formatter, it implicitly supports all date and time types defined in the library documentation, which includes ptime. That's why it worked right away.
Thanks for the explanation! I'm not sure if I had found out without your help. I don't know about others but maybe my questions here help to improve the (already pretty good) documentation. Or is this explained already somewhere that I just missed it? Boris

Boris wrote:
On Wed, 20 Aug 2008 20:36:47 +0200, Andrey Semashev <andrey.semashev@gmail.com> wrote:
[...]
If I build it with VC++ 9.0 SP1 the file test.txt contains afterwards:
[] message
Only if I use boost::log::formatters::date_time("TimeStamp") the timestamp is written.
This is not a bug. The problem is that you used attr formatter without specifying date type. The attr formatter by default supports most fundamental types and strings. For other types the attribute value type (or set of types) must be specified explicitly:
boost::log::formatters::attr< boost::posix_time::ptime >("TimeStamp")
As for the date_time formatter, it implicitly supports all date and time types defined in the library documentation, which includes ptime. That's why it worked right away.
Thanks for the explanation! I'm not sure if I had found out without your help. I don't know about others but maybe my questions here help to improve the (already pretty good) documentation. Or is this explained already somewhere that I just missed it?
I thought I mentioned it. I'll point that out in the attr formatter description section.
participants (2)
-
Andrey Semashev
-
Boris