Status Update

Following on from the high level design, this page will provide a more detailed design approach to implement status update logging in the Java broker.

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 instance.

This design will cover the following areas:

Logging Control

Initialy the use of a properties file will be used to enable/disable various logging options. The property value will be one of a set list. This will help avoid the ambigious parsing of Java Properties files.

# Comment Line
<logger> = <value [OFF|TRACE|DEBUG|INFO|WARN|ERROR|FATAL|ALL]>

The values for the <logger> are based on navigation through the hierarchy.

Hierarchy Refinement

Refining the hierarchy presented in the high level design such that we can implement it in terms of an easily parseable structure for use as the <logger> values.

qpid ─┬─ broker
      │
      │
      │              ┌── [<username>] ───┐
      │              ├─ [<ip/hostname>] ─┤
      ├─ connection ─┴───── [<id>] ──────┴─ channel ── [<id>] ──────┬── subscription ── [<id>]
      │                                                             │
      └─ virtualHost ── <name> ─┐                      ┌─  binding  │
                                │                      │            │
                                ├─ exchange ── <name> ─┤            │
                                │                      │            │
                                ├─ queue ── <name> ────┴────────────┘         
                                │                             
                                ├─ plugin ── <name>
                                │                 
                                └─ messagestore 

This hierachy has a number of paths which make it more difficult to process.

  1. Connection can be optionally followed with up to one of the following: username,ip/host, id
  2. Subscription can be reached through Connection and Virtualhost
  3. Exchange and Queue can be added in either order
  4. Binding can be routed through Queue and Exchange, or both in either order.

It is these difficulties that make it best to provide an abstraction layer so that a simple interface can be used at the site of the logging. These difficulties can be distilled to:

  1. Procsessing values for all values of '<name>'
  2. Overlapping configuration resolution
  3. Presentation of entities with multiple paths

Procsessing values for all values of '<name>'

To ensure that the logger path is processable the '<name>' must be present to make it easier to understand when we have an identifier or a <name> value. i.e. Is this logging all events for exchanges on Virtualhost called 'queue' or logging all exchange events that occur in relatation to queues.

qpid.virtualhost.queue.exchange = INFO

By introducing the use of the '*' wild card we can make these two situations easier to read:

qpid.virtualhost.queue.exchange = INFO
qpid.virtualhost.*.queue.exchange = INFO

The '*' can then be used at the end of the logger to ensure all logging from this point in the hierarchy will be logged, rather than just events to the specified entity.

Overlapping configuration resolution

The loops in the graph will be handled by the logger configurator so that only one log entry is created for each event, even if there are multiple matching entries in the configuration. For example, the follow two entries are equivalent and will both enable all loging for bindings. If the user wishes to log all binding operations then only one entry is necessary but the presence of both should not cause duplicate messages.

qpid.virtualhost.*.exchange.*.binding = INFO
qpid.virtualhost.*.queue.*.binding = INFO

The overlapping of configuration such as logging all details of connection from user guest and from ip 127.0.0.1 will not result in a duplicated logging if guest connects from 127.0.0.1.

qpid.connection.guest.* = INFO
qpid.connection.<127.0.0.1>.* = INFO

Presentation of entities with multiple paths

Each entitiy will have a prescribed log format which will be designed to take into consideration its place in the hierarchy, see Logging Format Design for further details.

Log Configuration processing

The configuration will be processed top-to-bottom. This allows for defaults to be set and specific cases to have further logging enabled. The example below enables INFO logging for all events and specifically adds DEBUG logging for all activity related to the user 'guest'.

qpid.* = INFO
qpid.connection.guest,* = DEBUG

Logging Abstraction

The abstraction layer allows us to fully decouple the logging mechanism from any operational logging that the broker may wish to perform.

    public boolean isInfoEnabledForPlugin(Plugin p, Object o);
    public void pluginInfo(Plugin p, Object o);
    public void pluginInfo(Plugin p, Object o, Throwable throwable);
    
    public boolean isInfoEnabled(Object o);
    public void info(Object o);
    public void info(Object o, Throwable throwable);
...
// Repeated for each level TRACE|DEBUG|INFO|WARN|ERROR|FATAL

Logging Usage

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

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

2009-06-29 13:35:10,1234 +0100 [ con:1(guest, 127.0.0.1, /)/ch:2/sub:1:qu(myqueue) ] Subscription Event occcured.
pubic class Channel
...
    plugin = getACLPlugin();
...
    if (_statusLogger.isInfoEnabledForPlugin(plugin, this))
    {
        _statusLogger.pluginInfo(plugin, this, "Plugin Event occured for this.");
    }
...

Would result in the following:

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

Initial Log Messages

TBC