Boost logo

Boost :

From: John Torjo (john.lists_at_[hidden])
Date: 2005-11-11 09:05:10


Hi Pavel,

>
> -------------------
>
> the check for DLL:
>
> #if defined(_DLL) || defined(_USRDLL)
> #ifndef BOOST_LOG_DYN_LINK
> #define BOOST_LOG_DYN_LINK
> #endif
> #endif
>
>
> would be better omitted.
> Logger may be used internally within DLL only
> and not exported. If user wants Boost-dynlink
> he should say it explicitly.
>
>

Myself, I love defaults, when they are provided. Instead of trying to
find out how to enable something, I'd rather have it enabled by default,
and eventually if I want to disable it, I will.

So, I could provide a way to disable this, with a define like
BOOST_LOG_NO_DYN_LINK

> If the code is kept anyway then it should handle
> other compilers too,
> e.g. for BCB it is __DLL__.
>
Yes, you're right.

> _____________________________________________________
> 3. log_manager.hpp: since this file is not intended
> for include by user it should be moved into detail/
> directory.
>
Yup, done that.

>
> -------------------
>
> Name DEFAULT_CACHE_LIMIT should be
> DefaultCacheLimit or so to avoid preprocessor clashes.
>

Will do.

> _____________________________________________________
> 4. detail/ts_win32.hpp: the functionality here is
> possibly covered by Boost.Thread (in header only
> form). If really so, it should be reused.
>

:)
I allowed for this since others asked to remove dependency on Boost.Thread

> --------------
>
> The #include <windows.h> may be replaced by few simple
> forward defines and declaration to speed up the
> compilation.

Yes.
>
> _____________________________________________________
> 5. detail/ts_posix.hpp: the same advice related
> to Boost.Thread as above.
>

See above.

> I am suspicious of MT safety on multiprocessor machines
> due to use of unprotected "m_count" value.
> This value may be cached and changes to it not visible.
>
> If possible, Boost.Thread should be reused to avoid
> such doubts.
>

This was taken from Boost.Thread.

> _____________________________________________________
> 6. basic_usage.html: the code snippets would look better
> if syntax highlighted.

Got it.

> -------------
>
> Code snippets for header and implementation file should
> be more visually separated.

Will do.

>
> --------------
>
> Code snippets may have more comments. Overcommenting
> is positive thing, especially for first few examples.

Right, will do so.

>
> _____________________________________________________
> 7. logs.html: there should be hyperlinks so one can
> check out what appenders/modifiers interfaces are.
>

Ok, will rewrite the docs in doxygen

> ---------------------
>
> The code snippet with
>
> BOOST_DEFINE_LOG(gui, "app.gui")
>
> should say what the 'gui' is - object,
> "string name" or "C++ name"?

Done.

>
> ---------------------
>
> Possible feature of logger: it would be nice
> to have ability to automatically append newline
> (if not already at the end of a log).
>
> Loggers I wrote do this and it helps since I
> do not need to search and fix source if I forget
> newline somewhere.

Already there : append_enter, which will be renamed : append_newline

> ---------------------
>
> There should be table of all available modifiers
> and all available appenders at this moment.
> This table should contain one-line mini-examples.
>

Yup, added to my TODO list.

> Modifier API:
> void modifier_func(const std::string & log_name, std::string &msg);
>
> Is it really needed to use std::string for
> log_name? Woudn't it be enough to have const char*?
>
> I ask because it may help to avoid one dynamic allocation
> per log and this may be quite important in RT applications.

The logger's name is kept in the logger_impl - so it's only one copied
only once per log.

>
>
> -----------------------
>
> Order in which appenders and modifiers are called is
> not specified.

In modifier_logger.html, at the end, I did explain the order. Maybe I
can place a link to it, from a FAQ or so.

>
> _____________________________________________________
> 9. manipulating_logs.html:
>
>
> "When manipulating logs, you alway manipulate a hierarchy of logs."
> (typo "alway")
> ==>>
> "You can manipulate with one or more logs at the same time."
>
Yes, corrected.

> -------------------
>
> DEFAULT_INDEX /cannot/ be uppercase (clashes with
> preprocessor).

I understand that it would better be lowercased, but "cannot" is a
pretty strong word. Care to exemplify?

>
> -------------------
>
> What if I do:
>
> manipulate_logs("*").xyz(....).abc(...);
>
> manipulate_logs("*").abc(....).xyz(...);
>
>
> Will the last call overwrite the previous or will
> they accumulate? Should be explained here.

Will explain.

