如果我们记录异常消息并抛出其他异常,它仍然是反模式吗?


18

我们的网络应用程序正在使用将ExceptionMapper某些异常映射到Response。我们记录异常消息,然后引发新异常,如下所示:

catch (SomeException ex) {
  LOG.error(ex.getMessage());
  throw new MyException(ex.getMessage());
}

我们不会再次抛出相同的异常,所以我的问题是,是否将其视为Log and Throw反模式。因此,最好删除相似位置的日志并将它们移至以下几个ExceptionMapper类:

@Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {

  // bla bla 

  @Override
  public Response toResponse(final MyException ex) {
    LOG.error(ex.getMessage());
    return Response.status(400).entity("something").build();
  }
}

3
您登录后ex.getMessage(),我会立即阻止您,这已经错了。
biziclop 2015年



IMO根本不提及这是一个Web服务是不公平的。确实确实改变了游戏规则,因为例如仅使用常规的异常处理机制可能会带来安全风险;您不希望仅在500错误响应中将任何和所有异常发送回去,因此需要对其进行检查和过滤。在处理具有外部客户端直接调用它的系统时,积极的现场日志记录也更为普遍。在重复调用的服务调用中记录堆栈跟踪可能导致难以管理的日志文件大小和性能问题。

@Gimby在这种情况下,OP不会在响应中发送任何错误详细信息(可能是样板“发生错误”内容)。另外,如何在没有堆栈跟踪的情况下诊断问题?滚动记录器通常会注意存储大小,日志数据可压缩。
Marko Topolnik

Answers:


36

您的代码实际上不是一个,而是三个反模式:

  1. 记录并重新抛出;
  2. 重新投掷而没有包装原始原因;
  3. 仅记录消息,而不记录堆栈跟踪(这是最糟糕的一条)。

如果您遵循最佳做法来:

  1. 根本不捕获(让异常自行传播);
  2. 如果被迫捕获受检查的异常,则将其包装为未检查并重新抛出;
  3. 除非在顶层,否则不要记录任何内容;
  4. 用以下命令记录整个异常stacktrace log.error("Error occurred", e);

那么您将不会遇到任何难题,包括当前的难题,因为记录的堆栈跟踪信息还将包括所有包装的异常。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.