简体   繁体   中英

Configuring multiple log4j2 loggers

I want to separate system logs from user logs. System logs being something that developers and maintainers will look at. User logs providing users with system information without all the technical details. I want to store the different log messages in different files, one for techs, one for users.

I have looked at a number of options including custom levels and filters. I could add a key word to the beginning of the message that a filter could use to identify user messages.I am experimenting with adding a separate logger just for user messages that uses the standard error levels.

I have written a simple demo program for testing. It creates 2 loggers then generates some error messages.

package demo;
import java.io.IOException;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Logdemo {
private final static Logger logger = LogManager.getLogger();
private final static Logger userLog = LogManager.getLogger("demo.userMsg");

public static void main(String[] args) throws IOException {
    try {
        ((Object) null).toString();
    } catch (Exception e) {
        logger.error("error message", e);
    }
    try {
        ((Object) null).toString();
    } catch (Exception e) {
        logger.fatal( "User level Red message" ,e);
    }
    try {
        ((Object) null).toString();
    } catch (Exception e) {
        userLog.error( "User level Amber message" ,e); 
    }
    logger.info("Errors Logged");
    userLog.info("Lunch is served.");
  }
}

In the config file I have:

    <Loggers>
        <Root level="all">
            <AppenderRef ref="RollingFile" level="ALL"/>
            <AppenderRef ref="Console" level="ALL"/>
        </Root>
        <userMsg name="demo.userMsg" level = "all">
            <AppenderRef ref="UserMsgFile" level="ALL"/>
        </userMsg> 
    </Loggers>
</Configuration>

From this I get the following error messages from NetBeans:

run:
2017-09-18 22:20:13,933 main ERROR Error processing element UserMsgFile [Appenders: null]): CLASS_NOT_FOUND
2017-09-18 22:20:13,936 main ERROR Error processing element userMsg  ([Loggers: null]): CLASS_NOT_FOUND
22:20:14.038 [main] INFO  demo.Logdemo - logger starting...
22:20:14.040 [main] ERROR demo.Logdemo - error message

All of the exception messages are written to the console, including the messages for the userLog. So I know that both loggers are working. The logger appender writes to a file OK. No file is created by the userLog logger, which uses an almost identical appender.

It seems that I haven't named something correctly to allow log4j2 to find the logger. I have tried various combinations of naming to get it right, but I can't figure out what the problem is.

The other thing I haven't yet got to is using the userLog logger across different classes. I don't need to know which class a user log message was produced by, so I would like to use the same logger name, without the class identifier, in all classes. I suspect I can't do that.

So my questions are: What error have I made in the config file?
Edit: The following config entry works. This gives two loggers. There were two problems. One was that the name of the logger is the package name. The other was that I didn't use the word Logger correctly.

    <Loggers>
    <Logger name="demo" level="all">  <!-- name = package name -->
        <AppenderRef ref="UserLogFile" level="ALL" />
    </Logger>
    <Root level="all">
        <AppenderRef ref="Console" level="ALL"/>
        <AppenderRef ref="SystemLogFile" level="ALL"/>
    </Root>
</Loggers>

Will I have to include the class name in the Logger initiation in each class?
Edit: I needed to include the package name. This took me a while to figure out.

The other problem I had was turning on debug messages for log4j2. This is achieved with:

    <Configuration status="WARN">  <!-- to debug, set status="TRACE"  -->

I have changed my approach. I have used the markers feature with an added logger. Adding a marker to a log message allows me to use a different appender to handle user messages. The sample code looks like this:

import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.MarkerManager;
import org.apache.logging.log4j.Marker;

    public class Logdemo {

    private final static Logger logger = LogManager.getLogger();
    static final Marker usrMkr = MarkerManager.getMarker("USR");

    public static void main(String[] args) throws IOException {
        logger.info("logger starting...");

        try {
            ((Object) null).toString();
        } catch (Exception e) {
            logger.fatal( usrMkr,"User message" );
        }
        try {
            ((Object) null).toString();
        } catch (Exception e) {
            logger.debug( "Debug error message" ,e); 
        }
        logger.info("Errors Logged");
      }
    }

The relevant parts of the config file look like:

     <RollingFile
       name="UserLogFile" 
       fileName="${basePath}/UserMsg.log"
       immediateFlush="false"
       filePattern="logs/$${date:yyyy-MM}/user-%d{MM-dd-yyyy}-%i.log">
       <MarkerFilter marker="USR" onMatch="ACCEPT" onMismatch="DENY"/>
     </RollingFile>
</Appenders>

<Loggers>
    <Logger name="demo" level="all">
        <AppenderRef ref="UserLogFile" level="ALL"/>
    </Logger>
    <Root level="all">
        <AppenderRef ref="Console" level="ALL"/>
        <AppenderRef ref="RollingFile" level="ALL"/>

    </Root>

</Loggers>

I created an appender with the MarkerFilter command added. I pointed the Logger to the appender to divert marked messages to a separate file. Note in the interests of brevity I have hacked out large chunks of the xml file.

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