Search in sources :

Example 26 with CallOptions

use of io.grpc.CallOptions in project grpc-java by grpc.

the class CensusModulesTest method testClientInterceptors.

// Test that Census ClientInterceptors uses the TagContext and Span out of the current Context
// to create the ClientCallTracer, and that it intercepts ClientCall.Listener.onClose() to call
// ClientCallTracer.callEnded().
private void testClientInterceptors(boolean nonDefaultContext) {
    grpcServerRule.getServiceRegistry().addService(ServerServiceDefinition.builder("package1.service2").addMethod(method, new ServerCallHandler<String, String>() {

        @Override
        public ServerCall.Listener<String> startCall(ServerCall<String, String> call, Metadata headers) {
            call.sendHeaders(new Metadata());
            call.sendMessage("Hello");
            call.close(Status.PERMISSION_DENIED.withDescription("No you don't"), new Metadata());
            return mockServerCallListener;
        }
    }).build());
    final AtomicReference<CallOptions> capturedCallOptions = new AtomicReference<>();
    ClientInterceptor callOptionsCaptureInterceptor = new ClientInterceptor() {

        @Override
        public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
            capturedCallOptions.set(callOptions);
            return next.newCall(method, callOptions);
        }
    };
    Channel interceptedChannel = ClientInterceptors.intercept(grpcServerRule.getChannel(), callOptionsCaptureInterceptor, censusStats.getClientInterceptor(), censusTracing.getClientInterceptor());
    ClientCall<String, String> call;
    if (nonDefaultContext) {
        Context ctx = io.opencensus.tags.unsafe.ContextUtils.withValue(Context.ROOT, tagger.emptyBuilder().putLocal(StatsTestUtils.EXTRA_TAG, TagValue.create("extra value")).build());
        ctx = ContextUtils.withValue(ctx, fakeClientParentSpan);
        Context origCtx = ctx.attach();
        try {
            call = interceptedChannel.newCall(method, CALL_OPTIONS);
        } finally {
            ctx.detach(origCtx);
        }
    } else {
        assertEquals(io.opencensus.tags.unsafe.ContextUtils.getValue(Context.ROOT), io.opencensus.tags.unsafe.ContextUtils.getValue(Context.current()));
        assertEquals(ContextUtils.getValue(Context.current()), BlankSpan.INSTANCE);
        call = interceptedChannel.newCall(method, CALL_OPTIONS);
    }
    // The interceptor adds tracer factory to CallOptions
    assertEquals("customvalue", capturedCallOptions.get().getOption(CUSTOM_OPTION));
    assertEquals(2, capturedCallOptions.get().getStreamTracerFactories().size());
    assertTrue(capturedCallOptions.get().getStreamTracerFactories().get(0) instanceof CallAttemptsTracerFactory);
    assertTrue(capturedCallOptions.get().getStreamTracerFactories().get(1) instanceof CensusStatsModule.CallAttemptsTracerFactory);
    // Make the call
    Metadata headers = new Metadata();
    call.start(mockClientCallListener, headers);
    StatsTestUtils.MetricsRecord record = statsRecorder.pollRecord();
    assertNotNull(record);
    TagValue methodTag = record.tags.get(RpcMeasureConstants.GRPC_CLIENT_METHOD);
    assertEquals(method.getFullMethodName(), methodTag.asString());
    if (nonDefaultContext) {
        TagValue extraTag = record.tags.get(StatsTestUtils.EXTRA_TAG);
        assertEquals("extra value", extraTag.asString());
        assertEquals(2, record.tags.size());
    } else {
        assertNull(record.tags.get(StatsTestUtils.EXTRA_TAG));
        assertEquals(1, record.tags.size());
    }
    if (nonDefaultContext) {
        verify(tracer).spanBuilderWithExplicitParent(eq("Sent.package1.service2.method3"), same(fakeClientParentSpan));
        verify(spyClientSpanBuilder).setRecordEvents(eq(true));
    } else {
        verify(tracer).spanBuilderWithExplicitParent(eq("Sent.package1.service2.method3"), ArgumentMatchers.<Span>isNotNull());
        verify(spyClientSpanBuilder).setRecordEvents(eq(true));
    }
    verify(spyClientSpan, never()).end(any(EndSpanOptions.class));
    // End the call
    call.halfClose();
    call.request(1);
    verify(mockClientCallListener).onClose(statusCaptor.capture(), any(Metadata.class));
    Status status = statusCaptor.getValue();
    assertEquals(Status.Code.PERMISSION_DENIED, status.getCode());
    assertEquals("No you don't", status.getDescription());
    // The intercepting listener calls callEnded() on ClientCallTracer, which records to Census.
    record = statsRecorder.pollRecord();
    assertNotNull(record);
    methodTag = record.tags.get(RpcMeasureConstants.GRPC_CLIENT_METHOD);
    assertEquals(method.getFullMethodName(), methodTag.asString());
    TagValue statusTag = record.tags.get(RpcMeasureConstants.GRPC_CLIENT_STATUS);
    assertEquals(Status.Code.PERMISSION_DENIED.toString(), statusTag.asString());
    if (nonDefaultContext) {
        TagValue extraTag = record.tags.get(StatsTestUtils.EXTRA_TAG);
        assertEquals("extra value", extraTag.asString());
    } else {
        assertNull(record.tags.get(StatsTestUtils.EXTRA_TAG));
    }
    verify(spyClientSpan).end(EndSpanOptions.builder().setStatus(io.opencensus.trace.Status.PERMISSION_DENIED.withDescription("No you don't")).setSampleToLocalSpanStore(false).build());
    verify(spyClientSpan, never()).end();
    assertZeroRetryRecorded();
}
Also used : SpanContext(io.opencensus.trace.SpanContext) Context(io.grpc.Context) TagContext(io.opencensus.tags.TagContext) Status(io.grpc.Status) StatsTestUtils(io.grpc.internal.testing.StatsTestUtils) Channel(io.grpc.Channel) Metadata(io.grpc.Metadata) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) CallOptions(io.grpc.CallOptions) MethodDescriptor(io.grpc.MethodDescriptor) EndSpanOptions(io.opencensus.trace.EndSpanOptions) ClientInterceptor(io.grpc.ClientInterceptor) TagValue(io.opencensus.tags.TagValue) CallAttemptsTracerFactory(io.grpc.census.CensusTracingModule.CallAttemptsTracerFactory)

