Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

alma::acs::logging::DispatchingLogQueue Class Reference

Inheritance diagram for alma::acs::logging::DispatchingLogQueue:

Inheritance graph
[legend]
Collaboration diagram for alma::acs::logging::DispatchingLogQueue:

Collaboration graph
[legend]
List of all members.

Package Functions

 DispatchingLogQueue ()
int getMaxQueueSize ()
synchronized void setMaxQueueSize (int maxQueueSize)
synchronized boolean log (LogRecord logRecord)
void flushAllAndWait ()
Future< Boolean > flush ()
boolean hasRemoteDispatcher ()
int recordQueueSize ()
int pendingFlushes ()
int realQueueSize ()
boolean flushesPeriodically ()
void setPeriodicFlushing (final int periodMillisec)
void setRemoteLogDispatcher (RemoteLogDispatcher remoteLogDispatcher)
void shutDown ()

Private Member Functions

void flushIfEnoughRecords (boolean conservative)
boolean flush (boolean isScheduled)
boolean flushLogRecords (final LogRecord[] logRecords)

Private Attributes

volatile PriorityBlockingQueue<
LogRecord > 
queue
final ReentrantLock flushLock
final ScheduledThreadPoolExecutor executor
ScheduledFuture<?> flushScheduleFuture
long lastFlushFinished
int currentFlushPeriod
boolean outOfCapacity
int preOverflowFlushPeriod
RemoteLogDispatcher remoteLogDispatcher
int maxQueueSize
final boolean DEBUG = Boolean.getBoolean("alma.acs.logging.verbose")

Static Private Attributes

boolean LOSSLESS = Boolean.getBoolean("alma.acs.logging.lossless")

Detailed Description

Queue for LogRecords which takes care of dispatching them to a remote log service, using the one provided in setRemoteLogDispatcher(RemoteLogDispatcher).

Technically this class is not a singleton, but it is foreseen to be used as a single instance. It is thread-safe, so multiple log handlers can submit records.

All log records to be sent remotely to the central log service must be submitted to the log(LogRecord) method. If the remote log service is not available (e.g. during startup, or later temporarily due to network problems), the log records will be cached. The cache size is given by MAX_QUEUE_SIZE. If the cache is more than 70% full, the log method will only accept records with level INFO or higher. If the cache is full, no records are accepted. The idea is to not jeopardize the running system, but rather stop remote logging.

The queue sorts log records by their log levels and thus dispatches the most important records first, using LogRecordComparator.

Author:
hsommer created Apr 19, 2005 1:48:27 PM


Constructor & Destructor Documentation

alma::acs::logging::DispatchingLogQueue::DispatchingLogQueue  )  [inline, package]
 


Member Function Documentation

boolean alma::acs::logging::DispatchingLogQueue::flush boolean  isScheduled  )  [inline, private]
 

Internal flush method which covers straight calls to flush as well as scheduled calls.

Threading note: this method is thread safe because competing threads are blocked on a flush lock (and additionally on queue.drainTo(..)), so that the second thread may unexpectedly not find any log records and thus will return immediately.

Parameters:
isScheduled true if this method is called by a timer, as opposed to some more direct thread. Used only for debugging.
Returns:
Success indicator: true if all or at least some log records were permanently taken off the queue by this flush request.

Future<Boolean> alma::acs::logging::DispatchingLogQueue::flush  )  [inline, package]
 

Tries to send log records to the remote log service, but at most RemoteLogDispatcher#getBufferSize(). If sending fails, the log records remain in the queue (actually they may be first taken out and then get re-submitted).

This method returns immediately, since flushing is done in a separate thread. The returned future object can be used to wait for termination of the log flush and get the result, or to cancel the flush. The result is a Boolean which is true if all or at least 1 log record could be taken off the log queue.

Reimplemented in alma::acs::logging::AcsLoggingHandlerTest::TestLogQueue.

void alma::acs::logging::DispatchingLogQueue::flushAllAndWait  )  [inline, package]
 

Flushes all log records if the remote log service has been made available before. Returns only when the log queue contains no more records, so execution time may be long. Should better not be called from the main thread.

boolean alma::acs::logging::DispatchingLogQueue::flushesPeriodically  )  [inline, package]
 

void alma::acs::logging::DispatchingLogQueue::flushIfEnoughRecords boolean  conservative  )  [inline, private]
 

Flushes if we have enough records in the queue to fill up the entire buffer for sending them remotely, and if the remote log service can be assumed to be available.

Since flushing happens in a separate thread with a certain time lag, this method can avoid creating too many flush requests by only generating them if the number of queued log records is a multiple of the send buffer as opposed to larger than the buffer. This is controlled by the conservative flag.

Note that the most important records are sent first because the queue sorts by log level, and that a successful flush() will call this method again to submit another flush; thus even a large queue will be drained fairly fast if the remote log service works, even in the absence of periodic flushing.

Parameters:
conservative 

boolean alma::acs::logging::DispatchingLogQueue::flushLogRecords final LogRecord[]  logRecords  )  [inline, private]
 

Extracted from flush(boolean) to improve readability of the code.

Parameters:
logRecords the records to be sent to the remote logger.
Returns:
true if all or at least some log records were permanently taken off the queue.

int alma::acs::logging::DispatchingLogQueue::getMaxQueueSize  )  [inline, package]
 

boolean alma::acs::logging::DispatchingLogQueue::hasRemoteDispatcher  )  [inline, package]
 

