Search in sources :

Example 11 with ClientInterceptor

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

the class LoggingChannelProviderTest method forTarget_interceptorCalled.

@Test
public void forTarget_interceptorCalled() {
    ClientInterceptor interceptor = mock(ClientInterceptor.class, delegatesTo(new NoopInterceptor()));
    InternalLoggingChannelInterceptor.Factory factory = mock(InternalLoggingChannelInterceptor.Factory.class);
    when(factory.create()).thenReturn(interceptor);
    LoggingChannelProvider.init(factory);
    ManagedChannelBuilder<?> builder = ManagedChannelBuilder.forTarget("localhost");
    ManagedChannel channel = builder.build();
    CallOptions callOptions = CallOptions.DEFAULT;
    ClientCall<Void, Void> unused = channel.newCall(method, callOptions);
    verify(interceptor).interceptCall(same(method), same(callOptions), ArgumentMatchers.<Channel>any());
    channel.shutdownNow();
    LoggingChannelProvider.finish();
}
Also used : InternalLoggingChannelInterceptor(io.grpc.observability.interceptors.InternalLoggingChannelInterceptor) ClientInterceptor(io.grpc.ClientInterceptor) ManagedChannel(io.grpc.ManagedChannel) CallOptions(io.grpc.CallOptions) Test(org.junit.Test)

Example 12 with ClientInterceptor

use of io.grpc.ClientInterceptor 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 13 with ClientInterceptor

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

the class ManagedChannelImplBuilder method getEffectiveInterceptors.

// Temporarily disable retry when stats or tracing is enabled to avoid breakage, until we know
// what should be the desired behavior for retry + stats/tracing.
// TODO(zdapeng): FIX IT
@VisibleForTesting
List<ClientInterceptor> getEffectiveInterceptors() {
    List<ClientInterceptor> effectiveInterceptors = new ArrayList<>(this.interceptors);
    if (statsEnabled) {
        ClientInterceptor statsInterceptor = null;
        try {
            Class<?> censusStatsAccessor = Class.forName("io.grpc.census.InternalCensusStatsAccessor");
            Method getClientInterceptorMethod = censusStatsAccessor.getDeclaredMethod("getClientInterceptor", boolean.class, boolean.class, boolean.class, boolean.class);
            statsInterceptor = (ClientInterceptor) getClientInterceptorMethod.invoke(null, recordStartedRpcs, recordFinishedRpcs, recordRealTimeMetrics, recordRetryMetrics);
        } catch (ClassNotFoundException e) {
            // Replace these separate catch statements with multicatch when Android min-API >= 19
            log.log(Level.FINE, "Unable to apply census stats", e);
        } catch (NoSuchMethodException e) {
            log.log(Level.FINE, "Unable to apply census stats", e);
        } catch (IllegalAccessException e) {
            log.log(Level.FINE, "Unable to apply census stats", e);
        } catch (InvocationTargetException e) {
            log.log(Level.FINE, "Unable to apply census stats", e);
        }
        if (statsInterceptor != null) {
            // First interceptor runs last (see ClientInterceptors.intercept()), so that no
            // other interceptor can override the tracer factory we set in CallOptions.
            effectiveInterceptors.add(0, statsInterceptor);
        }
    }
    if (tracingEnabled) {
        ClientInterceptor tracingInterceptor = null;
        try {
            Class<?> censusTracingAccessor = Class.forName("io.grpc.census.InternalCensusTracingAccessor");
            Method getClientInterceptroMethod = censusTracingAccessor.getDeclaredMethod("getClientInterceptor");
            tracingInterceptor = (ClientInterceptor) getClientInterceptroMethod.invoke(null);
        } catch (ClassNotFoundException e) {
            // Replace these separate catch statements with multicatch when Android min-API >= 19
            log.log(Level.FINE, "Unable to apply census stats", e);
        } catch (NoSuchMethodException e) {
            log.log(Level.FINE, "Unable to apply census stats", e);
        } catch (IllegalAccessException e) {
            log.log(Level.FINE, "Unable to apply census stats", e);
        } catch (InvocationTargetException e) {
            log.log(Level.FINE, "Unable to apply census stats", e);
        }
        if (tracingInterceptor != null) {
            effectiveInterceptors.add(0, tracingInterceptor);
        }
    }
    return effectiveInterceptors;
}
Also used : ClientInterceptor(io.grpc.ClientInterceptor) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 14 with ClientInterceptor

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

the class XdsNameResolverTest method assertCallSelectClusterResult.

