Calling log4j's log methods indirectly (from a helper method)
Asked Answered
D

4

1

I'd like to put the logger.debug(...) call into a helper method, and call that helper method from anywhere that needs to write the log. While this mostly works fine, the log entry itself shows the helper method as the source of the call, which is understandable since log4j isn't aware of me using a helper method for logging.

Is there any way to tell it to skip the helper method when figuring out the source of the logger.debug(...) call and instead use its caller?

By source, I mean %F:%L of org.apache.log4j.PatternLayout: https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

To illustrate what I mean, here's an example stack trace:

1. logger.debug(msg, throwable)
2. logHelper(logger, msg, throwable) <-- currently shows as the source of the call, since it calls logger.debug directly
3. someFunction <-- where the real logable event occurs, so I'd want this to be logged as the source

The reason I'm doing this is because I'd like an exception logged only by name (e.toString) if the log level is INFO, or with a full stack trace if the level is DEBUG. I'm open to suggestions for alternatives.

Thanks! :)

Drogheda answered 27/5, 2014 at 2:8 Comment(4)
This is the sort of thing that's much better done in the log configuration than hard-baked into code everywhere.Botswana
I understand exactly why you want to do this, I do something similar via common interim logging methods that enforce systematic formatting of, for example, a name of a variable and its value. For example log_debug(methodName,variableName,value) gives "name(value)", giving consistent output. This can't be done using log configuration, it is a common misunderstanding of the aim; one would have to remember to call each logger with the exact same calling pattern, and this defeats the purpose of having a helper method with named parameters. Note that java.util.Logging offers a methodName param too.Thibault
Related: Java Logging: show the source line number of the caller (not the logging helper method)Thibault
Now with a complete example for Log4j2 at: #35361387Thibault
T
1

For log4j2, you can write a simple wrapper class or generate one as Webel suggests. See my answer for log4j2: https://mcmap.net/q/355939/-java-logging-log4j-version2-x-show-the-method-of-an-end-client-caller-not-an-intermediate-logging-helper-method

Tyndall answered 19/8, 2016 at 19:41 Comment(0)
W
0

You can't instruct Log4J to "skip" a level in its source detection.

What you can do, though, is subclass PatternLayout and override the format(LoggingEvent) method to your liking (i.e. only produce the exception's toString() when in INFO mode, etc).

Wales answered 27/5, 2014 at 3:1 Comment(0)
D
0

One way to do this is to have the helper class call:

logger.log(LogHelper.class.getName(), Level.DEBUG, message, t);

... instead of:

logger.debug(message, t);

So when log4j tries to determine the source of the event, it will stop when it reaches the parent of LogHelper instead of the parent of Logger.

Verified working as expected.

Drogheda answered 27/5, 2014 at 4:20 Comment(3)
At least for log4j 2 I can't find that method under the Log4j 2 API for Interface LoggerThibault
I also seek this solution, but as far as I can tell the method you describe is for the log4j1.2 API, which offers Category.log(String callerFQCN, Priority level, Object message, Throwable t). There does not seem to be an equivalent for Logger in the log4J 2.5 API. Can anybody offer an answer compatible with direct use of Log4J 2.x ?Thibault
Java Logging: Log4j Version2.x: show the method of the caller (not an intermediate logging helper method)Thibault
T
0

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.

The method and source line, while expensive, can then be easily shown as part of the full location information by using the %l location conversion pattern element in the PatternLayout given in the configuration, or more specifically using the %L line number and/or the %M method conversion.

Now with complete example at: Java Logging: Log4j Version2.x: show the method of an end-client caller (not an intermediate logging helper method)

Thibault answered 13/2, 2016 at 11:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.