Logging method for thrown exception
I have methods that are defined as. public static void myMethod throws IOException . how can I use the Logger class to log the exception that is thrown to a file say named «test.log». I’ve heard of using logger.throwing. but it doesn’t seem to work. Could anyone give me a step by step tip on how to do this? I just basically need to log the exception that is thrown (I didn’t use try catches). Thank you so much!
3 Answers 3
You’ll need to add a catch clause. Below is a start for using the java.util.logging.Logger. Note that many projects use an Apache logger which is a bit more powerful and more complicated. Let’s say you have a class com.myCompany.Foo that reads some file stuff
typically, at the start of the class in the static field declarations you will have
private static final Logger LOGGER = Logger.getLogger("com.myCompany.Foo");
then, when you have a method that throws exceptions (this is a stupid method!)
int readFirstCharOfFile(File f) throws IOException < FileReader reader = null; try < reader = new FileReader(f); return reader.read(); >catch (IOException ioe) < // You have a lot of possibilities here, but this seems most reasonable LOGGER.log(Level.SEVERE, ioe.getMessage(), ioe); // whether you rethrow the Exception "depends" on the contract, but, in our case // the method declaration says that we do, so we do. throw ioe; >finally < if (reader != null) reader.close(); >>
The harder part is configuring the Logger to write where you want. IIRC, by default it goes to standard error. There is a lot of «magic» there that I never fully understood so I couldn’t explain all the intricacies.
You can Google to get info, here are a couple useful links I found. link1 and link2
How to log exceptions in Java?
There’s a common problem I’ve come across a few times when logging exceptions in Java. There seem to be various different types to deal with. E.g. some wrap other exceptions and some don’t have a message at all — only a type. Most code I’ve seen logs an exception by using either getMessage() or toString() . But these methods don’t always capture all the information needed to pinpoint the problem — other methods such as getCause() and getStackTrace() sometimes provide additional info. For example, the exception I’m looking at right now in my Eclipse Inspect window is an InvocationTargetException . The exception itself has no cause, no message, no stacktrace . but the target from getCause() is InvalidUseOfMatchersException , with these details populated. So my question is: Given an exception of any type as an input, please provide a single method that will output a nicely formatted string containing all relevant information about the Exception (e.g. possibly recursively calling getCause() amongst other things?) Before posting, I was nearly going to have a stab at it myself but really don’t want to reinvent the wheel — surely such a thing must have been done many times before.
7 Answers 7
The java.util.logging package is standard in Java SE. Its Logger includes an overloaded log method that accepts Throwable objects. It will log stacktraces of exceptions and their cause for you.
import java.util.logging.Level; import java.util.logging.Logger; [. ] Logger logger = Logger.getAnonymousLogger(); Exception e1 = new Exception(); Exception e2 = new Exception(e1); logger.log(Level.SEVERE, "an exception was thrown", e2);
SEVERE: an exception was thrown java.lang.Exception: java.lang.Exception at LogStacktrace.main(LogStacktrace.java:21) Caused by: java.lang.Exception at LogStacktrace.main(LogStacktrace.java:20)
Internally, this does exactly what @philipp-wendler suggests, by the way. See the source code for SimpleFormatter.java . This is just a higher level interface.
Keep in mind that if you use a custom formatter, you have to specifically support using Throwables (I just copied Oracle code) or else this will not work.
In addition to this idea, i checked how to do it using SL4J and founded this: baeldung.com/slf4j-log-exceptions
This answer was helpful. I was testing whether I could log exceptions in a way that included all the info about the error (including the error message of the deeply-nested original exception) and also allowed the program to continue to process more work. This worked well. The logged string included INFO: could not complete job for user Matt , com.mattwelke.Main$MathException: failed to do math , and Caused by: java.lang.IllegalArgumentException: you tried to divide 10.0 by 0. (meaning I got all the error context I needed in the logs). I imagine this would work well with SLF4J too.
What’s wrong with the printStacktrace() method provided by Throwable (and thus every exception)? It shows all the info you requested, including the type, message, and stack trace of the root exception and all (nested) causes. In Java 7, it even shows you the information about «supressed» exceptions that might occur in a try-with-resources statement.
Of course you wouldn’t want to write to System.err , which the no-argument version of the method does, so instead use one of the available overloads.
In particular, if you just want to get a String:
Exception e = . StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); String exceptionDetails = sw.toString();
If you happen to use the great Guava library, it provides a utility method doing this: com.google.common.base.Throwables#getStackTraceAsString(Throwable) .
Thanks for your answer but I think all printStacktrace() does is writes the stacktrace returned from getStacktrace() to the error stream? This isn’t really what I’m looking for. Also don’t think it would work in the case where the Exception wraps another Exception.
The overloads of printStackStrace write to another target, not to the error stream. And the printed information contains all causes, including their type, message, stack trace, and (nested) causes.
@flup Why would you consider this «rolling your own»? This way does use the standard Java method for this.
It should be quite simple if you are using LogBack or SLF4J. I do it as below
//imports import org.slf4j.Logger; import org.slf4j.LoggerFactory; //Initialize logger Logger logger = LoggerFactory.getLogger(.class); try < //try something >catch(Exception e) < //Actual logging of error logger.error("some message", e); >
A logging script that I have written some time ago might be of help, although it is not exactly what you want. It acts in a way like a System.out.println but with much more information about StackTrace etc. It also provides Clickable text for Eclipse:
private static final SimpleDateFormat extended = new SimpleDateFormat( "dd MMM yyyy (HH:mm:ss) zz" ); public static java.util.logging.Logger initLogger(final String name) < final java.util.logging.Logger logger = java.util.logging.Logger.getLogger( name ); try < Handler ch = new ConsoleHandler(); logger.addHandler( ch ); logger.setLevel( Level.ALL ); // Level selbst setzen logger.setUseParentHandlers( false ); final java.util.logging.SimpleFormatter formatter = new SimpleFormatter() < @Override public synchronized String format(final LogRecord record) < StackTraceElement[] trace = new Throwable().getStackTrace(); String clickable = "(" + trace[ 7 ].getFileName() + ":" + trace[ 7 ].getLineNumber() + ") "; /* Clickable text in Console. */ for( int i = 8; i < trace.length; i++ ) < /* 0 - 6 is the logging trace, 7 - x is the trace until log method was called */ if( trace[ i ].getFileName() == null ) continue; clickable = "(" + trace[ i ].getFileName() + ":" + trace[ i ].getLineNumber() + ") ->" + clickable; > final String time = " "; StringBuilder level = new StringBuilder("[" + record.getLevel() + "] "); while( level.length() < 15 ) /* extend for tabby display */ level.append(" "); StringBuilder name = new StringBuilder(record.getLoggerName()).append(": "); while( name.length() < 15 ) /* extend for tabby display */ name.append(" "); String thread = Thread.currentThread().getName(); if( thread.length() >18 ) /* trim if too long */ thread = thread.substring( 0, 16 ) + ". "; else < StringBuilder sb = new StringBuilder(thread); while( sb.length() < 18 ) /* extend for tabby display */ sb.append(" "); thread = sb.insert( 0, "Thread " ).toString(); >final String message = "\"" + record.getMessage() + "\" "; return level + time + thread + name + clickable + message + "\n"; > >; ch.setFormatter( formatter ); ch.setLevel( Level.ALL ); > catch( final SecurityException e ) < e.printStackTrace(); >return logger; >
Notice this outputs to the console, you can change that, see http://docs.oracle.com/javase/1.4.2/docs/api/java/util/logging/Logger.html for more information on that.
Now, the following will probably do what you want. It will go through all causes of a Throwable and save it in a String. Note that this does not use StringBuilder , so you can optimize by changing it.
Throwable e = . String detail = e.getClass().getName() + ": " + e.getMessage(); for( final StackTraceElement s : e.getStackTrace() ) detail += "\n\t" + s.toString(); while( ( e = e.getCause() ) != null )
How to log error in java exception handling.? [closed]
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
LOG.error("Error message "+e.getMessage());
@Tom Why is this on hold as opinion-based? The first case gives the logging framework all information needed, and the logging framework then can decide what info to actually log. The later approaches only give to the logging framework the message, and make it impossible to manage what is logged centrally via logging configuration.
You want to know which approach is the best, so everyone answer that with what he or she thinks is best. Therefore it is opinion-based.
4 Answers 4
Why do you not just try it out? You are the only one who knows which information do you need in your logging. Depending on the thrown exception you might want the stacktrace or not.
See below a small example to show the different outputs
private void logTest() < try < Files.readAllBytes(Paths.get("foobar")); >catch (IOException e) < logger.error("Error message ", e); logger.error("Error message " + e); logger.error("Error message " + e.getMessage()); >>
logger.error(«Error message «, e);
2015-10-07 13:42:11,239 [main] ERROR sub.optimal.Main - Error message java.nio.file.NoSuchFileException: foobar at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102) at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:230) at java.nio.file.Files.newByteChannel(Files.java:361) at java.nio.file.Files.newByteChannel(Files.java:407) at java.nio.file.Files.readAllBytes(Files.java:3152) at sub.optimal.Main.logTest(Main.java:43) at sub.optimal.Main.main(Main.java:53)
logger.error(«Error message » + e);
2015-10-07 13:42:11,243 [main] ERROR sub.optimal.Main - Error message java.nio.file.NoSuchFileException: foobar
logger.error(«Error message » + e.getMessage());
2015-10-07 13:42:11,243 [main] ERROR sub.optimal.Main - Error message foobar
Thanks @SubOptimal I tried it but i am confused that which one is good practice for production and effective development.
As I said it depends. If you know the exception itself contains all information you need to know for sport the error, like java.nio.file.NoSuchFileException: foobar then you might not want to clutter the log with the stacktrace. If you catch an exception where you don’t know what could be the cause or which information you might need to spot the origin, log as much as possible (means include the stacktrace).
@SubOptimal why not leave the decision of what to log on the apender’s layout? If you use error(String, Throwable), you can decide in the layout whether you want the message, the exception message, and the stack trace to be present in the log (and often you can change it even without recompiling). While if you use any of the other proposed forms, there’s no way to configure the logger to print the stacktrace.
@JiriTousek Dependent on the logger implementation this might be an option not all implementation might provide this feature (I’m not aware of this functionality in log4j before version 2). There might be a problem if different exception handlers in one class should log different level of exception information.
Use LOG.error(«Error message «,e); — that way you won’t lose the stack trace of the exception (note that you also need to make sure your logging framework’s output layout is set up so that it prints the stack traces).
Stack traces are a valuable part of the exception report since they tell you how the offending code was called, and therefore may help you understand what state your program was in when the error occurred.
If you for some reason want to log only the message and not the stack trace, I would still recommend using the above form and then configuring the logging framework to not print the stack trace (in Log4j, this is done by configuring the Appender). That way, if you change your mind later, you can add the stack trace to the logs by changing the configuration only, without the need to change the actual logging code. The choice of what info should be put in the log should be responsibility of the appender configuration, not the code that logs the entry.
Logging method for thrown exception
I have methods that are defined as. public static void myMethod throws IOException . how can I use the Logger class to log the exception that is thrown to a file say named «test.log». I’ve heard of using logger.throwing. but it doesn’t seem to work. Could anyone give me a step by step tip on how to do this? I just basically need to log the exception that is thrown (I didn’t use try catches). Thank you so much!
3 Answers 3
You’ll need to add a catch clause. Below is a start for using the java.util.logging.Logger. Note that many projects use an Apache logger which is a bit more powerful and more complicated. Let’s say you have a class com.myCompany.Foo that reads some file stuff
typically, at the start of the class in the static field declarations you will have
private static final Logger LOGGER = Logger.getLogger("com.myCompany.Foo");
then, when you have a method that throws exceptions (this is a stupid method!)
int readFirstCharOfFile(File f) throws IOException < FileReader reader = null; try < reader = new FileReader(f); return reader.read(); >catch (IOException ioe) < // You have a lot of possibilities here, but this seems most reasonable LOGGER.log(Level.SEVERE, ioe.getMessage(), ioe); // whether you rethrow the Exception "depends" on the contract, but, in our case // the method declaration says that we do, so we do. throw ioe; >finally < if (reader != null) reader.close(); >>
The harder part is configuring the Logger to write where you want. IIRC, by default it goes to standard error. There is a lot of «magic» there that I never fully understood so I couldn’t explain all the intricacies.
You can Google to get info, here are a couple useful links I found. link1 and link2