For #3, I agree that we should perform formatting on the application thread 
before transferring control to an asynchronous thread.

> On Feb 5, 2024, at 14:49, Piotr P. Karwasz <piotr.karw...@gmail.com> wrote:
> 
> Hi all (and especially Remko),
> 
> Lately I spent some time looking at the asynchronous logger/logger
> config and I think it could profit from some refactoring in 3.x.
> 
> The problems I am seeing are:
> 
> 1. The disruptors of `AsyncLogger` and `AsyncLoggerConfig` use
> different structures. The disruptor of `AsyncLoggerConfig` contains
> basically a `Pair<AsyncLogger, LogEvent>`, while `AsyncLogger` uses
> `RingBufferLogEvent`, which is basically `MutableLogEvent` with an
> additional field of type `AsyncLogger`.
> 
> The design of the `AsyncLoggerConfigDisruptor` seems better: it always
> uses an allocation-free `EventTranslatorTwoArg`[1], while
> `AsyncLoggerDisruptor` users must choose between a
> `EventTranslatorVarArg` which allocates a temporary array and an
> `EventTranslator` that copies the log event into a thread-bound
> structure first.
> 
> Can we remove `RingBufferLogEvent` and use `Pair<AsyncLogger,
> MutableLogEvent>` instead?
> 
> 2. I am not convinced by the utility of having multiple
> implementations of `ReusableMessage`. Since the `ReusableMessage`
> interface does not specify how to format messages, transferring data
> between a `ReusableParameterizedMessage` and `MutableLogEvent`
> requires a call to `ReusableMessage#formatTo` to account for the
> possibility of different formatting algorithms.
> 
> We could remove `ReusableObjectMessage`, `ReusableSimpleMessage`,
> `ReusableParameterizedMessage` and merge `ReusableMessageFactory` with
> `ReusableLogEventFactory`.
> 
> Instead of 4 thread locals for each type of `ReusableMessage` we would
> just have a single `Recycler<MutableLogEvent>` and the performance of
> `MutableLogEvent#setMessage` could be improved:
> 
> public void setMessage(final Message message) {
>    if (message instanceof MutableLogEvent) {
>        // NOP
>    } else ...
> }
> 
> 3. Before a thread jump, three values must be computed: the source
> location (optional), the context map and the formatted message.
> Currently the location were these are computed varies and can be as
> early as the `ReusableLogEventFactory`. I would propose to move them
> to the last moment before we pass control to another thread, i.e.:
> 
> * in `EventTranslator#translateTo` (this way nothing is computed if
> the ring buffer is full and the `AsyncQueueFullPolicy` chooses to
> discard the message) for `AsyncLogger`/`AsyncLoggerConfig`,
> * just before  the call to `Queue#offer` for the `AsyncAppender`.
> 
> What do you think?
> 
> Piotr
> 
> [1] 
> https://lmax-exchange.github.io/disruptor/javadoc/com.lmax.disruptor/com/lmax/disruptor/EventTranslatorTwoArg.html

Reply via email to