Example 27 with CallOptions

use of io.grpc.CallOptions in project grpc-java by grpc.

the class GrpcUtil method getTransportFromPickResult.

/**
 * Returns a transport out of a PickResult, or {@code null} if the result is "buffer".
 */
@Nullable
static ClientTransport getTransportFromPickResult(PickResult result, boolean isWaitForReady) {
    final ClientTransport transport;
    Subchannel subchannel = result.getSubchannel();
    if (subchannel != null) {
        transport = ((TransportProvider) subchannel.getInternalSubchannel()).obtainActiveTransport();
    } else {
        transport = null;
    }
    if (transport != null) {
        final ClientStreamTracer.Factory streamTracerFactory = result.getStreamTracerFactory();
        if (streamTracerFactory == null) {
            return transport;
        }
        return new ClientTransport() {

            @Override
            public ClientStream newStream(MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions, ClientStreamTracer[] tracers) {
                StreamInfo info = StreamInfo.newBuilder().setCallOptions(callOptions).build();
                ClientStreamTracer streamTracer = streamTracerFactory.newClientStreamTracer(info, headers);
                checkState(tracers[tracers.length - 1] == NOOP_TRACER, "lb tracer already assigned");
                tracers[tracers.length - 1] = streamTracer;
                return transport.newStream(method, headers, callOptions, tracers);
            }

            @Override
            public void ping(PingCallback callback, Executor executor) {
                transport.ping(callback, executor);
            }

            @Override
            public InternalLogId getLogId() {
                return transport.getLogId();
            }

            @Override
            public ListenableFuture<SocketStats> getStats() {
                return transport.getStats();
            }
        };
    }
    if (!result.getStatus().isOk()) {
        if (result.isDrop()) {
            return new FailingClientTransport(result.getStatus(), RpcProgress.DROPPED);
        }
        if (!isWaitForReady) {
            return new FailingClientTransport(result.getStatus(), RpcProgress.PROCESSED);
        }
    }
    return null;
}
Also used : ClientStreamTracer(io.grpc.ClientStreamTracer) Executor(java.util.concurrent.Executor) Subchannel(io.grpc.LoadBalancer.Subchannel) Metadata(io.grpc.Metadata) InternalMetadata(io.grpc.InternalMetadata) StreamInfo(io.grpc.ClientStreamTracer.StreamInfo) CallOptions(io.grpc.CallOptions) MethodDescriptor(io.grpc.MethodDescriptor) SocketStats(io.grpc.InternalChannelz.SocketStats) Nullable(javax.annotation.Nullable)