>
> ----------------------
>
> The rules where to use ampersand for appenders/modifiers
> should be the same. It is not acceptable sometimes to
> have it and sometimes not. This is really, really confusing.

They are the same.

>
> Perhaps using "index" to sort modifiers is overengineering.
>
> Intuitively I would expect sorting being derived from order
> of add_appender()/add_modifier() within manipulate_logs().
>
> If you remove the index the API would get pleasantly smaller
> w/o loosing feature.

And the way it's now you don't have to care about the index unless you
want to.

> ----------------------
>
> The last code snippet doesn't say whether
> BOOST_LOG_DEFINE_LEVEL can be in header.
>
> It also seems to put the value into
> boost::logging::level namespace which is wrong.

Why would you say this is wrong? I did this to prevent name clashes.

>
> If the macro is already within a namespace
> it would insert new subnamespace boost/.... here
> making big mess in code.
>
>
>
> Namespacing should be left to the user:
>
> BOOST_LOG_DEFINE_LEVEL(my_namespace::xyz, 1111)
>
> or
>
> namespace my_namespace {
> BOOST_LOG_DEFINE_LEVEL(xyz, 1111)
> }
>

Yes, you're right - I need to explain this.

> _____________________________________________________
> 10. predefined.html:
>
> append_enter ==>> append_newline
>

Yes, will do - Caleb suggested as well.

> ----------------
>
> prepend_thread_id should exists also for POSIX
> (there's one simple function for it).
>

Please show it to me - I don't know it.

> --------------------
> Missing escape sequences:
>
> $d - day with 1 or 2 digits
> $M - month with 1 or 2 digits
> $MON - month as Jan/Feb/....
> $ms - millisecond (it is quite useful for many common cases)
> $HH - like "03 AM"
>

Too many things on my TODO list :)
I'll think about it.

> --------------------
>
> ts_appender ==>> longer, more intuitive name
>

Yes, you're right.
Perhaps: 'dedicated_thread_appender'.

>
> "appender_array" - confusing documentation, no idea what is says.
>

Yup, you're right. Need to fix that.

>
> -----------------------
>
> rolling_file_appender - example needed, picture would help.
>
>
> Name should be "rotating....".
>

Again, you're right.

>
> Dedicated thread used for logging: does it work
> if both application executable and a DLLs do log into
> the same file? It is quite tricky to ensure singleton
> in such circumstances. Jason Hise works on library "Singleton"
> where he had solved this (after a lot of effort).

I know it's been successfully used on Windows. Would
Linux/some_other_platform be a problem?
>
> ----------------------
>
> Static destruction: currently the library cannot
> reliably log from destructors of static objects.
> The Jason's library contains support for this situation.
>

Will look into it.

>
> --------------------------
>
>
> It may be possible to design the BOOST_DECLARE_LOG
> and BOOST_DEFINE_LOG so that the log get initialized
> on first use: then the cache would not be needed.
>
> This way should be investigated since possible
> simplification of design and API would be rather high.
>

That's not the problem. The thing is that you need to specify the logs
modifiers and appenders. So, no matter what, you might still have a few
messages written to the logs, until you get a chance to initialize them.

You might be able to initialize them only within main() - for instance,
from a command line parameter or so.

>
> _____________________________________________________
> 11. Feature request: quite often I am not interested
> not in absolute time (2005/12/11 16:33) but in
> time offset from some event.
>
> I suggest to add API:
>
> manipulate_logs(...).set_time_start_point(
> bool either_in_all_threads_or_just_in_current_thread
> );
>

Yes, it's a very reasonable thing to ask.

> _____________________________________________________
> 12. Feature request: thread ID (both Win32 and POSIX)
> is of low use. I suggest to add API to specify
> string name as alternative to number:
>
> .prepend_thread_name()
>
> manipulate_logs(...).set_current_thread_name("gui thread");
>
>
> If not specified number ID would be default.

Yup, doable.

> _____________________________________________________
> 13. Feature request: Boost.Filesystem should be supported
> (for specifying file names). The library is stable
> and likely in next Standard.
>

There's no stoppping you from saying:
some_path.string();

>
>
> This is what was likely discussed all over: for
> some apps (e.g. embedded with tight constraints)
> I may wish to remove all logging code completely:
>
>
> BOOST_LOG(app, (<< "x = " << x));
>
> Some compilers may not optimize strings and logging support
> aways from the code - they won't be called but they will
> be present in the executable. A way to surely get rid of them
> should exists.
>

Right, will provide this.

>
> _____________________________________________________
> 15. caching.html: the docs doesn't say whether flushed
> logs follow the rules given by manipulate_logs().
>

Done it.