synchronized boolean alma::acs::logging::DispatchingLogQueue::log LogRecord  logRecord  )  [inline, package]
 

Adds a LogRecord to the internal queue, so that it gets scheduled for logging. If a high-level log record should be sent out immediately, the caller of this method should subsequently call flush(), as the log method itself does not trigger a flush based on levels.

Threading note: it seems ok to make this method "synchronized". This avoids problems with stale queue size, even though the damage would be small since the treatment of queue size is somewhat arbitrary anyway. Synchronization should not block callers long at all because flushing is done in a separate thread and only gets triggered here.

TODO: there is currently a minor problem with queue overflow: log records get drained from the queue, and when they can't be sent off to the log service, they are resubmitted to the queue. It could happen that in the meantime, some other record with INFO or higher level has been added to the queue, and that resubmitting some of the even more important records may fail. The solution would be to replace the 70%-filter rule with a running priority filter: any incoming record can kick out a less important record if the queue is full.

Parameters:
logRecord to be logged
Returns:
true if logRecord was added to the queue for logging. False if queue was too full for this record.

Reimplemented in alma::acs::logging::AcsLoggingHandlerTest::TestLogQueue.

int alma::acs::logging::DispatchingLogQueue::pendingFlushes  )  [inline, package]
 

Returns the number of currently waiting flush requests. This method is intended only for monitoring the logging system. Periodic flushing enabled by setPeriodicFlushing(int) is not counted as a waiting flush request.

Note that not all of these requested flushes necessarily result in a flushing of log records, because some of them may find an empty log record queue when they get executed, and thus end w/o effect.

int alma::acs::logging::DispatchingLogQueue::realQueueSize  )  [inline, package]
 

Waits if necessary until a flushing thread has finished, and then returns the real number of currently queued log records.

Note that during flushing, the records are first taken out of the queue, but then get resubmitted if sending them to the central log service failed. Therefore, calling queue.size() w/o flush synchronization may yield too low a value.

int alma::acs::logging::DispatchingLogQueue::recordQueueSize  )  [inline, package]
 

Returns the number of currently queued log messages. This method is intended only for testing and monitoring of the logging system.

synchronized void alma::acs::logging::DispatchingLogQueue::setMaxQueueSize int  maxQueueSize  )  [inline, package]
 

Sets the maximum size of the log queue. Logs will be dropped when the queue is full. The default is 1000, but gets overwritten by the value of <LoggingConfig MaxLogQueueSize/> in the CDB.

void alma::acs::logging::DispatchingLogQueue::setPeriodicFlushing final int  periodMillisec  )  [inline, package]
 

Triggers periodic calls to flush(boolean), or terminates such automatic flushing if periodMillisec == 0.

All control over periodic log flushing is confined in this method.

The call returns without further action if flushing is already enabled with the same period as periodMillisec.

Parameters:
periodMillisec the delay between end of last scheduled flush() and the next scheduled flush().

void alma::acs::logging::DispatchingLogQueue::setRemoteLogDispatcher RemoteLogDispatcher  remoteLogDispatcher  )  [inline, package]
 

Sets the remote log dispatcher. Should be called once the remote log service is available. Calling this method will not flush the log queue (need to call flushAllAndWait() separately), nor will it automatically trigger periodic flushes (call setPeriodicFlushing(int) for this).

Parameters:
remoteLogDispatcher The remoteLogDispatcher to set.

void alma::acs::logging::DispatchingLogQueue::shutDown  )  [inline, package]
 


Member Data Documentation

int alma::acs::logging::DispatchingLogQueue::currentFlushPeriod [private]
 

final boolean alma::acs::logging::DispatchingLogQueue::DEBUG = Boolean.getBoolean("alma.acs.logging.verbose") [private]
 

final ScheduledThreadPoolExecutor alma::acs::logging::DispatchingLogQueue::executor [private]
 

final ReentrantLock alma::acs::logging::DispatchingLogQueue::flushLock [private]
 

ScheduledFuture<?> alma::acs::logging::DispatchingLogQueue::flushScheduleFuture [private]
 

long alma::acs::logging::DispatchingLogQueue::lastFlushFinished [private]
 

boolean alma::acs::logging::DispatchingLogQueue::LOSSLESS = Boolean.getBoolean("alma.acs.logging.lossless") [static, private]
 

If true, them the queue does not drop any log records, but rather blocks loggers in log(LogRecord) until their request can be processed. Default is false, because application performance is more important than logging. For performance testing etc, setting this property may be useful though.

int alma::acs::logging::DispatchingLogQueue::maxQueueSize [private]
 

Underlying PriorityBlockingQueue is unbounded, but we don't want logging to cause memory problems while the remote logger is unavailable and all logs must be cached. Thus a maximum queue size. The chosen value must be larger than RemoteLogDispatcher#getBufferSize()

boolean alma::acs::logging::DispatchingLogQueue::outOfCapacity [private]
 

int alma::acs::logging::DispatchingLogQueue::preOverflowFlushPeriod [private]
 

volatile PriorityBlockingQueue<LogRecord> alma::acs::logging::DispatchingLogQueue::queue [private]
 

RemoteLogDispatcher alma::acs::logging::DispatchingLogQueue::remoteLogDispatcher [private]
 


The documentation for this class was generated from the following file:
Generated on Thu Apr 30 02:53:40 2009 for ACS Java API by doxygen 1.3.8