Example 28 with CallOptions

use of io.grpc.CallOptions in project grpc-java by grpc.

the class BinlogHelperTest method clientInterceptor_trailersOnlyResponseLogsPeerAddress.

@Test
public void clientInterceptor_trailersOnlyResponseLogsPeerAddress() throws Exception {
    final AtomicReference<ClientCall.Listener<byte[]>> interceptedListener = new AtomicReference<>();
    // capture these manually because ClientCall can not be mocked
    final AtomicReference<Metadata> actualClientInitial = new AtomicReference<>();
    final AtomicReference<Object> actualRequest = new AtomicReference<>();
    Channel channel = new Channel() {

        @Override
        public <RequestT, ResponseT> ClientCall<RequestT, ResponseT> newCall(MethodDescriptor<RequestT, ResponseT> methodDescriptor, CallOptions callOptions) {
            return new NoopClientCall<RequestT, ResponseT>() {

                @Override
                @SuppressWarnings("unchecked")
                public void start(Listener<ResponseT> responseListener, Metadata headers) {
                    interceptedListener.set((Listener<byte[]>) responseListener);
                    actualClientInitial.set(headers);
                }

                @Override
                public void sendMessage(RequestT message) {
                    actualRequest.set(message);
                }

                @Override
                public Attributes getAttributes() {
                    return Attributes.newBuilder().set(Grpc.TRANSPORT_ATTR_REMOTE_ADDR, peer).build();
                }
            };
        }

        @Override
        public String authority() {
            return "the-authority";
        }
    };
    @SuppressWarnings("unchecked") ClientCall.Listener<byte[]> mockListener = mock(ClientCall.Listener.class);
    MethodDescriptor<byte[], byte[]> method = MethodDescriptor.<byte[], byte[]>newBuilder().setType(MethodType.UNKNOWN).setFullMethodName("service/method").setRequestMarshaller(BYTEARRAY_MARSHALLER).setResponseMarshaller(BYTEARRAY_MARSHALLER).build();
    ClientCall<byte[], byte[]> interceptedCall = new BinlogHelper(mockSinkWriter).getClientInterceptor(CALL_ID).interceptCall(method, CallOptions.DEFAULT.withDeadlineAfter(1, TimeUnit.SECONDS), channel);
    Metadata clientInitial = new Metadata();
    interceptedCall.start(mockListener, clientInitial);
    verify(mockSinkWriter).logClientHeader(/*seq=*/
    eq(1L), anyString(), anyString(), any(Duration.class), any(Metadata.class), eq(Logger.LOGGER_CLIENT), eq(CALL_ID), ArgumentMatchers.<SocketAddress>isNull());
    verifyNoMoreInteractions(mockSinkWriter);
    // trailer only response
    {
        Status status = Status.INTERNAL.withDescription("some description");
        Metadata trailers = new Metadata();
        interceptedListener.get().onClose(status, trailers);
        verify(mockSinkWriter).logTrailer(/*seq=*/
        eq(2L), same(status), same(trailers), eq(Logger.LOGGER_CLIENT), eq(CALL_ID), same(peer));
        verifyNoMoreInteractions(mockSinkWriter);
        verify(mockListener).onClose(same(status), same(trailers));
    }
}
Also used : Status(io.grpc.Status) Channel(io.grpc.Channel) Metadata(io.grpc.Metadata) AtomicReference(java.util.concurrent.atomic.AtomicReference) Duration(com.google.protobuf.Duration) CallOptions(io.grpc.CallOptions) MethodDescriptor(io.grpc.MethodDescriptor) NoopClientCall(io.grpc.internal.NoopClientCall) ClientCall(io.grpc.ClientCall) NoopClientCall(io.grpc.internal.NoopClientCall) Test(org.junit.Test)

