
Hello, So here is the question: "Is there any interest in a logging library for boost?" John Torjo did not answer my mail, beside I looked at pantheios. it seems a little bit complex... My idea is that a logging library should be _simple_ to use. Here is a small example: // snippet on #include <fstream> #include <boost/logging.hpp> int main(int argc, char **argv) { BOOST_LOG_INIT(("[" >> boost::logging::level >> "]," >> boost::logging::filename >> "(" >> boost::logging::line >> ")," >> boost::logging::time >> "," >> boost::logging::trace >> boost::logging::eol), // log format 2); // log level BOOST_LOG_ADD_OUTPUT_STREAM(new std::ofstream("./output.log")); BOOST_LOG_ADD_OUTPUT_STREAM(&std::cout); BOOST_LOG(1, "something"); BOOST_LOG(2, "something else"); BOOST_LOG(3, "doesn't matter"); char you_want[256] = "you want"; BOOST_LOG(1, "Let's say " << you_want << " to display " << 2); return 0; } // snippet off You can find the first draft of a logging library in the boost Sandbox vault. It consists of a header files, some examples and documentation. Put the file at your boost root folder and unzip it. It compiles with msvc and vc-8_0. I'll try with gcc asap. So let me know if you think it worth something or not. JD

I havent had a chance to look at your code or pantheios yet but I am interested in your library. A boost library would be something to standardize on for larger projects. One facility I like to have however is the ability to output to the debugger. Does yours do this or do you intend to add it ? Its not always feasible to do this for performance reasons though so you need to be able to toggle it off and on of course(Full screen games are my biggest culprit there). I have a very simple library I wrote myself to allow this but it is lacking some features as well. It seems everyone has their own homegrown solution to this. TIA JD wrote:
Hello,
So here is the question: "Is there any interest in a logging library for boost?"
John Torjo did not answer my mail, beside I looked at pantheios. it seems a little bit complex... My idea is that a logging library should be _simple_ to use.
Here is a small example:
// snippet on #include <fstream> #include <boost/logging.hpp>
int main(int argc, char **argv) { BOOST_LOG_INIT(("[" >> boost::logging::level >> "]," >> boost::logging::filename >> "(" >> boost::logging::line >> ")," >> boost::logging::time >> "," >> boost::logging::trace >> boost::logging::eol), // log format 2); // log level
BOOST_LOG_ADD_OUTPUT_STREAM(new std::ofstream("./output.log")); BOOST_LOG_ADD_OUTPUT_STREAM(&std::cout);
BOOST_LOG(1, "something"); BOOST_LOG(2, "something else"); BOOST_LOG(3, "doesn't matter"); char you_want[256] = "you want"; BOOST_LOG(1, "Let's say " << you_want << " to display " << 2);
return 0; } // snippet off
You can find the first draft of a logging library in the boost Sandbox vault. It consists of a header files, some examples and documentation. Put the file at your boost root folder and unzip it.
It compiles with msvc and vc-8_0. I'll try with gcc asap.
So let me know if you think it worth something or not.
JD
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Richard Day wrote:
I havent had a chance to look at your code or pantheios yet but I am interested in your library. A boost library would be something to standardize on for larger projects. One facility I like to have however is the ability to output to the debugger. Does yours do this or do you intend to add it ?
Output to the debugger? You mean pass some kind of message to the debugger? And what the debugger does with those messages, just print them? I didn't think about that actually. But I guess there is no standardized way to do this, it depends on the debugger you use, or worst your system. I'm not sure an eventual Boost.Logging library should deal with this, but at least let some space for a particular user to append a interface to the debugger easily. How can it be done and still retain the simplicity of the library?
Its not always feasible to do this for performance reasons though so you need to be able to toggle it off and on of course(Full screen games are my biggest culprit there). I have a very simple library I wrote myself to allow this but it is lacking some features as well. It seems everyone has their own homegrown solution to this.
I think this is why there is still no logging library integrated into boost. Everybody has his idea (and sometime his own library) and nobody is able to agree on the minimum specification and stick with it. That is why my proposal is to define a small set of specifications, the lowest common denominator. I'm reading the old threads on this subject and try to aggregate something. JD

JD,你好! Almost every debugger could catch the message output by OutputDebugString(W) API in Windows box. ======= 2007-04-01 16:23:37 你在来信中写道:=======
Richard Day wrote:
I havent had a chance to look at your code or pantheios yet but I am interested in your library. A boost library would be something to standardize on for larger projects. One facility I like to have however is the ability to output to the debugger. Does yours do this or do you intend to add it ?
Output to the debugger? You mean pass some kind of message to the debugger? And what the debugger does with those messages, just print them? I didn't think about that actually. But I guess there is no standardized way to do this, it depends on the debugger you use, or worst your system. I'm not sure an eventual Boost.Logging library should deal with this, but at least let some space for a particular user to append a interface to the debugger easily. How can it be done and still retain the simplicity of the library?
Its not always feasible to do this for performance reasons though so you need to be able to toggle it off and on of course(Full screen games are my biggest culprit there). I have a very simple library I wrote myself to allow this but it is lacking some features as well. It seems everyone has their own homegrown solution to this.
I think this is why there is still no logging library integrated into boost. Everybody has his idea (and sometime his own library) and nobody is able to agree on the minimum specification and stick with it. That is why my proposal is to define a small set of specifications, the lowest common denominator. I'm reading the old threads on this subject and try to aggregate something.
JD
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
= = = = = = = = = = = = = = = = = = = = 致 礼! missdeer missdeer@gmail.com 2007-04-01

Hi Jean Daniel I also have been working on a logger and have been considering proposing it for inclusion in boost. I feel that a logger must be both simple and a natural extension of the standard stream libraries. Essentially everything should be a stream. A logger then is merely a facilitator for managing streams of messages generated by a piece of software. So if you want to send some of your logging output to a file you might attach a std::fstream to the logger. If you want to sent your output over a network you might attack a socket_stream to the logger. So basically the logger manages the aggregation of various streams of information. In addition to this the logger must enable a certain amount of control over these aggregate streams. Traditionally this is managed by masking off one or more streams when their output is not desired. The other form of control the logger would need to exert over the data itself would be formatting information. Each logging event will capture a definite amount of data at a given point in program execution. This data would typically be time, date, message etc. The logger should not format this data itself as that would be too restrictive on the desired output. Rather the logger should be able to accept a formatting object to do this job appropriately to the given task. For instance I might want one output stream going onto disk performing the absolute minimum of formatting for maximum performance. In addition to this I might want to be able to turn on a second output stream which writes much more user friendly messages to the terminal. The formatting of this stream could be much embellished as performance would not be critical. This would mean that I should be able to pass a formatting object to the logger for that stream that produces nicer results. For instance it could introduce terminal control codes into the collected data to give spiffing color output. So to put this into typical code one might have: #include <boost/logger/log.hpp> #include <iostream> #include <fstream> using namespace std; using namespace boost; fstream disk_stream("disk.log"); logger& log = logger::get_logger(STANDARD_LOGGER); int main(int argc, char* args[]) { log.attach_ostream("term", std::cout); // to terminal log.attach_ostream("disk", disk_stream); // to disk log.set_log_form("term", LOG_FORM_XTERM); // color formatted log.set_log_form("disk", LOG_FORM_RAW); // machine readable log << "Begin logging" << endl; for(int i = 0; i < 10; ++i) { log << "Message number " << i << endl; } } So basically the logger itself remains simple, all it does is manage a collection of std::ostream derived objects. Externally defined formatting objects are employed to manage the actual presentation. I personally feel that macros should be avoided as much as possible. One argument for using macros is the ability to conditionally include or exclude the logging code at compile time. However this view is usually a product of 'developer centric' thinking and misses the much more important 'user centric' aspects of logging. The fact is that there are an awful lot of reasons to add logging information to a piece of software other than debugging. It is often desirable to be able to monitor the ongoing state of any medium to large sized application so this activity is not solely for the benefit of the developer. On top of this, the number of places in a piece of software where performance is critical is often quite low. For really critical sections of code then of course a compile time defined macro could be appropriate. However I feel that in the many cases logging should be considered an integral part of the software being developed and so to be available in the production hardened release. The current version of my logger is hosted on sourceforge.net at http://sourceforge.net/projects/logplusplus/ Right now it is undergoing some major revision to separate out what really is core logger activity and what is 'optional extras'. When that is complete I will likely place it in the sandbox for interested people to assess. Jean, I will be looking over your contribution soon to see what common ground our loggers share and if there might be a possibility of some 'cross pollination' of ideas. Regards, -Galik JD wrote:
Hello,
So here is the question: "Is there any interest in a logging library for boost?"
John Torjo did not answer my mail, beside I looked at pantheios. it seems a little bit complex... My idea is that a logging library should be _simple_ to use.

I'd avise both of you to look at John Torjo's library, and read the review comments. John pulled the library, but it would benefit you greatly to see what others thought, and more specifically what they want in a boost logging library.

Jody Hagins wrote:
I'd avise both of you to look at John Torjo's library, and read the review comments. John pulled the library, but it would benefit you greatly to see what others thought, and more specifically what they want in a boost logging library. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Thanks Jody, we should definitely avoid starting from scratch again. The problem is that there is so many divergent propositions and ideas, and aggregate them won't be an easy task. Here is a couple of ideas I have glanced from previous threads: John Torjo had actually a similar point of view to mine. He was looking for simplicity. As we are talking to a wide range of users, the library should have almost no learning curve. Looking at the basic example in the tutorial should be enough to get the fundamental usage of it. John had also in mind the possibility to disconnect module of application from the logger. For example, from a certain point in the code, the GUI logs would be discarded. He also wanted the library to be small, and I fully agree with this. A header file and that's it. Not anyone agree with this, Vladimir Prus for example was expecting something more configurable. Pavel Vozenilek added: "Maybe it is possible to design a library which has (by default) this simple interface but allows very fine customization." That is why I'm trying to concentrate on the first part (design a library which has (by default) this simple interface) and then, a second part could be handled by other people interested in fine customization. As a first set of requirements, Caleb Epstein stated those, and Rene Riviera answered: <CE>: Uses iostreams <RR>: I disagree. Like most things STL it should be independent of a stream back end. And ideally independent of a formatting front end. It should only be a tagging, filtering, and multiplexing interface. <CE>: Thread-safe (e.g. two threads can't have their output intermixed in the output file/stream/whatever like they would with simple ostream<< operators) <RR>: Yes, but only if needed. It might not be appropriate depending on the front end or back end. For example you might be dumping the "output" to a database which would create individual debug records. No need for thread safety at the log level in that case. <CE>: Multiple possible output media (files, sockets, syslog, Windows event log, etc) RR: Multiplexing <CE>: Multiple named channels each with configurable "threshold" (e.g. error, warning, debug, etc) <RR>: And configurable, so that you can program what each one does on both the front end and to which back end they go to. <JD>: The log level (unsigned short) could handle that. OR maybe a mask would be more appropriate ? <CE>: Messages which won't be logged shouldn't even go through the formatting step. I'm pretty sure this cannot be done in a single call w/o macros though. Johan Nilson also engaged a lengthy discussion. Few ideas I have retain from him: Structured logging functionality. (<JD>: Is it formatting you are talking about?) log_item for formatting (<JD>: What I called log_element in the library I have posted). Daryl Green seems to have a put a lot of though into this and also define a set of requirements I'm trying to summarize here, some of them are pure citation: - The logging library must be very efficient in handling disabled "logs". - The logging library must be user extensible to add new output (appender) facilities. This should be very easy and not require in-depth knowledge/study of library/its docs to do. Appenders, which are likely to have system dependencies, should not be tightly coupled with the core logging facilities. (<JD>: Wishful thinking ?) - The library must scale well. This should include the ability to (efficiently) use a very minimal form of the library in small, perhaps single-threaded only, apps as well as achieving good performance on multiprocessor platforms in multi threaded apps. (<JD>: The first part I was talking about, but the multi threading shall not be an option for me). I agree also with Daryl that a very simple, extensible library can be submitted first and extended in the future. If we wait for a complete logging library to introduce it into boost, we'll never have it... Maxim Yegorushkin asked for file management (cycling through log file, file size control). I think this is interesting but shall not make it into the core library. Maybe an helper object, in a distinct header file could make it. Still I think this shall not be part of the first line of proposal as it tends to divert the discussion and prevent decision on the core logging library itself to be taken. Some few ideas I saw: + Scoped log (<JD>: what is a scoped log?) + fast compile time Technical questions: + thread id: How to retrieve thread id with Boost.Threads? + program name: Is argv[0] a good idea to retrieve program name? I don't why i wouldn't, but just in case. Now, some point raised during the formal review of John's library: - Roman Yakovenko: He was not pleased by the way John's library handles macro. In this library, here is the way you log something: BOOST_LOG(dbg) << "this is a debug message, i=" << i << std::endl; In any case, logging avtivated or not, the message will be streamed. What I developped in the logging library posted above is to encapsulate the streaming in the macro, as propose by many people during the discussion: BOOST_LOG(1, "this is a debug message, i=" << i << std::endl); The streaming will be performed only if necessary. Note, the library I posted does not handle it correctly (the test is perform after the streaming ;p), but it will. I also see the need of a compile time disabling. Here again, I'm not sure the library shall deal with this. Just define some macro like: BOOST_LOG_L1(trace) BOOST_LOG(1, trace) BOOST_LOG_L2(trace) BOOST_LOG(2, trace) #ifdef _DEBUG BOOST_LOG_L3(trace) BOOST_LOG(3, trace) #elseif BOOST_LOG_L3(trace) ; #endif // _DEBUG - Andras Erdei: "My main concern about logging is that it changes application behavior: often there are bugs that only surface in release code because logging is slow and it introduces synchronizing, so logging should be as fast as possible, and locks should be avoided whenever possible." So another requirement would be that the library shall be as fast as possible (pretty obvious) and the less intrusive as possible. But I'm afraid the caveats described by Andras are inevitable. "I do not want to declare and define and initialize logs, just include a header, and then write "LOG << ..."; i do not want to give names to logfiles, and i don't want runtime configurable logs and log levels and multiline log entries and calling functions that log from inside "LOG << ..." statements" Well, I think the initialization part is essential, or you have a library that is deciding things for you, and I don't think it's a good thing. " and i do not want to pay (with runtime and additional typing) for the features i do not use." Seems fair. -> Library shall stay simple. The more simple it is, the more it has chance to get into boost and then be developed to something more evolved. To Andras remarks, John answered: " I made the logging library flexible (or at least I hope so :)), so users can tweak the lib to their needs.Logging can be so much more that writing to one file." I think this is where troubles starts. As I said, the logging library shall be simple to the cost of not being configurable at first. After inclusion to boost, it can get better. Yes, it looks like petty politics, but how come there is no logging library into boost with all the interest it has in the past then ? JD

