Remko Popma created LOG4J2-1278:
-----------------------------------

             Summary: Garbage-free logging API
                 Key: LOG4J2-1278
                 URL: https://issues.apache.org/jira/browse/LOG4J2-1278
             Project: Log4j 2
          Issue Type: Improvement
          Components: API
    Affects Versions: 2.5
            Reporter: Remko Popma


Looking at the current Logger API, there are a few methods (for each log level) 
that take a vararg parameter:
{code}
// org.apache.logging.log4j.Logger
debug(String, Object...) // arguably this method is used the most
debug(String, Supplier<?>...)
debug(Marker, String, Object...)
debug(Marker, String, Supplier<?>...)
{code}

This ticket is to explore options for providing similar functionality without 
creating temporary objects (see LOG4J2-1270 for motivation).

Here are some of the options I can think of:

*1. Thread-local StringBuilderMessage*
One option is that we provide a new MessageFactory that always returns the same 
Message object (cached in a ThreadLocal). This Message exposes its 
StringBuilder. Users build the log message text by appending to the 
StringBuilder. When the Logger.log method is called, and the Message is 
enqueued in the RingBufferLogEvent, the StringBuilder text is copied to the 
RingBufferLogEvent.

Pros: feasible, low effort, no Logger API changes
Cons: not the nicest user-facing API

*2. Logger with unrolled varargs*
Another way to avoid the varargs is adding extra methods to the Logger 
interface that take a varying number of parameters. For example:
{code}
// add methods to org.apache.logging.log4j.Logger
trace(String, Object)
trace(String, Object, Object)
trace(String, Object, Object, Object)
trace(String, Object, Object, Object, Object)
trace(String, Object, Object, Object, Object, Object)
trace(String, Object, Object, Object, Object, Object, Object)
trace(String, Object...) // fallback to vararg if 7 parameters or more
...
// same for DEBUG, INFO, WARN, ERROR, FATAL, and LOG(Level)
{code}

Pros: transparent to users
Cons: grows Logger interface from 200+ methods\(!) to an even larger number

*3. New interface (LevelLogger) with unrolled varargs*
Another option that avoids the method explosion is providing a new interface 
(e.g. LevelLogger). This interface has extra methods for a varying number of 
parameters. For example:
{code}
// new interface LevelLogger
log(String, Object)
log(String, Object, Object)
log(String, Object, Object, Object)
log(String, Object, Object, Object, Object)
log(String, Object, Object, Object, Object, Object)
log(String, Object, Object, Object, Object, Object, Object)
log(String, Object...) // fallback to vararg if 7 parameters or more
{code}

For each log level, the same interface can be used, so the number of methods 
can stay small. There are several ways in which client code could obtain a 
LevelLogger. One option is from the Logger, but other things are possible too.
{code}
Logger logger = LogManager.getLogger(MyClass.class);
logger.info().log("This a {} message with {} params", "vararg-free", 2);
{code}

*Avoiding Autoboxing*
To avoid auto-boxing of primitive parameters (like the integer in the above 
example), one option is to provide a utility method. Client code would look 
like this:
{code}
// static import Unboxer.*;
logger.info().log("This a {} message with {} params", "GC-free", box(2));
{code}

{{Unboxer.box(int)}} returns a StringBuilder containing the primitive value 
converted to text. Unboxer internally can be implemented with a cached ring 
buffer of StringBuilders, with as many slots as there are unrolled varargs.

*4. LevelLogger with method chaining*
A different way to avoid auto-boxing is method chaining.
Client code would look like this:
{code}
String type = "GC-free";
int count = 2;
logger.info().log("This a ").add(type).add(" message with ").add(count).add(" 
params").commit();
{code}

Pros: feasible, medium effort
Cons: API very similar to StringBuilder, but more fragile since users must 
remember to call commit()



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-dev-h...@logging.apache.org

Reply via email to