You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4cxx-user@logging.apache.org by Josh Kelley <jo...@gmail.com> on 2008/03/18 15:09:38 UTC

Use of operator<<

I saw that I can use the << operator within the LOG4CXX_DEBUG, etc.
macros; e.g.:

    LOG4CXX_DEBUG(logger, "Read " << path << " and got " << out);

This seems very convenient (and a whole lot more convenient than
formatting strings myself or having to use something like
boost::format for every log statement), but as far as I can tell, it's
undocumented.  Is this use of operator<< officially supported, or is
it an implementation detail that I should not be relying upon?

If it is supported, then can I add a wiki page about it?  If it's not
supported, then is there a recommended way of doing formatted logging?

Thanks.

Josh Kelley

Re: Use of operator<<

Posted by Curt Arnold <ca...@apache.org>.
On Mar 19, 2008, at 11:40 AM, Jacob L. Anawalt wrote:

> Curt Arnold wrote:
>> On Mar 18, 2008, at 12:01 PM, Jacob L. Anawalt wrote:
>>>
>>> again. If it hadn't been, I was thinking that the current online  
>>> API docs looked a little more efficient for simple strings (which  
>>> is where I currently use the logging macros), and that I would re- 
>>> implement the older style macros as  
>>> LS_LOG4CXX_*(logger,streamInput).
>> I don't follow the last sentence.  The current macro definitions  
>> (and the implementation of the supporting classes) attempts to  
>> avoid the use of an actual std::basic_ostream if possible, so it  
>> should be more efficient for logging simple strings than the 0.9.7  
>> implementation or an alternative using logstream.
>
> I hadn't looked at how the latest (svn HEAD) auto-detecting method  
> worked, so I was going off of your statement that  
> "...experimentation hopefully results...", and stating that in case  
> it didn't, I could simply fall back to writing my own macros like  
> the 0.9.7 ones.
>
> Since 'current' seemed to get a little blurred, this is what I was  
> referring to:
>
> 1) 0.9.7 version:
> #define LOG4CXX_DEBUG ( logger, message ) { \
>        if (logger->isDebugEnabled()) {\
>        ::log4cxx::StringBuffer oss; \
>        oss << message; \
>        logger->forcedLog(::log4cxx::Level::DEBUG, oss.str(),  
> __FILE__, __LINE__); }}
>
> 2) current online API docs:
> #define LOG4CXX_DEBUG (logger,message) { \
>        if (LOG4CXX_UNLIKELY(logger->isDebugEnabled())) {\
>           logger->forcedLog(::log4cxx::Level::getDebug(), message,  
> LOG4CXX_LOCATION); }}

The on-line docs have not been updated and that code does not reflect  
the current SVN HEAD.  A staged copy of the new online docs 0.10.0 RC2  
can be viewed at http://svn.apache.org/repos/asf/logging/site/trunk/docs/log4cxx/index.html 
.  That will be updated for RC3 and the a release candidate is  
accepted, that content will be pushed to the public web site.


