Hello,
I use log4j2 AsycLogger Implementation With a custom database appender.
As i investigated the async logger mechanism works like that.
- Messages are put into DistruptorRingBuffer
*Than *
RingBufferLogEventHandler's onEvent mehtod is called and message is passed
to appender asyncronously.
In *AbstractDatabaseAppender* case
The messages also put into an ArrayList to make batches for bulk insert to
table.
@Override
public final void append(final LogEvent event) {
this.readLock.lock();
try {
this.getManager().write(event);
} catch (final LoggingException e) {
LOGGER.error("Unable to write to database [{}] for appender
[{}].", this.getManager().getName(),
this.getName(), e);
throw e;
} catch (final Exception e) {
LOGGER.error("Unable to write to database [{}] for appender
[{}].", this.getManager().getName(),
this.getName(), e);
throw new AppenderLoggingException("Unable to write to
database in appender: " + e.getMessage(), e);
} finally {
this.readLock.unlock();
}
}
Than Abstract Database manager puts LogEvent into ArrayList
public final synchronized void write(final LogEvent event) {
if (this.bufferSize > 0) {
this.buffer.add(event);
if (this.buffer.size() >= this.bufferSize || event.isEndOfBatch()) {
this.flush();
}
} else {
this.connectAndStart();
try {
this.writeInternal(event);
} finally {
this.commitAndClose();
}
}
}
After that correspoding LogEvent object can be re-used in the
DistruptorRingBuffer mechanism.
So if a delay could happen in the database the LogEvent objects are
overriden with same referance which causes inconsitency while preparing
batches.
I believe this points to a bug or design problem.
Thanks for any help and guidance.
--
*Tolga KAVUKÇU*