Description
In a simple use case, e.g.:
logger.error("Hello, {}!", "Problem", new Exception("Oh oh"));
Without the transform plugin, the default parameterized message formatter captures the last argument as a throwable -
if it's the last argument and the previous argument count match the placeholder count.
When processed by the ExtendedThrowablePatternConverter
, it is fetched -
from LogEvent.getThrown()
, which was previously populated when the LogEvent was created, from Message.getThrowable()
.
This provides the throwable pattern converter the information to format the throwable as a message/stacktrace.
Here is the code generated by the transform plugin:
Logger var10000 = logger;
Object log4j2$$p0 = new Exception("Oh oh");
Object log4j2$$p1 = "Problem";
Object log4j2$$p2 = "Hello, {}!";
var10000.atError().withLocation(Cache.locations[0]).log(log4j2$$p2, log4j2$$p1, log4j2$$p0);
It create a LogBuilder
, but does not use its .withThrowable(Throwable)
method -
leading to a LogEvent
that does not have the throwable set.
My thought is that to resolve that, the transform plugin needs - at build time - to analyze the logger call in the same way the logger does to extract the throwable arg and set it using .withThrowable(Throwable)
.
An alternative (might be simpler) - is to change the DefaultLogBuilder
(in log4j-api
), so that DefaultLogBuilder.logMessage(Message)
changes from
logger.logMessage(level, marker, fqcn, location, message, throwable);
to something like
logger.logMessage(level, marker, fqcn, location, message, throwable != null ? throwable : message.getThrowable());