TracedOperationCallable extends OperationCallable<RequestT, ResponseT, MetadataT> { @Override public ApiFuture<Void> cancel(String operationName, ApiCallContext context) { SpanName cancelSpanName = SpanName.of(spanName.getClientName(), spanName.getMethodName() + ".Cancel"); ApiTracer tracer = tracerFactory.newTracer(context.getTracer(), cancelSpanName, OperationType.Unary); TraceFinisher<Void> finisher = new TraceFinisher<>(tracer); try { context = context.withTracer(tracer); ApiFuture<Void> future = innerCallable.cancel(operationName, 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 testExternalOperationCancel() { Mockito.reset(innerCallable, tracerFactory); when(tracerFactory.newTracer( any(ApiTracer.class), any(SpanName.class), eq(OperationType.Unary))) .thenReturn(tracer); SettableApiFuture<Void> innerCancelResult = SettableApiFuture.create(); when(innerCallable.cancel(anyString(), any(ApiCallContext.class))) .thenReturn(innerCancelResult); tracedOperationCallable.cancel("some external operation", callContext); verify(tracerFactory, times(1)) .newTracer( parentTracer, SpanName.of(SPAN_NAME.getClientName(), SPAN_NAME.getMethodName() + ".Cancel"), OperationType.Unary); }