Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

The logging hierarchy identified is not suitable to be directly used by Log4j as there is multiple routes and loops in the graph.

To better address this and to allow us to more eaily move between logging implementations an abstraction is recommended. This approach will allow the simplification of the logic around determining if logging should be performed in the main code base. For example a Binding logging statement can be controlled via Exchange and Queue, each of which may be limited to s specific instanceAbstracting the logging is recommended as this will allow us to simply provide Qpid specific optimisations such as providing the log prefix.

This design will cover the following areas:
Contents

Table of Contents
minLevel3
maxLevel3

Additional Documentation

Logging Configuration

At this stage configuration will be limited to the addtion addition to the main config.xml file of the following option:

Code Block
xml
xml
<broker>
 ...
 <logging>
    <level>INFO</level>
 <logging> <status-updates>ON</status-updates>
 ...
</broker>

This INFO level status-update on setting will be the default value if the section is not included in the configuration file. The setting will be global for all virtualhosts and will be exposed via the management console as logger 'qpid.operationalstatus' to allow dynamic level setting.

The ability to configure more fine grained logging will be investigated here, but will not be implemented in the initial phase.

Logging Levels

The following six levels represent the range of levels that will be available as part of the logging configuration. Whilst the initial implementation may not include specific messages at each level this section simply describes the type of message that would appear at each level and the behaviour associated with logging at that level. The levels are listed in order of the frequency of logging events. In addition to these six levels the values ALL and OFF may be used, these respectively represent TRACE and FATAL. FATAL messages will always be logged as they are associated with a broker shutdown.

Status Updates

In the first phase updates only status updates will be provided. Status updates should take the form of general FATAL
Occurs when an unrecoverable error has occured. A stack trace is automatically generated and a System.exit(1) is called halting the process.
e.g. Data corruption
ERROR
Occurs when a problem occurs in the system but it can generally continue to operate.
e.g. Unexpected error occurs that is limited to a single connection, i.e. not message store related.
WARN
Occurs when a potententialy harmful situation occurs.
e.g. Unexpected connection closure
INFO
General operational logging level, no logging on message delivery path way . and No performance impact. Recommended The recommendation will be to have these enabled for production use.
e.g. Creation/Destruction events DEBUG
Additional logging on

The status updates can also be used in a second phase to provide additional logging to assist development.
The additional logging can be performed on the message delivery path way. May This may have performance impact . Not and so would not be recommended for long term production use.
e.g. Message Enqueue/Dequeue
TRACE
Full delivery path debugging. Will have performance impact. Not intended for production use.
e.g. Message selector behaviour

Logging Abstraction

The abstraction layer allows us to fully decouple the logging mechanism from any operational logging that the broker may wish to perform. The following code highlights show how we would abstract the logging operations.

...


public interface OperationalLogger
{
    public boolean isInfoEnabled(LogEntity entity);
    public void info(LogEntity entity, Object message);
    public void info(LogEntity entity , Object message, Throwable throwable);
// Repeated for each level TRACE|DEBUG|INFO|WARN|ERROR|FATAL
}

...


public interface LogEntity
{
    public String getLogPrefix();
    public void setCreator(LogEntity creator);
}

The LogEntity allows the OperationLogger to delegate the creation of the formated prefix as specfiecied here. Further additions to this interface may be required to enable selective configurations however this The approach to logging is that a LogActor will be recoreded as a ThreadLocal and will be used to perform logging the log messages as highlighted on Logging Format Design. The LogActor will take two parameters, the LogSubject and the LogMessage. When a Status event occurs that should be logged the LogActor can be retrieved from the thread thus avoiding passing the LogActor through as a parameter to all locations were it must be logged. The initial LogActors will be AMQPActor and ManagementActor. Later phases would introduce HouseKeepingActor. These LogActors are responsible for checking that the logging should be performed for both themselves and the LogSubject. The LogActor then provids their log formatted name as per the format design along with the message to the RootMessageLogger. Initially the configuration will be a simple on/off, however, in a future phase the details can be used to identify if logging should proceed for that LogActor and LogSubject combination. At this stage selective configurations is not part of this design.

The addition use of the ability to set a creator LogActor allows for situations such as Binding to have a Connection associated with the Binding. This will allow a Binding create event to be logged like this:

No Format
2009-06-29 13:35:10,1234 +0100 INFOMESSAGE [ con:1(guest@127.0.0.1/)/ch:2/] [ex(amq.direct)/qu(testQueue)/bd(routingKey)] ]BND-1001 Created: Binding Created

rather having no details about how the creation occuredoccurred:

No Format
2009-06-29 13:35:10,1234 +0100 INFOMESSAGE [ vh(/)/ex(amq.direct)/qu(testQueue)/bd(routingKey) ] Created BindingBDN-1001 : Create

...

Interfaces

Code Block
java
java
titleLogging by a LogEntityLogActor

/**
 * LogActor the entity that is stored as in a ThreadLocal and used to perform logging.
 *
 * The actor is responsible for formatting its display name for the log entry.
 * 
 * The actor performs the requested logging.
 */