Example 29 with CallOptions

use of io.grpc.CallOptions in project grpc-java by grpc.

the class BinlogHelperTest method clientInterceptor.

@Test
public void clientInterceptor() throws Exception {
    final AtomicReference<ClientCall.Listener<byte[]>> interceptedListener = new AtomicReference<>();
    // capture these manually because ClientCall can not be mocked
    final AtomicReference<Metadata> actualClientInitial = new AtomicReference<>();
    final AtomicReference<Object> actualRequest = new AtomicReference<>();
    final SettableFuture<Void> halfCloseCalled = SettableFuture.create();
    final SettableFuture<Void> cancelCalled = SettableFuture.create();
    Channel channel = new Channel() {

        @Override
        public <RequestT, ResponseT> ClientCall<RequestT, ResponseT> newCall(MethodDescriptor<RequestT, ResponseT> methodDescriptor, CallOptions callOptions) {
            return new NoopClientCall<RequestT, ResponseT>() {

                @Override
                @SuppressWarnings("unchecked")
                public void start(Listener<ResponseT> responseListener, Metadata headers) {
                    interceptedListener.set((Listener<byte[]>) responseListener);
                    actualClientInitial.set(headers);
                }

                @Override
                public void sendMessage(RequestT message) {
                    actualRequest.set(message);
                }

                @Override
                public void cancel(String message, Throwable cause) {
                    cancelCalled.set(null);
                }

                @Override
                public void halfClose() {
                    halfCloseCalled.set(null);
                }

                @Override
                public Attributes getAttributes() {
                    return Attributes.newBuilder().set(Grpc.TRANSPORT_ATTR_REMOTE_ADDR, peer).build();
                }
            };
        }

        @Override
        public String authority() {
            return "the-authority";
        }
    };
    @SuppressWarnings("unchecked") ClientCall.Listener<byte[]> mockListener = mock(ClientCall.Listener.class);
    MethodDescriptor<byte[], byte[]> method = MethodDescriptor.<byte[], byte[]>newBuilder().setType(MethodType.UNKNOWN).setFullMethodName("service/method").setRequestMarshaller(BYTEARRAY_MARSHALLER).setResponseMarshaller(BYTEARRAY_MARSHALLER).build();
    ClientCall<byte[], byte[]> interceptedCall = new BinlogHelper(mockSinkWriter).getClientInterceptor(CALL_ID).interceptCall(method, CallOptions.DEFAULT, channel);
    // send client header
    {
        Metadata clientInitial = new Metadata();
        interceptedCall.start(mockListener, clientInitial);
        verify(mockSinkWriter).logClientHeader(/*seq=*/
        eq(1L), eq("service/method"), eq("the-authority"), ArgumentMatchers.<Duration>isNull(), same(clientInitial), eq(Logger.LOGGER_CLIENT), eq(CALL_ID), ArgumentMatchers.<SocketAddress>isNull());
        verifyNoMoreInteractions(mockSinkWriter);
        assertSame(clientInitial, actualClientInitial.get());
    }
    // receive server header
    {
        Metadata serverInitial = new Metadata();
        interceptedListener.get().onHeaders(serverInitial);
        verify(mockSinkWriter).logServerHeader(/*seq=*/
        eq(2L), same(serverInitial), eq(Logger.LOGGER_CLIENT), eq(CALL_ID), same(peer));
        verifyNoMoreInteractions(mockSinkWriter);
        verify(mockListener).onHeaders(same(serverInitial));
    }
    // send client msg
    {
        byte[] request = "this is a request".getBytes(US_ASCII);
        interceptedCall.sendMessage(request);
        verify(mockSinkWriter).logRpcMessage(/*seq=*/
        eq(3L), eq(EventType.EVENT_TYPE_CLIENT_MESSAGE), same(BYTEARRAY_MARSHALLER), same(request), eq(Logger.LOGGER_CLIENT), eq(CALL_ID));
        verifyNoMoreInteractions(mockSinkWriter);
        assertSame(request, actualRequest.get());
    }
    // client half close
    {
        interceptedCall.halfClose();
        verify(mockSinkWriter).logHalfClose(/*seq=*/
        eq(4L), eq(Logger.LOGGER_CLIENT), eq(CALL_ID));
        halfCloseCalled.get(1, TimeUnit.SECONDS);
        verifyNoMoreInteractions(mockSinkWriter);
    }
    // receive server msg
    {
        byte[] response = "this is a response".getBytes(US_ASCII);
        interceptedListener.get().onMessage(response);
        verify(mockSinkWriter).logRpcMessage(/*seq=*/
        eq(5L), eq(EventType.EVENT_TYPE_SERVER_MESSAGE), same(BYTEARRAY_MARSHALLER), same(response), eq(Logger.LOGGER_CLIENT), eq(CALL_ID));
        verifyNoMoreInteractions(mockSinkWriter);
        verify(mockListener).onMessage(same(response));
    }
    // receive trailer
    {
        Status status = Status.INTERNAL.withDescription("some description");
        Metadata trailers = new Metadata();
        interceptedListener.get().onClose(status, trailers);
        verify(mockSinkWriter).logTrailer(/*seq=*/
        eq(6L), same(status), same(trailers), eq(Logger.LOGGER_CLIENT), eq(CALL_ID), ArgumentMatchers.<SocketAddress>isNull());
        verifyNoMoreInteractions(mockSinkWriter);
        verify(mockListener).onClose(same(status), same(trailers));
    }
    // cancel
    {
        interceptedCall.cancel(null, null);
        verify(mockSinkWriter).logCancel(/*seq=*/
        eq(7L), eq(Logger.LOGGER_CLIENT), eq(CALL_ID));
        cancelCalled.get(1, TimeUnit.SECONDS);
    }
}
Also used : Metadata(io.grpc.Metadata) CallOptions(io.grpc.CallOptions) ByteString(com.google.protobuf.ByteString) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) NoopClientCall(io.grpc.internal.NoopClientCall) ClientCall(io.grpc.ClientCall) NoopClientCall(io.grpc.internal.NoopClientCall) SocketAddress(java.net.SocketAddress) DomainSocketAddress(io.netty.channel.unix.DomainSocketAddress) InetSocketAddress(java.net.InetSocketAddress) Status(io.grpc.Status) Channel(io.grpc.Channel) AtomicReference(java.util.concurrent.atomic.AtomicReference) Duration(com.google.protobuf.Duration) MethodDescriptor(io.grpc.MethodDescriptor) Test(org.junit.Test)