private void assertCallSelectClusterResult(CallInfo call, InternalConfigSelector configSelector, String expectedCluster, @Nullable Double expectedTimeoutSec) {
    Result result = configSelector.selectConfig(new PickSubchannelArgsImpl(call.methodDescriptor, new Metadata(), CallOptions.DEFAULT));
    assertThat(result.getStatus().isOk()).isTrue();
    ClientInterceptor interceptor = result.getInterceptor();
    ClientCall<Void, Void> clientCall = interceptor.interceptCall(call.methodDescriptor, CallOptions.DEFAULT, channel);
    clientCall.start(new NoopClientCallListener<Void>(), new Metadata());
    assertThat(testCall.callOptions.getOption(XdsNameResolver.CLUSTER_SELECTION_KEY)).isEqualTo("cluster:" + expectedCluster);
    @SuppressWarnings("unchecked") Map<String, ?> config = (Map<String, ?>) result.getConfig();
    if (expectedTimeoutSec != null) {
        // Verify the raw service config contains a single method config for method with the
        // specified timeout.
        List<Map<String, ?>> rawMethodConfigs = JsonUtil.getListOfObjects(config, "methodConfig");
        Map<String, ?> methodConfig = Iterables.getOnlyElement(rawMethodConfigs);
        List<Map<String, ?>> methods = JsonUtil.getListOfObjects(methodConfig, "name");
        assertThat(Iterables.getOnlyElement(methods)).isEmpty();
        assertThat(JsonUtil.getString(methodConfig, "timeout")).isEqualTo(expectedTimeoutSec + "s");
    } else {
        assertThat(config).isEmpty();
    }
}
Also used : PickSubchannelArgsImpl(io.grpc.internal.PickSubchannelArgsImpl) Metadata(io.grpc.Metadata) ClientInterceptor(io.grpc.ClientInterceptor) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ResolutionResult(io.grpc.NameResolver.ResolutionResult) Result(io.grpc.InternalConfigSelector.Result)

Example 15 with ClientInterceptor

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

the class XdsNameResolverTest method assertCallSelectRlsPluginResult.

private void assertCallSelectRlsPluginResult(CallInfo call, InternalConfigSelector configSelector, String expectedPluginName, Double expectedTimeoutSec) {
    Result result = configSelector.selectConfig(new PickSubchannelArgsImpl(call.methodDescriptor, new Metadata(), CallOptions.DEFAULT));
    assertThat(result.getStatus().isOk()).isTrue();
    ClientInterceptor interceptor = result.getInterceptor();
    ClientCall<Void, Void> clientCall = interceptor.interceptCall(call.methodDescriptor, CallOptions.DEFAULT, channel);
    clientCall.start(new NoopClientCallListener<Void>(), new Metadata());
    assertThat(testCall.callOptions.getOption(XdsNameResolver.CLUSTER_SELECTION_KEY)).isEqualTo("cluster_specifier_plugin:" + expectedPluginName);
    @SuppressWarnings("unchecked") Map<String, ?> config = (Map<String, ?>) result.getConfig();
    List<Map<String, ?>> rawMethodConfigs = JsonUtil.getListOfObjects(config, "methodConfig");
    Map<String, ?> methodConfig = Iterables.getOnlyElement(rawMethodConfigs);
    List<Map<String, ?>> methods = JsonUtil.getListOfObjects(methodConfig, "name");
    assertThat(Iterables.getOnlyElement(methods)).isEmpty();
    assertThat(JsonUtil.getString(methodConfig, "timeout")).isEqualTo(expectedTimeoutSec + "s");
}
Also used : PickSubchannelArgsImpl(io.grpc.internal.PickSubchannelArgsImpl) Metadata(io.grpc.Metadata) ClientInterceptor(io.grpc.ClientInterceptor) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ResolutionResult(io.grpc.NameResolver.ResolutionResult) Result(io.grpc.InternalConfigSelector.Result)

Aggregations

ClientInterceptor (io.grpc.ClientInterceptor)34 CallOptions (io.grpc.CallOptions)23 Metadata (io.grpc.Metadata)22 Channel (io.grpc.Channel)18 MethodDescriptor (io.grpc.MethodDescriptor)15 ManagedChannel (io.grpc.ManagedChannel)14 Test (org.junit.Test)13 ClientCall (io.grpc.ClientCall)11 SimpleForwardingClientCall (io.grpc.ForwardingClientCall.SimpleForwardingClientCall)8 ChannelFactoryBuilder (com.navercorp.pinpoint.grpc.client.ChannelFactoryBuilder)5 DefaultChannelFactoryBuilder (com.navercorp.pinpoint.grpc.client.DefaultChannelFactoryBuilder)5 UnaryCallDeadlineInterceptor (com.navercorp.pinpoint.grpc.client.UnaryCallDeadlineInterceptor)5 ClientOption (com.navercorp.pinpoint.grpc.client.config.ClientOption)5 Status (io.grpc.Status)5 SslOption (com.navercorp.pinpoint.grpc.client.config.SslOption)4 ForwardingClientCall (io.grpc.ForwardingClientCall)4 SimpleForwardingClientCallListener (io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener)4 PickSubchannelArgs (io.grpc.LoadBalancer.PickSubchannelArgs)4 SocketAddress (java.net.SocketAddress)4 AtomicLong (java.util.concurrent.atomic.AtomicLong)4