简体   繁体   中英

Log runtime exceptions in file log4j2

I was reading the log4j2 documentation and I've made some code with that library, but I can't find a solution to log the runtime exceptions, like null pointers, timeouts or something like that in a file, I just see those exceptions in the console. I've read about this, and I see that I can achieve that with an aspect but my question is: There is a way to log those exceptions in a file through XML configuration?

EDIT:

I have a log4j2 configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="5">
    <Appenders>

        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout>
                <Pattern>%r %d{yyyy-MM-dd HH:mm:ss:sss} %c %L %M %sn [%t] %-5p %m%n</Pattern>
            </PatternLayout>
        </Console>

        <File name="testingFile" fileName="testLog4j.log" append="true" ignoreExceptions="false" immediateFlush="true">

            <!--Layout type="PatternLayout">
                <Pattern>%r %d{yyyy-MM-dd HH:mm:ss:sss} %c %L %M %sn [%t] %-5p %msg%n</Pattern>
            </Layout-->
            <PatternLayout alwaysWriteExceptions="false">
                <Pattern>"%-5p [%t] %logger - %msg%ex%n</Pattern>
            </PatternLayout>

        </File>

    </Appenders>

    <Loggers>
        <Root level="all">
            <AppenderRef ref="console" level="info"/>
            <AppenderRef ref="testingFile" level="error"/>
        </Root>



        <!--Logger name="com.example" level="error" additivity="true">
            <AppenderRef ref="testingFile" />
        </Logger-->
    </Loggers>
</Configuration>

And I have the following class:

public class Application {

    private static final Logger logger = LogManager.getLogger(Application.class.getName());

    public static void main(String args[]) throws Exception{

        while(true){
            //logger.debug("test");
            logger.trace("trace");
            logger.debug("debug");
            logger.info("test");
            logger.warn("test");
            logger.error("test");
            logger.fatal("test");
            logger.error("test");
            String s = null;
            s.substring(0);
        }
    }

When you reach the line s.substring(0) you get a NullPointerException , this exception is logged in the console and not in the File Appender, and I want to log this kinds of exceptions in my file appender.

Checked all your XML configurations and they seem ok. The only thing that you need to get runtime exceptions logged in the file is:

  private static final Logger logger = LogManager.getLogger(Log4j2Example.class);
  public static void main(String[] args) {
    try {
      String s = null;
      s.substring(0);
    } catch (Exception e) {
      logger.error("RunTime Exception: " + e, e);
    }
  }

The toString of Exception is inherited from Throwable where it prints the Exception class name and the message. This gets added to the string " RunTime Exception: " to form one string that is getting printed.

So you need to pass the exception to the logger.error as an argument.

logger.error("RunTime Exception: " + e, e);

Log4j2 file appender:

Did you define a Log4j2 File appender ?

So, to log to a file won't require any changes to your Java code. Maybe logging to the console can work without it, but I have a log4j2.xml file in my project root that defines how Log4j2 should log.

Here is my current version with a Console appender and a File appender defined:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout pattern="%-5level %logger{36} - %msg%n"/>
            </Console>
            <File name="File" fileName="logs/app.log">
                <PatternLayout pattern="%-5level %logger{36} - %msg%n"/>
            </File>
        </Appenders>
        <Loggers>
            <Root level="TRACE">
                <AppenderRef ref="Console"/>
                <AppenderRef ref="File"/>
            </Root>
        </Loggers>
    </Configuration>

There might be other ways to achieve the same result. Have a look at the Logj42 Configuration page .

If you want, have a look at the other types of appenders available here . If you're not happy with how the log messages display you can read up on Pattern layouts .


Logging exceptions:

You asked about logging errors and seem to successfully be able to log general log statements.

You just need to wrap your code in a try-catch .

For example:

try {
    logger.info("Hello world");

    // I want to test my exception handling
    throw new RuntimeException("Triggering an error");
} catch (Exception e) {
    String errorMessage = "An error has occurred";
    logger.error(errorMessage, e);
    throw new RuntimeException(errorMessage, e);
}

Note that I catch an Exception and throw a RuntimeException . An Exception is a checked exception - so calling code will need to catch it, while RuntimeException (a subclass of Exception ) is an unchecked exception. So by throwing the RuntimeException I'm sort of insinuating that something totally unexpected happened and that the calling code won't know how to deal with it - so they don't need to catch it, and since its an unchecked exception they won't have to.

So in the catch clause you can, depending on your requirements, throw an Exception , or a RuntimeException , or your own custom exception which can be either a checked exception (a subclass of Exception ), or an unchecked exception (a subclass of RuntimeException ).

If you don't throw your Exception from the catch clause the code will continue executing subsequent to the catch clause which is most likely not what you want.

I see your code is inside a public static void main(String args[]) method. So maybe you don't have to throw the Exception from the catch clause as program execution will in any case stop subsequent to the catch clause if the catch clause is at the end of the method. Maybe Java will print something on the console if you throw something out of that method - but it won't be caught and logged by Log4j2 .


Logging with aspects:

I see you can log using aspects. See for example here . That said, I will just try and get everything working with try-catch . I haven't had to use aspects for logging and it feels like its a bit of work for a benefit that isn't too clear so I can't unfortunately help with that.

Hope the rest of my answer was useful:)

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