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();
}
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();
}
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;
}
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();
}
}
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");
}
Aggregations