use of io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener in project grpc-java by grpc.
the class XdsTestClient method runQps.
private void runQps() throws InterruptedException, ExecutionException {
final SettableFuture<Void> failure = SettableFuture.create();
final class PeriodicRpc implements Runnable {
@Override
public void run() {
List<RpcConfig> configs = rpcConfigs;
for (RpcConfig cfg : configs) {
makeRpc(cfg);
}
}
private void makeRpc(final RpcConfig config) {
final long requestId;
final Set<XdsStatsWatcher> savedWatchers = new HashSet<>();
synchronized (lock) {
currentRequestId += 1;
requestId = currentRequestId;
savedWatchers.addAll(watchers);
}
ManagedChannel channel = channels.get((int) (requestId % channels.size()));
TestServiceGrpc.TestServiceStub stub = TestServiceGrpc.newStub(channel);
final AtomicReference<ClientCall<?, ?>> clientCallRef = new AtomicReference<>();
final AtomicReference<String> hostnameRef = new AtomicReference<>();
stub = stub.withDeadlineAfter(config.timeoutSec, TimeUnit.SECONDS).withInterceptors(new ClientInterceptor() {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
ClientCall<ReqT, RespT> call = next.newCall(method, callOptions);
clientCallRef.set(call);
return new SimpleForwardingClientCall<ReqT, RespT>(call) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
headers.merge(config.metadata);
super.start(new SimpleForwardingClientCallListener<RespT>(responseListener) {
@Override
public void onHeaders(Metadata headers) {
hostnameRef.set(headers.get(XdsTestServer.HOSTNAME_KEY));
super.onHeaders(headers);
}
}, headers);
}
};
}
});
if (config.rpcType == RpcType.EMPTY_CALL) {
stub.emptyCall(EmptyProtos.Empty.getDefaultInstance(), new StreamObserver<EmptyProtos.Empty>() {
@Override
public void onCompleted() {
handleRpcCompleted(requestId, config.rpcType, hostnameRef.get(), savedWatchers);
}
@Override
public void onError(Throwable t) {
handleRpcError(requestId, config.rpcType, Status.fromThrowable(t), savedWatchers);
}
@Override
public void onNext(EmptyProtos.Empty response) {
}
});
} else if (config.rpcType == RpcType.UNARY_CALL) {
SimpleRequest request = SimpleRequest.newBuilder().setFillServerId(true).build();
stub.unaryCall(request, new StreamObserver<SimpleResponse>() {
@Override
public void onCompleted() {
handleRpcCompleted(requestId, config.rpcType, hostnameRef.get(), savedWatchers);
}
@Override
public void onError(Throwable t) {
if (printResponse) {
logger.log(Level.WARNING, "Rpc failed", t);
}
handleRpcError(requestId, config.rpcType, Status.fromThrowable(t), savedWatchers);
}
@Override
public void onNext(SimpleResponse response) {
// service and rely on parsing stdout.
if (printResponse) {
System.out.println("Greeting: Hello world, this is " + response.getHostname() + ", from " + clientCallRef.get().getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR));
}
// TODO(ericgribkoff) Delete when server is deployed that sets metadata value.
if (hostnameRef.get() == null) {
hostnameRef.set(response.getHostname());
}
}
});
} else {
throw new AssertionError("Unknown RPC type: " + config.rpcType);
}
statsAccumulator.recordRpcStarted(config.rpcType);
}
private void handleRpcCompleted(long requestId, RpcType rpcType, String hostname, Set<XdsStatsWatcher> watchers) {
statsAccumulator.recordRpcFinished(rpcType, Status.OK);
notifyWatchers(watchers, rpcType, requestId, hostname);
}
private void handleRpcError(long requestId, RpcType rpcType, Status status, Set<XdsStatsWatcher> watchers) {
statsAccumulator.recordRpcFinished(rpcType, status);
notifyWatchers(watchers, rpcType, requestId, null);
}
}
long nanosPerQuery = TimeUnit.SECONDS.toNanos(1) / qps;
ListenableScheduledFuture<?> future = exec.scheduleAtFixedRate(new PeriodicRpc(), 0, nanosPerQuery, TimeUnit.NANOSECONDS);
Futures.addCallback(future, new FutureCallback<Object>() {
@Override
public void onFailure(Throwable t) {
failure.setException(t);
}
@Override
public void onSuccess(Object o) {
}
}, MoreExecutors.directExecutor());
failure.get();
}
use of io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener in project grpc-java by grpc.
the class FaultFilter method buildClientInterceptor.
@Nullable
@Override
public ClientInterceptor buildClientInterceptor(FilterConfig config, @Nullable FilterConfig overrideConfig, PickSubchannelArgs args, final ScheduledExecutorService scheduler) {
checkNotNull(config, "config");
if (overrideConfig != null) {
config = overrideConfig;
}
FaultConfig faultConfig = (FaultConfig) config;
Long delayNanos = null;
Status abortStatus = null;
if (faultConfig.maxActiveFaults() == null || activeFaultCounter.get() < faultConfig.maxActiveFaults()) {
Metadata headers = args.getHeaders();
if (faultConfig.faultDelay() != null) {
delayNanos = determineFaultDelayNanos(faultConfig.faultDelay(), headers);
}
if (faultConfig.faultAbort() != null) {
abortStatus = determineFaultAbortStatus(faultConfig.faultAbort(), headers);
}
}
if (delayNanos == null && abortStatus == null) {
return null;
}
final Long finalDelayNanos = delayNanos;
final Status finalAbortStatus = getAbortStatusWithDescription(abortStatus);
final class FaultInjectionInterceptor implements ClientInterceptor {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(final MethodDescriptor<ReqT, RespT> method, final CallOptions callOptions, final Channel next) {
Executor callExecutor = callOptions.getExecutor();
if (callExecutor == null) {
// This should never happen in practice because
// ManagedChannelImpl.ConfigSelectingClientCall always provides CallOptions with
// a callExecutor.
// TODO(https://github.com/grpc/grpc-java/issues/7868)
callExecutor = MoreExecutors.directExecutor();
}
if (finalDelayNanos != null) {
Supplier<? extends ClientCall<ReqT, RespT>> callSupplier;
if (finalAbortStatus != null) {
callSupplier = Suppliers.ofInstance(new FailingClientCall<ReqT, RespT>(finalAbortStatus, callExecutor));
} else {
callSupplier = new Supplier<ClientCall<ReqT, RespT>>() {
@Override
public ClientCall<ReqT, RespT> get() {
return next.newCall(method, callOptions);
}
};
}
final DelayInjectedCall<ReqT, RespT> delayInjectedCall = new DelayInjectedCall<>(finalDelayNanos, callExecutor, scheduler, callOptions.getDeadline(), callSupplier);
final class DeadlineInsightForwardingCall extends ForwardingClientCall<ReqT, RespT> {
@Override
protected ClientCall<ReqT, RespT> delegate() {
return delayInjectedCall;
}
@Override
public void start(Listener<RespT> listener, Metadata headers) {
Listener<RespT> finalListener = new SimpleForwardingClientCallListener<RespT>(listener) {
@Override
public void onClose(Status status, Metadata trailers) {
if (status.getCode().equals(Code.DEADLINE_EXCEEDED)) {
// TODO(zdapeng:) check effective deadline locally, and
// do the following only if the local deadline is exceeded.
// (If the server sends DEADLINE_EXCEEDED for its own deadline, then the
// injected delay does not contribute to the error, because the request is
// only sent out after the delay. There could be a race between local and
// remote, but it is rather rare.)
String description = String.format("Deadline exceeded after up to %d ns of fault-injected delay", finalDelayNanos);
if (status.getDescription() != null) {
description = description + ": " + status.getDescription();
}
status = Status.DEADLINE_EXCEEDED.withDescription(description).withCause(status.getCause());
// Replace trailers to prevent mixing sources of status and trailers.
trailers = new Metadata();
}
delegate().onClose(status, trailers);
}
};
delegate().start(finalListener, headers);
}
}
return new DeadlineInsightForwardingCall();
} else {
return new FailingClientCall<>(finalAbortStatus, callExecutor);
}
}
}
return new FaultInjectionInterceptor();
}
use of io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener in project brave by openzipkin.
the class BaseITTracingClientInterceptor method initMessageTaggingClient.
void initMessageTaggingClient() {
SpanCustomizer customizer = CurrentSpanCustomizer.create(tracing);
AtomicInteger sends = new AtomicInteger(1);
AtomicInteger recvs = new AtomicInteger(1);
closeClient(client);
client = newClient(new ClientInterceptor() {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return new SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
super.start(new SimpleForwardingClientCallListener<RespT>(responseListener) {
@Override
public void onMessage(RespT message) {
customizer.tag("grpc.message_recv." + recvs.getAndIncrement(), message.toString());
delegate().onMessage(message);
}
}, headers);
}
@Override
public void sendMessage(ReqT message) {
customizer.tag("grpc.message_send." + sends.getAndIncrement(), message.toString());
delegate().sendMessage(message);
}
};
}
}, grpcTracing.newClientInterceptor());
}
use of io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener in project brave by openzipkin.
the class TracingClientInterceptor method interceptCall.
/**
* This sets as span in scope both for the interception and for the start of the request. It does
* not set a span in scope during the response listener as it is unexpected it would be used at
* that fine granularity. If users want access to the span in a response listener, they will need
* to wrap the executor with one that's aware of the current context.
*/
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(final MethodDescriptor<ReqT, RespT> method, final CallOptions callOptions, final Channel next) {
Span span = tracer.nextSpan();
try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
return new SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
injector.inject(span.context(), headers);
span.kind(Span.Kind.CLIENT).start();
try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
parser.onStart(method, callOptions, headers, span.customizer());
super.start(new SimpleForwardingClientCallListener<RespT>(responseListener) {
@Override
public void onMessage(RespT message) {
try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
parser.onMessageReceived(message, span.customizer());
delegate().onMessage(message);
}
}
@Override
public void onClose(Status status, Metadata trailers) {
try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
super.onClose(status, trailers);
parser.onClose(status, trailers, span.customizer());
} finally {
span.finish();
}
}
}, headers);
}
}
@Override
public void sendMessage(ReqT message) {
try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
super.sendMessage(message);
parser.onMessageSent(message, span.customizer());
}
}
};
} catch (RuntimeException | Error e) {
parser.onError(e, span.customizer());
span.finish();
throw e;
}
}
use of io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener in project grpc-java by grpc.
the class BinlogHelper method getClientInterceptor.
public ClientInterceptor getClientInterceptor(final long callId) {
return new ClientInterceptor() {
boolean trailersOnlyResponse = true;
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(final MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
final AtomicLong seq = new AtomicLong(1);
final String methodName = method.getFullMethodName();
final String authority = next.authority();
// The timeout should reflect the time remaining when the call is started, so do not
// compute remaining time here.
final Deadline deadline = min(callOptions.getDeadline(), Context.current().getDeadline());
return new SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
@Override
public void start(final ClientCall.Listener<RespT> responseListener, Metadata headers) {
final Duration timeout = deadline == null ? null : Durations.fromNanos(deadline.timeRemaining(TimeUnit.NANOSECONDS));
writer.logClientHeader(seq.getAndIncrement(), methodName, authority, timeout, headers, GrpcLogEntry.Logger.LOGGER_CLIENT, callId, /*peerAddress=*/
null);
ClientCall.Listener<RespT> wListener = new SimpleForwardingClientCallListener<RespT>(responseListener) {
@Override
public void onMessage(RespT message) {
writer.logRpcMessage(seq.getAndIncrement(), EventType.EVENT_TYPE_SERVER_MESSAGE, method.getResponseMarshaller(), message, GrpcLogEntry.Logger.LOGGER_CLIENT, callId);
super.onMessage(message);
}
@Override
public void onHeaders(Metadata headers) {
trailersOnlyResponse = false;
writer.logServerHeader(seq.getAndIncrement(), headers, GrpcLogEntry.Logger.LOGGER_CLIENT, callId, getPeerSocket(getAttributes()));
super.onHeaders(headers);
}
@Override
public void onClose(Status status, Metadata trailers) {
SocketAddress peer = trailersOnlyResponse ? getPeerSocket(getAttributes()) : null;
writer.logTrailer(seq.getAndIncrement(), status, trailers, GrpcLogEntry.Logger.LOGGER_CLIENT, callId, peer);
super.onClose(status, trailers);
}
};
super.start(wListener, headers);
}
@Override
public void sendMessage(ReqT message) {
writer.logRpcMessage(seq.getAndIncrement(), EventType.EVENT_TYPE_CLIENT_MESSAGE, method.getRequestMarshaller(), message, GrpcLogEntry.Logger.LOGGER_CLIENT, callId);
super.sendMessage(message);
}
@Override
public void halfClose() {
writer.logHalfClose(seq.getAndIncrement(), GrpcLogEntry.Logger.LOGGER_CLIENT, callId);
super.halfClose();
}
@Override
public void cancel(String message, Throwable cause) {
writer.logCancel(seq.getAndIncrement(), GrpcLogEntry.Logger.LOGGER_CLIENT, callId);
super.cancel(message, cause);
}
};
}
};
}
Aggregations