tags:

views:

78

answers:

3

Hi all

suppose I have a common class with logger initialized by 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 flows - say it is called from classes "BackgroundTask" and "UserRequest". How to make output of SomeCalculationLogic's logger redirected to different log files (like background.log and main.log) depending on what calling class is?

A: 

I would suggest to use inheritance and not declare 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);
}
Xavier Combelle
`log` should be declared `protected` for this to work. And since its `static`, it is not going to be "overridden" by child class data members anyway :-(
Péter Török
nice I didn't know your solution is far better I tend to -1 mine but I will not
Xavier Combelle
+1  A: 

I see three possible ways:

  • if it is enough to log all messages into the same file but prefix them differently depending on context, so that they become easily filterable, you could use a nested diagnostic context, as described in a previous answer of mine,
  • if you absolutely need to have separate log files, you could subclass your class with two different loggers and associated appenders, as Xavier suggested (just his solutions is unfortunately not working as it is),
  • or try this alternative solution.

A working implementation of a subclassing 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;
  }
}
Péter Török
Just a minor syntax error, the keyword "extends" is missing ;)
Sylvain M
@Sylvain, thanks, fixed :-)
Péter Török
+1  A: 

What 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()
  }
}

The result is: in background.log: 2010-06-25 14:23:35,496 INFO background: doing calculations...

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

Sylvain M