简体   繁体   中英

Log4j - Changing logger level for a particular logger instance

I use apache log4j for my application logging. I use log4j.xml to initialize the loggers when my application server starts. For each class, I invoke Loggers.getLogger("loggername") to get the logging instance to log details of that class.

For example: in log4j.xml

<appender name="default" class="org.apache.log4j.RollingFileAppender">
                <param name="File" value="${log.dir}/logs/serverout.txt" />
                <param name ="Append" value="TRUE"/>
                <layout class="org.apache.log4j.PatternLayout">
                        <param name="ConversionPattern" value="%d{[HH:mm:ss:SSS]|[MM-dd-yyyy]}|[%c]|[%p]|[%L]: %m|%n"/>
                </layout>
                <param name="MaxFileSize" value="10MB"/>
                <param name="MaxBackupIndex" value="100"/>
</appender>
<logger name="com.mypackage" additivity="false">
                <level value="INFO"/>
                <appender-ref ref="default"/>
</logger>

And how I invoke in each class

private static Logger logger = Logger.getLogger(MPMyclass.class.getName());

My requirement: Basically, I run an application server when there would be many user sessions. Each session has a unique sessionId. Each session is an instance of several classes. Each class has its own instance of Logger. If I want to enable log level for a particular class (MPMyclass) .. I can just get the logger name(com.mypackage) and set its level so that it changes the level overall. But I want it in a way so that I can set only to a particular session not overall. If I have a class name MPMyclass , there are many instance of MPMyclass, my requirement is to change the logger level of an instance of that class not all instance.

Possible solution: 1. Each session/instance has a unique sessionId. So I can get/set levels. But this is too much complicated as there are many classes it would be clumsy to set/get. 2. I can have a Hashtable to store each instance of class with their unqiue sessionid, but it is also not recommended as there are too many classes and instance of classes it is deftly not a good soln.

I am working on to solve this with simple solution with the help of log4j or through Java design. Please suggest me if there is anything that I can work on.

Thanks

I suggest that you write a custom RollingFileAppender (or any other Appender) to control this thing and combine it with MDC and JMX.

It should look something like this:

public class MyRollingFileAppender extends RollingFileAppender implements MyRollingFileAppenderMBean {

    private final Set<String> enabledSessions = new HashSet<>();

    @Override
    public synchronized void doAppend(LoggingEvent event) {
        if (enabledSessions.contains(event.getMDC("sessionId"))) {
            super.doAppend(event);
        }
    }

    @Override
    public synchronized void enable(String... sessionIds) throws JMException {
        for (String sessionId : sessionIds) {
            enabledSessions.add(sessionId);
        }
    }

    @Override
    public synchronized void disable(String... sessionIds) throws JMException {
        // do the opposite here...
    }

}

Follow this link to get the idea about MDC: https://blog.oio.de/2010/11/09/logging-additional-information-like-sessionid-in-every-log4j-message/

If your final objective is to easily find log entries of a particular session (or a particular user) you could automatically add the session id (or the user id or even a custom transaction id) to each log entry. This can be done using a Nested Diagnostic Context or a Mapped Diagnostic Context . Google can give you many usage examples for them.

If you really want to change log level for specific class instances used by a specific session, I think it's not a good idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM