How to create different log files for different packages using same log4j logger?

前端 未结 4 718
别跟我提以往
别跟我提以往 2020-12-03 11:19

I\'m trying to set up separate log files for different packages. I\'m using a Wrapper class for a log4j logger. Every class in my application calls same wrapper

相关标签:
4条回答
  • 2020-12-03 11:49

    Creating 2 appenders and 2 loggers would do what you want.

    0 讨论(0)
  • 2020-12-03 11:50

    You can do this like that(com.myco.a and com.myco.b being your 2 different packages):

    log4j.logger.com.myco.a=DEBUG, infoout 
    log4j.logger.com.myco.b=DEBUG, aar 
    

    Cheers.

    0 讨论(0)
  • 2020-12-03 11:58

    Read the required custom file location from a property file or so for each packages. Then you can use the below given method to update the log4j file location set in the log4j prop file:

    private void updateLog4jConfiguration(String logFile) { 
        java.util.Properties properties = new Properties(); 
        try { 
            InputStream configStream = getClass().getResourceAsStream( "/log4j.properties");
            properties.load(configStream); 
            configStream.close();
            } 
        catch (IOException e) {
            System.out.println("Error: Cannot laod configuration file "); 
            } 
        properties.setProperty("log4j.appender.FILE.file", logFile); 
        org.apache.log4j.LogManager.resetConfiguration(); 
        org.apache.log4j.PropertyConfigurator.configure(properties); 
    }
    
    0 讨论(0)
  • 2020-12-03 12:04

    If you create a static Logger within MyLogger class, then you have one Logger instance, with the name set to MyLogger. When you call that logger from other packages, Log4j is not able to determine the origin of those calls, as they all use the same Logger.

    The best way to handle it, is to define a separate Logger within each class, but if you want to use one class as a point of contact with Log4j, then you can do this:

    package com.daniel.logger;
    import org.apache.log4j.Logger;
    
    import com.daniel.package1.ClassA;
    import com.daniel.package2.ClassB;
    
    public class MyLogger{
    
        public static void write(String message, Class<?> clazz){
            Logger.getLogger(clazz).info(message);
        }
    
        public static void main(String[] args){
            ClassA.log();
            ClassB.log();
        }
    }
    

    Then, one of the class using it could look like:

    package com.daniel.package1;
    
    import com.daniel.logger.MyLogger;
    
    public class ClassA {
    
        public static void log(){
            MyLogger.write("ClassA",ClassA.class);
        }
    }
    

    And the log4j.properties file would look like:

    log4j.appender.package1=org.apache.log4j.FileAppender 
    log4j.appender.package1.File=package1.log
    log4j.appender.package1.layout=org.apache.log4j.PatternLayout
    
    log4j.appender.package2=org.apache.log4j.FileAppender
    log4j.appender.package2.File=package2.log
    log4j.appender.package2.layout=org.apache.log4j.PatternLayout
    
    log4j.logger.com.daniel.package1=DEBUG,package1
    log4j.logger.com.daniel.package2=DEBUG,package2
    

    If you don't want to pass the Class from ClassA, you could use a nasty trick with reflection, that gets the calling class' name, but I wouldn't recommend that due to a performance hit:

    public class MyLogger
    {
    
        public static void write(String message){
            StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
            Logger.getLogger(stackTraceElements[2].getClassName()).info(message);
        }
    
        public static void main(String[] args){
            ClassA.log();
            ClassB.log();
        }
    }
    
    0 讨论(0)
提交回复
热议问题