On May 26, 2006, at 7:13 AM, Jeffrey Graham wrote:

Hello,

I downloaded the CVS version 408722 just several days ago and have the following 2 problems with the pattern layout under Linux..

1) %p always shows the current log level, not the level of the message

When you set the level of the logstream, you are setting the level of the logging requests that are generated from the logstream, not the threshold for the logger. So if I do:

log4cxx::logstream logWrapper::logs(Logger::getRootLogger(), Level::getInfo());
logs << "Info Message" << LOG4CXX_ENDMSG;
logs.setLevel(Level::getDebug());
logs << "Debug Message" << LOG4CXX_ENDMSG;

You would generate an INFO level request and a DEBUG level request. The threshold of the logger is a totally distinct thing.


2) %Q does not print the fractional seconds fo time, but the "%d {ISO8601}" does.

You should use the java.text.SimpleDateFormat syntax (http:// java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html which does support fractional seconds. For backward compatibility with log4cxx 0.9.7 if a strftime-type format (that is with %'s) is detected, then apr_strftime used to format the time. %Q is not implemented in APR's apr_strftime (and is not documented typically in systems that do implement it).



Help, especially on the %p issue is greatly appreciated.

I am using streams in C++.


My code looks like this (inside a class called logWrapper where logger and logs are declared static):

Have a logstream as a class member is strongly discouraged. All actions on a logger are atomic, so they can be members or static members. However, logstreams keep an internal state and interleaved calls could result in scrambled messages. For example, if you had:

class Foo {
   private:
static log4cxx::logstream ls(Logger::getRootLogger(), Level::getInfo());
   public:
   Foo() {}
   void action1() {
         ls << "Hello" << " World" << LOG4CXX_ENDMSG;
   }
   void action2() {
         ls << "Kitty" << LOG4CXX_ENDMSG;
   }
}

you could end up with any of the following combinations if action2 and action2 were called simultaneously;

Hello World
Kitty

Kitty
Hello World

KittyHello World
(blank)

HelloKitty
World

KittyHello
World


logstream's make no attempt to synchronize their action and couldn't avoid the interleaving of actions if they tried. They are designed to be instantiated upon entry to a routine and potentially used repeatedly in the body of a routine. They are not designed to be shared or long-lived.

In addition, use Level::getInfo() in preference to Level::INFO as static member variables have initialization order issues and INFO and the like may be removed if they prove to be unsafe in the current implementation.

Using a logstream* seems to be strange since it would likely leak.

Reply via email to