
Hi, I've been thinking (yes) and am now taking a 180-degree turn on my previous standpoints in this discussion: I propose that John's Boost.Log library should remain basically as-is - *but* - should be moved into e.g. boost::text_log instead. The library should be renamed to reflect that (can't think of a really good, pronouncable name). Why ... well here are some points : - The library is in its current state extremely flexible due to the text-based manipulation. - Even though flexible, it is still easy to use and extend. - Many people (everyone except me?) seems to be happy with text-based logging. - Performance of using streams in the interface (in the caller's context) seems to be ok with everyone, as long as logging to the specific log can be turned off. - It's all-in-all kind of beautiful in it's simplicity and ease of use. (Did I say that it was flexible?) - Fast compile times (as said earlier) - ... etc ... I'd even go so far as to say that the current implementation is too general (log_manager concept etc). Why not make it even simpler and only put in some effort to make the threading support more loosely coupled (as is already in progress). I'd definitely like light-weight Win32+Posix compatible integrated threading support. Keep the naming (and concepts + implementation) simple and concrete: e.g. strings, streams, a single log manager implementation and just stick to that to make it clear what the library actually does. I'd personally very much like some kind of structured logging functionality, and I'll probably work on that offline in the near time. I'll keep the discussions (including requirements) from here in mind and post to the list when (and if) I come up with something useful. Any interest? So why did I take this turn? Basically, because structured logging and the kind of flexibility provided by John's implementation doesn't mix well. I don't want to complicate things for the rare occasions where people really *need* structured logging. There are ways to implement structured logging and extensibility in what's logged; I though about using the extension object pattern[1], but it has a certain performance impact - especially in the single-threaded environment. I'm currently leaning towards a (hybrid?) approach where logs are parameterized on their log_item type, but the log_item type would always derive from a basic_log item - that provides the extensibility should it be needed in the (few) cases. Formatting should still be based on message ids + insertions and left off to execute in the background. Sorry for stirring up all this, but I hope that it at least gave some feed for thought ;-) Regards // Johan --- [1] Brief example for the extension objects idea (pseudo pseudo-code): struct log_item_extension {}; struct log_item { typedef /* implementation defined */ ext_id; void add_extension(ext_id, const log_item_extension& p_ext); const log_item_extension& extension(ext_id) const; } struct time_stamp : log_item_extension { time_stamp() : m_ts(get_timestamp()) {} const /* impl-defined */& ts() const; private: /* impl-defined */ m_ts; }; struct severity : log_item_extension { severity(int value) : m_value(value) {} int value() const { return m_val; ] private: int m_val; } ..... void init_logs() { app.add_modifier(time_stamp()); syslog.add_modifier(severity()); ... syslog.add_appender(event_log_appender()); } ... void event_log_appender::operator()(log& log, const log_item& log_item) { try { const severity& sev = dynamic_cast<severity&>(log_item.extension(severity::id())); const source& src = dynamic_cast<source&>(log_item.extension(source::id())); ... etc ... } catch (boost::log::bad_extension& be) { assert(be.what()); } } ----