如何只记录异常的一部分?

How to log only part of an exception?

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 用 Either log or rethrow this exception 标记这个。这对我们来说很有意义,所以我们将 e 添加到记录器行:

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

虽然这解决了声纳问题,并且确实为我们提供了更多有用的信息,但我们现在被 40 行堆栈跟踪淹没了。 (并且该方法称为 LOT )

是否可以两全其美?就像记录了错误,但只是其中的一部分(实际上,只有前两行就可以),并且没有被 SonarQube 标记?

您可以只使用原因消息而不使用完整堆栈:

e.getMessage()

Returns the detail message string of this throwable.

堆栈traces/Logs总是在生产系统中拯救,这些是系统运行时的记录。

PS:请检查为什么这个特定方法会发生这么多异常。

如果不想记录,可以将记录器级别更改为 debug/trace,这样可以避免减少堆栈跟踪。

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);

下面是一段代码(从 e.printStackTrace() 复制而来),它将打印消息和前 5 行。

免责声明:请不要在生产中使用它。

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]);
}

也许最好的解决方案是标记 SonarQube 警告。

为了说服记录器仅打印堆栈跟踪的“有趣位”,您很可能需要编写自定义日志消息格式化程序或附加程序。可靠地计算出有趣的位是什么(在您的应用程序可能抛出的所有异常等中)可能是一个挑战。

请注意,记录异常消息(如建议的那样)不会关闭 SonarQube。至少,如果要相信这个测试用例,则不会:

另一方面,它看起来像:

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

SonarQube 可以接受,但它不记录任何堆栈帧。