>
>
> It seemed to me that 2 is more efficient than 1 when the argument to  
> the macro is either a static string, eg "Hello World", or a  
> std::string containing some string my program needed to generate  
> anyway because 2 does not create a temporary StringBuffer and avoids  
> the << and str() function calls.
>
> 3) this morning's svn HEAD (which I wasn't referring to before):
> #define LOG4CXX_DEBUG ( logger, message ) { \
>        if (LOG4CXX_UNLIKELY(logger->isDebugEnabled())) {\
>           ::log4cxx::helpers::MessageBuffer oss_; \
>           logger->forcedLog(::log4cxx::Level::getDebug(),  
> oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
>
> Taking an initial look at 3 this morning, it appears to create a  
> temporary object, and call << and str() as well. Based on what you  
> have said about 3 avoiding creating an ostream, it must be more  
> efficient than 1 and possibly only slightly less efficient than 2.  
> Someone needing that extra boost and only using strings may prefer  
> to duplicate 2 with their own localized name.

As far as I remember, there was no discernible performance difference  
due to the construction of MessageBuffer.

>
>
>> Adding W would not transparently support logging TCHAR*
>
> True, and MessageBuffer appears to be a clever solution to this.
>
> I haven't had luck with everything 'just working' when defining  
> UNICODE or not so instead I specify what my stream and character  
> types are and define conversion boundaries within the software. The  
> days are fading away where I even care to write something new for MS  
> Windows desktops that isn't UNICODE inside. I am glad you have a  
> solution that works for all of us.
>
> Thank you,
> -- 
> Jacob Anawalt
> Gecko Software, Inc.
> janawalt@geckosoftware.com
> 435-752-8026


Re: Use of operator<<

Posted by "Jacob L. Anawalt" <ja...@geckosoftware.com>.
Curt Arnold wrote:
> 
> On Mar 18, 2008, at 12:01 PM, Jacob L. Anawalt wrote:
>>
>> again. If it hadn't been, I was thinking that the current online API 
>> docs looked a little more efficient for simple strings (which is where 
>> I currently use the logging macros), and that I would re-implement the 
>> older style macros as LS_LOG4CXX_*(logger,streamInput).
> 
> I don't follow the last sentence.  The current macro definitions (and 
> the implementation of the supporting classes) attempts to avoid the use 
> of an actual std::basic_ostream if possible, so it should be more 
> efficient for logging simple strings than the 0.9.7 implementation or an 
> alternative using logstream.
> 

I hadn't looked at how the latest (svn HEAD) auto-detecting method worked, so I 
was going off of your statement that "...experimentation hopefully results...", 
and stating that in case it didn't, I could simply fall back to writing my own 
macros like the 0.9.7 ones.

Since 'current' seemed to get a little blurred, this is what I was referring to:

1) 0.9.7 version:
#define LOG4CXX_DEBUG ( logger, message ) { \
         if (logger->isDebugEnabled()) {\
         ::log4cxx::StringBuffer oss; \
         oss << message; \
         logger->forcedLog(::log4cxx::Level::DEBUG, oss.str(), __FILE__, 
__LINE__); }}

2) current online API docs:
#define LOG4CXX_DEBUG (logger,message) { \
         if (LOG4CXX_UNLIKELY(logger->isDebugEnabled())) {\
            logger->forcedLog(::log4cxx::Level::getDebug(), message, 
LOG4CXX_LOCATION); }}

It seemed to me that 2 is more efficient than 1 when the argument to the macro 
is either a static string, eg "Hello World", or a std::string containing some 
string my program needed to generate anyway because 2 does not create a 
temporary StringBuffer and avoids the << and str() function calls.

3) this morning's svn HEAD (which I wasn't referring to before):
#define LOG4CXX_DEBUG ( logger, message ) { \
         if (LOG4CXX_UNLIKELY(logger->isDebugEnabled())) {\
            ::log4cxx::helpers::MessageBuffer oss_; \
            logger->forcedLog(::log4cxx::Level::getDebug(), oss_.str(oss_ << 
message), LOG4CXX_LOCATION); }}

Taking an initial look at 3 this morning, it appears to create a temporary 
object, and call << and str() as well. Based on what you have said about 3 
avoiding creating an ostream, it must be more efficient than 1 and possibly only 
slightly less efficient than 2. Someone needing that extra boost and only using 
strings may prefer to duplicate 2 with their own localized name.

> 
> Adding W would not transparently support logging TCHAR* 

True, and MessageBuffer appears to be a clever solution to this.

I haven't had luck with everything 'just working' when defining UNICODE or not 
so instead I specify what my stream and character types are and define 
conversion boundaries within the software. The days are fading away where I even 
care to write something new for MS Windows desktops that isn't UNICODE inside. I 
am glad you have a solution that works for all of us.

Thank you,
-- 
Jacob Anawalt
Gecko Software, Inc.
janawalt@geckosoftware.com
435-752-8026

Re: Use of operator<<

Posted by Curt Arnold <ca...@apache.org>.
On Mar 18, 2008, at 12:01 PM, Jacob L. Anawalt wrote:

> Stephen Bartnikowski wrote:
>>> -----Original Message-----
>>> From: Josh Kelley [mailto:joshkel@gmail.com]
>>>    LOG4CXX_DEBUG(logger, "Read " << path << " and got " << out);
>>>
>
> Nice. I hadn't tried that since 'message' was documented to expect a  
> string and I didn't know if it would break in future versions, so I  
> had written out the long form of what the macro wrapped. I will be  
> correcting that shortly.
>
>> this:
>> #define LOGGING_DEBUG(message) { \
>>   if ((*pLogger)->isDebugEnabled()) {\
>>      log4cxx::logstream oss(*pLogger, log4cxx::Level::getDebug());\
>>      oss.setLocation(LOG4CXX_LOCATION);\
>>      oss << message;\
>>      oss.end_message();}}
>> This assumes you have the following declared and initialized:
>> log4cxx::LoggerPtr* pLogger;
>
> I see that the current online API documentation doesn't use the  
> logstream, and have read Curt's response saying it is supported once  
> again. If it hadn't been, I was thinking that the current online API  
> docs looked a little more efficient for simple strings (which is  
> where I currently use the logging macros), and that I would re- 
> implement the older style macros as LS_LOG4CXX_*(logger,streamInput).

