Search code examples
javaloggingcdi

Logger cdi with multiple file


I wan to produce logger with multiple log file .
this is my cdi produce class:

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import java.io.IOException;
import java.util.logging.*;

@ApplicationScoped
public class LoggerProducer {

    @Produces
    private Logger logger(InjectionPoint ip) throws IOException {
        return generalLogger(ip);
    }

    @Produces
    @Log(Log.LogType.GENERAL)
    private Logger generalLogger(InjectionPoint ip) throws IOException {
        LogManager.getLogManager().reset();

        Handler handler = new FileHandler(Log.LogType.GENERAL.getValue(), 200000, 5, true);
        handler.setLevel(Level.ALL);
        handler.setFormatter(new LogFormat());

        Logger logger = Logger.getGlobal();
        logger.setLevel(Level.ALL);
        logger.addHandler(handler);
        return logger;
    }

    @Produces
    @Log(Log.LogType.SIGNAL)
    private Logger signalLogger(InjectionPoint ip) throws IOException {
        LogManager.getLogManager().reset();

        Handler handler = new FileHandler(Log.LogType.SIGNAL.getValue(), 200000, 5, true);
        handler.setLevel(Level.ALL);
        handler.setFormatter(new LogFormat());

        Logger logger = Logger.getGlobal();
        logger.setLevel(Level.ALL);
        logger.addHandler(handler);
        return logger;
    }

    @Produces
    @Log(Log.LogType.ACTIVATION_KEY)
    private Logger activationKeyLogger(InjectionPoint ip) throws IOException {
        LogManager.getLogManager().reset();

        Handler handler = new FileHandler(Log.LogType.ACTIVATION_KEY.getValue(), 200000, 5, true);
        handler.setLevel(Level.ALL);
        handler.setFormatter(new LogFormat());

        Logger logger = Logger.getGlobal();
        logger.setLevel(Level.ALL);
        logger.addHandler(handler);
        return logger;
    }
}

and this is my annotation :

@Retention(RUNTIME)
@Target({FIELD, METHOD})
@Qualifier
public @interface Log {

    LogType value() default LogType.GENERAL;

    public enum LogType {
        GENERAL("logs/general.log"),
        SIGNAL("logs/signal.log"),
        ACTIVATION_KEY("logs/activation_key.log");

        private String value;

        LogType(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }
    }
}

My problem is that logs are always written in the last file that was annotated.
for example :
first logger written on file with annotation: @Log(Log.LogType.GENERAL)
when logger write a log to file with annotation: @Log(Log.LogType.SIGNAL)
now GENERAL logs also written to SIGNAL file .
there is any solution for fix this problem ?

Note: Log Engine is java.util.logging.Logger
Note: JavaEE 8 with OpenLiberty application Server


Solution

  • I think the Problem is that you're always using the global Logger.
    There is only one Logger of a certain Name.
    When you change the Filehandler of this Logger, every already existing Instance of is Logger will use the new Filehandler.

    You will have to use a different Name for the different Loggers.

    @ApplicationScoped
    public class LoggerProducer {
    
        @Produces
        private Logger logger(InjectionPoint ip) throws IOException {
            return generalLogger(ip);
        }
    
        @Produces
        @Log(Log.LogType.GENERAL)
        private Logger generalLogger(InjectionPoint ip) throws IOException {
            return getLogger(ip, Log.LogType.GENERAL);
        }
    
        @Produces
        @Log(Log.LogType.SIGNAL)
        private Logger signalLogger(InjectionPoint ip) throws IOException {
            return getLogger(ip, Log.LogType.SIGNAL);
        }
    
        @Produces
        @Log(Log.LogType.ACTIVATION_KEY)
        private Logger activationKeyLogger(InjectionPoint ip) throws IOException {
            return getLogger(ip, Log.LogType.ACTIVATION_KEY);
        }
        
        private Logger getLogger(InjectionPoint ip, Log.LogType type){
            LogManager.getLogManager().reset();
    
            Handler handler = new FileHandler(type.getValue(), 200000, 5, true);
            handler.setLevel(Level.ALL);
            handler.setFormatter(new LogFormat());
    
            Logger logger = Logger.getLogger(ip.getMember().getDeclaringClass().getName() + "-" + type.name())
            logger.setLevel(Level.ALL);
            logger.addHandler(handler);
            return logger;
        }
    }
    

    This should get you a new Logger for every InjectionPoint/Logtype combination