public interface LogActor
{
    /**
     * Logs the specified LogMessage about the LogSubject
     *
     * Currently logging has a global setting however this will later be revised and
     * as such the LogActor will need to take into consideration any new configuration 
     * as a means of enabling the logging of LogActors and LogSubjects.
     *
     * @param actor   The actor that is requesting the logging
     * @param message The message to log
     */
    public void message(LogSubject subject, LogMessage message);
}
Code Block
java
java
titleLogSubject

/**
 * Each LogSubject that wishes to be logged will implement this to provide their
 * own display representation.
 * 
 * The display representation is retrieved through the toString() method.
 */
public interface LogSubject
{
    /**
     * Logs the message as provided by String.valueOf(message).
     *
     * @returns String the display representation of this LogSubject
     */
    public String toString();
}
Code Block
java
java
titleRootMessageLogger

/**
 * The RootMessageLogger is used by the LogActors to query if
 * logging is enabled for the requested message and to provide the actual
 * message that should be logged.
 */
public interface RootMessageLogger
{
    /**
     * Determine if the LogSubject and the LogActor should be
     * generating log messages.
     *
     * @param logSubject The subject of this log request
     * @param logActor   The actor requesting the logging
     * @return boolean true if the message should be logged.
     */
    boolean isMessageEnabled(LogActor actor, LogSubject subject);

    /**
     * Log the raw message to the configured logger.
     *
     * @param message   The message to log
     * @param throwable Optional Throwable that should provide stact trace
     */
    void rawMessage(String message, Throwable throwable);
}

Code Block
java
java
titleRawMessageLogger

/**
 * A RawMessage Logger takes the given String and any Throwable and writes the
 * data to its resource.
 */
public interface RawMessageLogger
{
    /**
     * Log the message and formatted stack trace for any Throwable.
     *
     * @param message   String to log.
     * @param throwable Throwable for which to provide stack trace.
     */
    public void rawMessage(String message, Throwable throwable);
}

Logging Usage

Code Block
java
java
titleLogging of a Channel Creation

pubic class Connection
...
   LogActor amqpActor = // retrieved from ThreadLocal.
   //_channelSubject is an instance LogSubject that knows how to represent this Connection
   amqpActor.logMessage(_connectionSubject, LogMessages.CHANNEL_CREATE(this));

...
pubic class Subscription
...
    if (_statusLogger.isInfoEnabled(this))
    {
        _statusLogger.info(this, "Subscription Event occured.");
    }
...

Would result in the following based on the Logging Format Design.

No Format
2009-06-29 13:35:10,1234 +0100 INFOMESSAGE [ con:1(guest@127.0.0.1/)/] [ch:2/sub:1:qu(myqueue) ] Subscription Event occcured.] ChM-1001 : Channel Created
Code Block
java
java
titleLogging of a newly created LogEntity via connectionnew consumer creation
...
    binding = new ExchangeBinding(...);
    ((LogEntity)binding).setCreator(connection);
... 
// Verify binding can be performed/created
...
    if (_statusLogger.isInfoEnabled(binding))
    {
        _statusLogger.info(binding, "Created");
    }
amqpActor.logMessage(_subsriptionSubject, LogMessages.SUBSCRIPTION_CREATE(this));
...

Would result in the following:

No Format
2009-06-29 13:35:10,1234 +0100 INFOMESSAGE [ con:1(guest@127.0.0.1/)/ch:2/pl(ACL, Consume, qu(myQueue)) ] Plugin Event occured for this. 

Initial Log Messages

FATAL

At this level it is only expected that broker/virtualhost wide components could cause a FATAL issue.

Broker
ManagementConsole
VirtualHost
MessageStore

MetaData not Found

ERROR

Broker

Startup errors

ManagementConsole

Startup errors
UserManagement notification(Create, Update, Delete)
Access Right modification/reload

VirtualHost
MessageStore

Recover errors

Connection

Unhandled exceptions leading to connection closure

Channel
Queue
Exchange
Binding
Subscription

WARN

Broker
ManagementConsole
VirtualHost
MessageStore
Connection

Unclean connection closure
Unsupported protocol version

Channel
Queue
Exchange
Binding
Subscription

INFO

Broker
] [sub:1:qu(myqueue)] Sub-1001 : Subscription Created

Initial Status Messages

Broker

Startup
Configuration details
Ready
Shutdown

ManagementConsole

Startup
Configuration details
Ready
Close

VirtualHost

Create
Configuration details
Close

MessageStore

Startup
Recover Status
Start
Progress
End
Close

Connection

Open
Close

Channel

Create
Flow Status
Destroy

Queue

Create
Destroy

Exchange

Create
Destroy

Binding

Create
Destroy

Subscription

Create
Destroy

DEBUG

Broker
ManagementConsole
VirtualHost

Message Expiry

MessageStore
Connection

Creation Configuration details

Channel

Acknowledge
Commit
MessageRejection

Queue

Enqueue
Dequeue

Exchange

Route

Binding
Subscription

Send/Add to prefetch/unacked map

TRACE

Broker
ManagementConsole
VirtualHost
MessageStore

Enqueue
Dequeue

Connection
Channel
Queue

Message State Change(Available->Aquire...)

Exchange
Binding

...