[ 
https://issues.apache.org/jira/browse/LOG4J2-3472?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17522196#comment-17522196
 ] 

Remko Popma commented on LOG4J2-3472:
-------------------------------------

I have been thinking about how to make this work as a configuration plugin. 
(And one restriction is that I prefer to avoid DI features that are only 
available in 3.x, because I am hoping to include this in a 2.x release.)

What makes this tricky is that the Disruptor provides multiple WaitStrategy 
implementations, some with default constructors, some with constructors that 
take arguments of various types. Custom WaitStrategy implementations will 
likely also have constructors requiring some arguments, and we don't know what 
types those arguments will be.

So, what would a configuration look like?
h3. Idea 1: Users configure a factory

The simplest thing to implement (but not very pretty) that I can think of is 
where users configure a factory.
The specified factory class name must have a public no-argument constructor.
During configuration Log4j will instantiate the factory and ask the factory to 
create a WaitStrategy object.

looks something like this:
{code:java}
<configuration>
    <AsyncWaitStrategyFactory class="my.package.MyWaitStrategyFactory" />
    <Appenders> ...
{code}
...where the specified class name implements a new 
{{org.apache.logging.log4j.core.async.AsyncWaitStrategyFactory}} interface:
{code:java}
public interface AsyncWaitStrategyFactory {
    /**
     * Returns a non-null implementation of the LMAX Disruptor's WaitStrategy 
interface.
     * This wait strategy will be used by Async Loggers and Async LoggerConfigs.
     *
     * @return the WaitStrategy instance to be used by Async Loggers and Async 
LoggerConfigs
     */
    WaitStrategy createWaitStrategy();
}
{code}
h3. Idea 2: Users configure a WaitStrategy

Alternatively, without the factory idea, we can try to allow users to configure 
the WaitStrategy directly.
I imagine a configuration could then look like something like this:
{code:xml}
<Configuration>
  <AsyncWaitStrategy class="com.lmax.disruptor.TimeoutBlockingWaitStrategy">
    <!-- TimeoutBlockingWaitStrategy constructor requires a long and a TimeUnit 
parameter -->
    <ConstructorArgument value="10"          type="long" /> <!--timeout-->
    <ConstructorArgument value="MILLISECONDS" 
type="java.util.concurrent.TimeUnit" />
  </AsyncWaitStrategy>
...
{code}
Question:
Are the existing plugin facilities available in 2.x able to handle this? I 
don't think we have anything this generic.

I could be wrong but perhaps the closest thing would be something like the 
below, where we create separate plugins for a limited number of supported types:
{code:xml}
<Configuration>
  <AsyncWaitStrategy class="com.lmax.disruptor.TimeoutBlockingWaitStrategy">
    <LongArg value="200" /> <!--timeout-->
    <TimeUnitArg value="MILLISECONDS" />
  </AsyncWaitStrategy>
...
{code}
This last one is technically feasible but limited to the supported types.

The drawback of this approach is that users may not be able to configure their 
custom WaitStrategy if it requires constructor arguments for which there is no 
plugin types. (Unless they are committed enough to become familiar with the 
Log4j 2 plugin system and create their own plugin - quite a steep hurdle, since 
[our plugin docs|https://logging.apache.org/log4j/2.x/manual/plugins.html] are 
very high level...)
----
So perhaps option 1 is the most flexible and straightforward.

Thoughts?

> Allow configuration of custom Disruptor WaitStrategy
> ----------------------------------------------------
>
>                 Key: LOG4J2-3472
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-3472
>             Project: Log4j 2
>          Issue Type: New Feature
>          Components: Configuration, Core
>    Affects Versions: 2.17.2
>            Reporter: Remko Popma
>            Assignee: Remko Popma
>            Priority: Major
>             Fix For: 2.17.3
>
>
> See also LOG4J2-2858.
> Currently Log4j allows a fixed set of disruptor WaitStrategies to be 
> configured. The current code has two drawbacks:
>  * the fixed set does not include all built-in WaitStrategies that the 
> disruptor library provides
>  * the configuration does not allow custom implementations of the 
> {{com.lmax.disruptor.WaitStrategy}} interface.
> h4. Proposal:
> Introduce a {{org.apache.logging.log4j.core.async.WaitStrategyProvider}} 
> interface. Users may configure instances of this interface by setting system 
> property {{log4j2.asyncWaitStrategyProvider}}.
> Proposed implementation is to modify {{DisruptorUtil::createWaitStrategy}} to 
> check for the existence of this system property, before doing anything else. 
> If this property exists and a class can be instantiated based on the value of 
> this property, and the resulting WaitStrategyProvider instance provides a 
> non-null {{com.lmax.disruptor.WaitStrategy}} instance, then this waitstrategy 
> is returned from  {{DisruptorUtil::createWaitStrategy}}. Otherwise, we fall 
> back to the existing logic.
> Note that for simplicity I do not propose to have separate system properties 
> for Async Loggers and Async LoggerConfigs.



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to