How to log only part of an exception?

Viewed 272
private static InputStream getFileFromClassPathOrFileSystem(String path) {
    try {
        //try to get from something like file:///some/path, and if missing Scheme exception, go to catch clause
        return Files.newInputStream(Paths.get(URI.create(path)));
    } catch (IllegalArgumentException | IOException e) {
        LOGGER.info("Could not retrieve from file system, trying classpath. If the exception is 'Missing scheme' this can be ignored");
        return Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
    }
}

SonarQube flags this with Either log or rethrow this exception. That makes sense to us so we added e to the logger line:

LOGGER.info("Could not retrieve from file system, trying classpath. If the exception is 'Missing scheme' this can be ignored", e);

While this fixed the sonar issue, and indeed gives us a bit more useful information, we are now flooded with a 40 line stack trace. (and the method is called a LOT )

Is it possible to have the best of both worlds? Like having the error logged, but only part of it (actually, just the first two lines is fine), and without being flagged by SonarQube?

3 Answers

Maybe the best solution is to flag the SonarQube warning.

In order to convince a logger to print only the "interesting bits" of a stacktrace, you will most likely need to write a custom log message formatter or appender. Reliably working out what the interesting bits are (across all exceptions that your application may throw, etc) is likely to be a challenge.

Note that logging the exception message (as suggested) won't shut up SonarQube. At least, not if this testcase is to be believed:

On the other hand, it looks like:

} catch (Exception e) { // Compliant
  String message = "Some context for exception" + e.getMessage();
  JAVA_LOGGER.info(message);
}

is acceptable to SonarQube, though it doesn't log any stackframes.

you can use just the cause message without the full stack:

e.getMessage()

Returns the detail message string of this throwable.

Stack traces/Logs are always to rescue in production systems, these are transcripts of runtime of system.

PS: Please check why those many exceptions are happening for this particular method.

If you don't want to log, you can change the logger level to debug/trace, this avoids cutting down stack traces.

LOGGER.debug("Could not retrieve from file system, trying classpath. If the exception is 'Missing scheme' this can be ignored", e);
LOGGER.trace("Could not retrieve from file system, trying classpath. If the exception is 'Missing scheme' this can be ignored", e);

Coming to question, below is the piece of code (that copied from e.printStackTrace()) which would print message and first 5 lines.

Disclaimer: Please don't use this in production.

StackTraceElement[] ele = e.getStackTrace();
System.out.println(e.getMessage());
for(int i=0; i<ele.length && i<=5; i++){
System.out.println("at " + ele[i]);
}
Related