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