The following 3 posts offer answers for how to use an intermediate logging helper and still get the underlying logger to report from the method of a client to that logging h
For Log4j2 the answer is provided completely by the use of logger wrappers as described in the Log4j2 manual under Example Usage of a Generated Logger Wrapper. One can simply generate (using the org.apache.logging.log4j.core.tools.Generate$ExtendedLogger tools illustrated there) a logger wrapper with a single STUB level, and then adapt that to create custom logging methods mimicking the use of the logIfEnabled(FQCN, LEVEL, Marker, message, Throwable) - possibly ignoring the STUB level and using the regular ones - then if desired, deleting or commenting out the STUB level and its methods). For this purpose the FormattedMessage can be helpful.
Example:
java -cp log4j-core-2.5.jar org.apache.logging.log4j.core.tools.Generate\$ExtendedLogger com.mycomp.ExtLogger STUB=350 > com/mycomp/ExtLogger.java
Then adapt the generated class (most support methods omitted):
public final class ExtLogger extends ExtendedLoggerWrapper {
...
private final ExtendedLoggerWrapper logger;
private static final String FQCN = ExtLogger.class.getName();
private static final Level STUB = Level.forName("STUB", 350);
//Delete this afterwards if level not used.
private ExtLogger(final Logger logger) {
super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory());
this.logger = this;
}
/**
* Returns a custom Logger with the name of the calling class.
*
* @return The custom Logger for the calling class.
*/
public static ExtLogger create() {
final Logger wrapped = LogManager.getLogger();
return new ExtLogger(wrapped);
}
/**
* Returns a custom Logger using the fully qualified name of the Class as
* the Logger name.
*
* @param loggerName The Class whose name should be used as the Logger name.
* If null it will default to the calling class.
* @return The custom Logger.
*/
public static ExtLogger create(final Class> loggerName) {
final Logger wrapped = LogManager.getLogger(loggerName);
return new ExtLogger(wrapped);
}
...
/**
* Logs a message object with the {@code STUB} level.
*
* @param message the message object to log.
*/
public void stub(final String message) {
logger.logIfEnabled(FQCN, STUB, null, message, (Throwable) null);
}
/**
* Example: Adapt with custom formatting.
* Here DEBUG level is used just as an example.
*
* @param name
* @param value
*/
public void echo(final String name, Object value) {
Message m = new FormattedMessage("echo: %s(%s)",name,value);
logger.logIfEnabled(FQCN, Level.DEBUG, null, m, (Throwable) null);
}
...
}
Then in a client class it will now log "on behalf" of that client correctly via the logger's helper methods, in this case the formatting example echo(name,value):
public class TestLog4j {
private static final ExtLogger extLogger = ExtLogger.create(TestLog4j.class);
public static void elseWhere() {
extLogger.echo("aVariableName", 4);
}
public static void main(String[] args) {
extLogger.echo("aStringVariableName","from main");
elseWhere();
}
}
Simple PatternLayout:
Output:
DEBUG [TestLog4j::main(63)] testlogging.TestLog4j - echo: aStringVariableName(from main)
DEBUG [TestLog4j::elseWhere(42)] testlogging.TestLog4j - echo: aVariableName(4)
Once you've got the hang of using logger.logIfEnabled(FQCN,...) with the FQCN (which log4j searches for in the stack trace) you may wish to delete or comment out the stub(..) methods and STUB level if you don't use an additional level.