TracedOperationCallable extends OperationCallable<RequestT, ResponseT, MetadataT> { @Override public OperationFuture<ResponseT, MetadataT> futureCall( RequestT request, ApiCallContext context) { ApiTracer tracer = tracerFactory.newTracer(context.getTracer(), spanName, OperationType.LongRunning); TraceFinisher<ResponseT> finisher = new TraceFinisher<>(tracer); try { context = context.withTracer(tracer); OperationFuture<ResponseT, MetadataT> future = innerCallable.futureCall(request, context); ApiFutures.addCallback(future, finisher, MoreExecutors.directExecutor()); return future; } catch (RuntimeException e) { finisher.onFailure(e); throw e; } } TracedOperationCallable(
      @Nonnull OperationCallable<RequestT, ResponseT, MetadataT> innerCallable,
      @Nonnull ApiTracerFactory tracerFactory,
      @Nonnull SpanName spanName); @Override OperationFuture<ResponseT, MetadataT> futureCall(
      RequestT request, ApiCallContext context); @Override OperationFuture<ResponseT, MetadataT> resumeFutureCall(
      String operationName, ApiCallContext context); @Override ApiFuture<Void> cancel(String operationName, ApiCallContext context);  }
@Test public void testTracerCreated() { tracedOperationCallable.futureCall("test", callContext); verify(tracerFactory, times(1)).newTracer(parentTracer, SPAN_NAME, OperationType.LongRunning); }
@Test public void testOperationFinish() { innerResult.set("successful result"); tracedOperationCallable.futureCall("test", callContext); verify(tracer, times(1)).operationSucceeded(); }
@Test public void testOperationFailed() { RuntimeException fakeError = new RuntimeException("fake error"); innerResult.setException(fakeError); tracedOperationCallable.futureCall("test", callContext); verify(tracer, times(1)).operationFailed(fakeError); }
@Test public void testSyncError() { RuntimeException fakeError = new RuntimeException("fake error"); @SuppressWarnings("unchecked") OperationCallable<String, String, Long>[] innerCallableWrapper = new OperationCallable[] {innerCallable}; reset(innerCallableWrapper); when(innerCallable.futureCall(eq("failing test"), any(ApiCallContext.class))) .thenThrow(fakeError); try { tracedOperationCallable.futureCall("failing test", callContext); } catch (RuntimeException e) { } verify(tracer, times(1)).operationFailed(fakeError); }