Log4j: output file depending on source call class

Suppose I have a generic class with a logger initialized with its name:

public class SomeCalculationLogic { private static final Log log = LogFactory.getLog(SomeCalculationLogic .class); public void doCalculation() { log.info("doing calculations..."); ... } } 

This class is used by two logically different threads - let's say it is called from the "BackgroundTask" and "UserRequest" classes. How do I make SomeCalculationLogic log file output redirected to different log files (for example, background.log and main.log) depending on which call class?

+4
source share
3 answers

I see three possible ways:

  • if it is enough to write all the messages to the same file, but prefix them differently depending on the context, so that they become easily filtered, you could use the nested diagnostic context, as described in my previous answer ,
  • If you absolutely need to have separate log files, you can subclass your class with two different registrars and related additives, as Xavier suggested (only his solutions, unfortunately, do not work as they are),
  • or try this alternative solution .

A working implementation of a subclassifying solution would be something like this:

 public class SomeCalculationLogic { protected abstract Log getLog(); public void doCalculation() { getLog().info("doing calculations..."); ... } } public class BackgroundCalculationLogic extends SomeCalculationLogic { private static Log log = LogFactory.getLog(BackgroundCalculationLogic.class); protected Log getLog() { return log; } } public class UserRequestCalculationLogic extends SomeCalculationLogic { private static Log log = LogFactory.getLog(UserRequestCalculationLogic.class); protected Log getLog() { return log; } } 
+3
source

How about writing something like this in your log4j.xml

 <appender name="main-logfile" class="org.apache.log4j.RollingFileAppender"> <param name="file" value="${user.home}/.logs/main.log"/> <layout class="org.apache.log4j.PatternLayout"> <param name="conversionPattern" value="%d %-5p %c{1}: %m%n"/> </layout> </appender> <logger name="com.calculationlogic.main" additivity="false"> <appender-ref ref="main-logfile"/> <layout class="org.apache.log4j.PatternLayout"> <param name="conversionPattern" value="%d %-5p %c{1}: %m%n"/> </layout> </logger> <appender name="background-logfile" class="org.apache.log4j.RollingFileAppender"> <param name="file" value="${user.home}/.logs/background.log"/> </appender> <logger name="com.calculationlogic.background" additivity="false"> <appender-ref ref="background-logfile"/> </logger> 

and then the java part:

 public class SomeCalculationLogic { private final Category logger; public SomeCalculationLogic(final Category logger){ this.logger = logger; } public void doCalculation() { log.info("doing calculations..."); } } public class BackgroundTask{ public BackgroundTask(){ new SomeCalculationLogic(Logger.getLogger("com.calculationlogic.background")).doCalculation() } } public class MainTask{ public MainTask(){ new SomeCalculationLogic(Logger.getLogger("com.calculationlogic.main")).doCalculation() } } 

Result: in background.log: 2010-06-25 14: 23: 35,496 Reference INFO: performing calculations ...

in main.log: 2010-06-25 14: 23: 35,495 INFO main: do the calculations ...

+1
source

I would suggest using inheritance and not declaring final fields.

 public class SomeCalculationLogic { private static Log log = LogFactory.getLog(SomeCalculationLogic .class); public void doCalculation() { log.info("doing calculations..."); ... } } public class BackgroundCalculationLogic { private static Log log = LogFactory.getLog(BackgroundCalculationLogic .class); } public class UserRequestCalculationLogic { private static Log log = LogFactory.getLog(UserRequestCalculationLogic .class); } 
0
source

Source: https://habr.com/ru/post/1313845/


All Articles