I don't follow the last sentence.  The current macro definitions (and  
the implementation of the supporting classes) attempts to avoid the  
use of an actual std::basic_ostream if possible, so it should be more  
efficient for logging simple strings than the 0.9.7 implementation or  
an alternative using logstream.

>
>
> I hope the auto-detecting methods work well. If they didn't or again  
> if the "stream in the macro" version hadn't returned and I needed  
> wchar_t support I probably would have taken the "add a W to the  
> macro name" easy way out (LSW_LOG4CXX_*(logger,wideStreamInput)).
>

Adding W would not transparently support logging TCHAR* (programming  
model used on Windows  where TCHAR either char or wchar_t depending on  
preprocessor macros).  The LOG4CXX_ macros needed to effectively  
perform parameter matching (which compiler does, but not the  
preprocessor) to determine the matching stream type. 

Re: Use of operator<<

Posted by "Jacob L. Anawalt" <ja...@geckosoftware.com>.
Stephen Bartnikowski wrote:
>> -----Original Message-----
>> From: Josh Kelley [mailto:joshkel@gmail.com] 
>>
>>     LOG4CXX_DEBUG(logger, "Read " << path << " and got " << out);
>>

Nice. I hadn't tried that since 'message' was documented to expect a string and 
I didn't know if it would break in future versions, so I had written out the 
long form of what the macro wrapped. I will be correcting that shortly.

> this:
> 
> #define LOGGING_DEBUG(message) { \
>    if ((*pLogger)->isDebugEnabled()) {\
>       log4cxx::logstream oss(*pLogger, log4cxx::Level::getDebug());\
>       oss.setLocation(LOG4CXX_LOCATION);\
>       oss << message;\
>       oss.end_message();}}
> 
> This assumes you have the following declared and initialized:
> log4cxx::LoggerPtr* pLogger;
> 

I see that the current online API documentation doesn't use the logstream, and 
have read Curt's response saying it is supported once again. If it hadn't been, 
I was thinking that the current online API docs looked a little more efficient 
for simple strings (which is where I currently use the logging macros), and that 
I would re-implement the older style macros as LS_LOG4CXX_*(logger,streamInput).

I hope the auto-detecting methods work well. If they didn't or again if the 
"stream in the macro" version hadn't returned and I needed wchar_t support I 
probably would have taken the "add a W to the macro name" easy way out 
(LSW_LOG4CXX_*(logger,wideStreamInput)).

-- 
Jacob Anawalt
Gecko Software, Inc.
janawalt@geckosoftware.com
435-752-8026

RE: Use of operator<<

Posted by Stephen Bartnikowski <sb...@barkinglizards.com>.
> -----Original Message-----
> From: Curt Arnold [mailto:carnold@apache.org] 
> Sent: Tuesday, March 18, 2008 10:42 AM
> To: Log4CXX User
> Subject: Re: Use of operator<<
> 
> 
> On Mar 18, 2008, at 10:25 AM, Stephen Bartnikowski wrote:
> >
> > Hi Josh,
> >
> > As far as I can tell support was dropped for those macros, 
> which made 
> > me sad too. But it's not too hard to cook up some macros of 
> your own. 
> > I did it like
> > this:
> >
> > #define LOGGING_DEBUG(message) { \
> >   if ((*pLogger)->isDebugEnabled()) {\
> >      log4cxx::logstream oss(*pLogger, log4cxx::Level::getDebug());\
> >      oss.setLocation(LOG4CXX_LOCATION);\
> >      oss << message;\
> >      oss.end_message();}}
> >
> > This assumes you have the following declared and initialized:
> > log4cxx::LoggerPtr* pLogger;
> >
> > Hope this helps you out. I don't know if there's an 
> official way for 
> > doing this.
> >
> > - Stephen
> >
> 
> 
> Support for operator<< in the logging macros was restored 
> last September.  It had been dropped since it was not obvious 
> how to allow the macros to work with both wide and byte 
> character strings, but a lot of experimentation hopefully 
> results in a reasonable solution that avoids the surprising 
> expensive cost of std::basic_ostream construction for simple 
> streams and uses the compiler to determine whether to use 
> wide characters based on the first argument.
> 
> logstream and the insertional operator support inside the 
> LOG4CXX_ macros serve different goals.  The logstream was 
> designed so you could pass it into methods that expected a 
> std::basic_ostream or you could perform a complicated set up 
> involving field widths etc and then reuse it multiple times.  
> The insertion operator support is to simplify formatting that 
> occurs within the scope of one logging request.
> 
> Steven, it would be helpful if you could redefine your 
> current macros in terms of the LOG4CXX_ macros and see if 
> there are any unexpected problems.
> 
> I'll add some text to the documentation before building the 
> next release candidate.