On Sun, 01 Apr 2007 12:08:00 +0200 JD <jean.daniel.michaud@gmail.com> wrote:
Here is a couple of ideas I have glanced from previous threads:
Having done you research is a great start. As you can see, the opinions differ widely. I think you have to have a simple interface that is efficient and easy to use. However, you also need a way to offer extensive customizations. This is the hard part, and where the real problem exists.
I think this is where troubles starts. As I said, the logging library shall be simple to the cost of not being configurable at first. After inclusion to boost, it can get better. Yes, it looks like petty politics, but how come there is no logging library into boost with all
the interest it has in the past then ?
I think because there could not be a good enough agreement. You have to bring a very good library, with a polished argument. OR... you have to be willing to endure the lengthy discussions that will lead to such.

Hello, JD! You wrote on Sun, 01 Apr 2007 12:08:00 +0200: J> Thanks Jody, we should definitely avoid starting from scratch again. The problem is that there is so many divergent propositions and ideas, and aggregate them won't be an easy task. Here is a couple of ideas I have glanced from previous threads: John Torjo had actually a similar point of view to mine. He was looking for simplicity. As we are talking to a wide range of users, the library should have almost no learning curve. Looking at the basic example in the tutorial should be enough to get the fundamental usage of it. John had also in mind the possibility to disconnect module of application from the logger. For example, from a certain point in the code, the GUI logs would be discarded. He also wanted the library to be small, and I fully agree with this. A header file and that's it. I think this is a very bad idea. Every one try to implement libs in headers. Why? Why not provide good and comprehensive infrastructure for C++ development? That is major problem. No one can easily pick package from well known source(repository), say download it and write one or two lines in jam and had a working solution. With such infrastructure building complex libs with many dependecies will be as easy as "Just include this header and every things will work". Sorry for offtopic, but this problem must be addressed somehow :( J> Not anyone agree with this, Vladimir Prus for example was expecting something more configurable. I strongly agreed with it. You provide very good overview about logging problems and their posible solutions. Looking at it I see that many of them already addressed in http://log4cpp.sourceforge.net . We use log4cpp over 5 years in 27/7 high loaded multithreaded application servers on Windows/Linux. There is no good documentation, but concepts and even api is very close to log4j. So log4j documentation is perfect start. With best regards, Konstantin Litvinenko.

Externally defined formatting objects are employed to manage the actual presentation.
I personally feel that macros should be avoided as much as possible. One argument for using macros is the ability to conditionally include or exclude the logging code at compile time.
However this view is usually a product of 'developer centric' thinking and misses the much more important 'user centric' aspects of logging. The fact is that there are an awful lot of reasons to add logging information to a piece of software other than debugging. It is often desirable to be able to monitor the ongoing state of any medium to large sized application so this activity is not solely for the benefit of the developer.
On top of this, the number of places in a piece of software where performance is critical is often quite low. For really critical sections of code then of course a compile time defined macro could be appropriate. However I feel that in the many cases logging should be considered an integral part of the software being developed and so to be available in the production hardened release.
This has been briefly discussed in the past. Caleb Epstein: * Messages which won't be logged shouldn't even go through the formatting step. I'm pretty sure this cannot be done in a single call w/o macros though. Rene Riviera: It's possible without macros for some compilers using careful template instantiation. Darren cook: I like this idea. E.g. from Caleb's next mail: BOOST_LOG (log_name) << the << things << to << output; BOOST_LOGD (log_name, the << things << to << output); Daniel Frey: OK, although there is more to keep in mind. In our logging system, we also added a try/catch macro around the expression that is to be logged. The reason is, that we never want a log-message to abort the program. For me, macro are fine. In the logging case, it allows you to log anywhere in your code without any overhead (no need to declare extern global macro) moreover the logger instance is hidden in the library internal. I think it enhance code readability (in the case of a logging library!). Then, it avoid user to deal with the log manager instantiation. At first, I though it was a flaw in the library but I tend to think that as a feature now :) Again, _simplicity_ is really what should be aimed at.
The current version of my logger is hosted on sourceforge.net at http://sourceforge.net/projects/logplusplus/
Right now it is undergoing some major revision to separate out what really is core logger activity and what is 'optional extras'. When that is complete I will likely place it in the sandbox for interested people to assess.
Jean, I will be looking over your contribution soon to see what common ground our loggers share and if there might be a possibility of some 'cross pollination' of ideas.
My point is not really to deliver a library, but more to start the discussion over and agree on a minimum set of requirements. I'm not sure this can be done actually... :) What you could you anyway, is to "boostify" your library and try to submit it (doc, test, bjam, etc...). See http://www.boost.org/more/lib_guide.htm and http://www.boost.org/more/submission_process.htm. JD

AMDG JD <jean.daniel.michaud <at> gmail.com> writes:
Caleb Epstein: * Messages which won't be logged shouldn't even go through the formatting step. I'm pretty sure this cannot be done in a single call w/o macros though.
I don't see why this wouldn't work: std::string x, y; //... logger << lazy(lambda::var(x) + ":" + y, _level = 2); If you need a compile-time switch: logger << lazy(lambda::var(x) + ":" + y, _level = mpl::int_<2>()); if you want to shut off all logging: struct logger { template<class T> logger& operator<<(const T&) {} }; In Christ, Steven Watanabe

Hi, After looking forward to a Boost Logging library for a while, I have been playing with this idea. This library http://channel.sourceforge.net/ which I believe the author is working towards including in Boost could be used to help write the logging library? Why because it works both acrosss local and remote machines and supports a asyncronous subscribing machenism. Boost.Logging could use Boost.Channel (hopefully) to allow doing of something like below somewhere along the lines of... Boost.Logging Log; // Some of these channels could be a built-in to Boost logging. // add one channel at a time Log.AddChannel(new SysLogOnLocal()); Log.AddChannel(new SysLogOnRemoteChannel("remote ip")); Log.AddChannel(new SysLogLocalAndRemoteChannel(""remote ip"); Log.AddChannel(stdout); Log.AddChannel(stderr); Log.AddChannel(GuiWindow); // add lots all together Log.AddChannel(new LocalInfoChannel(), new LocalAndRemoteInfoChannel(), new ErrorChannel(), new WarningChannel()); // writes to the info channel Log.Write(LocalInfoChannel, "Hello World"); // writes to the info channel Log.Write(LocalAndRemoteInfoChannel, "Hello World"); // writes to all the channels that the logger is subscribed to (nasty)... Log.Write("Hello World"); The possibility and the power of this thing could be, well a powerful logging library.... I suggest you look into this library during this design phase... Thanks Shams -- "JD" <jean.daniel.michaud@gmail.com> wrote in message news:eumhck$vk2$1@sea.gmane.org...
Hello,
So here is the question: "Is there any interest in a logging library for boost?"
John Torjo did not answer my mail, beside I looked at pantheios. it seems a little bit complex... My idea is that a logging library should be _simple_ to use.
Here is a small example:
// snippet on #include <fstream> #include <boost/logging.hpp>
int main(int argc, char **argv) { BOOST_LOG_INIT(("[" >> boost::logging::level >> "]," >> boost::logging::filename >> "(" >> boost::logging::line >> ")," >> boost::logging::time >> "," >> boost::logging::trace >> boost::logging::eol), // log format 2); // log level
BOOST_LOG_ADD_OUTPUT_STREAM(new std::ofstream("./output.log")); BOOST_LOG_ADD_OUTPUT_STREAM(&std::cout);
BOOST_LOG(1, "something"); BOOST_LOG(2, "something else"); BOOST_LOG(3, "doesn't matter"); char you_want[256] = "you want"; BOOST_LOG(1, "Let's say " << you_want << " to display " << 2);
return 0; } // snippet off
You can find the first draft of a logging library in the boost Sandbox vault. It consists of a header files, some examples and documentation. Put the file at your boost root folder and unzip it.
It compiles with msvc and vc-8_0. I'll try with gcc asap.
So let me know if you think it worth something or not.
JD
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 3/31/07, JD <jean.daniel.michaud@gmail.com> wrote:
Hello,
So here is the question: "Is there any interest in a logging library for boost?"
Of course there is. I see from later emails you've read the discussion surrounding John Torjo's submission (some of which was from me). Thanks for taking the time to do that. You might also give careful reading to Gennadiy Rozental's review of the library, which I believe convinced John to retract his submission: http://thread.gmane.org/gmane.comp.lib.boost.devel/134338/focus=134399 You might also want to look at this message, where I took a brief stab at implementing some of the concepts that were raised in the library proposal discussion: http://article.gmane.org/gmane.comp.lib.boost.devel/135968
Here is a small example: [...]
You can find the first draft of a logging library in the boost Sandbox vault. It consists of a header files, some examples and documentation. Put the file at your boost root folder and unzip it.
Where? I find few web sites as difficult to locate content in as the Boost Vault, so please post a fully qualified URL or the filename and the folder in which it can be found so we can look at it. Searching for "logging" turns up nothing useful. Aside[1]: Why does the Vault have *so many* folders, many of which are empty? I think this adds to the difficulty in finding arbitrary code. Aside[2]: Can the Vault URLs be made shorter (e.g. so that they don't include some long PHP session ID that makes sharing difficult)?
So let me know if you think it worth something or not.
In your example above, you're showing what looks like a 100% macro-based interface. I would recommend strongly against this. Any logging library should be free-standing and usable without *requiring* macros like the above. There will almost certainly need to be macros to implement functionality like "don't format this if it won't be logged", but it is more important to demonstrate the core classes than the macros as an introduction to how the library works. -- Caleb Epstein

Where? I find few web sites as difficult to locate content in as the Boost Vault, so please post a fully qualified URL or the filename and the folder in which it can be found so we can look at it. Searching for "logging" turns up nothing useful.

Caleb Epstein wrote:
On 3/31/07, JD <jean.daniel.michaud@gmail.com> wrote:
Hello,
So here is the question: "Is there any interest in a logging library for boost?"
Of course there is.
I see from later emails you've read the discussion surrounding John Torjo's submission (some of which was from me). Thanks for taking the time to do that. You might also give careful reading to Gennadiy Rozental's review of the library, which I believe convinced John to retract his submission:
http://thread.gmane.org/gmane.comp.lib.boost.devel/134338/focus=134399
Ouch. Gennadiy is one tough guy... He seems to have very precise idea of what is a log library, and has apparently developed one. I wonder why it's still not included into boost!...
You might also want to look at this message, where I took a brief stab at implementing some of the concepts that were raised in the library proposal discussion:
Yes, I may have use of this.
In your example above, you're showing what looks like a 100% macro-based interface. I would recommend strongly against this.
Any logging library should be free-standing and usable without *requiring* macros like the above.
Why? I like macros for this particular case. Here again there is a debate, that is not close to being over...

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of JD Sent: Monday, April 02, 2007 12:56 PM To: boost@lists.boost.org Subject: Re: [boost] Boost Logging library - first draft
Caleb Epstein wrote:
On 3/31/07, JD <jean.daniel.michaud@gmail.com> wrote:
Hello,
So here is the question: "Is there any interest in a logging library for boost?"
Of course there is.
I see from later emails you've read the discussion surrounding John Torjo's submission (some of which was from me). Thanks for taking
The gist of what I got out of the previous discussion(s) was that what is desired is a C++ api from which the user can construct and deploy a logging solution tailored to their own needs. For example, one user may need an extremely lightweight logging solution (no bells and whistles) whereas another might like a more heavyweight solution (timestamps etc). The user would configure what they want using the supplied logging api via policies or whatever. Given this idea, they would then necessarily define their own macros using their tailored logging classes. Of course, lots of examples as to how to define these macros guide the user. If I am totally off base, I am sure someone else will chime in. :) joe the
time to do that. You might also give careful reading to Gennadiy Rozental's review of the library, which I believe convinced John to retract his submission:
http://thread.gmane.org/gmane.comp.lib.boost.devel/134338/focus=134399
Ouch. Gennadiy is one tough guy... He seems to have very precise idea of what is a log library, and has apparently developed one. I wonder why it's still not included into boost!...
You might also want to look at this message, where I took a brief
stab
at implementing some of the concepts that were raised in the library proposal discussion:
Yes, I may have use of this.
In your example above, you're showing what looks like a 100% macro-based interface. I would recommend strongly against this.
Any logging library should be free-standing and usable without *requiring* macros like the above.
Why? I like macros for this particular case. Here again there is a debate, that is not close to being over...
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 4/2/07, JD <jean.daniel.michaud@gmail.com> wrote:
Caleb Epstein wrote:
Any logging library should be free-standing and usable without *requiring* macros like the above.
Why? I like macros for this particular case. Here again there is a debate, that is not close to being over...
Believe me, if you propose only a macro interface to your logging library, it won't stand a chance in the review phase. Do not read this to mean that I think there shouldn't be *any* macros. Far from it. I think some macros are unavoidable and can be used quite powerfully. I mean that the library concepts and classes should be clearly specified and usable without any macros. Some users will prefer the class interfaces, and others will want to write their *own* macros that suit their needs better than the ones you provide. All of this is possible with a well documented interface, so start there. -- Caleb Epstein

Hello JD, Sunday, April 1, 2007, 12:47:04 AM, you wrote:
Hello,
So here is the question: "Is there any interest in a logging library for boost?"
John Torjo did not answer my mail, beside I looked at pantheios. it seems a little bit complex... My idea is that a logging library should be _simple_ to use.
Here is a small example:
[snip]
You can find the first draft of a logging library in the boost Sandbox vault. It consists of a header files, some examples and documentation. Put the file at your boost root folder and unzip it.
It compiles with msvc and vc-8_0. I'll try with gcc asap.
So let me know if you think it worth something or not.
I've took a quick look at the implementation and the docs of the library. First, I'd like to thank you for performing this analysis of previous proposals attempts. You did a great job of summarizing all opinions and suggestions were made which helps to better understand the requirements to this kind of lib. Now to the point. I understand and agree that the logging library should be simple to use but I see no reason we should sacrifice the extensibility for it. To my mind a carefully designed library interface is the way to go, not the functionality and extensibility limitation. And unfortunately, I see little ways of extension of your implementation to get the functionality I got used to. I may be wrong and may have missed something. 1. The whole design looks more like a stream dispatcher rather than a logging library which has to be more complex. I see no scope logging support, no custom log record attributes, no filter or wide logging support, and I see no obvious way to implement these on the user side to plug them into your lib. The way to completely wipe out logging from the user code during compile time would be good too, though it's not very difficult to implement it. 2. The logger object is a singleton which, I think, would be inappropriate once I would have custom attributes. I think the logger should be separated from the core library, which indeed would be a singleton. This would not only make attributes possible, but form a "source" concept. A logger would be an implementation of this concept, though allowing other implementations of "sources" (like, a third-party application console interceptor, for example). 3. The "sink" (or "target") concept is simplified down to a stream, which is not a best choice. Remember that the log record is more than just a string. It consists of a number of parts (attributes) - record number, time, source code location, severity level, and (yet another attribute) message text. There may be other user- or library-defined attributes. And the "sink" should be able to define which attributes to log and how to format them. In fact, a "sink" may apply its own filters to wipe out the unneeded records from the output. This is not possible with a simple stream "sink". 4. The library is header-only, which will raise some problems in a complex applications that consist of more than one module. The logger instance will be visible only in one module, other modules will have their own loggers, which obviously mean problems with their initialization (which streams to add as "sinks"?). I believe that logging library should be implemented as a shared lib. 5. I think there are too many macros in the interface. I'd rather have BOOST_LOG as an inevitable minimum, but no more than that. If you are interested, I could describe my view of architecture of such logging library (I'm working on the implementation on an early stage). Though, I think, many of us already have such view in our minds and maybe have it implemented. And finally some implementation-regarded notes (though I understand this was just a draft, I couldn't hold myself, sorry :) ): 1. The logger is default-constructible from the user's code, but it seems that you intended to make it singleton. 2. logger::get_instance is not thread-safe - function-scope statics are used. 3. You should not define namespace bl = boost::logging; in the library code. 4. Element global operators should be in boost::logging namespace. They will be reachable via ADL. 5. Each logging record involves std::stringstream (even not ostringstream) construction, formatted output copying, and destruction. I'm afraid, that would be a performance impact on the application. 6. I believe, some of the "Logging typedefs declarations" might have been hidden into the logger class and renamed. Some other names (like null_deleter) might have been hidden to an internal namespace. PS: I hope I didn't kill your encouragement with my reply. This is the last thing I'd wanted to do. -- Best regards, Andrey mailto:andysem@mail.ru

Now to the point. I understand and agree that the logging library should be simple to use but I see no reason we should sacrifice the extensibility for it. To my mind a carefully designed library interface is the way to go, not the functionality and extensibility limitation. And unfortunately, I see little ways of extension of your implementation to get the functionality I got used to. I may be wrong and may have missed something.
[All that follows concern the library I proposed. For more general comments on an eventual Boost.Logging, please refere to the end of this post] There is no way to extend my library as basically it offers all what I need and look for from a logging library! :) No kidding.
1. The whole design looks more like a stream dispatcher rather than a logging library which has to be more complex. I see no scope logging
Ok so if I understand, and correct me if I'm wrong, a scope logging facility would be some kind of macro added at the beginning of a function. This macro holds an object (RAII style) that would log the function name in its constructor (with eventually arguments) and log the exit of the function in its destructor. I'll add it.
support, no custom log record attributes, no filter or wide logging support, and I see no obvious way to implement these on the user side to plug them into your lib. The way to completely wipe out logging from the user code during compile time would be good too, though it's not very difficult to implement it.
- Log record attributes (what is it? just to be sure of what we are talking about.) - filter - wide logging (I guess it means internationalization (let's say i18n))
2. The logger object is a singleton which, I think, would be inappropriate once I would have custom attributes. I think the logger should be separated from the core library, which indeed would be a singleton. This would not only make attributes possible, but form a "source" concept. A logger would be an implementation of this concept, though allowing other implementations of "sources" (like, a third-party application console interceptor, for example).
For me the logger is the core of the logging library. So the source is the logger. It's the object who is responsible to collect logs generated by the user? Does he format them?
3. The "sink" (or "target") concept is simplified down to a stream, which is not a best choice. Remember that the log record is more than just a string. It consists of a number of parts (attributes) - record number, time, source code location, severity level, and (yet another attribute) message text. There may be other user- or library-defined attributes. And the "sink" should be able to define which attributes to log and how to format them. In fact, a "sink" may apply its own filters to wipe out the unneeded records from the output. This is not possible with a simple stream "sink".
Ok it's clearer now. An attribute is what I call the element of the log. Well I'm using my element_list as a description of the format of my logs. In doing such thing as: "[" >> boost::logging::level >> "] - " >> boost::logging::filename I am defining the format "attributes" of my logs. Ideally, user can define any class deriving from log_element and implementing the toString function for output.
4. The library is header-only, which will raise some problems in a complex applications that consist of more than one module. The logger instance will be visible only in one module, other modules will have their own loggers, which obviously mean problems with their initialization (which streams to add as "sinks"?). I believe that logging library should be implemented as a shared lib.
So, let's talk concrete. If you have two lib: my_library.lib my_other_library.lib main.cpp Including the header in each library will lead to having two differents instance of a logger in my final executable? The header-only solution seems so great to me. Include and forget...
5. I think there are too many macros in the interface. I'd rather have BOOST_LOG as an inevitable minimum, but no more than that.
I didn't want the user to manipulate objects and variables. But that is not boost philosophy, I can understand that.
If you are interested, I could describe my view of architecture of such logging library (I'm working on the implementation on an early stage). Though, I think, many of us already have such view in our minds and maybe have it implemented.
Please, if this library is mature enough, submit it!!
And finally some implementation-regarded notes (though I understand this was just a draft, I couldn't hold myself, sorry :) ): 1. The logger is default-constructible from the user's code, but it seems that you intended to make it singleton.
I'm calling the default constructor in the get_instance.
2. logger::get_instance is not thread-safe - function-scope statics are used. 3. You should not define namespace bl = boost::logging; in the library code. 4. Element global operators should be in boost::logging namespace. They will be reachable via ADL.
Does not compile with msvc.
5. Each logging record involves std::stringstream (even not ostringstream) construction, formatted output copying, and destruction. I'm afraid, that would be a performance impact on the application.
Yes that's a pb. std::strstream logger::m_str ?
6. I believe, some of the "Logging typedefs declarations" might have been hidden into the logger class and renamed. Some other names (like null_deleter) might have been hidden to an internal namespace.
[general comments here] Actually I have no hope the draft I propose will grow to something acceptable. It was a way for me to sparkle the debate and have something to talk about. I have no pretension to write such library, at least alone. Thank you Andrey, you comments are _very much_ appreciated. But still...
PS: I hope I didn't kill your encouragement with my reply. This is the last thing I'd wanted to do.
... I think I took this problem too lightly. We shall not focus on implementation at first but more on the requirements. Austin Bingham, in an other post, was also saying that we should first write the minimal requirements of the Boost.Logging library on some wiki or whatever... On the other hand, from the profile I draw in my summary earlier, Konstantin mention log4cpp (http://log4cpp.sourceforge.net) as a potential candidate. And still, some people propose their homegrown libraries... Like everybody here, I have a limited amount of time. I was wondering if it would be possible to assemble a small team led by some boost authoritative guy (Gennadiy?) to pull this. JD

Hello JD, ...Beware of the long post... Monday, April 2, 2007, 10:11:20 PM, you wrote:
There is no way to extend my library as basically it offers all what I need and look for from a logging library! :) No kidding.
You're lucky, but we should remember that there are people who would want something more than that.
1. The whole design looks more like a stream dispatcher rather than a logging library which has to be more complex. I see no scope logging
Ok so if I understand, and correct me if I'm wrong, a scope logging facility would be some kind of macro added at the beginning of a function. This macro holds an object (RAII style) that would log the function name in its constructor (with eventually arguments) and log the exit of the function in its destructor. I'll add it.
Not necessarily function scope, not necessarily macro and not necessarily actually log scope entry/exit. :) The key feature is to maintain a loggable call stack that comes visible at each log record. But in principle you are right - it's a scope guard that tells the logging library the name of the current scope.
support, no custom log record attributes, no filter or wide logging support, and I see no obvious way to implement these on the user side to plug them into your lib. The way to completely wipe out logging from the user code during compile time would be good too, though it's not very difficult to implement it.
- Log record attributes (what is it? just to be sure of what we are talking about.)
I guess, you understood me as you have mentioned below. But to be clear, an "attribute" is basically a piece of information of which the logging record consists. Attributes may have different types (integrals, strings and more complex types). Some examples of attributes: log severity level, log origin, log record text, the call stack described above. I believe, Gennadiy meant something like attributes in his review when he described "key words", but the attribute concept seems to me more generalized. Since each entity (e.g. class, subsystem, module, thread, process...) in a user's application may have its own set of attributes, it is important that the logger (the "source", in general) must not be a singleton. It must be able to represent the entity's set of attributes. For example: class A { logger m_log; A() : m_log(origin("class A")) // set the log origin attribute { } void do_smth() { log_scope scope("A::do_smth"); // Here we'll form a record which has at least 3 attributes: // - the "origin", string, equals "class A" // - the call stack with "A::do_smth" on top of it // - the message "I'm doing something" // There may be other attributes, such as date/time, // record number, thread id/name, source file name and line, etc. m_log.strm() << "I'm doing something"; } }; class B { logger m_log; B() : m_log(origin("class B")) { } void do_smth() { log_scope scope("B::do_smth"); // ... all the same, but the set of attributes is different // At least origin and scope attributes are different, but it // doesn't mean that B cannot have completely different set of // attributes, nor does it mean that it can't have the same // attributes that A has. m_log.strm() << "I'm doing something too"; A a; a.do_smth(); // Here A logs its own attributes, not B's } }; This approach gives another useful feature. We can now associate the different entities interaction. If we had not only logger-specific attribute set but in addition a thread-specific one, we could add some attribute to it right before the call to A::do_smth. See: class B { void do_smth() { log_scope scope("B::do_smth"); // ... all the same, but the set of attributes is different // At least origin and scope attributes are different, but it // doesn't mean that B cannot have completely different set of // attributes, nor does it mean that it can't have the same // attributes that A has. m_log.strm() << "I'm doing something too"; thread_attribute guard( /* attribute name */ "job", /* attribute value */ std::string("Very important job")); A a; a.do_smth(); // Here A logs its own attributes, not B's, // plus a new attribute "job" we defined above. // Later, when reading logs, we may see that // A::do_smth was called as a part of this // "Very important job" action, not something else. } };
- filter
The filter is basically a predicate which takes a record (or we may say, a set of attributes) and tell, wether this record should be passed to output. Filters are allowed to be connected in more complex filters. Each filter may be targeted to one or several attributes. For example, one filter may be checking that the record severity is higher than 2, the second one checks that the record is generated within a thread named "Main", the third requires that the message text matches regexp "/Warning.*/", and the record passes to output only if the second and either of first or third filters are satisfied. I see a wide field of Boost.Lambda and Boost.Bind in conjunction with Boost.Function exploit here. And as I've said before, these filters should be able to be applied in two phases: globally, at the library core level, and on per-sink basis.
- wide logging (I guess it means internationalization (let's say i18n))
Generally, yes. At least the ability to log wide strings (std::wstring) without conversion to narrow ones (std::string) should be provided. IMHO, a reasonable compromise should be reached in this part since a mixed-mode logging library, especially with multibyte support, would be too inefficient in a general-purpose use case. So I think there should be a compile-time library configuration policy to select the native char type.
2. The logger object is a singleton which, I think, would be inappropriate once I would have custom attributes. I think the logger should be separated from the core library, which indeed would be a singleton. This would not only make attributes possible, but form a "source" concept. A logger would be an implementation of this concept, though allowing other implementations of "sources" (like, a third-party application console interceptor, for example).
For me the logger is the core of the logging library. So the source is the logger. It's the object who is responsible to collect logs generated by the user? Does he format them?
Yes, the logger collects the record, though, as I exposed my view above, it shouldn't be the core. It does not format the collected data, it's sinks' task, since each sink may represent log records in different way. One sink may redirect to console, the other one may write XML log file and the third one may write a binary zlib-compressed archive.
3. The "sink" (or "target") concept is simplified down to a stream, which is not a best choice. Remember that the log record is more than just a string. It consists of a number of parts (attributes) - record number, time, source code location, severity level, and (yet another attribute) message text. There may be other user- or library-defined attributes. And the "sink" should be able to define which attributes to log and how to format them. In fact, a "sink" may apply its own filters to wipe out the unneeded records from the output. This is not possible with a simple stream "sink".
Ok it's clearer now. An attribute is what I call the element of the log. Well I'm using my element_list as a description of the format of my logs. In doing such thing as:
"[" >>> boost::logging::level >> "] - " >> boost::logging::filename I was thinking of something similar in my lib to implement text-based sinks, though I imagined something more lambda-like (it's just a pseudo-code yet): sink.format() << attr("sn") << "[" << attr("date") << "] " << attr("message");
I am defining the format "attributes" of my logs. Ideally, user can define any class deriving from log_element and implementing the toString function for output.
I think the logic should be opposite - the sink decides how to represent the record, so toString is not appropriate here. I think, some kind of visitor is needed here.
4. The library is header-only, which will raise some problems in a complex applications that consist of more than one module. The logger instance will be visible only in one module, other modules will have their own loggers, which obviously mean problems with their initialization (which streams to add as "sinks"?). I believe that logging library should be implemented as a shared lib.
So, let's talk concrete. If you have two lib: my_library.lib my_other_library.lib main.cpp
Including the header in each library will lead to having two differents instance of a logger in my final executable? The header-only solution seems so great to me. Include and forget...
Let's make it complicated: my_library.dll my_other_library.dll main.exe All three modules use your logging lib. How would you initialize it?
If you are interested, I could describe my view of architecture of such logging library (I'm working on the implementation on an early stage). Though, I think, many of us already have such view in our minds and maybe have it implemented.
Please, if this library is mature enough, submit it!!
As I've said, it's on the early stage. I need some time to finish the implementation, not to mention docs and tests.
And finally some implementation-regarded notes (though I understand this was just a draft, I couldn't hold myself, sorry :) ): 1. The logger is default-constructible from the user's code, but it seems that you intended to make it singleton.
I'm calling the default constructor in the get_instance.
But get_instance is a member, as far as I can see. The constructor should be private or protected. Otherwise you have no singleton.
2. logger::get_instance is not thread-safe - function-scope statics are used. 3. You should not define namespace bl = boost::logging; in the library code. 4. Element global operators should be in boost::logging namespace. They will be reachable via ADL.
Does not compile with msvc.
Hm? Which version do you try?
5. Each logging record involves std::stringstream (even not ostringstream) construction, formatted output copying, and destruction. I'm afraid, that would be a performance impact on the application.
Yes that's a pb. std::strstream logger::m_str ?
I guess...
.... I think I took this problem too lightly. We shall not focus on implementation at first but more on the requirements. Austin Bingham, in an other post, was also saying that we should first write the minimal requirements of the Boost.Logging library on some wiki or whatever... On the other hand, from the profile I draw in my summary earlier, Konstantin mention log4cpp (http://log4cpp.sourceforge.net) as a potential candidate. And still, some people propose their homegrown libraries... Like everybody here, I have a limited amount of time. I was wondering if it would be possible to assemble a small team led by some boost authoritative guy (Gennadiy?) to pull this.
As I said, I'm very interested in such lib and would be glad to participate. -- Best regards, Andrey mailto:andysem@mail.ru

On 4/2/07, JD <jean.daniel.michaud@gmail.com> wrote:
There is no way to extend my library as basically it offers all what I need and look for from a logging library! :) No kidding.
That doesn't sound like a very good place to start then.
1. The whole design looks more like a stream dispatcher rather than a logging library which has to be more complex. I see no scope logging
Ok so if I understand, and correct me if I'm wrong, a scope logging facility would be some kind of macro added at the beginning of a function. This macro holds an object (RAII style) that would log the function name in its constructor (with eventually arguments) and log the exit of the function in its destructor. I'll add it.
Please, don't start with a macro. Use an object that adds information about the current scope (e.g. BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) to a thread-local in its constructor and removes it in its dtor. Not unlike boost::scoped_lock. In some logging code I've implemented at work, I call this a "Tracer". These are usable not just at function scope, but inside nested scopes as well (e.g. you can put one inside a 'for' loop to trace its execution). Personally I never end up using them, but some folks can't live without them.
support, no custom log record attributes, no filter or wide logging support, and I see no obvious way to implement these on the user side to plug them into your lib. The way to completely wipe out logging from the user code during compile time would be good too, though it's not very difficult to implement it.
- Log record attributes (what is it? just to be sure of what we are talking about.)
I suspect the "standard" tuple of information (some) folks want to collect for every log message: thread ID, timestamp, filename, line number, and message. Perhaps function name as well.
- filter - wide logging (I guess it means internationalization (let's say i18n))
2. The logger object is a singleton which, I think, would be inappropriate once I would have custom attributes. I think the logger should be separated from the core library, which indeed would be a singleton. This would not only make attributes possible, but form a "source" concept. A logger would be an implementation of this concept, though allowing other implementations of "sources" (like, a third-party application console interceptor, for example).
For me the logger is the core of the logging library. So the source is the logger. It's the object who is responsible to collect logs generated by the user? Does he format them?
3. The "sink" (or "target") concept is simplified down to a stream, which is not a best choice. Remember that the log record is more than just a string. It consists of a number of parts (attributes) - record number, time, source code location, severity level, and (yet another attribute) message text. There may be other user- or library-defined attributes. And the "sink" should be able to define which attributes to log and how to format them. In fact, a "sink" may apply its own filters to wipe out the unneeded records from the output. This is not possible with a simple stream "sink".
Ok it's clearer now. An attribute is what I call the element of the log. Well I'm using my element_list as a description of the format of my logs. In doing such thing as:
"[" >> boost::logging::level >> "] - " >> boost::logging::filename
I think your stream insertion operators are pointing the wrong way.
Including the header in each library will lead to having two differents instance of a logger in my final executable? The header-only solution seems so great to me. Include and forget...
This is not good for more complex applications that need to share logs across different modules.
std::strstream logger::m_str ?
What about a thread-local stream object that is reused?
... I think I took this problem too lightly. We shall not focus on implementation at first but more on the requirements. Austin Bingham, in
Requirements are tough, because everyone (including me!) has different ones. I think it might be more productive to try and identify the core concepts required to implement the various requested features and come up with clear specifications for their interfaces. Then take these
an other post, was also saying that we should first write the minimal requirements of the Boost.Logging library on some wiki or whatever... On the other hand, from the profile I draw in my summary earlier, Konstantin mention log4cpp (http://log4cpp.sourceforge.net) as a potential candidate.
I'd argue strongly against basing any Boost.Logging library on any of the multitude of C++ ports of log4j (of which there are at least log4cpp, log4cplus, log4cxx). They are generally bloated, suffer from a horribly baroque runtime configuration, and do not make good use of C++ language features. Some of them are also more or less dead projects (e.g. Apache's log4cxx's home page mentions that "At this point, log4cxx-0.9.7 is substantially out of date, has known serious deficiencies" but no successor version has been released in over two years. A clean-room design (which might borrow some concepts from log4*) is a much better idea IMHO.
And still, some people propose their homegrown libraries... Like everybody here, I have a limited amount of time. I was wondering if it would be possible to assemble a small team led by some boost authoritative guy (Gennadiy?) to pull this.
I doubt you can impose upon Gennadiy to take this on in addition to his maintainership of Boost.Test. -- Caleb Epstein

Hello Caleb, Tuesday, April 3, 2007, 5:59:32 AM, you wrote: [snip]
std::strstream logger::m_str ?
What about a thread-local stream object that is reused?
An access to TLS may cost some time (basically, it's a search on a tree or a hash-table), which will take place at each log record. IMHO, this may harm the performance. [snip] -- Best regards, Andrey mailto:andysem@mail.ru

Hello, Caleb! You wrote on Mon, 2 Apr 2007 21:59:32 -0400: CE> I'd argue strongly against basing any Boost.Logging library on any of CE> the multitude of C++ ports of log4j (of which there are at least CE> log4cpp, log4cplus, log4cxx). They are generally bloated, suffer from CE> a horribly baroque runtime configuration, I can say only about log4cpp. I don't see any problem with it runtime configuration. I can control all aspects of logging. Yes, sometimes function arguments and return values surprise me, but this can be easily fixed to be more natural. Also I never do configuring by hands - only from config files. Recently I added factories into library to make writting different kind of configurators easy task. About bloating. I know every peace of library and can say that there is samething not needed. CE> and do not make good use of C++ language features. About what features you talk? All you need is: 1) configure - this is one call, say `logging::configure(filename)`. 2) Do logging - `logger.error('Somethis wrong');`, `logger.infoStream() << "Value is " << value";`. What else do you need? CE> Some of them are CE> also more or less dead projects (e.g. Apache's log4cxx's home page CE> mentions that "At this point, log4cxx-0.9.7 is substantially out of CE> date, has known serious deficiencies" but no successor version has been CE> released in over two years. Last release of log4cpp was at 2005/07/29 and it is not dead. With best regards, Konstantin Litvinenko.

Hello, Konstantin! You wrote to Caleb Epstein on Tue, 3 Apr 2007 08:46:48 +0300: KL> I can say only about log4cpp. I don't see any problem with it KL> runtime configuration. I can control all aspects of logging. Yes, KL> sometimes function arguments and return values surprise me, but this KL> can be easily fixed to be more natural. Also I never do configuring by KL> hands - only from config files. Recently I added factories into library KL> to make writting different kind of configurators easy task. About KL> bloating. I know every peace of library and can say that there is KL> samething not needed. Ups, should read "...and can't say that there is samething not needed." With best regards, Konstantin Litvinenko.

On 2007-04-03, Caleb Epstein <caleb.epstein@gmail.com> wrote:
... I think I took this problem too lightly. We shall not focus on implementation at first but more on the requirements. Austin Bingham, in
Requirements are tough, because everyone (including me!) has different ones. I think it might be more productive to try and identify the core concepts required to implement the various requested features and come up with clear specifications for their interfaces. Then take these
FWIW, figuring out the "requested features" is what I figured the first step would need to be. Some people need complex routing and filtering, others need file-based configuration, and others will tell you that these features are a waste of time. If we can get a handle on what people want and then start to couple that information with implementation ideas, we'll have made some real progress. I just want to contrast this with what I see on the list. Every other week or so, someone submits a logging library that "they've been working on for a while" and which "has great features X, Y, and Z". Some people like it, others point out its failings, and the matter never gets any further. I simply don't think that this is an efficient way to zero in on a useful, generally acceptable logging system. -- Austin Bingham Signal & Information Sciences Laboratory Applied Research Laboratories, University of Texas at Austin 10000 Burnet Rd., Austin, TX 78758 email: abingham@arlut.utexas.edu cell: (512) 799-2444 office: (512) 835-3832

Hi, I have uploaded the small logging object I proposed a few weeks ago with some changes following Andrey remarks.
And finally some implementation-regarded notes (though I understand this was just a draft, I couldn't hold myself, sorry :) ): 1. The logger is default-constructible from the user's code, but it seems that you intended to make it singleton.
fixed
2. logger::get_instance is not thread-safe - function-scope statics are used.
I think it's fixed now...
3. You should not define namespace bl = boost::logging; in the library code.
fixed
4. Element global operators should be in boost::logging namespace. They will be reachable via ADL.
ADL does not work with old compilers (msvc-6.0)
5. Each logging record involves std::stringstream (even not ostringstream) construction, formatted output copying, and destruction. I'm afraid, that would be a performance impact on the application.
fixed
6. I believe, some of the "Logging typedefs declarations" might have been hidden into the logger class and renamed. Some other names (like null_deleter) might have been hidden to an internal namespace.
Got to think about that. It also compiles with bjam v2 now on a 1.34.0. And it also compiles when added in multiple source files (hum). Here it is: (http://minilien.com/?2oscdAofQK) Just download it in boot_1_34_0 and unzip it. Next steps: Allow formatting per sink. Allow max level definition per sink. Allow severity/level definition. Regards, JD

Hello JD, Tuesday, May 15, 2007, 12:05:43 PM, you wrote:
Hi,
I have uploaded the small logging object I proposed a few weeks ago with some changes following Andrey remarks.
[snip] Just wanted to tell you that I'm planning to make a preliminary announcement of my implementation this weekend or so. The core functionality is almost ready, but there are no docs and just a couple of simple tests yet. -- Best regards, Andrey mailto:andysem@mail.ru

Andrey Semashev wrote:
Hello JD,
Tuesday, May 15, 2007, 12:05:43 PM, you wrote:
Hi,
I have uploaded the small logging object I proposed a few weeks ago with some changes following Andrey remarks.
[snip]
Just wanted to tell you that I'm planning to make a preliminary announcement of my implementation this weekend or so. The core functionality is almost ready, but there are no docs and just a couple of simple tests yet.
Hi Andrey, Great! But I think you'd better have a documentation (with at least a tutorial) and some examples. Maybe you could introduce your library in regard of the requirements from the wiki... Anyway that's great news. JD

JD wrote:
Hi Andrey,
Great! But I think you'd better have a documentation (with at least a tutorial) and some examples. Maybe you could introduce your library in regard of the requirements from the wiki...
Anyway that's great news.
JD
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Hello JD and Andrey, A boost logging library would be really cool! I find that log4cxx, log4cpp and log4cplus are the current alternatives. More power to you all!! :)

Hello JD, Wednesday, May 16, 2007, 11:03:05 AM, you wrote:
Just wanted to tell you that I'm planning to make a preliminary announcement of my implementation this weekend or so. The core functionality is almost ready, but there are no docs and just a couple of simple tests yet.
Hi Andrey,
Great! But I think you'd better have a documentation (with at least a tutorial) and some examples.
I think there'll be an example/test with lots of comments explaining everything.
Maybe you could introduce your library in regard of the requirements from the wiki...
I tried to follow them during the development. Though they are not all implemented yet. -- Best regards, Andrey mailto:andysem@mail.ru

Hi, I've finished a conversion of my library (boostification) and placed it in the Vault under the file name boost-logger-lpp.zip I have spent some time reading through the old posts as directed and found much interesting insights there. LogPlusPlus (my logger) is largely complete and so has not been designed or implemented based on any of this discussion, however I do feel it might hit some nails on the head although in its current state it also misses others. http://www.boost-consulting.com/vault/index.php?action=downloadfile&filename=boost-logger-lpp.zip&directory=& In the src directory there is a file called 'test.cpp' that works as a tutorial and a demo program rolled into one. I have been planning to revise the back-end of the implementation for some time and to that end would be grateful for any comments on how to implement things differently.

Gareth Buxton wrote:
I've finished a conversion of my library (boostification) and placed it in the Vault under the file name boost-logger-lpp.zip
I have spent some time reading through the old posts as directed and found much interesting insights there. LogPlusPlus (my logger) is largely complete and so has not been designed or implemented based on any of this discussion, however I do feel it might hit some nails on the head although in its current state it also misses others.
In the src directory there is a file called 'test.cpp' that works as a tutorial and a demo program rolled into one.
I have been planning to revise the back-end of the implementation for some time and to that end would be grateful for any comments on how to implement things differently.
Hi Gareth, I take a quick look at your library. As a reminder, here is the boost wiki aggregating the requirements for an eventual Boost.Logging library: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost.Logging 0- I was not able to compile the library with bjam: Jamfile:9: in load-jamfiles *** argument error * rule project ( name : location ? ) * called with: ( boost/logger : source-location ../src ) * extra argument ../src G:\Program Files\boost_1_33_1\tools/build/v1\allyourbase.jam:1274:see definition of rule 'project' being called G:\Program Files\boost_1_33_1\tools\build\v1\bootstrap.jam:21: in boost-build G:\Program Files\boost_1_33_1\boost-build.jam:16: in module scope or with the makefile: make: *** No rule to make target `log_output.o', needed by `test'. Stop. 1- Concerning formatting, I think it is a normal phase of the library usage and shall be done without any class construction. It shall be defined during library initialization in the more natural way possible. Look at the way I did for the draft I proposed. I'm not saying that it is the absolute right way but IMO it looks easier that having to define a deriving class. 2- I think it lacks the scoped logging that is apparently a very demanded feature. (requirement #2) 3- As far as I can see, there is no lazy evaluation (req #4). This is a very strong requirement. 4- Sorry if I insist, even if macro is evil, but the library shall provide macro to allow logging anywhere in the code without having to declare, allocate or define any extern global variables. 5- What happens if two threads log at the same time? ThThisi s ias a lloogg :) Technical aspect: - The stream_map use std::string for indexing. One of the requirement on the library that I think anybody agree on is it shall be fast. I think it would be a better idea to map your strings to unique references (using a set), and avoid using string to string comparison in the map but instead compare their references. As a conclusion, your library looks simple and small but still lacks some of the key features that was discussed in the previous posts. In particular, I really think the formatting part shall be simpler for the user, it may seems presumptuous, but have a quick look to the "XML output" example of the draft I proposed. I am really looking for this in a Boost.Logging library. Moreover, I think the documentation is a little sparse (but it shall be noted that code is commented though!). Anyone else reviewed Gareth's work? JD

Hello Gareth, Monday, April 2, 2007, 7:37:54 AM, you wrote:
Hi,
I've finished a conversion of my library (boostification) and placed it in the Vault under the file name boost-logger-lpp.zip
I have spent some time reading through the old posts as directed and found much interesting insights there. LogPlusPlus (my logger) is largely complete and so has not been designed or implemented based on any of this discussion, however I do feel it might hit some nails on the head although in its current state it also misses others.
In the src directory there is a file called 'test.cpp' that works as a tutorial and a demo program rolled into one.
I have been planning to revise the back-end of the implementation for some time and to that end would be grateful for any comments on how to implement things differently.
I took a look at the docs and the implementation. The implementation is text stream oriented, it does not provide attribute support except the severity level, that is implemented as a mask of named streams inside the logger. But the log message text is still formatted regardless of wether it will be actually logged. As for loggers, they are not default-constructible, which gave me a bad surprise. It appears like I would have to get and setup a logger in each function separately, even if these functions are members of a single class. I may have missed something here. Each logger may output to one or several streams but it is not clear wether I can decide which log record goes to which stream. I got the impression that the record is simply output into each stream the logger has, which means I would have to create as many loggers as many independently configurable sinks I need. This flaw is partially solved with the ability to connect loggers to each other (as they essentially are streams) but this makes such initialization too complex. There are other features not present in the implementation, such as wide characters support, scope logging and mature filtering. The lib looks quite simple and useful for relatively small solutions but still lacks extensibility to be suitable for industrial usage. I don't agree with some design approaches, but the ability to build logging hierarchies looks nice. Such feature may be useful to control several sinks in a common manner, though, IMO, it is not the most wanted thing. -- Best regards, Andrey mailto:andysem@mail.ru

My colleague and I have just finished an initial implementation of a new logging library. We think we have some nice features that we hope may be of interest. 1) Each logging statement is a standalone object (thread-safe initialised), which can be controlled independently. Here are some of the consequences of this design choice: a) You can control whether a log statement is on/off based on file, file & line, function name or any other indexing scheme you can come up with (e.g. "application component") b) Each logging statement can have a separate list of "destinations". These can be turned on and off at runtime. c) We have lua bindings to the library, which is our primary way of controling the amount of output. 2) A statement which is "off" is cheap (i.e. no streaming happens) The main reason for this is that we want to be able to sprinkle a copious amount of log statements throughout our code and then turn them on/off should the need arise. 3) Intuitive interface: LOG (<list of destinations>) << "blah"; If you find the feature set interesting, let us know and we can start filling in some more details. We'd be willing to work on boostifying it should there be enough interest. Tom
participants (15)
-
Andrey Semashev
-
Austin Bingham
-
Caleb Epstein
-
Gareth Buxton
-
Greer, Joe
-
JD
-
Jody Hagins
-
Konstantin Litvinenko
-
missdeer
-
Paul Giaccone
-
Piyo
-
Richard Day
-
Shams
-
Steven Watanabe
-
Tomas Puverle