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 Andrew Chalk <ac...@magnacartasoftware.com> on 2007/02/06 19:25:55 UTC

Upgrading to v0.9.8

I had to upgrade an app. that used log4cxx. We made a lot of use of lines 
like:

LOG4CXX_INFO(eventLogger, _T("Binding to: " << sBindIP.c_str() << ". Port: " 
<< usPort << ". Link: " << sLinkNo.c_str()));

I.e. we used inline ostringstream constructs.

In 0.9.8 none of this appears to work. We appear to have to make major 
modifications to our code along the lines of:

ostringstream os;
os << _T("Binding to: " << sBindIP.c_str() << ". Port: " << usPort << ". 
Link: " << sLinkNo.c_str());
LOG4CXX_INFO(eventLogger, os.str().c_str());

Am I missing a way to continue with inline ostringstream?

Many thanks., 




Re: Upgrading to v0.9.8

Posted by Andrew Chalk <ac...@magnacartasoftware.com>.
Thanks.


"Curt Arnold" <ca...@apache.org> wrote in message 
news:9823CEE2-D8F9-4D3D-87F3-11944237E318@apache.org...
>
> On Feb 6, 2007, at 12:25 PM, Andrew Chalk wrote:
>
>> I had to upgrade an app. that used log4cxx. We made a lot of use of 
>> lines
>> like:
>>
>> LOG4CXX_INFO(eventLogger, _T("Binding to: " << sBindIP.c_str() <<  ". 
>> Port: "
>> << usPort << ". Link: " << sLinkNo.c_str()));
>>
>> I.e. we used inline ostringstream constructs.
>>
>> In 0.9.8 none of this appears to work. We appear to have to make major
>> modifications to our code along the lines of:
>>
>> ostringstream os;
>> os << _T("Binding to: " << sBindIP.c_str() << ". Port: " << usPort  << ".
>> Link: " << sLinkNo.c_str());
>> LOG4CXX_INFO(eventLogger, os.str().c_str());
>>
>> Am I missing a way to continue with inline ostringstream?
>>
>> Many thanks.,
>>
>
> The log4cxx 0.9.7 macros looked like:
>
> #define LOG4CXX_INFO(logger, message) { \
> if (logger->isInfoEnabled()) {\
> ::log4cxx::StringBuffer oss; \
> oss << message; \
> logger->forcedLog(::log4cxx::Level::INFO, oss.str(), __FILE__, 
>  __LINE__); }}
>
> And would allow you to pass a TCHAR* (where TCHAR was either char or 
> wchar_t depending on the compile flags) or any other statement  fragment 
> that could complete the oss << message statement.
>
> In log4cxx 0.10.0, we did not want the artificial limit of supporting 
> only one character type per build since many apps could easily use  both 
> char and wchar_t within the same application.  The macro looks  like:
>
> #define LOG4CXX_INFO(logger, message) { \
>         if (logger->isInfoEnabled()) {\
>             logger->forcedLog(::log4cxx::Level::INFO, message, 
> LOG4CXX_LOCATION); }}
>
> and the compiler picks the appropriate flavor of forcedLog  (std::string 
> or std::wstring) based on the type of the message  expression.  However 
> that requires that message be an expression and  not a statement fragment. 
> I do not believe that it is possible to  construct a macro that will both 
> accept statement fragments that  0.9.7 accepted and also support multiple 
> string types, but I'm  willing to be proved wrong.
>
> You appear to be misusing the Win32 _T construct (http:// 
> msdn2.microsoft.com/en-us/library/c426s321(VS.80).aspx) which is  intended 
> to be used to decorate a string literal so that it matches  the TCHAR 
> type.  For example, _T("Hello, World") would expand to  "Hello, World"L if 
> _UNICODE is set and "Hello, World" otherwise.  The  examples shown about 
> would not compile if _UNICODE was set since they  would just add a L to 
> the end of the fragment and change .c_str()  to .c_str()L.
>
> log4cxx no longer defines or uses _T.  It does define LOG4CXX_STR()  to 
> create string literals that match the internal logchar type,  however 
> LOG4CXX_STR should not be used in logging statements since  both char and 
> wchar_t flavors are provided regardless of the logchar  type.
>
> That is do
>
> LOG4CXX_INFO(logger, "Hello, World");
>
> or
>
> LOG4CXX_INFO(logger, "Hello, World"L);
>
> but do not do:
>
> LOG4CXX_INFO(logger, LOG4CXX_STR("Hello, World"));
>
> The last would compile and work properly, but it reflects a 
> misunderstanding of logchar as the internal char type.
>
> It appears from your fragments that you have no interest in wchar_t 
> strings (or other string types like CFString on Macs) and would be 
> willing to trade the multiple string type support for getting the 
> statement fragment support back.  You could create your own header  file 
> that you include after logger.h that redefines LOG4CXX_INFO et  al for 
> your own objectives, so instead of rewriting all your logging  calls, all 
> you have to do is create the header file and include it  where ever you 
> used statement fragments.
> 




Re: Upgrading to v0.9.8