Curt,

Everything seems to build and run fine if I replace the macro I mentioned
above with:

#define LOGGING_DEBUG(message) LOG4CXX_DEBUG((*pLogger), message)

Thanks,
Stephen


Re: Use of operator<<

Posted by Curt Arnold <ca...@apache.org>.
On Mar 18, 2008, at 10:25 AM, Stephen Bartnikowski wrote:
>
> Hi Josh,
>
> As far as I can tell support was dropped for those macros, which  
> made me sad
> too. But it's not too hard to cook up some macros of your own. I did  
> it like
> this:
>
> #define LOGGING_DEBUG(message) { \
>   if ((*pLogger)->isDebugEnabled()) {\
>      log4cxx::logstream oss(*pLogger, log4cxx::Level::getDebug());\
>      oss.setLocation(LOG4CXX_LOCATION);\
>      oss << message;\
>      oss.end_message();}}
>
> This assumes you have the following declared and initialized:
> log4cxx::LoggerPtr* pLogger;
>
> Hope this helps you out. I don't know if there's an official way for  
> doing
> this.
>
> - Stephen
>


Support for operator<< in the logging macros was restored last  
September.  It had been dropped since it was not obvious how to allow  
the macros to work with both wide and byte character strings, but a  
lot of experimentation hopefully results in a reasonable solution that  
avoids the surprising expensive cost of std::basic_ostream  
construction for simple streams and uses the compiler to determine  
whether to use wide characters based on the first argument.

logstream and the insertional operator support inside the LOG4CXX_  
macros serve different goals.  The logstream was designed so you could  
pass it into methods that expected a std::basic_ostream or you could  
perform a complicated set up involving field widths etc and then reuse  
it multiple times.  The insertion operator support is to simplify  
formatting that occurs within the scope of one logging request.

Steven, it would be helpful if you could redefine your current macros  
in terms of the LOG4CXX_ macros and see if there are any unexpected  
problems.

I'll add some text to the documentation before building the next  
release candidate.

RE: Use of operator<<

Posted by Stephen Bartnikowski <sb...@barkinglizards.com>.
> -----Original Message-----
> From: Josh Kelley [mailto:joshkel@gmail.com] 
> Sent: Tuesday, March 18, 2008 9:10 AM
> To: log4cxx-user@logging.apache.org
> Subject: Use of operator<<
> 
> I saw that I can use the << operator within the LOG4CXX_DEBUG, etc.
> macros; e.g.:
> 
>     LOG4CXX_DEBUG(logger, "Read " << path << " and got " << out);
> 
> This seems very convenient (and a whole lot more convenient 
> than formatting strings myself or having to use something 
> like boost::format for every log statement), but as far as I 
> can tell, it's undocumented.  Is this use of operator<< 
> officially supported, or is it an implementation detail that 
> I should not be relying upon?
> 
> If it is supported, then can I add a wiki page about it?  If 
> it's not supported, then is there a recommended way of doing 
> formatted logging?
> 
> Thanks.
> 
> Josh Kelley
> 

Hi Josh,

As far as I can tell support was dropped for those macros, which made me sad
too. But it's not too hard to cook up some macros of your own. I did it like
this:

#define LOGGING_DEBUG(message) { \
   if ((*pLogger)->isDebugEnabled()) {\
      log4cxx::logstream oss(*pLogger, log4cxx::Level::getDebug());\
      oss.setLocation(LOG4CXX_LOCATION);\
      oss << message;\
      oss.end_message();}}

This assumes you have the following declared and initialized:
log4cxx::LoggerPtr* pLogger;

Hope this helps you out. I don't know if there's an official way for doing
this.

- Stephen