Skip to content

Unchecked exceptions can't be captured from a ServerInterceptor #1552

Description

@zackangelo

I'm attempting to add instrumentation to our gRPC service implementations using a ServerInterceptor, namely failure rates on a per-method basis. To do this, I'm using a SimpleForwardingServerCall, overriding the close method and then checking the status to see if the call succeeded.

When an unchecked exception is thrown from a service implementation:

@Override
    public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
       throw new RuntimeException("BOOM!");
    }

and given an interceptCall method that looks something like this:

@Override
  public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
      MethodDescriptor<ReqT, RespT> method,
      ServerCall<RespT> call,
      final Metadata requestHeaders,
      ServerCallHandler<ReqT, RespT> next) {

    return next.startCall(method, new SimpleForwardingServerCall<RespT>(call) {
      @Override
      public void close(Status status, Metadata trailers) {
        logger.info("ERROR ENCOUNTERED"); // <-- never see this
        super.close(status, trailers);
      }
    }, requestHeaders);
  }

the close method is never called, so there isn't an opportunity to log the failure.

The exception seems to bubble up to the Executor instead:

Mar 15, 2016 12:26:59 PM io.grpc.internal.SerializingExecutor$TaskRunner run
SEVERE: Exception while executing runnable io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$2@3e694e4a
java.lang.RuntimeException: BOOM!
    at io.grpc.examples.helloworld.HelloWorldServer$GreeterImpl.sayHello(HelloWorldServer.java:98)
    at io.grpc.examples.helloworld.GreeterGrpc$MethodHandlers.invoke(GreeterGrpc.java:161)
    at io.grpc.stub.ServerCalls$1$1.onHalfClose(ServerCalls.java:147)
    at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:255)
    at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$2.runInContext(ServerImpl.java:458)
    at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:54)
    at io.grpc.internal.SerializingExecutor$TaskRunner.run(SerializingExecutor.java:154)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745) 

I've also tried returning a ForwardingServerCallListener from interceptCall and the onComplete callback is invoked, but it doesn't have enough information for me to determine if the call was a failure.

Is there another API I can take a look at that will allow me to capture these failures?

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions