Lazar Zoltan Lazar Zoltan - 1 month ago 9
Java Question

Logging in seperate .log files using log4j

I working on a multi-module maven web project.

Lets say the structure looks something like this:

Project
Module1
Module2
Persist
log4j.properties


I managed to log all the log-entrys into one file (placing the log4j.properties files into the project-persist module). So far, this is clear.
Now, there are some modules which I would like to seperate the logs into other files.
Adding just a new appender (testAppender in the example) doesn't work for me because then I don't get the path of the .java file the log was written from.
If I write it like this:

Logger log = Logger.getLogger("testAppender");


I get something like this:

2017-276-06 15:00:00,032 [INFO ] Start rule activation. (testAppender)[__ejb-thread-pool3]


And this is what I want:

2016-06-06 15:00:00,032 [INFO ] Start rule activation. (Module1.src.main.java.somepkg.MyClass)[__ejb-thread-pool3]


Where MyClass is the .java file.

I also tried to add a complitly new (independent) log4j.properties file to the Maven-modules (Module1 and Module2), just like in the Persist-module, I want seperate the logs from, with a different path to the .log file, but it logs only the entrys from the maven tests - which is another problem I have, but one at a time.

Is there a way to add a new appender that will seperate the log entrys by the modules they comming from and to have them printed in the .log file?
Thanks!

Answer Source

So, I found a solution to this problem.

I made a class that gets a logger object and from the logger object I take the informations I need to seperate them. I initilize the logger manually, kind of. Hope this will help someone!

In every class where the Logger is used, I also call the initilizer.

public class ClassA{

     private final Logger LOGGER = Logger.getLogger(getClass());
     static{         
        LogConfig.init(LOGGER);    
     }

     some code...
  }

A here is what I did in the LogConfig class:

public class LogConfig {

public static RollingFileAppender init(Logger LOGGER) {

    String logInfo = LOGGER.getClass().toString();

    String loglevel = getLogLevel(logInfo);
    String logClazz = getLogClazz(logInfo);
    String logModule = getModule(logInfo);

    PatternLayout PL = new PatternLayout("%d [%-5p] %m (%c)[%t]%n");

    try {
        if (logModule == "presentation") {
        RollingFileAppender appender = new RollingFileAppender(PL, "PathToLogFile_1.log", true);
        return appender;
    } 
    else if (logModule == "business") {
        RollingFileAppender appender = new RollingFileAppender(PL, "PathToLogFile_2.log", true);
        return appender;
    }

    RollingFileAppender appender = new RollingFileAppender(PL, "PathToLogFile_3.log", true);
    return appender;

    }catch (IOException e) {
        e.printStackTrace();
    }
    return null;
    }

private static String getLogClazz(String logInfo) {
    return logInfo.substring(logInfo.indexOf("("), logInfo.indexOf(")") + 1);
}

private static String getLogLevel(String logInfo) {
    return logInfo.substring(24, 31);
}

private static String getModule(String logInfo) {
    logInfo = logInfo.substring(logInfo.indexOf("(") + 15, logInfo.length());
    return logInfo.substring(0, logInfo.indexOf("."));
    }
}

If you ever use this code, noticethat you will have to adjust the three methods that return the classname, log level and module name, depending on how you have named your packages, classes, modules etc..

The LOGGER.getClass().toString(); returned a string that looks something like this

[timestamp]    (moduleName.packageName.src.java.yourClassName);

With the String.class() methods you can easily take the information you need.