I have some code which is a standalone java application comprising of 30+ classes.
Most of these inherit from some other base classes.
Each and every class has this method to get and use a log4j logger
public static Logger getLogger() {
if (logger != null) return logger;
try {
PropertyUtil propUtil = PropertyUtil.getInstance("app-log.properties");
if (propUtil != null && propUtil.getProperties() != null)
PropertyConfigurator.configure(propUtil.getProperties ());
logger = Logger.getLogger(ExtractData.class);
return logger;
} catch (Exception exception) {
exception.printStackTrace();
}
}
A) My question is whether this should be refactored to some common logger which is initialized once and used across by all classes? Is that a better practice?
B) If yes, how can this be done ? How can I pass the logger around ?
C) This is actually being used in the code not as Logger.debug() but getLogger().debug().
What is the impact of this in terms of performance?
A) in Log4J, you have logger hierarchies, not a single logger. This typically boils down to one logger per class, where loggers are identified by classname. The logger is initialized like this:
This is a good practice in that it allows you to fine-tune logging behaviour for modules (packages) or even individual classes within your app. So you may disable logging for some packages, log at INFO level in others, and log on DEBUG level for some critical classes e.g. when you want to catch a bug.
B) However, if you want a single logger everywhere, simply use the root logger in every class:
C) for calls to not too complex methods, the performance difference is likely negligible, as the JIT compiler will agressively inline calls anyway. For complicated methods it is more of an open question.
Note that the method you show does unnecessary work by loading logger configuration – this is done automatically by Log4J if you name your config file
log4j.propertiesand put it on the classpath. However, even if you need to use a nonstandard config file name, you could still load the Log4J configuration in a single place upon startup, and omit the lazy loading of the logger. Then what is left isand this will surely be inlined by the compiler. You may want to retain
getLoggernevertheless, to avoid modifying a lot of caller code.Note that it is unnecessary for
getLoggerto bepublic, as all classes are supposed to have their own logger reference anyway.