> --------------
>
> It doesn't say whether manual flush() is needed and what
> is default.
>
> Complete example is sorely needed.
>

Will do.

>
> _____________________________________________________
> 16. thread_safe.html: this page is messy and I am not
> able to understand what it is for and what it
> tries to explain.
>
> What is very missing is getting ensured that ALL logs no matter
> what are MT safe.

Funny, but that's what it says in the beginning "The Boost Log library
is thread-safe, while being efficient."

> _____________________________________________________
> 19. examples.html: every example could be linked here,
> together with short description.
>
Will do.

>
> _____________________________________________________
> 20. Feature: since each log may span to several lines
> a modifier could be added to the library:
>
> .add_modifier(log_ending("###"))
>
>
> where every log will be ended with [optional \n if needed]###\n.
>
>
> This would allow easier create tools that manipulate
> with logs.
>
>
> Similar modifier:
> .add_modifier(log_starting("@@@"))
>
> where every log starts with @@@ (no newlines)
> may be considered but this one is not that urgent.
>

I did not understand what you're saying.

> The documentation lacks reference for some important
> objects like manipulate_logs(). At least list of all
> standalone functions should exists.

Yes, there will be reference.

> The documentation should contain complete example how to write
> a) custom appender and modifier

I do have an example of creating a simple modifier & adppender
(modifier_logger.html)

> Manipulating with one log can use single preallocated
> buffer and fall back to heap if needed. Even if it would
> complicate API for appenders/modifiers it feels as worth.
>
>
> It may be worth to create your own "preallocated_string"
> class and work with it instead of with std::string.
>

I'll think about it.

> 26. Similary to OutputDebugString() on Win32 with POSIX
> saving to syslog may be implemented.
>

I need help with this one...

> On Win32 EventLog suppot may be added (very handy
> for errors).
>

... same here

> _____________________________________________________
> 27. There should be way to disable thread locking
> manually when useful (e.g. via macro). For some
> people with single thread app such overhead may
> feel too high.

There is. If you disable threads (BOOST_HAS_THEADS is not defined),
there's no thread locking.

>
> _____________________________________________________
> 28. src/log_manager.cpp: name_matches_spec() may be more optimised:
>
> if ( (spec == "*") || spec.empty() )
>
> ==>>
>
> if (spec.empty() || strcmp(spec.c_str(), "*") == 0)
>
> -> one dynamic allocation less.

spec == "*" -> is usually optimized by providing the right operator==,
and that's the STL vendor's business

For instance:
template<class _Elem,
        class _Traits,
        class _Alloc> inline
        bool __cdecl operator==(
                const basic_string<_Elem, _Traits, _Alloc>& _Left,
                const _Elem *_Right)
        { // test for string vs. NTCS equality
        return (_Left.compare(_Right) == 0);
        }

> ----------------
>
> Length of lines may be limited.
> Some lines have over 240 characters and that
> very hard to read.
> I'd say that 90-100 chars is reasonable limit.
>
Yes, I need to improve on that.

> -----------------------
>
> The file log_impl.hpp should be wrapped by:
>
> #include <boost/detail/workaround.hpp>
>
>
> #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
> # pragma warn -8026 // some functions are not expanded inline
> #endif
>
> .... file contents ....
>
> #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
> # pragma warn .8026
> #endif
>
>
Done. thanks.

> _____________________________________________________
> 31. log.hpp: the code to find out release mode
>
> #ifndef NDEBUG
> #define BOOST_LOG_IS_DEBUG_MODE 1
> #else
> #define BOOST_LOG_IS_DEBUG_MODE 0
> #endif
>
>
> doesn't work correctly on BCB. Here IDE uses
> by default _DEBUG macro. I suggest:
>
>
> #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
> // IDE of BCB uses _DEBUG to indicate debug mode, it doesn't
> // (by default) use NDEBUG.
> # ifdef _DEBUG
> # define BOOST_LOG_IS_DEBUG_MODE 1
> # else
> # define BOOST_LOG_IS_DEBUG_MODE 0
> # endif
> #else
> # ifdef NDEBUG
> # define BOOST_LOG_IS_DEBUG_MODE 0
> # else
> # define BOOST_LOG_IS_DEBUG_MODE 1
> # endif
> #endif

Done, thanks.

Thanks for the thorough review.

Best,
John

-- 
John Torjo,    Contributing editor, C/C++ Users Journal
-- "Win32 GUI Generics" -- generics & GUI do mix, after all
-- http://www.torjo.com/win32gui/surfaces.html - Sky's the limit!
-- http://www.torjo.com/cb/ - Click, Build, Run!

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