Posted by Curt Arnold <ca...@apache.org>.
On Feb 6, 2007, at 12:25 PM, Andrew Chalk wrote:

> I had to upgrade an app. that used log4cxx. We made a lot of use of  
> lines
> like:
>
> LOG4CXX_INFO(eventLogger, _T("Binding to: " << sBindIP.c_str() <<  
> ". Port: "
> << usPort << ". Link: " << sLinkNo.c_str()));
>
> I.e. we used inline ostringstream constructs.
>
> In 0.9.8 none of this appears to work. We appear to have to make major
> modifications to our code along the lines of:
>
> ostringstream os;
> os << _T("Binding to: " << sBindIP.c_str() << ". Port: " << usPort  
> << ".
> Link: " << sLinkNo.c_str());
> LOG4CXX_INFO(eventLogger, os.str().c_str());
>
> Am I missing a way to continue with inline ostringstream?
>
> Many thanks.,
>

The log4cxx 0.9.7 macros looked like:

#define LOG4CXX_INFO(logger, message) { \
	if (logger->isInfoEnabled()) {\
	::log4cxx::StringBuffer oss; \
	oss << message; \
	logger->forcedLog(::log4cxx::Level::INFO, oss.str(), __FILE__,  
__LINE__); }}

And would allow you to pass a TCHAR* (where TCHAR was either char or  
wchar_t depending on the compile flags) or any other statement  
fragment that could complete the oss << message statement.

In log4cxx 0.10.0, we did not want the artificial limit of supporting  
only one character type per build since many apps could easily use  
both char and wchar_t within the same application.  The macro looks  
like:

#define LOG4CXX_INFO(logger, message) { \
         if (logger->isInfoEnabled()) {\
             logger->forcedLog(::log4cxx::Level::INFO, message,  
LOG4CXX_LOCATION); }}

and the compiler picks the appropriate flavor of forcedLog  
(std::string or std::wstring) based on the type of the message  
expression.  However that requires that message be an expression and  
not a statement fragment.  I do not believe that it is possible to  
construct a macro that will both accept statement fragments that  
0.9.7 accepted and also support multiple string types, but I'm  
willing to be proved wrong.

You appear to be misusing the Win32 _T construct (http:// 
msdn2.microsoft.com/en-us/library/c426s321(VS.80).aspx) which is  
intended to be used to decorate a string literal so that it matches  
the TCHAR type.  For example, _T("Hello, World") would expand to  
"Hello, World"L if _UNICODE is set and "Hello, World" otherwise.  The  
examples shown about would not compile if _UNICODE was set since they  
would just add a L to the end of the fragment and change .c_str()  
to .c_str()L.

log4cxx no longer defines or uses _T.  It does define LOG4CXX_STR()  
to create string literals that match the internal logchar type,  
however LOG4CXX_STR should not be used in logging statements since  
both char and wchar_t flavors are provided regardless of the logchar  
type.

That is do

LOG4CXX_INFO(logger, "Hello, World");

or

LOG4CXX_INFO(logger, "Hello, World"L);

but do not do:

LOG4CXX_INFO(logger, LOG4CXX_STR("Hello, World"));

The last would compile and work properly, but it reflects a  
misunderstanding of logchar as the internal char type.

It appears from your fragments that you have no interest in wchar_t  
strings (or other string types like CFString on Macs) and would be  
willing to trade the multiple string type support for getting the  
statement fragment support back.  You could create your own header  
file that you include after logger.h that redefines LOG4CXX_INFO et  
al for your own objectives, so instead of rewriting all your logging  
calls, all you have to do is create the header file and include it  
where ever you used statement fragments.

RE: Upgrading to v0.9.8

Posted by Stephen Bartnikowski <sb...@barkinglizards.com>.
Hi Andrew,

That's pretty much what I had to do. Fortunately, I had already been using
macros to do all of my logging, so I just changed my project's logging
macros to adapt.

In your case, however, you're going to have to either cut and paste a lot of
code, or re-factor a lot of code.

( Log4cxx dev team, please correct me if I'm wrong. )

Stephen Bartnikowski
Barking Lizards Technology
www.barkinglizards.com

-----Original Message-----
From: news [mailto:news@sea.gmane.org] On Behalf Of Andrew Chalk
Sent: Tuesday, February 06, 2007 12:26 PM
To: log4cxx-user@logging.apache.org
Subject: Upgrading to v0.9.8

I had to upgrade an app. that used log4cxx. We made a lot of use of lines 
like:

LOG4CXX_INFO(eventLogger, _T("Binding to: " << sBindIP.c_str() << ". Port: "

<< usPort << ". Link: " << sLinkNo.c_str()));

I.e. we used inline ostringstream constructs.

In 0.9.8 none of this appears to work. We appear to have to make major 
modifications to our code along the lines of:

ostringstream os;
os << _T("Binding to: " << sBindIP.c_str() << ". Port: " << usPort << ". 
Link: " << sLinkNo.c_str());
LOG4CXX_INFO(eventLogger, os.str().c_str());

Am I missing a way to continue with inline ostringstream?

Many thanks.,