Thrift异常中的异常消息如何工作?

时间:2015-05-27 07:53:25

标签: java scala thrift thrift-protocol

我将节点IDL文件定义为服务方法可能抛出的异常类型:

exception SampleException {
    1: list<string> failed
}

在日志中看到正确的异常消息的合同是什么?我看过这样的日志消息:Unhandled exception in foo.bar.Service my.package.SomeException: null。我猜它在哪里说null这应该是异常消息?

不幸的是,异常并没有很好的记录。我应该为其添加string message字段吗?还有其他转换,如该字段的名称?

1 个答案:

答案 0 :(得分:2)

节俭异常(一般情况下)

  

在日志中看到正确的异常消息的合同是什么?

没有合约定义了如何将消息写入任何日志。 Thrift旨在与协议无关且与传输无关。例如,如果您构建的HTTP服务器将某些内容写入其日志文件中,则这完全在Thrift之外,这只是您的HTTP服务器的一个问题。

  

我应该为其添加字符串消息字段吗?是否有其他惯例,如该领域的名称?

不,除了您选择的语言可能强加的内容之外,既没有约定也没有限制。从技术上讲,exception就像struct一样。例如,以下IDL取自ThriftTest.thrift文件。

exception Xception2 {
  1: i32 errorCode,
  2: Xtruct struct_thing
}

上面使用的Xtruct是嵌套在异常中的另一个struct。你看,你几乎可以做任何关于结构的Thrift异常的事情。这使您可以向客户端发送丰富的错误信息,而不仅仅是一个字符串说&#34; 服务器上发生了丑陋的事情&#34;等等。

struct的区别在于系统如何处理它们:异常在服务器上序列化,然后在客户端上重新引发。意外的例外是

  • 被捕获并重新抛出为通用TApplicationException
  • 或根本没有被抓住

后一种行为是一种与语言有关的事情,现在即将改变,而且#34;未被捕获&#34;进入&#34;重新抛出为通用TApplicationException&#34;方向。

  

不幸的是,异常没有很好的记录

这是Thrift Whitepaper关于例外情况的说法:

  

2.4例外

     

异常在语法和功能上等同于结构   除了使用exception关键字声明它们之外   struct关键字。

     

生成的对象根据需要从异常基类继承   在每种目标编程语言中,为了无缝地   与任何给定语言的本机异常处理集成。   同样,设计重点在于使代码熟悉   给应用程序开发人员。

如何确保调用Exception(string) CTOR?

  

我看过这样的日志消息:

Unhandled exception in foo.bar.Service my.package.SomeException: null 
     

我猜它在哪里说null这应该是异常消息? [...]对于生成到Scala / Java的已定义异常,确保调用此构造函数的正确方法是什么:public Exception(String message)

非常喜欢&#34;从不&#34;或更精确&#34;没办法&#34;。这些是Thrift(主干版本)从上面的IDL生成的所有CTOR:

  public Xception() {
  }

  public Xception(
    int errorCode,
    String message)
  {
    this();
    this.errorCode = errorCode;
    setErrorCodeIsSet(true);
    this.message = message;
  }

  /**
   * Performs a deep copy on <i>other</i>.
   */
  public Xception(Xception other) {
    __isset_bitfield = other.__isset_bitfield;
    this.errorCode = other.errorCode;
    if (other.isSetMessage()) {
      this.message = other.message;
    }
  }

由于所有生成的异常都来自TException,因此他们必须调用其中一个参数化的CTOR才能将message和/或cause调到Exception基础。但Xception显然不会这样做。原因可能是Thrift允许您将任何定义为异常成员,并保证(或假定)任何内容。换句话说,人们无法确定异常中是否只有一个字段。因此,您最终会收到null错误消息。

底线(TL; DR)

我认为,一般来说你是对的this behaviour should be changed。目前,我看到的唯一解决方法是在进入日志之前显式捕获TException并使用toString()成员函数重新打包它们:

} catch (org.apache.thrift.TException te) {
  throw new Exception(te.toString());
}