Example 30 with CallOptions

use of io.grpc.CallOptions in project grpc-java by grpc.

the class BinlogHelperTest method clientDeadlineLogged_deadlineSetViaCallOption.

@Test
public void clientDeadlineLogged_deadlineSetViaCallOption() {
    MethodDescriptor<byte[], byte[]> method = MethodDescriptor.<byte[], byte[]>newBuilder().setType(MethodType.UNKNOWN).setFullMethodName("service/method").setRequestMarshaller(BYTEARRAY_MARSHALLER).setResponseMarshaller(BYTEARRAY_MARSHALLER).build();
    @SuppressWarnings("unchecked") ClientCall.Listener<byte[]> mockListener = mock(ClientCall.Listener.class);
    ClientCall<byte[], byte[]> call = new BinlogHelper(mockSinkWriter).getClientInterceptor(CALL_ID).interceptCall(method, CallOptions.DEFAULT.withDeadlineAfter(1, TimeUnit.SECONDS), new Channel() {

        @Override
        public <RequestT, ResponseT> ClientCall<RequestT, ResponseT> newCall(MethodDescriptor<RequestT, ResponseT> methodDescriptor, CallOptions callOptions) {
            return new NoopClientCall<>();
        }

        @Override
        public String authority() {
            return null;
        }
    });
    call.start(mockListener, new Metadata());
    ArgumentCaptor<Duration> callOptTimeoutCaptor = ArgumentCaptor.forClass(Duration.class);
    verify(mockSinkWriter).logClientHeader(anyLong(), AdditionalMatchers.or(ArgumentMatchers.<String>isNull(), anyString()), AdditionalMatchers.or(ArgumentMatchers.<String>isNull(), anyString()), callOptTimeoutCaptor.capture(), any(Metadata.class), any(GrpcLogEntry.Logger.class), anyLong(), AdditionalMatchers.or(ArgumentMatchers.<SocketAddress>isNull(), ArgumentMatchers.<SocketAddress>any()));
    Duration timeout = callOptTimeoutCaptor.getValue();
    assertThat(TimeUnit.SECONDS.toNanos(1) - Durations.toNanos(timeout)).isAtMost(TimeUnit.MILLISECONDS.toNanos(250));
}
Also used : Channel(io.grpc.Channel) Metadata(io.grpc.Metadata) Duration(com.google.protobuf.Duration) CallOptions(io.grpc.CallOptions) ByteString(com.google.protobuf.ByteString) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Logger(io.grpc.binarylog.v1.GrpcLogEntry.Logger) ClientCall(io.grpc.ClientCall) NoopClientCall(io.grpc.internal.NoopClientCall) SocketAddress(java.net.SocketAddress) DomainSocketAddress(io.netty.channel.unix.DomainSocketAddress) InetSocketAddress(java.net.InetSocketAddress) Test(org.junit.Test)

Aggregations

CallOptions (io.grpc.CallOptions)81 Test (org.junit.Test)61 Metadata (io.grpc.Metadata)50 Channel (io.grpc.Channel)36 MethodDescriptor (io.grpc.MethodDescriptor)28 ClientInterceptor (io.grpc.ClientInterceptor)23 ManagedChannel (io.grpc.ManagedChannel)18 ClientStreamTracer (io.grpc.ClientStreamTracer)17 ClientCall (io.grpc.ClientCall)15 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)11 Status (io.grpc.Status)11 Context (io.grpc.Context)10 Subchannel (io.grpc.LoadBalancer.Subchannel)10 MockClientTransportInfo (io.grpc.internal.TestUtils.MockClientTransportInfo)10 ForwardingSubchannel (io.grpc.util.ForwardingSubchannel)9 SimpleForwardingClientCall (io.grpc.ForwardingClientCall.SimpleForwardingClientCall)8 NoopClientCall (io.grpc.internal.NoopClientCall)8 SocketAddress (java.net.SocketAddress)8 SimpleForwardingClientCallListener (io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener)7 ByteString (com.google.protobuf.ByteString)6