mirror of https://github.com/grpc/grpc-java.git
all: API refactoring in preparation to support retry stats (#8355)
Rebased PR #8343 into the first commit of this PR, then (the 2nd commit) reverted the part for metric recording of retry attempts. The PR as a whole is mechanical refactoring. No behavior change (except that some of the old code path when tracer is created is moved into the new method `streamCreated()`). The API change is documented in go/grpc-stats-api-change-for-retry-java
This commit is contained in:
parent
b2764595e6
commit
860e97d12a
|
|
@ -19,7 +19,6 @@ package io.grpc;
|
|||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import io.grpc.Grpc;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
|
|
@ -28,6 +27,18 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/2861")
|
||||
@ThreadSafe
|
||||
public abstract class ClientStreamTracer extends StreamTracer {
|
||||
|
||||
/**
|
||||
* The stream is being created on a ready transport.
|
||||
*
|
||||
* @param headers the mutable initial metadata. Modifications to it will be sent to the socket but
|
||||
* not be seen by client interceptors and the application.
|
||||
*
|
||||
* @since 1.40.0
|
||||
*/
|
||||
public void streamCreated(@Grpc.TransportAttr Attributes transportAttrs, Metadata headers) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Headers has been sent to the socket.
|
||||
*/
|
||||
|
|
@ -54,22 +65,6 @@ public abstract class ClientStreamTracer extends StreamTracer {
|
|||
* Factory class for {@link ClientStreamTracer}.
|
||||
*/
|
||||
public abstract static class Factory {
|
||||
/**
|
||||
* Creates a {@link ClientStreamTracer} for a new client stream.
|
||||
*
|
||||
* @param callOptions the effective CallOptions of the call
|
||||
* @param headers the mutable headers of the stream. It can be safely mutated within this
|
||||
* method. It should not be saved because it is not safe for read or write after the
|
||||
* method returns.
|
||||
*
|
||||
* @deprecated use {@link
|
||||
* #newClientStreamTracer(io.grpc.ClientStreamTracer.StreamInfo, io.grpc.Metadata)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ClientStreamTracer newClientStreamTracer(CallOptions callOptions, Metadata headers) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ClientStreamTracer} for a new client stream. This is called inside the
|
||||
* transport when it's creating the stream.
|
||||
|
|
@ -81,12 +76,15 @@ public abstract class ClientStreamTracer extends StreamTracer {
|
|||
*
|
||||
* @since 1.20.0
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
|
||||
return newClientStreamTracer(info.getCallOptions(), headers);
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
/** An abstract class for internal use only. */
|
||||
@Internal
|
||||
public abstract static class InternalLimitedInfoFactory extends Factory {}
|
||||
|
||||
/**
|
||||
* Information about a stream.
|
||||
*
|
||||
|
|
@ -99,15 +97,21 @@ public abstract class ClientStreamTracer extends StreamTracer {
|
|||
public static final class StreamInfo {
|
||||
private final Attributes transportAttrs;
|
||||
private final CallOptions callOptions;
|
||||
private final boolean isTransparentRetry;
|
||||
|
||||
StreamInfo(Attributes transportAttrs, CallOptions callOptions) {
|
||||
StreamInfo(Attributes transportAttrs, CallOptions callOptions, boolean isTransparentRetry) {
|
||||
this.transportAttrs = checkNotNull(transportAttrs, "transportAttrs");
|
||||
this.callOptions = checkNotNull(callOptions, "callOptions");
|
||||
this.isTransparentRetry = isTransparentRetry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attributes of the transport that this stream was created on.
|
||||
*
|
||||
* @deprecated Use {@link ClientStreamTracer#streamCreated(Attributes, Metadata)} to handle
|
||||
* the transport Attributes instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Grpc.TransportAttr
|
||||
public Attributes getTransportAttrs() {
|
||||
return transportAttrs;
|
||||
|
|
@ -120,16 +124,25 @@ public abstract class ClientStreamTracer extends StreamTracer {
|
|||
return callOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the stream is a transparent retry.
|
||||
*
|
||||
* @since 1.40.0
|
||||
*/
|
||||
public boolean isTransparentRetry() {
|
||||
return isTransparentRetry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this StreamInfo into a new Builder.
|
||||
*
|
||||
* @since 1.21.0
|
||||
*/
|
||||
public Builder toBuilder() {
|
||||
Builder builder = new Builder();
|
||||
builder.setTransportAttrs(transportAttrs);
|
||||
builder.setCallOptions(callOptions);
|
||||
return builder;
|
||||
return new Builder()
|
||||
.setCallOptions(callOptions)
|
||||
.setTransportAttrs(transportAttrs)
|
||||
.setIsTransparentRetry(isTransparentRetry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -146,6 +159,7 @@ public abstract class ClientStreamTracer extends StreamTracer {
|
|||
return MoreObjects.toStringHelper(this)
|
||||
.add("transportAttrs", transportAttrs)
|
||||
.add("callOptions", callOptions)
|
||||
.add("isTransparentRetry", isTransparentRetry)
|
||||
.toString();
|
||||
}
|
||||
|
||||
|
|
@ -157,6 +171,7 @@ public abstract class ClientStreamTracer extends StreamTracer {
|
|||
public static final class Builder {
|
||||
private Attributes transportAttrs = Attributes.EMPTY;
|
||||
private CallOptions callOptions = CallOptions.DEFAULT;
|
||||
private boolean isTransparentRetry;
|
||||
|
||||
Builder() {
|
||||
}
|
||||
|
|
@ -164,9 +179,12 @@ public abstract class ClientStreamTracer extends StreamTracer {
|
|||
/**
|
||||
* Sets the attributes of the transport that this stream was created on. This field is
|
||||
* optional.
|
||||
*
|
||||
* @deprecated Use {@link ClientStreamTracer#streamCreated(Attributes, Metadata)} to handle
|
||||
* the transport Attributes instead.
|
||||
*/
|
||||
@Grpc.TransportAttr
|
||||
public Builder setTransportAttrs(Attributes transportAttrs) {
|
||||
@Deprecated
|
||||
public Builder setTransportAttrs(@Grpc.TransportAttr Attributes transportAttrs) {
|
||||
this.transportAttrs = checkNotNull(transportAttrs, "transportAttrs cannot be null");
|
||||
return this;
|
||||
}
|
||||
|
|
@ -179,11 +197,21 @@ public abstract class ClientStreamTracer extends StreamTracer {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the stream is a transparent retry.
|
||||
*
|
||||
* @since 1.40.0
|
||||
*/
|
||||
public Builder setIsTransparentRetry(boolean isTransparentRetry) {
|
||||
this.isTransparentRetry = isTransparentRetry;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new StreamInfo.
|
||||
*/
|
||||
public StreamInfo build() {
|
||||
return new StreamInfo(transportAttrs, callOptions);
|
||||
return new StreamInfo(transportAttrs, callOptions, isTransparentRetry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import static org.junit.Assert.fail;
|
|||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import io.grpc.ClientStreamTracer.StreamInfo;
|
||||
import io.grpc.internal.SerializingExecutor;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
|
@ -271,7 +272,7 @@ public class CallOptionsTest {
|
|||
}
|
||||
}
|
||||
|
||||
private static class FakeTracerFactory extends ClientStreamTracer.Factory {
|
||||
private static class FakeTracerFactory extends ClientStreamTracer.InternalLimitedInfoFactory {
|
||||
final String name;
|
||||
|
||||
FakeTracerFactory(String name) {
|
||||
|
|
@ -279,8 +280,7 @@ public class CallOptionsTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(
|
||||
ClientStreamTracer.StreamInfo info, Metadata headers) {
|
||||
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
|
||||
return new ClientStreamTracer() {};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.Internal;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
|
|
@ -632,28 +633,28 @@ public abstract class BinderTransport
|
|||
public synchronized ClientStream newStream(
|
||||
final MethodDescriptor<?, ?> method,
|
||||
final Metadata headers,
|
||||
final CallOptions callOptions) {
|
||||
final CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
if (isShutdown()) {
|
||||
return newFailingClientStream(shutdownStatus, callOptions, attributes, headers);
|
||||
return newFailingClientStream(shutdownStatus, attributes, headers, tracers);
|
||||
} else {
|
||||
int callId = latestCallId++;
|
||||
if (latestCallId == LAST_CALL_ID) {
|
||||
latestCallId = FIRST_CALL_ID;
|
||||
}
|
||||
StatsTraceContext statsTraceContext =
|
||||
StatsTraceContext.newClientContext(tracers, attributes, headers);
|
||||
Inbound.ClientInbound inbound =
|
||||
new Inbound.ClientInbound(
|
||||
this, attributes, callId, GrpcUtil.shouldBeCountedForInUse(callOptions));
|
||||
if (ongoingCalls.putIfAbsent(callId, inbound) != null) {
|
||||
Status failure = Status.INTERNAL.withDescription("Clashing call IDs");
|
||||
shutdownInternal(failure, true);
|
||||
return newFailingClientStream(failure, callOptions, attributes, headers);
|
||||
return newFailingClientStream(failure, attributes, headers, tracers);
|
||||
} else {
|
||||
if (inbound.countsForInUse() && numInUseStreams.getAndIncrement() == 0) {
|
||||
clientTransportListener.transportInUse(true);
|
||||
}
|
||||
StatsTraceContext statsTraceContext =
|
||||
StatsTraceContext.newClientContext(callOptions, attributes, headers);
|
||||
|
||||
Outbound.ClientOutbound outbound =
|
||||
new Outbound.ClientOutbound(this, callId, method, headers, statsTraceContext);
|
||||
if (method.getType().clientSendsOneMessage()) {
|
||||
|
|
@ -763,12 +764,12 @@ public abstract class BinderTransport
|
|||
}
|
||||
|
||||
private static ClientStream newFailingClientStream(
|
||||
Status failure, CallOptions callOptions, Attributes attributes, Metadata headers) {
|
||||
Status failure, Attributes attributes, Metadata headers,
|
||||
ClientStreamTracer[] tracers) {
|
||||
StatsTraceContext statsTraceContext =
|
||||
StatsTraceContext.newClientContext(callOptions, attributes, headers);
|
||||
StatsTraceContext.newClientContext(tracers, attributes, headers);
|
||||
statsTraceContext.clientOutboundHeaders();
|
||||
statsTraceContext.streamClosed(failure);
|
||||
return new FailingClientStream(failure);
|
||||
return new FailingClientStream(failure, tracers);
|
||||
}
|
||||
|
||||
private static InternalLogId buildLogId(
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkState;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.base.Supplier;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.ClientCall;
|
||||
|
|
@ -138,15 +139,6 @@ final class CensusStatsModule {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ClientCallTracer} for a new call.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
ClientCallTracer newClientCallTracer(
|
||||
TagContext parentCtx, String fullMethodName) {
|
||||
return new ClientCallTracer(this, parentCtx, fullMethodName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server tracer factory.
|
||||
*/
|
||||
|
|
@ -231,6 +223,7 @@ final class CensusStatsModule {
|
|||
}
|
||||
|
||||
private final CensusStatsModule module;
|
||||
final TagContext parentCtx;
|
||||
private final TagContext startCtx;
|
||||
|
||||
volatile long outboundMessageCount;
|
||||
|
|
@ -240,11 +233,22 @@ final class CensusStatsModule {
|
|||
volatile long outboundUncompressedSize;
|
||||
volatile long inboundUncompressedSize;
|
||||
|
||||
ClientTracer(CensusStatsModule module, TagContext startCtx) {
|
||||
ClientTracer(CensusStatsModule module, TagContext parentCtx, TagContext startCtx) {
|
||||
this.module = checkNotNull(module, "module");
|
||||
this.parentCtx = parentCtx;
|
||||
this.startCtx = checkNotNull(startCtx, "startCtx");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamCreated(Attributes transportAttrs, Metadata headers) {
|
||||
if (module.propagateTags) {
|
||||
headers.discardAll(module.statsHeader);
|
||||
if (!module.tagger.empty().equals(parentCtx)) {
|
||||
headers.put(module.statsHeader, parentCtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NonAtomicVolatileUpdate")
|
||||
public void outboundWireSize(long bytes) {
|
||||
|
|
@ -315,12 +319,14 @@ final class CensusStatsModule {
|
|||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static final class ClientCallTracer extends ClientStreamTracer.Factory {
|
||||
static final class CallAttemptsTracerFactory extends
|
||||
ClientStreamTracer.InternalLimitedInfoFactory {
|
||||
@Nullable
|
||||
private static final AtomicReferenceFieldUpdater<ClientCallTracer, ClientTracer>
|
||||
private static final AtomicReferenceFieldUpdater<CallAttemptsTracerFactory, ClientTracer>
|
||||
streamTracerUpdater;
|
||||
|
||||
@Nullable private static final AtomicIntegerFieldUpdater<ClientCallTracer> callEndedUpdater;
|
||||
@Nullable
|
||||
private static final AtomicIntegerFieldUpdater<CallAttemptsTracerFactory> callEndedUpdater;
|
||||
|
||||
/**
|
||||
* When using Atomic*FieldUpdater, some Samsung Android 5.0.x devices encounter a bug in their
|
||||
|
|
@ -328,14 +334,14 @@ final class CensusStatsModule {
|
|||
* (potentially racy) direct updates of the volatile variables.
|
||||
*/
|
||||
static {
|
||||
AtomicReferenceFieldUpdater<ClientCallTracer, ClientTracer> tmpStreamTracerUpdater;
|
||||
AtomicIntegerFieldUpdater<ClientCallTracer> tmpCallEndedUpdater;
|
||||
AtomicReferenceFieldUpdater<CallAttemptsTracerFactory, ClientTracer> tmpStreamTracerUpdater;
|
||||
AtomicIntegerFieldUpdater<CallAttemptsTracerFactory> tmpCallEndedUpdater;
|
||||
try {
|
||||
tmpStreamTracerUpdater =
|
||||
AtomicReferenceFieldUpdater.newUpdater(
|
||||
ClientCallTracer.class, ClientTracer.class, "streamTracer");
|
||||
CallAttemptsTracerFactory.class, ClientTracer.class, "streamTracer");
|
||||
tmpCallEndedUpdater =
|
||||
AtomicIntegerFieldUpdater.newUpdater(ClientCallTracer.class, "callEnded");
|
||||
AtomicIntegerFieldUpdater.newUpdater(CallAttemptsTracerFactory.class, "callEnded");
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.SEVERE, "Creating atomic field updaters failed", t);
|
||||
tmpStreamTracerUpdater = null;
|
||||
|
|
@ -352,7 +358,8 @@ final class CensusStatsModule {
|
|||
private final TagContext parentCtx;
|
||||
private final TagContext startCtx;
|
||||
|
||||
ClientCallTracer(CensusStatsModule module, TagContext parentCtx, String fullMethodName) {
|
||||
CallAttemptsTracerFactory(
|
||||
CensusStatsModule module, TagContext parentCtx, String fullMethodName) {
|
||||
this.module = checkNotNull(module);
|
||||
this.parentCtx = checkNotNull(parentCtx);
|
||||
TagValue methodTag = TagValue.create(fullMethodName);
|
||||
|
|
@ -370,7 +377,7 @@ final class CensusStatsModule {
|
|||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(
|
||||
ClientStreamTracer.StreamInfo info, Metadata headers) {
|
||||
ClientTracer tracer = new ClientTracer(module, startCtx);
|
||||
ClientTracer tracer = new ClientTracer(module, parentCtx, startCtx);
|
||||
// TODO(zhangkun83): Once retry or hedging is implemented, a ClientCall may start more than
|
||||
// one streams. We will need to update this file to support them.
|
||||
if (streamTracerUpdater != null) {
|
||||
|
|
@ -383,12 +390,6 @@ final class CensusStatsModule {
|
|||
"Are you creating multiple streams per call? This class doesn't yet support this case");
|
||||
streamTracer = tracer;
|
||||
}
|
||||
if (module.propagateTags) {
|
||||
headers.discardAll(module.statsHeader);
|
||||
if (!module.tagger.empty().equals(parentCtx)) {
|
||||
headers.put(module.statsHeader, parentCtx);
|
||||
}
|
||||
}
|
||||
return tracer;
|
||||
}
|
||||
|
||||
|
|
@ -416,7 +417,7 @@ final class CensusStatsModule {
|
|||
long roundtripNanos = stopwatch.elapsed(TimeUnit.NANOSECONDS);
|
||||
ClientTracer tracer = streamTracer;
|
||||
if (tracer == null) {
|
||||
tracer = new ClientTracer(module, startCtx);
|
||||
tracer = new ClientTracer(module, parentCtx, startCtx);
|
||||
}
|
||||
MeasureMap measureMap = module.statsRecorder.newMeasureMap()
|
||||
// TODO(songya): remove the deprecated measure constants once they are completed removed.
|
||||
|
|
@ -686,8 +687,8 @@ final class CensusStatsModule {
|
|||
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
|
||||
// New RPCs on client-side inherit the tag context from the current Context.
|
||||
TagContext parentCtx = tagger.getCurrentTagContext();
|
||||
final ClientCallTracer tracerFactory =
|
||||
newClientCallTracer(parentCtx, method.getFullMethodName());
|
||||
final CallAttemptsTracerFactory tracerFactory = new CallAttemptsTracerFactory(
|
||||
CensusStatsModule.this, parentCtx, method.getFullMethodName());
|
||||
ClientCall<ReqT, RespT> call =
|
||||
next.newCall(method, callOptions.withStreamTracerFactory(tracerFactory));
|
||||
return new SimpleForwardingClientCall<ReqT, RespT>(call) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package io.grpc.census;
|
|||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.ClientCall;
|
||||
|
|
@ -222,7 +223,7 @@ final class CensusTracingModule {
|
|||
}
|
||||
|
||||
@VisibleForTesting
|
||||
final class ClientCallTracer extends ClientStreamTracer.Factory {
|
||||
final class ClientCallTracer extends ClientStreamTracer.InternalLimitedInfoFactory {
|
||||
volatile int callEnded;
|
||||
|
||||
private final boolean isSampledToLocalTracing;
|
||||
|
|
@ -243,11 +244,7 @@ final class CensusTracingModule {
|
|||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(
|
||||
ClientStreamTracer.StreamInfo info, Metadata headers) {
|
||||
if (span != BlankSpan.INSTANCE) {
|
||||
headers.discardAll(tracingHeader);
|
||||
headers.put(tracingHeader, span.getContext());
|
||||
}
|
||||
return new ClientTracer(span);
|
||||
return new ClientTracer(span, tracingHeader);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -273,9 +270,19 @@ final class CensusTracingModule {
|
|||
|
||||
private static final class ClientTracer extends ClientStreamTracer {
|
||||
private final Span span;
|
||||
final Metadata.Key<SpanContext> tracingHeader;
|
||||
|
||||
ClientTracer(Span span) {
|
||||
ClientTracer(Span span, Metadata.Key<SpanContext> tracingHeader) {
|
||||
this.span = checkNotNull(span, "span");
|
||||
this.tracingHeader = tracingHeader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamCreated(Attributes transportAtts, Metadata headers) {
|
||||
if (span != BlankSpan.INSTANCE) {
|
||||
headers.discardAll(tracingHeader);
|
||||
headers.put(tracingHeader, span.getContext());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ public class CensusModulesTest {
|
|||
instanceof CensusTracingModule.ClientCallTracer);
|
||||
assertTrue(
|
||||
capturedCallOptions.get().getStreamTracerFactories().get(1)
|
||||
instanceof CensusStatsModule.ClientCallTracer);
|
||||
instanceof CensusStatsModule.CallAttemptsTracerFactory);
|
||||
|
||||
// Make the call
|
||||
Metadata headers = new Metadata();
|
||||
|
|
@ -388,11 +388,12 @@ public class CensusModulesTest {
|
|||
new CensusStatsModule(
|
||||
tagger, tagCtxSerializer, statsRecorder, fakeClock.getStopwatchSupplier(),
|
||||
true, recordStarts, recordFinishes, recordRealTime);
|
||||
CensusStatsModule.ClientCallTracer callTracer =
|
||||
localCensusStats.newClientCallTracer(
|
||||
tagger.empty(), method.getFullMethodName());
|
||||
CensusStatsModule.CallAttemptsTracerFactory callAttemptsTracerFactory =
|
||||
new CensusStatsModule.CallAttemptsTracerFactory(
|
||||
localCensusStats, tagger.empty(), method.getFullMethodName());
|
||||
Metadata headers = new Metadata();
|
||||
ClientStreamTracer tracer = callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
ClientStreamTracer tracer =
|
||||
callAttemptsTracerFactory.newClientStreamTracer(STREAM_INFO, headers);
|
||||
|
||||
if (recordStarts) {
|
||||
StatsTestUtils.MetricsRecord record = statsRecorder.pollRecord();
|
||||
|
|
@ -455,7 +456,7 @@ public class CensusModulesTest {
|
|||
|
||||
tracer.inboundUncompressedSize(552);
|
||||
tracer.streamClosed(Status.OK);
|
||||
callTracer.callEnded(Status.OK);
|
||||
callAttemptsTracerFactory.callEnded(Status.OK);
|
||||
|
||||
if (recordFinishes) {
|
||||
StatsTestUtils.MetricsRecord record = statsRecorder.pollRecord();
|
||||
|
|
@ -522,6 +523,7 @@ public class CensusModulesTest {
|
|||
censusTracing.newClientCallTracer(null, method);
|
||||
Metadata headers = new Metadata();
|
||||
ClientStreamTracer clientStreamTracer = callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
clientStreamTracer.streamCreated(Attributes.EMPTY, headers);
|
||||
verify(tracer).spanBuilderWithExplicitParent(
|
||||
eq("Sent.package1.service2.method3"), ArgumentMatchers.<Span>isNull());
|
||||
verify(spyClientSpan, never()).end(any(EndSpanOptions.class));
|
||||
|
|
@ -575,11 +577,15 @@ public class CensusModulesTest {
|
|||
|
||||
@Test
|
||||
public void clientStreamNeverCreatedStillRecordStats() {
|
||||
CensusStatsModule.ClientCallTracer callTracer =
|
||||
censusStats.newClientCallTracer(tagger.empty(), method.getFullMethodName());
|
||||
|
||||
CensusStatsModule.CallAttemptsTracerFactory callAttemptsTracerFactory =
|
||||
new CensusStatsModule.CallAttemptsTracerFactory(
|
||||
censusStats, tagger.empty(), method.getFullMethodName());
|
||||
ClientStreamTracer streamTracer =
|
||||
callAttemptsTracerFactory.newClientStreamTracer(STREAM_INFO, new Metadata());
|
||||
fakeClock.forwardTime(3000, MILLISECONDS);
|
||||
callTracer.callEnded(Status.DEADLINE_EXCEEDED.withDescription("3 seconds"));
|
||||
Status status = Status.DEADLINE_EXCEEDED.withDescription("3 seconds");
|
||||
streamTracer.streamClosed(status);
|
||||
callAttemptsTracerFactory.callEnded(status);
|
||||
|
||||
// Upstart record
|
||||
StatsTestUtils.MetricsRecord record = statsRecorder.pollRecord();
|
||||
|
|
@ -680,10 +686,13 @@ public class CensusModulesTest {
|
|||
fakeClock.getStopwatchSupplier(),
|
||||
propagate, recordStats, recordStats, recordStats);
|
||||
Metadata headers = new Metadata();
|
||||
CensusStatsModule.ClientCallTracer callTracer =
|
||||
census.newClientCallTracer(clientCtx, method.getFullMethodName());
|
||||
CensusStatsModule.CallAttemptsTracerFactory callAttemptsTracerFactory =
|
||||
new CensusStatsModule.CallAttemptsTracerFactory(
|
||||
census, clientCtx, method.getFullMethodName());
|
||||
// This propagates clientCtx to headers if propagates==true
|
||||
callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
ClientStreamTracer streamTracer =
|
||||
callAttemptsTracerFactory.newClientStreamTracer(STREAM_INFO, headers);
|
||||
streamTracer.streamCreated(Attributes.EMPTY, headers);
|
||||
if (recordStats) {
|
||||
// Client upstart record
|
||||
StatsTestUtils.MetricsRecord clientRecord = statsRecorder.pollRecord();
|
||||
|
|
@ -746,7 +755,8 @@ public class CensusModulesTest {
|
|||
|
||||
// Verifies that the client tracer factory uses clientCtx, which includes the custom tags, to
|
||||
// record stats.
|
||||
callTracer.callEnded(Status.OK);
|
||||
streamTracer.streamClosed(Status.OK);
|
||||
callAttemptsTracerFactory.callEnded(Status.OK);
|
||||
|
||||
if (recordStats) {
|
||||
// Client completion record
|
||||
|
|
@ -769,10 +779,12 @@ public class CensusModulesTest {
|
|||
|
||||
@Test
|
||||
public void statsHeadersNotPropagateDefaultContext() {
|
||||
CensusStatsModule.ClientCallTracer callTracer =
|
||||
censusStats.newClientCallTracer(tagger.empty(), method.getFullMethodName());
|
||||
CensusStatsModule.CallAttemptsTracerFactory callAttemptsTracerFactory =
|
||||
new CensusStatsModule.CallAttemptsTracerFactory(
|
||||
censusStats, tagger.empty(), method.getFullMethodName());
|
||||
Metadata headers = new Metadata();
|
||||
callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
callAttemptsTracerFactory.newClientStreamTracer(STREAM_INFO, headers)
|
||||
.streamCreated(Attributes.EMPTY, headers);
|
||||
assertFalse(headers.containsKey(censusStats.statsHeader));
|
||||
// Clear recorded stats to satisfy the assertions in wrapUp()
|
||||
statsRecorder.rolloverRecords();
|
||||
|
|
@ -803,7 +815,8 @@ public class CensusModulesTest {
|
|||
CensusTracingModule.ClientCallTracer callTracer =
|
||||
censusTracing.newClientCallTracer(fakeClientParentSpan, method);
|
||||
Metadata headers = new Metadata();
|
||||
callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
ClientStreamTracer streamTracer = callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
streamTracer.streamCreated(Attributes.EMPTY, headers);
|
||||
|
||||
verify(mockTracingPropagationHandler).toByteArray(same(fakeClientSpanContext));
|
||||
verifyNoMoreInteractions(mockTracingPropagationHandler);
|
||||
|
|
@ -831,7 +844,8 @@ public class CensusModulesTest {
|
|||
censusTracing.newClientCallTracer(fakeClientParentSpan, method);
|
||||
Metadata headers = new Metadata();
|
||||
|
||||
callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
ClientStreamTracer streamTracer = callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
streamTracer.streamCreated(Attributes.EMPTY, headers);
|
||||
|
||||
assertThat(headers.keys()).isNotEmpty();
|
||||
}
|
||||
|
|
@ -845,7 +859,7 @@ public class CensusModulesTest {
|
|||
|
||||
CensusTracingModule.ClientCallTracer callTracer =
|
||||
censusTracing.newClientCallTracer(BlankSpan.INSTANCE, method);
|
||||
callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
callTracer.newClientStreamTracer(STREAM_INFO, headers).streamCreated(Attributes.EMPTY, headers);
|
||||
|
||||
assertThat(headers.keys()).isEmpty();
|
||||
}
|
||||
|
|
@ -862,7 +876,7 @@ public class CensusModulesTest {
|
|||
|
||||
CensusTracingModule.ClientCallTracer callTracer =
|
||||
censusTracing.newClientCallTracer(BlankSpan.INSTANCE, method);
|
||||
callTracer.newClientStreamTracer(STREAM_INFO, headers);
|
||||
callTracer.newClientStreamTracer(STREAM_INFO, headers).streamCreated(Attributes.EMPTY, headers);
|
||||
|
||||
assertThat(headers.keys()).containsExactlyElementsIn(originalHeaderKeys);
|
||||
}
|
||||
|
|
@ -1186,13 +1200,18 @@ public class CensusModulesTest {
|
|||
tagger, tagCtxSerializer, localStats.getStatsRecorder(), fakeClock.getStopwatchSupplier(),
|
||||
false, false, true, false /* real-time */);
|
||||
|
||||
CensusStatsModule.ClientCallTracer callTracer =
|
||||
localCensusStats.newClientCallTracer(
|
||||
tagger.empty(), method.getFullMethodName());
|
||||
CensusStatsModule.CallAttemptsTracerFactory callAttemptsTracerFactory =
|
||||
new CensusStatsModule.CallAttemptsTracerFactory(
|
||||
localCensusStats, tagger.empty(), method.getFullMethodName());
|
||||
|
||||
callTracer.newClientStreamTracer(STREAM_INFO, new Metadata());
|
||||
Metadata headers = new Metadata();
|
||||
ClientStreamTracer tracer =
|
||||
callAttemptsTracerFactory.newClientStreamTracer(STREAM_INFO, headers);
|
||||
tracer.streamCreated(Attributes.EMPTY, headers);
|
||||
fakeClock.forwardTime(30, MILLISECONDS);
|
||||
callTracer.callEnded(Status.PERMISSION_DENIED.withDescription("No you don't"));
|
||||
Status status = Status.PERMISSION_DENIED.withDescription("No you don't");
|
||||
tracer.streamClosed(status);
|
||||
callAttemptsTracerFactory.callEnded(status);
|
||||
|
||||
// Give OpenCensus a chance to update the views asynchronously.
|
||||
Thread.sleep(100);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package io.grpc.internal;
|
||||
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor;
|
||||
import io.grpc.ServerStreamTracer;
|
||||
|
|
@ -50,7 +50,8 @@ public class StatsTraceContextBenchmark {
|
|||
@BenchmarkMode(Mode.SampleTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
public StatsTraceContext newClientContext() {
|
||||
return StatsTraceContext.newClientContext(CallOptions.DEFAULT, Attributes.EMPTY, emptyMetadata);
|
||||
return StatsTraceContext.newClientContext(
|
||||
new ClientStreamTracer[] { new ClientStreamTracer() {} }, Attributes.EMPTY, emptyMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
import com.google.common.util.concurrent.SettableFuture;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Compressor;
|
||||
import io.grpc.Deadline;
|
||||
import io.grpc.Decompressor;
|
||||
|
|
@ -205,10 +206,12 @@ final class InProcessTransport implements ServerTransport, ConnectionClientTrans
|
|||
|
||||
@Override
|
||||
public synchronized ClientStream newStream(
|
||||
final MethodDescriptor<?, ?> method, final Metadata headers, final CallOptions callOptions) {
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
StatsTraceContext statsTraceContext =
|
||||
StatsTraceContext.newClientContext(tracers, getAttributes(), headers);
|
||||
if (shutdownStatus != null) {
|
||||
return failedClientStream(
|
||||
StatsTraceContext.newClientContext(callOptions, attributes, headers), shutdownStatus);
|
||||
return failedClientStream(statsTraceContext, shutdownStatus);
|
||||
}
|
||||
|
||||
headers.put(GrpcUtil.USER_AGENT_KEY, userAgent);
|
||||
|
|
@ -226,12 +229,12 @@ final class InProcessTransport implements ServerTransport, ConnectionClientTrans
|
|||
"Request metadata larger than %d: %d",
|
||||
serverMaxInboundMetadataSize,
|
||||
metadataSize));
|
||||
return failedClientStream(
|
||||
StatsTraceContext.newClientContext(callOptions, attributes, headers), status);
|
||||
return failedClientStream(statsTraceContext, status);
|
||||
}
|
||||
}
|
||||
|
||||
return new InProcessStream(method, headers, callOptions, authority).clientStream;
|
||||
return new InProcessStream(method, headers, callOptions, authority, statsTraceContext)
|
||||
.clientStream;
|
||||
}
|
||||
|
||||
private ClientStream failedClientStream(
|
||||
|
|
@ -377,12 +380,12 @@ final class InProcessTransport implements ServerTransport, ConnectionClientTrans
|
|||
|
||||
private InProcessStream(
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
String authority) {
|
||||
String authority , StatsTraceContext statsTraceContext) {
|
||||
this.method = checkNotNull(method, "method");
|
||||
this.headers = checkNotNull(headers, "headers");
|
||||
this.callOptions = checkNotNull(callOptions, "callOptions");
|
||||
this.authority = authority;
|
||||
this.clientStream = new InProcessClientStream(callOptions, headers);
|
||||
this.clientStream = new InProcessClientStream(callOptions, statsTraceContext);
|
||||
this.serverStream = new InProcessServerStream(method, headers);
|
||||
}
|
||||
|
||||
|
|
@ -673,9 +676,10 @@ final class InProcessTransport implements ServerTransport, ConnectionClientTrans
|
|||
@GuardedBy("this")
|
||||
private int outboundSeqNo;
|
||||
|
||||
InProcessClientStream(CallOptions callOptions, Metadata headers) {
|
||||
InProcessClientStream(
|
||||
CallOptions callOptions, StatsTraceContext statsTraceContext) {
|
||||
this.callOptions = callOptions;
|
||||
statsTraceCtx = StatsTraceContext.newClientContext(callOptions, attributes, headers);
|
||||
statsTraceCtx = statsTraceContext;
|
||||
}
|
||||
|
||||
private synchronized void setListener(ServerStreamListener listener) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import io.grpc.CallCredentials.RequestInfo;
|
|||
import io.grpc.CallOptions;
|
||||
import io.grpc.ChannelCredentials;
|
||||
import io.grpc.ChannelLogger;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.CompositeCallCredentials;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor;
|
||||
|
|
@ -104,7 +105,8 @@ final class CallCredentialsApplyingTransportFactory implements ClientTransportFa
|
|||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public ClientStream newStream(
|
||||
final MethodDescriptor<?, ?> method, Metadata headers, final CallOptions callOptions) {
|
||||
final MethodDescriptor<?, ?> method, Metadata headers, final CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
CallCredentials creds = callOptions.getCredentials();
|
||||
if (creds == null) {
|
||||
creds = channelCallCredentials;
|
||||
|
|
@ -113,10 +115,10 @@ final class CallCredentialsApplyingTransportFactory implements ClientTransportFa
|
|||
}
|
||||
if (creds != null) {
|
||||
MetadataApplierImpl applier = new MetadataApplierImpl(
|
||||
delegate, method, headers, callOptions, applierListener);
|
||||
delegate, method, headers, callOptions, applierListener, tracers);
|
||||
if (pendingApplier.incrementAndGet() > 0) {
|
||||
applierListener.onComplete();
|
||||
return new FailingClientStream(shutdownStatus);
|
||||
return new FailingClientStream(shutdownStatus, tracers);
|
||||
}
|
||||
RequestInfo requestInfo = new RequestInfo() {
|
||||
@Override
|
||||
|
|
@ -152,9 +154,9 @@ final class CallCredentialsApplyingTransportFactory implements ClientTransportFa
|
|||
return applier.returnStream();
|
||||
} else {
|
||||
if (pendingApplier.get() >= 0) {
|
||||
return new FailingClientStream(shutdownStatus);
|
||||
return new FailingClientStream(shutdownStatus, tracers);
|
||||
}
|
||||
return delegate.newStream(method, headers, callOptions);
|
||||
return delegate.newStream(method, headers, callOptions, tracers);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import com.google.common.base.MoreObjects;
|
|||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientCall;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Codec;
|
||||
import io.grpc.Compressor;
|
||||
import io.grpc.CompressorRegistry;
|
||||
|
|
@ -254,9 +255,11 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
|
|||
effectiveDeadline, context.getDeadline(), callOptions.getDeadline());
|
||||
stream = clientStreamProvider.newStream(method, callOptions, headers, context);
|
||||
} else {
|
||||
ClientStreamTracer[] tracers = GrpcUtil.getClientStreamTracers(callOptions, headers, false);
|
||||
stream = new FailingClientStream(
|
||||
DEADLINE_EXCEEDED.withDescription(
|
||||
"ClientCall started after deadline exceeded: " + effectiveDeadline));
|
||||
"ClientCall started after deadline exceeded: " + effectiveDeadline),
|
||||
tracers);
|
||||
}
|
||||
|
||||
if (callExecutorIsDirect) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package io.grpc.internal;
|
||||
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
import io.grpc.InternalInstrumented;
|
||||
import io.grpc.Metadata;
|
||||
|
|
@ -46,10 +47,15 @@ public interface ClientTransport extends InternalInstrumented<SocketStats> {
|
|||
* @param method the descriptor of the remote method to be called for this stream.
|
||||
* @param headers to send at the beginning of the call
|
||||
* @param callOptions runtime options of the call
|
||||
* @param tracers a non-empty array of tracers. The last element in it is reserved to be set by
|
||||
* the load balancer's pick result and otherwise is a no-op tracer.
|
||||
* @return the newly created stream.
|
||||
*/
|
||||
// TODO(nmittler): Consider also throwing for stopping.
|
||||
ClientStream newStream(MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions);
|
||||
ClientStream newStream(
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
// Using array for tracers instead of a list or composition for better performance.
|
||||
ClientStreamTracer[] tracers);
|
||||
|
||||
/**
|
||||
* Pings a remote endpoint. When an acknowledgement is received, the given callback will be
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.SettableFuture;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Context;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
import io.grpc.InternalLogId;
|
||||
|
|
@ -133,7 +134,8 @@ final class DelayedClientTransport implements ManagedClientTransport {
|
|||
*/
|
||||
@Override
|
||||
public final ClientStream newStream(
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions) {
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
try {
|
||||
PickSubchannelArgs args = new PickSubchannelArgsImpl(method, headers, callOptions);
|
||||
SubchannelPicker picker = null;
|
||||
|
|
@ -141,14 +143,14 @@ final class DelayedClientTransport implements ManagedClientTransport {
|
|||
while (true) {
|
||||
synchronized (lock) {
|
||||
if (shutdownStatus != null) {
|
||||
return new FailingClientStream(shutdownStatus);
|
||||
return new FailingClientStream(shutdownStatus, tracers);
|
||||
}
|
||||
if (lastPicker == null) {
|
||||
return createPendingStream(args);
|
||||
return createPendingStream(args, tracers);
|
||||
}
|
||||
// Check for second time through the loop, and whether anything changed
|
||||
if (picker != null && pickerVersion == lastPickerVersion) {
|
||||
return createPendingStream(args);
|
||||
return createPendingStream(args, tracers);
|
||||
}
|
||||
picker = lastPicker;
|
||||
pickerVersion = lastPickerVersion;
|
||||
|
|
@ -158,7 +160,8 @@ final class DelayedClientTransport implements ManagedClientTransport {
|
|||
callOptions.isWaitForReady());
|
||||
if (transport != null) {
|
||||
return transport.newStream(
|
||||
args.getMethodDescriptor(), args.getHeaders(), args.getCallOptions());
|
||||
args.getMethodDescriptor(), args.getHeaders(), args.getCallOptions(),
|
||||
tracers);
|
||||
}
|
||||
// This picker's conclusion is "buffer". If there hasn't been a newer picker set (possible
|
||||
// race with reprocess()), we will buffer it. Otherwise, will try with the new picker.
|
||||
|
|
@ -173,8 +176,9 @@ final class DelayedClientTransport implements ManagedClientTransport {
|
|||
* schedule tasks on syncContext.
|
||||
*/
|
||||
@GuardedBy("lock")
|
||||
private PendingStream createPendingStream(PickSubchannelArgs args) {
|
||||
PendingStream pendingStream = new PendingStream(args);
|
||||
private PendingStream createPendingStream(
|
||||
PickSubchannelArgs args, ClientStreamTracer[] tracers) {
|
||||
PendingStream pendingStream = new PendingStream(args, tracers);
|
||||
pendingStreams.add(pendingStream);
|
||||
if (getPendingStreamsCount() == 1) {
|
||||
syncContext.executeLater(reportTransportInUse);
|
||||
|
|
@ -239,7 +243,8 @@ final class DelayedClientTransport implements ManagedClientTransport {
|
|||
}
|
||||
if (savedReportTransportTerminated != null) {
|
||||
for (PendingStream stream : savedPendingStreams) {
|
||||
Runnable runnable = stream.setStream(new FailingClientStream(status, RpcProgress.REFUSED));
|
||||
Runnable runnable = stream.setStream(
|
||||
new FailingClientStream(status, RpcProgress.REFUSED, stream.tracers));
|
||||
if (runnable != null) {
|
||||
// Drain in-line instead of using an executor as failing stream just throws everything
|
||||
// away. This is essentially the same behavior as DelayedStream.cancel() but can be done
|
||||
|
|
@ -346,9 +351,11 @@ final class DelayedClientTransport implements ManagedClientTransport {
|
|||
private class PendingStream extends DelayedStream {
|
||||
private final PickSubchannelArgs args;
|
||||
private final Context context = Context.current();
|
||||
private final ClientStreamTracer[] tracers;
|
||||
|
||||
private PendingStream(PickSubchannelArgs args) {
|
||||
private PendingStream(PickSubchannelArgs args, ClientStreamTracer[] tracers) {
|
||||
this.args = args;
|
||||
this.tracers = tracers;
|
||||
}
|
||||
|
||||
/** Runnable may be null. */
|
||||
|
|
@ -357,7 +364,8 @@ final class DelayedClientTransport implements ManagedClientTransport {
|
|||
Context origContext = context.attach();
|
||||
try {
|
||||
realStream = transport.newStream(
|
||||
args.getMethodDescriptor(), args.getHeaders(), args.getCallOptions());
|
||||
args.getMethodDescriptor(), args.getHeaders(), args.getCallOptions(),
|
||||
tracers);
|
||||
} finally {
|
||||
context.detach(origContext);
|
||||
}
|
||||
|
|
@ -382,6 +390,13 @@ final class DelayedClientTransport implements ManagedClientTransport {
|
|||
syncContext.drain();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onEarlyCancellation(Status reason) {
|
||||
for (ClientStreamTracer tracer : tracers) {
|
||||
tracer.streamClosed(reason);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTimeoutInsight(InsightBuilder insight) {
|
||||
if (args.getCallOptions().isWaitForReady()) {
|
||||
|
|
|
|||
|
|
@ -324,11 +324,15 @@ class DelayedStream implements ClientStream {
|
|||
});
|
||||
} else {
|
||||
drainPendingCalls();
|
||||
onEarlyCancellation(reason);
|
||||
// Note that listener is a DelayedStreamListener
|
||||
listener.closed(reason, RpcProgress.PROCESSED, new Metadata());
|
||||
}
|
||||
}
|
||||
|
||||
protected void onEarlyCancellation(Status reason) {
|
||||
}
|
||||
|
||||
@GuardedBy("this")
|
||||
private void setRealStream(ClientStream realStream) {
|
||||
checkState(this.realStream == null, "realStream already set to %s", this.realStream);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package io.grpc.internal;
|
|||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.internal.ClientStreamListener.RpcProgress;
|
||||
|
|
@ -30,27 +31,33 @@ public final class FailingClientStream extends NoopClientStream {
|
|||
private boolean started;
|
||||
private final Status error;
|
||||
private final RpcProgress rpcProgress;
|
||||
private final ClientStreamTracer[] tracers;
|
||||
|
||||
/**
|
||||
* Creates a {@code FailingClientStream} that would fail with the given error.
|
||||
*/
|
||||
public FailingClientStream(Status error) {
|
||||
this(error, RpcProgress.PROCESSED);
|
||||
public FailingClientStream(Status error, ClientStreamTracer[] tracers) {
|
||||
this(error, RpcProgress.PROCESSED, tracers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code FailingClientStream} that would fail with the given error.
|
||||
*/
|
||||
public FailingClientStream(Status error, RpcProgress rpcProgress) {
|
||||
public FailingClientStream(
|
||||
Status error, RpcProgress rpcProgress, ClientStreamTracer[] tracers) {
|
||||
Preconditions.checkArgument(!error.isOk(), "error must not be OK");
|
||||
this.error = error;
|
||||
this.rpcProgress = rpcProgress;
|
||||
this.tracers = tracers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(ClientStreamListener listener) {
|
||||
Preconditions.checkState(!started, "already started");
|
||||
started = true;
|
||||
for (ClientStreamTracer tracer : tracers) {
|
||||
tracer.streamClosed(error);
|
||||
}
|
||||
listener.closed(error, rpcProgress, new Metadata());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.google.common.base.Preconditions;
|
|||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.SettableFuture;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
import io.grpc.InternalLogId;
|
||||
import io.grpc.Metadata;
|
||||
|
|
@ -45,8 +46,9 @@ class FailingClientTransport implements ClientTransport {
|
|||
|
||||
@Override
|
||||
public ClientStream newStream(
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions) {
|
||||
return new FailingClientStream(error, rpcProgress);
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
return new FailingClientStream(error, rpcProgress, tracers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 2021 The gRPC Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.internal;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Status;
|
||||
|
||||
public abstract class ForwardingClientStreamTracer extends ClientStreamTracer {
|
||||
|
||||
/**
|
||||
* Returns the underlying {@code ClientStreamTracer}.
|
||||
*/
|
||||
protected abstract ClientStreamTracer delegate();
|
||||
|
||||
@Override
|
||||
public void streamCreated(Attributes transportAttrs, Metadata headers) {
|
||||
delegate().streamCreated(transportAttrs, headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundHeaders() {
|
||||
delegate().outboundHeaders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundHeaders() {
|
||||
delegate().inboundHeaders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundTrailers(Metadata trailers) {
|
||||
delegate().inboundTrailers(trailers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamClosed(Status status) {
|
||||
delegate().streamClosed(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundMessage(int seqNo) {
|
||||
delegate().outboundMessage(seqNo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundMessage(int seqNo) {
|
||||
delegate().inboundMessage(seqNo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundMessageSent(int seqNo, long optionalWireSize, long optionalUncompressedSize) {
|
||||
delegate().outboundMessageSent(seqNo, optionalWireSize, optionalUncompressedSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundMessageRead(int seqNo, long optionalWireSize, long optionalUncompressedSize) {
|
||||
delegate().inboundMessageRead(seqNo, optionalWireSize, optionalUncompressedSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundWireSize(long bytes) {
|
||||
delegate().outboundWireSize(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundUncompressedSize(long bytes) {
|
||||
delegate().outboundUncompressedSize(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundWireSize(long bytes) {
|
||||
delegate().inboundWireSize(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundUncompressedSize(long bytes) {
|
||||
delegate().inboundUncompressedSize(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("delegate", delegate()).toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import com.google.common.base.MoreObjects;
|
|||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
import io.grpc.InternalLogId;
|
||||
import io.grpc.Metadata;
|
||||
|
|
@ -45,8 +46,9 @@ abstract class ForwardingConnectionClientTransport implements ConnectionClientTr
|
|||
|
||||
@Override
|
||||
public ClientStream newStream(
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions) {
|
||||
return delegate().newStream(method, headers, callOptions);
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
return delegate().newStream(method, headers, callOptions, tracers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package io.grpc.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Objects;
|
||||
|
|
@ -26,8 +27,11 @@ import com.google.common.base.Stopwatch;
|
|||
import com.google.common.base.Supplier;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.ClientStreamTracer.InternalLimitedInfoFactory;
|
||||
import io.grpc.ClientStreamTracer.StreamInfo;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
import io.grpc.InternalLogId;
|
||||
import io.grpc.InternalMetadata;
|
||||
|
|
@ -54,12 +58,14 @@ import java.net.URI;
|
|||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
|
@ -253,6 +259,8 @@ public final class GrpcUtil {
|
|||
public static final CallOptions.Key<Boolean> CALL_OPTIONS_RPC_OWNED_BY_BALANCER =
|
||||
CallOptions.Key.create("io.grpc.internal.CALL_OPTIONS_RPC_OWNED_BY_BALANCER");
|
||||
|
||||
private static final ClientStreamTracer NOOP_TRACER = new ClientStreamTracer() {};
|
||||
|
||||
/**
|
||||
* Returns true if an RPC with the given properties should be counted when calculating the
|
||||
* in-use state of a transport.
|
||||
|
|
@ -711,9 +719,14 @@ public final class GrpcUtil {
|
|||
return new ClientTransport() {
|
||||
@Override
|
||||
public ClientStream newStream(
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions) {
|
||||
return transport.newStream(
|
||||
method, headers, callOptions.withStreamTracerFactory(streamTracerFactory));
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
StreamInfo info = StreamInfo.newBuilder().setCallOptions(callOptions).build();
|
||||
ClientStreamTracer streamTracer =
|
||||
newClientStreamTracer(streamTracerFactory, 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
|
||||
|
|
@ -743,6 +756,64 @@ public final class GrpcUtil {
|
|||
return null;
|
||||
}
|
||||
|
||||
/** Gets stream tracers based on CallOptions. */
|
||||
public static ClientStreamTracer[] getClientStreamTracers(
|
||||
CallOptions callOptions, Metadata headers, boolean isTransparentRetry) {
|
||||
List<ClientStreamTracer.Factory> factories = callOptions.getStreamTracerFactories();
|
||||
ClientStreamTracer[] tracers = new ClientStreamTracer[factories.size() + 1];
|
||||
StreamInfo streamInfo = StreamInfo.newBuilder()
|
||||
.setCallOptions(callOptions)
|
||||
.setIsTransparentRetry(isTransparentRetry)
|
||||
.build();
|
||||
for (int i = 0; i < factories.size(); i++) {
|
||||
tracers[i] = newClientStreamTracer(factories.get(i), streamInfo, headers);
|
||||
}
|
||||
// Reserved to be set later by the lb as per the API contract of ClientTransport.newStream().
|
||||
// See also GrpcUtil.getTransportFromPickResult()
|
||||
tracers[tracers.length - 1] = NOOP_TRACER;
|
||||
return tracers;
|
||||
}
|
||||
|
||||
// A util function for backward compatibility to support deprecated StreamInfo.getAttributes().
|
||||
@VisibleForTesting
|
||||
static ClientStreamTracer newClientStreamTracer(
|
||||
final ClientStreamTracer.Factory streamTracerFactory, final StreamInfo info,
|
||||
final Metadata headers) {
|
||||
ClientStreamTracer streamTracer;
|
||||
if (streamTracerFactory instanceof InternalLimitedInfoFactory) {
|
||||
streamTracer = streamTracerFactory.newClientStreamTracer(info, headers);
|
||||
} else {
|
||||
streamTracer = new ForwardingClientStreamTracer() {
|
||||
final ClientStreamTracer noop = new ClientStreamTracer() {};
|
||||
AtomicReference<ClientStreamTracer> delegate = new AtomicReference<>(noop);
|
||||
|
||||
void maybeInit(StreamInfo info, Metadata headers) {
|
||||
delegate.compareAndSet(noop, streamTracerFactory.newClientStreamTracer(info, headers));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClientStreamTracer delegate() {
|
||||
return delegate.get();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void streamCreated(Attributes transportAttrs, Metadata headers) {
|
||||
StreamInfo streamInfo = info.toBuilder().setTransportAttrs(transportAttrs).build();
|
||||
maybeInit(streamInfo, headers);
|
||||
delegate().streamCreated(transportAttrs, headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamClosed(Status status) {
|
||||
maybeInit(info, headers);
|
||||
delegate().streamClosed(status);
|
||||
}
|
||||
};
|
||||
}
|
||||
return streamTracer;
|
||||
}
|
||||
|
||||
/** Quietly closes all messages in MessageProducer. */
|
||||
static void closeQuietly(MessageProducer producer) {
|
||||
InputStream message;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import io.grpc.Attributes;
|
|||
import io.grpc.CallOptions;
|
||||
import io.grpc.ChannelLogger;
|
||||
import io.grpc.ChannelLogger.ChannelLogLevel;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.ConnectivityState;
|
||||
import io.grpc.ConnectivityStateInfo;
|
||||
import io.grpc.EquivalentAddressGroup;
|
||||
|
|
@ -667,8 +668,9 @@ final class InternalSubchannel implements InternalInstrumented<ChannelStats>, Tr
|
|||
|
||||
@Override
|
||||
public ClientStream newStream(
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions) {
|
||||
final ClientStream streamDelegate = super.newStream(method, headers, callOptions);
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
final ClientStream streamDelegate = super.newStream(method, headers, callOptions, tracers);
|
||||
return new ForwardingClientStream() {
|
||||
@Override
|
||||
protected ClientStream delegate() {
|
||||
|
|
|
|||
|
|
@ -532,8 +532,10 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
|||
ClientTransport transport =
|
||||
getTransport(new PickSubchannelArgsImpl(method, headers, callOptions));
|
||||
Context origContext = context.attach();
|
||||
ClientStreamTracer[] tracers = GrpcUtil.getClientStreamTracers(
|
||||
callOptions, headers, /* isTransparentRetry= */ false);
|
||||
try {
|
||||
return transport.newStream(method, headers, callOptions);
|
||||
return transport.newStream(method, headers, callOptions, tracers);
|
||||
} finally {
|
||||
context.detach(origContext);
|
||||
}
|
||||
|
|
@ -569,13 +571,16 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
|||
}
|
||||
|
||||
@Override
|
||||
ClientStream newSubstream(ClientStreamTracer.Factory tracerFactory, Metadata newHeaders) {
|
||||
CallOptions newOptions = callOptions.withStreamTracerFactory(tracerFactory);
|
||||
ClientStream newSubstream(
|
||||
Metadata newHeaders, ClientStreamTracer.Factory factory, boolean isTransparentRetry) {
|
||||
CallOptions newOptions = callOptions.withStreamTracerFactory(factory);
|
||||
ClientStreamTracer[] tracers =
|
||||
GrpcUtil.getClientStreamTracers(newOptions, newHeaders, isTransparentRetry);
|
||||
ClientTransport transport =
|
||||
getTransport(new PickSubchannelArgsImpl(method, newHeaders, newOptions));
|
||||
Context origContext = context.attach();
|
||||
try {
|
||||
return transport.newStream(method, newHeaders, newOptions);
|
||||
return transport.newStream(method, newHeaders, newOptions, tracers);
|
||||
} finally {
|
||||
context.detach(origContext);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkState;
|
|||
|
||||
import io.grpc.CallCredentials.MetadataApplier;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Context;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor;
|
||||
|
|
@ -36,7 +37,7 @@ final class MetadataApplierImpl extends MetadataApplier {
|
|||
private final CallOptions callOptions;
|
||||
private final Context ctx;
|
||||
private final MetadataApplierListener listener;
|
||||
|
||||
private final ClientStreamTracer[] tracers;
|
||||
private final Object lock = new Object();
|
||||
|
||||
// null if neither apply() or returnStream() are called.
|
||||
|
|
@ -52,13 +53,14 @@ final class MetadataApplierImpl extends MetadataApplier {
|
|||
|
||||
MetadataApplierImpl(
|
||||
ClientTransport transport, MethodDescriptor<?, ?> method, Metadata origHeaders,
|
||||
CallOptions callOptions, MetadataApplierListener listener) {
|
||||
CallOptions callOptions, MetadataApplierListener listener, ClientStreamTracer[] tracers) {
|
||||
this.transport = transport;
|
||||
this.method = method;
|
||||
this.origHeaders = origHeaders;
|
||||
this.callOptions = callOptions;
|
||||
this.ctx = Context.current();
|
||||
this.listener = listener;
|
||||
this.tracers = tracers;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -69,7 +71,7 @@ final class MetadataApplierImpl extends MetadataApplier {
|
|||
ClientStream realStream;
|
||||
Context origCtx = ctx.attach();
|
||||
try {
|
||||
realStream = transport.newStream(method, origHeaders, callOptions);
|
||||
realStream = transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
} finally {
|
||||
ctx.detach(origCtx);
|
||||
}
|
||||
|
|
@ -80,7 +82,7 @@ final class MetadataApplierImpl extends MetadataApplier {
|
|||
public void fail(Status status) {
|
||||
checkArgument(!status.isOk(), "Cannot fail with OK status");
|
||||
checkState(!finalized, "apply() or fail() already called");
|
||||
finalizeWith(new FailingClientStream(status));
|
||||
finalizeWith(new FailingClientStream(status, tracers));
|
||||
}
|
||||
|
||||
private void finalizeWith(ClientStream stream) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.google.common.util.concurrent.SettableFuture;
|
|||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientCall;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.ConnectivityState;
|
||||
import io.grpc.ConnectivityStateInfo;
|
||||
import io.grpc.Context;
|
||||
|
|
@ -86,12 +87,14 @@ final class OobChannel extends ManagedChannel implements InternalInstrumented<Ch
|
|||
@Override
|
||||
public ClientStream newStream(MethodDescriptor<?, ?> method,
|
||||
CallOptions callOptions, Metadata headers, Context context) {
|
||||
ClientStreamTracer[] tracers = GrpcUtil.getClientStreamTracers(
|
||||
callOptions, headers, /* isTransparentRetry= */ false);
|
||||
Context origContext = context.attach();
|
||||
// delayed transport's newStream() always acquires a lock, but concurrent performance doesn't
|
||||
// matter here because OOB communication should be sparse, and it's not on application RPC's
|
||||
// critical path.
|
||||
try {
|
||||
return delayedTransport.newStream(method, headers, callOptions);
|
||||
return delayedTransport.newStream(method, headers, callOptions, tracers);
|
||||
} finally {
|
||||
context.detach(origContext);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,11 +203,11 @@ abstract class RetriableStream<ReqT> implements ClientStream {
|
|||
}
|
||||
}
|
||||
|
||||
private Substream createSubstream(int previousAttemptCount) {
|
||||
private Substream createSubstream(int previousAttemptCount, boolean isTransparentRetry) {
|
||||
Substream sub = new Substream(previousAttemptCount);
|
||||
// one tracer per substream
|
||||
final ClientStreamTracer bufferSizeTracer = new BufferSizeTracer(sub);
|
||||
ClientStreamTracer.Factory tracerFactory = new ClientStreamTracer.Factory() {
|
||||
ClientStreamTracer.Factory tracerFactory = new ClientStreamTracer.InternalLimitedInfoFactory() {
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(
|
||||
ClientStreamTracer.StreamInfo info, Metadata headers) {
|
||||
|
|
@ -217,7 +217,7 @@ abstract class RetriableStream<ReqT> implements ClientStream {
|
|||
|
||||
Metadata newHeaders = updateHeaders(headers, previousAttemptCount);
|
||||
// NOTICE: This set _must_ be done before stream.start() and it actually is.
|
||||
sub.stream = newSubstream(tracerFactory, newHeaders);
|
||||
sub.stream = newSubstream(newHeaders, tracerFactory, isTransparentRetry);
|
||||
return sub;
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ abstract class RetriableStream<ReqT> implements ClientStream {
|
|||
* Client stream is not yet started.
|
||||
*/
|
||||
abstract ClientStream newSubstream(
|
||||
ClientStreamTracer.Factory tracerFactory, Metadata headers);
|
||||
Metadata headers, ClientStreamTracer.Factory tracerFactory, boolean isTransparentRetry);
|
||||
|
||||
/** Adds grpc-previous-rpc-attempts in the headers of a retry/hedging RPC. */
|
||||
@VisibleForTesting
|
||||
|
|
@ -322,7 +322,7 @@ abstract class RetriableStream<ReqT> implements ClientStream {
|
|||
state.buffer.add(new StartEntry());
|
||||
}
|
||||
|
||||
Substream substream = createSubstream(0);
|
||||
Substream substream = createSubstream(0, false);
|
||||
if (isHedging) {
|
||||
FutureCanceller scheduledHedgingRef = null;
|
||||
|
||||
|
|
@ -399,7 +399,7 @@ abstract class RetriableStream<ReqT> implements ClientStream {
|
|||
// If this run is not cancelled, the value of state.hedgingAttemptCount won't change
|
||||
// until state.addActiveHedge() is called subsequently, even the state could possibly
|
||||
// change.
|
||||
Substream newSubstream = createSubstream(state.hedgingAttemptCount);
|
||||
Substream newSubstream = createSubstream(state.hedgingAttemptCount, false);
|
||||
boolean cancelled = false;
|
||||
FutureCanceller future = null;
|
||||
|
||||
|
|
@ -784,8 +784,7 @@ abstract class RetriableStream<ReqT> implements ClientStream {
|
|||
if (rpcProgress == RpcProgress.REFUSED
|
||||
&& noMoreTransparentRetry.compareAndSet(false, true)) {
|
||||
// transparent retry
|
||||
final Substream newSubstream = createSubstream(
|
||||
substream.previousAttemptCount);
|
||||
final Substream newSubstream = createSubstream(substream.previousAttemptCount, true);
|
||||
if (isHedging) {
|
||||
boolean commit = false;
|
||||
synchronized (lock) {
|
||||
|
|
@ -863,8 +862,9 @@ abstract class RetriableStream<ReqT> implements ClientStream {
|
|||
@Override
|
||||
public void run() {
|
||||
// retry
|
||||
Substream newSubstream =
|
||||
createSubstream(substream.previousAttemptCount + 1);
|
||||
Substream newSubstream = createSubstream(
|
||||
substream.previousAttemptCount + 1,
|
||||
false);
|
||||
drain(newSubstream);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Context;
|
||||
import io.grpc.Metadata;
|
||||
|
|
@ -48,21 +47,12 @@ public final class StatsTraceContext {
|
|||
* Factory method for the client-side.
|
||||
*/
|
||||
public static StatsTraceContext newClientContext(
|
||||
final CallOptions callOptions, final Attributes transportAttrs, Metadata headers) {
|
||||
List<ClientStreamTracer.Factory> factories = callOptions.getStreamTracerFactories();
|
||||
if (factories.isEmpty()) {
|
||||
return NOOP;
|
||||
ClientStreamTracer[] tracers, Attributes transportAtts, Metadata headers) {
|
||||
StatsTraceContext ctx = new StatsTraceContext(tracers);
|
||||
for (ClientStreamTracer tracer : tracers) {
|
||||
tracer.streamCreated(transportAtts, headers);
|
||||
}
|
||||
ClientStreamTracer.StreamInfo info =
|
||||
ClientStreamTracer.StreamInfo.newBuilder()
|
||||
.setTransportAttrs(transportAttrs).setCallOptions(callOptions).build();
|
||||
// This array will be iterated multiple times per RPC. Use primitive array instead of Collection
|
||||
// so that for-each doesn't create an Iterator every time.
|
||||
StreamTracer[] tracers = new StreamTracer[factories.size()];
|
||||
for (int i = 0; i < tracers.length; i++) {
|
||||
tracers[i] = factories.get(i).newClientStreamTracer(info, headers);
|
||||
}
|
||||
return new StatsTraceContext(tracers);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import io.grpc.CallOptions;
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.ClientCall;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Context;
|
||||
import io.grpc.InternalConfigSelector;
|
||||
import io.grpc.Metadata;
|
||||
|
|
@ -57,9 +58,11 @@ final class SubchannelChannel extends Channel {
|
|||
if (transport == null) {
|
||||
transport = notReadyTransport;
|
||||
}
|
||||
ClientStreamTracer[] tracers = GrpcUtil.getClientStreamTracers(
|
||||
callOptions, headers, /* isTransparentRetry= */ false);
|
||||
Context origContext = context.attach();
|
||||
try {
|
||||
return transport.newStream(method, headers, callOptions);
|
||||
return transport.newStream(method, headers, callOptions, tracers);
|
||||
} finally {
|
||||
context.detach(origContext);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package io.grpc.util;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.ExperimentalApi;
|
||||
import io.grpc.Metadata;
|
||||
|
|
@ -27,6 +28,11 @@ public abstract class ForwardingClientStreamTracer extends ClientStreamTracer {
|
|||
/** Returns the underlying {@code ClientStreamTracer}. */
|
||||
protected abstract ClientStreamTracer delegate();
|
||||
|
||||
@Override
|
||||
public void streamCreated(Attributes transportAttrs, Metadata headers) {
|
||||
delegate().streamCreated(transportAttrs, headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundHeaders() {
|
||||
delegate().outboundHeaders();
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public class ClientStreamTracerTest {
|
|||
Attributes.newBuilder().set(TRANSPORT_ATTR_KEY, "value").build();
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // info.getTransportAttrs()
|
||||
public void streamInfo_empty() {
|
||||
StreamInfo info = StreamInfo.newBuilder().build();
|
||||
assertThat(info.getCallOptions()).isSameInstanceAs(CallOptions.DEFAULT);
|
||||
|
|
@ -41,6 +42,7 @@ public class ClientStreamTracerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // info.getTransportAttrs()
|
||||
public void streamInfo_withInfo() {
|
||||
StreamInfo info = StreamInfo.newBuilder()
|
||||
.setCallOptions(callOptions).setTransportAttrs(transportAttrs).build();
|
||||
|
|
@ -49,6 +51,7 @@ public class ClientStreamTracerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // info.setTransportAttrs()
|
||||
public void streamInfo_noEquality() {
|
||||
StreamInfo info1 = StreamInfo.newBuilder()
|
||||
.setCallOptions(callOptions).setTransportAttrs(transportAttrs).build();
|
||||
|
|
@ -60,6 +63,7 @@ public class ClientStreamTracerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // info.getTransportAttrs()
|
||||
public void streamInfo_toBuilder() {
|
||||
StreamInfo info1 = StreamInfo.newBuilder()
|
||||
.setCallOptions(callOptions).setTransportAttrs(transportAttrs).build();
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ import io.grpc.Attributes;
|
|||
import io.grpc.CallOptions;
|
||||
import io.grpc.ChannelLogger;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.ClientStreamTracer.StreamInfo;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
import io.grpc.InternalChannelz.TransportStats;
|
||||
|
|
@ -172,7 +171,7 @@ public abstract class AbstractTransportTest {
|
|||
.setRequestMarshaller(StringMarshaller.INSTANCE)
|
||||
.setResponseMarshaller(StringMarshaller.INSTANCE)
|
||||
.build();
|
||||
private CallOptions callOptions;
|
||||
private final CallOptions callOptions = CallOptions.DEFAULT;
|
||||
|
||||
private Metadata.Key<String> asciiKey = Metadata.Key.of(
|
||||
"ascii-key", Metadata.ASCII_STRING_MARSHALLER);
|
||||
|
|
@ -186,24 +185,14 @@ public abstract class AbstractTransportTest {
|
|||
= mock(ManagedClientTransport.Listener.class);
|
||||
private MockServerListener serverListener = new MockServerListener();
|
||||
private ArgumentCaptor<Throwable> throwableCaptor = ArgumentCaptor.forClass(Throwable.class);
|
||||
private final TestClientStreamTracer clientStreamTracer1 = new TestClientStreamTracer();
|
||||
private final TestClientStreamTracer clientStreamTracer2 = new TestClientStreamTracer();
|
||||
private final ClientStreamTracer.Factory clientStreamTracerFactory = mock(
|
||||
ClientStreamTracer.Factory.class,
|
||||
delegatesTo(new ClientStreamTracer.Factory() {
|
||||
final ArrayDeque<TestClientStreamTracer> tracers =
|
||||
new ArrayDeque<>(Arrays.asList(clientStreamTracer1, clientStreamTracer2));
|
||||
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata metadata) {
|
||||
metadata.put(tracerHeaderKey, tracerKeyValue);
|
||||
TestClientStreamTracer tracer = tracers.poll();
|
||||
if (tracer != null) {
|
||||
return tracer;
|
||||
}
|
||||
return new TestClientStreamTracer();
|
||||
}
|
||||
}));
|
||||
private final TestClientStreamTracer clientStreamTracer1 = new TestHeaderClientStreamTracer();
|
||||
private final TestClientStreamTracer clientStreamTracer2 = new TestHeaderClientStreamTracer();
|
||||
private final ClientStreamTracer[] tracers = new ClientStreamTracer[] {
|
||||
clientStreamTracer1, clientStreamTracer2
|
||||
};
|
||||
private final ClientStreamTracer[] noopTracers = new ClientStreamTracer[] {
|
||||
new ClientStreamTracer() {}
|
||||
};
|
||||
|
||||
private final TestServerStreamTracer serverStreamTracer1 = new TestServerStreamTracer();
|
||||
private final TestServerStreamTracer serverStreamTracer2 = new TestServerStreamTracer();
|
||||
|
|
@ -230,7 +219,6 @@ public abstract class AbstractTransportTest {
|
|||
@Before
|
||||
public void setUp() {
|
||||
server = newServer(Arrays.asList(serverStreamTracerFactory));
|
||||
callOptions = CallOptions.DEFAULT.withStreamTracerFactory(clientStreamTracerFactory);
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
@ -291,7 +279,8 @@ public abstract class AbstractTransportTest {
|
|||
// after having sent a RST_STREAM to the server. Previously, this would have broken the
|
||||
// Netty channel.
|
||||
|
||||
ClientStream stream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream stream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, noopTracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
stream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation
|
||||
|
|
@ -314,7 +303,8 @@ public abstract class AbstractTransportTest {
|
|||
|
||||
// Test that the channel is still usable i.e. we can receive headers from the server on a
|
||||
// new stream.
|
||||
stream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
stream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, noopTracers);
|
||||
stream.start(mockClientStreamListener2);
|
||||
serverStreamCreation
|
||||
= serverTransportListener.takeStreamOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
|
@ -449,7 +439,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportInUse(true);
|
||||
|
|
@ -501,7 +492,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportInUse(true);
|
||||
|
|
@ -539,7 +531,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportInUse(true);
|
||||
|
|
@ -594,7 +587,8 @@ public abstract class AbstractTransportTest {
|
|||
client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
// Stream prevents termination
|
||||
ClientStream stream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream stream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
stream.start(clientStreamListener);
|
||||
client.shutdown(Status.UNAVAILABLE);
|
||||
|
|
@ -633,22 +627,19 @@ public abstract class AbstractTransportTest {
|
|||
|
||||
@Test
|
||||
public void newStream_duringShutdown() throws Exception {
|
||||
InOrder inOrder = inOrder(clientStreamTracerFactory);
|
||||
server.start(serverListener);
|
||||
client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
// Stream prevents termination
|
||||
ClientStream stream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
inOrder.verify(clientStreamTracerFactory).newClientStreamTracer(
|
||||
any(ClientStreamTracer.StreamInfo.class), any(Metadata.class));
|
||||
ClientStream stream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, noopTracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
stream.start(clientStreamListener);
|
||||
client.shutdown(Status.UNAVAILABLE);
|
||||
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportShutdown(any(Status.class));
|
||||
|
||||
ClientStream stream2 = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
inOrder.verify(clientStreamTracerFactory).newClientStreamTracer(
|
||||
any(ClientStreamTracer.StreamInfo.class), any(Metadata.class));
|
||||
ClientStream stream2 = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener2 = new ClientStreamListenerBase();
|
||||
stream2.start(clientStreamListener2);
|
||||
Status clientStreamStatus2 =
|
||||
|
|
@ -683,15 +674,14 @@ public abstract class AbstractTransportTest {
|
|||
client.shutdown(shutdownReason);
|
||||
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportTerminated();
|
||||
Thread.sleep(100);
|
||||
ClientStream stream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream stream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
stream.start(clientStreamListener);
|
||||
assertEquals(
|
||||
shutdownReason, clientStreamListener.status.get(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
assertNotNull(clientStreamListener.trailers.get(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
verify(mockClientTransportListener, never()).transportInUse(anyBoolean());
|
||||
verify(clientStreamTracerFactory).newClientStreamTracer(
|
||||
any(ClientStreamTracer.StreamInfo.class), any(Metadata.class));
|
||||
assertNull(clientStreamTracer1.getInboundTrailers());
|
||||
assertSame(shutdownReason, clientStreamTracer1.getStatus());
|
||||
// Assert no interactions
|
||||
|
|
@ -708,7 +698,8 @@ public abstract class AbstractTransportTest {
|
|||
// CALL_OPTIONS_RPC_OWNED_BY_BALANCER in CallOptions. It won't be counted for in-use signal.
|
||||
ClientStream stream1 = client.newStream(
|
||||
methodDescriptor, new Metadata(),
|
||||
callOptions.withOption(GrpcUtil.CALL_OPTIONS_RPC_OWNED_BY_BALANCER, Boolean.TRUE));
|
||||
callOptions.withOption(GrpcUtil.CALL_OPTIONS_RPC_OWNED_BY_BALANCER, Boolean.TRUE),
|
||||
noopTracers);
|
||||
ClientStreamListenerBase clientStreamListener1 = new ClientStreamListenerBase();
|
||||
stream1.start(clientStreamListener1);
|
||||
MockServerTransportListener serverTransportListener
|
||||
|
|
@ -717,7 +708,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverTransportListener.takeStreamOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
// stream2 is the normal RPC, and will be counted for in-use
|
||||
ClientStream stream2 = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream stream2 = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, noopTracers);
|
||||
ClientStreamListenerBase clientStreamListener2 = new ClientStreamListenerBase();
|
||||
stream2.start(clientStreamListener2);
|
||||
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportInUse(true);
|
||||
|
|
@ -743,7 +735,8 @@ public abstract class AbstractTransportTest {
|
|||
server.start(serverListener);
|
||||
client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
ClientStream stream1 = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream stream1 = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, noopTracers);
|
||||
ClientStreamListenerBase clientStreamListener1 = new ClientStreamListenerBase();
|
||||
stream1.start(clientStreamListener1);
|
||||
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportInUse(true);
|
||||
|
|
@ -751,7 +744,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
StreamCreation serverStreamCreation1
|
||||
= serverTransportListener.takeStreamOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
ClientStream stream2 = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream stream2 = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, noopTracers);
|
||||
ClientStreamListenerBase clientStreamListener2 = new ClientStreamListenerBase();
|
||||
stream2.start(clientStreamListener2);
|
||||
StreamCreation serverStreamCreation2
|
||||
|
|
@ -773,11 +767,13 @@ public abstract class AbstractTransportTest {
|
|||
server.start(serverListener);
|
||||
client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
ClientStream stream1 = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream stream1 = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, noopTracers);
|
||||
ClientStreamListenerBase clientStreamListener1 = new ClientStreamListenerBase();
|
||||
stream1.start(clientStreamListener1);
|
||||
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportInUse(true);
|
||||
ClientStream stream2 = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream stream2 = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, noopTracers);
|
||||
ClientStreamListenerBase clientStreamListener2 = new ClientStreamListenerBase();
|
||||
stream2.start(clientStreamListener2);
|
||||
|
||||
|
|
@ -792,7 +788,6 @@ public abstract class AbstractTransportTest {
|
|||
|
||||
@Test
|
||||
public void basicStream() throws Exception {
|
||||
InOrder clientInOrder = inOrder(clientStreamTracerFactory);
|
||||
InOrder serverInOrder = inOrder(serverStreamTracerFactory);
|
||||
server.start(serverListener);
|
||||
client = newClientTransport(server);
|
||||
|
|
@ -816,14 +811,10 @@ public abstract class AbstractTransportTest {
|
|||
Metadata clientHeadersCopy = new Metadata();
|
||||
|
||||
clientHeadersCopy.merge(clientHeaders);
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, clientHeaders, callOptions);
|
||||
ArgumentCaptor<ClientStreamTracer.StreamInfo> streamInfoCaptor = ArgumentCaptor.forClass(null);
|
||||
clientInOrder.verify(clientStreamTracerFactory).newClientStreamTracer(
|
||||
streamInfoCaptor.capture(), same(clientHeaders));
|
||||
ClientStreamTracer.StreamInfo streamInfo = streamInfoCaptor.getValue();
|
||||
assertThat(streamInfo.getTransportAttrs()).isSameInstanceAs(
|
||||
((ConnectionClientTransport) client).getAttributes());
|
||||
assertThat(streamInfo.getCallOptions()).isSameInstanceAs(callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, clientHeaders, callOptions, tracers);
|
||||
assertThat(((TestHeaderClientStreamTracer) clientStreamTracer1).transportAttrs)
|
||||
.isSameInstanceAs(((ConnectionClientTransport) client).getAttributes());
|
||||
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
|
|
@ -974,7 +965,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
Metadata clientHeaders = new Metadata();
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, clientHeaders, callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, clientHeaders, callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation
|
||||
|
|
@ -1005,7 +997,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation
|
||||
|
|
@ -1044,7 +1037,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation
|
||||
|
|
@ -1080,7 +1074,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation
|
||||
|
|
@ -1122,7 +1117,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation
|
||||
|
|
@ -1155,7 +1151,8 @@ public abstract class AbstractTransportTest {
|
|||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
final ClientStream clientStream =
|
||||
client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase() {
|
||||
|
||||
@Override
|
||||
|
|
@ -1196,7 +1193,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation
|
||||
|
|
@ -1230,7 +1228,8 @@ public abstract class AbstractTransportTest {
|
|||
|
||||
final SettableFuture<Boolean> closedCalled = SettableFuture.create();
|
||||
final ClientStream clientStream =
|
||||
client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
final Status status = Status.CANCELLED.withDescription("nevermind");
|
||||
clientStream.start(new ClientStreamListener() {
|
||||
private boolean messageReceived = false;
|
||||
|
|
@ -1311,7 +1310,8 @@ public abstract class AbstractTransportTest {
|
|||
= serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation
|
||||
|
|
@ -1331,8 +1331,6 @@ public abstract class AbstractTransportTest {
|
|||
// Cause should not be transmitted between server and client
|
||||
assertNull(clientStreamStatus.getCause());
|
||||
|
||||
verify(clientStreamTracerFactory).newClientStreamTracer(
|
||||
any(ClientStreamTracer.StreamInfo.class), any(Metadata.class));
|
||||
assertTrue(clientStreamTracer1.getOutboundHeaders());
|
||||
assertNull(clientStreamTracer1.getInboundTrailers());
|
||||
assertSame(clientStreamStatus, clientStreamTracer1.getStatus());
|
||||
|
|
@ -1353,7 +1351,8 @@ public abstract class AbstractTransportTest {
|
|||
serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
serverTransport = serverTransportListener.transport;
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation =
|
||||
|
|
@ -1515,7 +1514,8 @@ public abstract class AbstractTransportTest {
|
|||
|
||||
// boilerplate
|
||||
ClientStream clientStream =
|
||||
client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation server
|
||||
|
|
@ -1547,7 +1547,8 @@ public abstract class AbstractTransportTest {
|
|||
|
||||
// boilerplate
|
||||
ClientStream clientStream =
|
||||
client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListener clientListener = mock(ClientStreamListener.class);
|
||||
clientStream.start(clientListener);
|
||||
StreamCreation server
|
||||
|
|
@ -1594,7 +1595,8 @@ public abstract class AbstractTransportTest {
|
|||
assertEquals(0, clientBefore.streamsStarted);
|
||||
assertEquals(0, clientBefore.lastRemoteStreamCreatedTimeNanos);
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation = serverTransportListener
|
||||
|
|
@ -1624,7 +1626,8 @@ public abstract class AbstractTransportTest {
|
|||
TransportStats clientBefore = getTransportStats(client);
|
||||
assertEquals(1, clientBefore.streamsStarted);
|
||||
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, noopTracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
StreamCreation serverStreamCreation = serverTransportListener
|
||||
|
|
@ -1654,7 +1657,8 @@ public abstract class AbstractTransportTest {
|
|||
server.start(serverListener);
|
||||
client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
MockServerTransportListener serverTransportListener
|
||||
|
|
@ -1693,7 +1697,8 @@ public abstract class AbstractTransportTest {
|
|||
server.start(serverListener);
|
||||
client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
MockServerTransportListener serverTransportListener
|
||||
|
|
@ -1733,7 +1738,8 @@ public abstract class AbstractTransportTest {
|
|||
server.start(serverListener);
|
||||
client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
MockServerTransportListener serverTransportListener =
|
||||
|
|
@ -1768,7 +1774,8 @@ public abstract class AbstractTransportTest {
|
|||
server.start(serverListener);
|
||||
client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
MockServerTransportListener serverTransportListener
|
||||
|
|
@ -1809,7 +1816,8 @@ public abstract class AbstractTransportTest {
|
|||
server.start(serverListener);
|
||||
client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
MockServerTransportListener serverTransportListener
|
||||
|
|
@ -1849,7 +1857,8 @@ public abstract class AbstractTransportTest {
|
|||
server.start(serverListener);
|
||||
ManagedClientTransport client = newClientTransport(server);
|
||||
startTransport(client, mockClientTransportListener);
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
|
||||
|
|
@ -1896,8 +1905,8 @@ public abstract class AbstractTransportTest {
|
|||
Metadata.Key.of("foo-bin", Metadata.BINARY_BYTE_MARSHALLER),
|
||||
new byte[GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE]);
|
||||
|
||||
ClientStream clientStream =
|
||||
client.newStream(methodDescriptor, tooLargeMetadata, callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, tooLargeMetadata, callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
|
||||
|
|
@ -1931,7 +1940,8 @@ public abstract class AbstractTransportTest {
|
|||
new byte[GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE]);
|
||||
|
||||
ClientStream clientStream =
|
||||
client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
|
||||
|
|
@ -1975,7 +1985,8 @@ public abstract class AbstractTransportTest {
|
|||
new byte[GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE]);
|
||||
|
||||
ClientStream clientStream =
|
||||
client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
|
||||
|
|
@ -2011,7 +2022,9 @@ public abstract class AbstractTransportTest {
|
|||
ManagedClientTransport client = newClientTransport(server);
|
||||
ManagedClientTransport.Listener listener = mock(ManagedClientTransport.Listener.class);
|
||||
startTransport(client, listener);
|
||||
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata(), callOptions);
|
||||
ClientStream clientStream = client.newStream(
|
||||
methodDescriptor, new Metadata(), callOptions,
|
||||
new ClientStreamTracer[] { new ClientStreamTracer() {} });
|
||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||
clientStream.start(clientStreamListener);
|
||||
|
||||
|
|
@ -2092,6 +2105,16 @@ public abstract class AbstractTransportTest {
|
|||
verify(listener, timeout(TIMEOUT_MS)).transportReady();
|
||||
}
|
||||
|
||||
private final class TestHeaderClientStreamTracer extends TestClientStreamTracer {
|
||||
Attributes transportAttrs;
|
||||
|
||||
@Override
|
||||
public void streamCreated(Attributes transportAttrs, Metadata metadata) {
|
||||
this.transportAttrs = transportAttrs;
|
||||
metadata.put(tracerHeaderKey, tracerKeyValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MockServerListener implements ServerListener {
|
||||
public final BlockingQueue<MockServerTransportListener> listeners
|
||||
= new LinkedBlockingQueue<>();
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import io.grpc.CallCredentials.MetadataApplier;
|
|||
import io.grpc.CallCredentials.RequestInfo;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ChannelLogger;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.IntegerMarshaller;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor;
|
||||
|
|
@ -48,6 +49,7 @@ import org.junit.Test;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
|
|
@ -103,6 +105,9 @@ public class CallCredentials2ApplyingTest {
|
|||
private static final Metadata.Key<String> CREDS_KEY =
|
||||
Metadata.Key.of("test-creds", Metadata.ASCII_STRING_MARSHALLER);
|
||||
private static final String CREDS_VALUE = "some credentials";
|
||||
private static final ClientStreamTracer[] tracers = new ClientStreamTracer[] {
|
||||
new ClientStreamTracer() {}
|
||||
};
|
||||
|
||||
private final Metadata origHeaders = new Metadata();
|
||||
private ForwardingConnectionClientTransport transport;
|
||||
|
|
@ -118,7 +123,9 @@ public class CallCredentials2ApplyingTest {
|
|||
origHeaders.put(ORIG_HEADER_KEY, ORIG_HEADER_VALUE);
|
||||
when(mockTransportFactory.newClientTransport(address, clientTransportOptions, channelLogger))
|
||||
.thenReturn(mockTransport);
|
||||
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
ClientTransportFactory transportFactory = new CallCredentialsApplyingTransportFactory(
|
||||
mockTransportFactory, null, mockExecutor);
|
||||
|
|
@ -134,7 +141,7 @@ public class CallCredentials2ApplyingTest {
|
|||
Attributes transportAttrs = Attributes.newBuilder().set(ATTR_KEY, ATTR_VALUE).build();
|
||||
when(mockTransport.getAttributes()).thenReturn(transportAttrs);
|
||||
|
||||
transport.newStream(method, origHeaders, callOptions);
|
||||
transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
|
||||
ArgumentCaptor<RequestInfo> infoCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(
|
||||
|
|
@ -155,7 +162,7 @@ public class CallCredentials2ApplyingTest {
|
|||
.build();
|
||||
when(mockTransport.getAttributes()).thenReturn(transportAttrs);
|
||||
|
||||
transport.newStream(method, origHeaders, callOptions);
|
||||
transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
|
||||
ArgumentCaptor<RequestInfo> infoCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(
|
||||
|
|
@ -176,8 +183,10 @@ public class CallCredentials2ApplyingTest {
|
|||
when(mockTransport.getAttributes()).thenReturn(transportAttrs);
|
||||
Executor anotherExecutor = mock(Executor.class);
|
||||
|
||||
transport.newStream(method, origHeaders,
|
||||
callOptions.withAuthority("calloptions-authority").withExecutor(anotherExecutor));
|
||||
transport.newStream(
|
||||
method, origHeaders,
|
||||
callOptions.withAuthority("calloptions-authority").withExecutor(anotherExecutor),
|
||||
tracers);
|
||||
|
||||
ArgumentCaptor<RequestInfo> infoCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(
|
||||
|
|
@ -199,13 +208,15 @@ public class CallCredentials2ApplyingTest {
|
|||
any(io.grpc.CallCredentials2.MetadataApplier.class));
|
||||
|
||||
FailingClientStream stream =
|
||||
(FailingClientStream) transport.newStream(method, origHeaders, callOptions);
|
||||
(FailingClientStream) transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
|
||||
verify(mockTransport, never()).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertEquals(Status.Code.UNAUTHENTICATED, stream.getError().getCode());
|
||||
assertSame(ex, stream.getError().getCause());
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -226,14 +237,14 @@ public class CallCredentials2ApplyingTest {
|
|||
any(RequestInfo.class), same(mockExecutor),
|
||||
any(io.grpc.CallCredentials2.MetadataApplier.class));
|
||||
|
||||
ClientStream stream = transport.newStream(method, origHeaders, callOptions);
|
||||
ClientStream stream = transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions, tracers);
|
||||
assertSame(mockStream, stream);
|
||||
assertEquals(CREDS_VALUE, origHeaders.get(CREDS_KEY));
|
||||
assertEquals(ORIG_HEADER_VALUE, origHeaders.get(ORIG_HEADER_KEY));
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -254,12 +265,14 @@ public class CallCredentials2ApplyingTest {
|
|||
any(io.grpc.CallCredentials2.MetadataApplier.class));
|
||||
|
||||
FailingClientStream stream =
|
||||
(FailingClientStream) transport.newStream(method, origHeaders, callOptions);
|
||||
(FailingClientStream) transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
|
||||
verify(mockTransport, never()).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertSame(error, stream.getError());
|
||||
transport.shutdownNow(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdownNow(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -269,12 +282,15 @@ public class CallCredentials2ApplyingTest {
|
|||
when(mockTransport.getAttributes()).thenReturn(Attributes.EMPTY);
|
||||
|
||||
// Will call applyRequestMetadata(), which is no-op.
|
||||
DelayedStream stream = (DelayedStream) transport.newStream(method, origHeaders, callOptions);
|
||||
DelayedStream stream = (DelayedStream) transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
ArgumentCaptor<MetadataApplier> applierCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(
|
||||
any(RequestInfo.class), same(mockExecutor), applierCaptor.capture());
|
||||
verify(mockTransport, never()).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
verify(mockTransport, never()).shutdown(Status.UNAVAILABLE);
|
||||
|
|
@ -283,11 +299,11 @@ public class CallCredentials2ApplyingTest {
|
|||
headers.put(CREDS_KEY, CREDS_VALUE);
|
||||
applierCaptor.getValue().apply(headers);
|
||||
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions, tracers);
|
||||
assertSame(mockStream, stream.getRealStream());
|
||||
assertEquals(CREDS_VALUE, origHeaders.get(CREDS_KEY));
|
||||
assertEquals(ORIG_HEADER_VALUE, origHeaders.get(ORIG_HEADER_KEY));
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -297,7 +313,8 @@ public class CallCredentials2ApplyingTest {
|
|||
when(mockTransport.getAttributes()).thenReturn(Attributes.EMPTY);
|
||||
|
||||
// Will call applyRequestMetadata(), which is no-op.
|
||||
DelayedStream stream = (DelayedStream) transport.newStream(method, origHeaders, callOptions);
|
||||
DelayedStream stream = (DelayedStream) transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
ArgumentCaptor<MetadataApplier> applierCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(
|
||||
|
|
@ -306,11 +323,13 @@ public class CallCredentials2ApplyingTest {
|
|||
Status error = Status.FAILED_PRECONDITION.withDescription("channel not secure for creds");
|
||||
applierCaptor.getValue().fail(error);
|
||||
|
||||
verify(mockTransport, never()).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
FailingClientStream failingStream = (FailingClientStream) stream.getRealStream();
|
||||
assertSame(error, failingStream.getError());
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -318,14 +337,14 @@ public class CallCredentials2ApplyingTest {
|
|||
@Test
|
||||
public void noCreds() {
|
||||
callOptions = callOptions.withCallCredentials(null);
|
||||
ClientStream stream = transport.newStream(method, origHeaders, callOptions);
|
||||
ClientStream stream = transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions, tracers);
|
||||
assertSame(mockStream, stream);
|
||||
assertNull(origHeaders.get(CREDS_KEY));
|
||||
assertEquals(ORIG_HEADER_VALUE, origHeaders.get(ORIG_HEADER_KEY));
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import io.grpc.CallCredentials;
|
|||
import io.grpc.CallCredentials.RequestInfo;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ChannelLogger;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.IntegerMarshaller;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor;
|
||||
|
|
@ -49,6 +50,7 @@ import org.junit.Test;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
|
|
@ -86,6 +88,9 @@ public class CallCredentialsApplyingTest {
|
|||
@Mock
|
||||
private ChannelLogger channelLogger;
|
||||
|
||||
private static final ClientStreamTracer[] tracers = new ClientStreamTracer[] {
|
||||
new ClientStreamTracer() {}
|
||||
};
|
||||
private static final String AUTHORITY = "testauthority";
|
||||
private static final String USER_AGENT = "testuseragent";
|
||||
private static final Attributes.Key<String> ATTR_KEY = Attributes.Key.create("somekey");
|
||||
|
|
@ -117,7 +122,9 @@ public class CallCredentialsApplyingTest {
|
|||
origHeaders.put(ORIG_HEADER_KEY, ORIG_HEADER_VALUE);
|
||||
when(mockTransportFactory.newClientTransport(address, clientTransportOptions, channelLogger))
|
||||
.thenReturn(mockTransport);
|
||||
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
ClientTransportFactory transportFactory = new CallCredentialsApplyingTransportFactory(
|
||||
mockTransportFactory, null, mockExecutor);
|
||||
|
|
@ -133,7 +140,7 @@ public class CallCredentialsApplyingTest {
|
|||
Attributes transportAttrs = Attributes.newBuilder().set(ATTR_KEY, ATTR_VALUE).build();
|
||||
when(mockTransport.getAttributes()).thenReturn(transportAttrs);
|
||||
|
||||
transport.newStream(method, origHeaders, callOptions);
|
||||
transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
|
||||
ArgumentCaptor<RequestInfo> infoCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(infoCaptor.capture(), same(mockExecutor),
|
||||
|
|
@ -154,8 +161,10 @@ public class CallCredentialsApplyingTest {
|
|||
when(mockTransport.getAttributes()).thenReturn(transportAttrs);
|
||||
Executor anotherExecutor = mock(Executor.class);
|
||||
|
||||
transport.newStream(method, origHeaders,
|
||||
callOptions.withAuthority("calloptions-authority").withExecutor(anotherExecutor));
|
||||
transport.newStream(
|
||||
method, origHeaders,
|
||||
callOptions.withAuthority("calloptions-authority").withExecutor(anotherExecutor),
|
||||
tracers);
|
||||
|
||||
ArgumentCaptor<RequestInfo> infoCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(infoCaptor.capture(),
|
||||
|
|
@ -175,15 +184,17 @@ public class CallCredentialsApplyingTest {
|
|||
any(RequestInfo.class), same(mockExecutor),
|
||||
any(CallCredentials.MetadataApplier.class));
|
||||
|
||||
FailingClientStream stream =
|
||||
(FailingClientStream) transport.newStream(method, origHeaders, callOptions);
|
||||
FailingClientStream stream = (FailingClientStream) transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
verify(mockTransport, never()).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertEquals(Status.Code.UNAUTHENTICATED, stream.getError().getCode());
|
||||
assertSame(ex, stream.getError().getCause());
|
||||
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -193,14 +204,15 @@ public class CallCredentialsApplyingTest {
|
|||
when(mockTransport.getAttributes()).thenReturn(Attributes.EMPTY);
|
||||
|
||||
callOptions = callOptions.withCallCredentials(new FakeCallCredentials(CREDS_KEY, CREDS_VALUE));
|
||||
ClientStream stream = transport.newStream(method, origHeaders, callOptions);
|
||||
ClientStream stream = transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions, tracers);
|
||||
assertSame(mockStream, stream);
|
||||
assertEquals(CREDS_VALUE, origHeaders.get(CREDS_KEY));
|
||||
assertEquals(ORIG_HEADER_VALUE, origHeaders.get(ORIG_HEADER_KEY));
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -220,13 +232,15 @@ public class CallCredentialsApplyingTest {
|
|||
}).when(mockCreds).applyRequestMetadata(any(RequestInfo.class),
|
||||
same(mockExecutor), any(CallCredentials.MetadataApplier.class));
|
||||
|
||||
FailingClientStream stream =
|
||||
(FailingClientStream) transport.newStream(method, origHeaders, callOptions);
|
||||
FailingClientStream stream = (FailingClientStream) transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
verify(mockTransport, never()).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertSame(error, stream.getError());
|
||||
transport.shutdownNow(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdownNow(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -236,23 +250,26 @@ public class CallCredentialsApplyingTest {
|
|||
when(mockTransport.getAttributes()).thenReturn(Attributes.EMPTY);
|
||||
|
||||
// Will call applyRequestMetadata(), which is no-op.
|
||||
DelayedStream stream = (DelayedStream) transport.newStream(method, origHeaders, callOptions);
|
||||
DelayedStream stream = (DelayedStream) transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
ArgumentCaptor<CallCredentials.MetadataApplier> applierCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(any(RequestInfo.class),
|
||||
same(mockExecutor), applierCaptor.capture());
|
||||
verify(mockTransport, never()).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
verify(mockTransport, never()).shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
|
||||
Metadata headers = new Metadata();
|
||||
headers.put(CREDS_KEY, CREDS_VALUE);
|
||||
applierCaptor.getValue().apply(headers);
|
||||
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions, tracers);
|
||||
assertSame(mockStream, stream.getRealStream());
|
||||
assertEquals(CREDS_VALUE, origHeaders.get(CREDS_KEY));
|
||||
assertEquals(ORIG_HEADER_VALUE, origHeaders.get(ORIG_HEADER_KEY));
|
||||
|
|
@ -261,20 +278,20 @@ public class CallCredentialsApplyingTest {
|
|||
|
||||
@Test
|
||||
public void delayedShutdown_shutdownShutdownNowThenApply() {
|
||||
transport.newStream(method, origHeaders, callOptions);
|
||||
transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
ArgumentCaptor<CallCredentials.MetadataApplier> applierCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(any(RequestInfo.class),
|
||||
same(mockExecutor), applierCaptor.capture());
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
transport.shutdownNow(Status.ABORTED);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport, never()).shutdown(any(Status.class));
|
||||
verify(mockTransport, never()).shutdownNow(any(Status.class));
|
||||
Metadata headers = new Metadata();
|
||||
headers.put(CREDS_KEY, CREDS_VALUE);
|
||||
applierCaptor.getValue().apply(headers);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
verify(mockTransport).shutdownNow(Status.ABORTED);
|
||||
|
|
@ -282,12 +299,12 @@ public class CallCredentialsApplyingTest {
|
|||
|
||||
@Test
|
||||
public void delayedShutdown_shutdownThenApplyThenShutdownNow() {
|
||||
transport.newStream(method, origHeaders, callOptions);
|
||||
transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
ArgumentCaptor<CallCredentials.MetadataApplier> applierCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(any(RequestInfo.class),
|
||||
same(mockExecutor), applierCaptor.capture());
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport, never()).shutdown(any(Status.class));
|
||||
Metadata headers = new Metadata();
|
||||
|
|
@ -308,25 +325,25 @@ public class CallCredentialsApplyingTest {
|
|||
Metadata headers = new Metadata();
|
||||
headers.put(CREDS_KEY, CREDS_VALUE);
|
||||
|
||||
transport.newStream(method, origHeaders, callOptions);
|
||||
transport.newStream(method, origHeaders, callOptions);
|
||||
transport.newStream(method, origHeaders, callOptions);
|
||||
transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
transport.newStream(method, origHeaders, callOptions, tracers);
|
||||
ArgumentCaptor<CallCredentials.MetadataApplier> applierCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds, times(3)).applyRequestMetadata(any(RequestInfo.class),
|
||||
same(mockExecutor), applierCaptor.capture());
|
||||
applierCaptor.getAllValues().get(1).apply(headers);
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport, never()).shutdown(Status.UNAVAILABLE);
|
||||
|
||||
applierCaptor.getAllValues().get(0).apply(headers);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport, never()).shutdown(Status.UNAVAILABLE);
|
||||
|
||||
applierCaptor.getAllValues().get(2).apply(headers);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -336,7 +353,8 @@ public class CallCredentialsApplyingTest {
|
|||
when(mockTransport.getAttributes()).thenReturn(Attributes.EMPTY);
|
||||
|
||||
// Will call applyRequestMetadata(), which is no-op.
|
||||
DelayedStream stream = (DelayedStream) transport.newStream(method, origHeaders, callOptions);
|
||||
DelayedStream stream = (DelayedStream) transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
ArgumentCaptor<CallCredentials.MetadataApplier> applierCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockCreds).applyRequestMetadata(any(RequestInfo.class),
|
||||
|
|
@ -345,11 +363,13 @@ public class CallCredentialsApplyingTest {
|
|||
Status error = Status.FAILED_PRECONDITION.withDescription("channel not secure for creds");
|
||||
applierCaptor.getValue().fail(error);
|
||||
|
||||
verify(mockTransport, never()).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
FailingClientStream failingStream = (FailingClientStream) stream.getRealStream();
|
||||
assertSame(error, failingStream.getError());
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -357,14 +377,15 @@ public class CallCredentialsApplyingTest {
|
|||
@Test
|
||||
public void noCreds() {
|
||||
callOptions = callOptions.withCallCredentials(null);
|
||||
ClientStream stream = transport.newStream(method, origHeaders, callOptions);
|
||||
ClientStream stream = transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions);
|
||||
verify(mockTransport).newStream(method, origHeaders, callOptions, tracers);
|
||||
assertSame(mockStream, stream);
|
||||
assertNull(origHeaders.get(CREDS_KEY));
|
||||
assertEquals(ORIG_HEADER_VALUE, origHeaders.get(ORIG_HEADER_KEY));
|
||||
transport.shutdown(Status.UNAVAILABLE);
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions)
|
||||
assertTrue(transport.newStream(method, origHeaders, callOptions, tracers)
|
||||
instanceof FailingClientStream);
|
||||
verify(mockTransport).shutdown(Status.UNAVAILABLE);
|
||||
}
|
||||
|
|
@ -373,7 +394,8 @@ public class CallCredentialsApplyingTest {
|
|||
public void justCallOptionCreds() {
|
||||
callOptions = callOptions.withCallCredentials(new FakeCallCredentials(CREDS_KEY, CREDS_VALUE));
|
||||
|
||||
ClientStream stream = transport.newStream(method, origHeaders, callOptions);
|
||||
ClientStream stream = transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
assertSame(mockStream, stream);
|
||||
assertEquals(CREDS_VALUE, origHeaders.get(CREDS_KEY));
|
||||
|
|
@ -388,7 +410,8 @@ public class CallCredentialsApplyingTest {
|
|||
transportFactory.newClientTransport(address, clientTransportOptions, channelLogger);
|
||||
callOptions = callOptions.withCallCredentials(null);
|
||||
|
||||
ClientStream stream = transport.newStream(method, origHeaders, callOptions);
|
||||
ClientStream stream = transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
assertSame(mockStream, stream);
|
||||
assertEquals(CREDS_VALUE, origHeaders.get(CREDS_KEY));
|
||||
|
|
@ -406,7 +429,8 @@ public class CallCredentialsApplyingTest {
|
|||
String creds2Value = "some more credentials";
|
||||
callOptions = callOptions.withCallCredentials(new FakeCallCredentials(creds2Key, creds2Value));
|
||||
|
||||
ClientStream stream = transport.newStream(method, origHeaders, callOptions);
|
||||
ClientStream stream = transport.newStream(
|
||||
method, origHeaders, callOptions, tracers);
|
||||
|
||||
assertSame(mockStream, stream);
|
||||
assertEquals(CREDS_VALUE, origHeaders.get(CREDS_KEY));
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import static org.mockito.Mockito.timeout;
|
|||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
|
@ -47,6 +48,7 @@ import io.grpc.Attributes;
|
|||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientCall;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.ClientStreamTracer.StreamInfo;
|
||||
import io.grpc.Codec;
|
||||
import io.grpc.Context;
|
||||
import io.grpc.Deadline;
|
||||
|
|
@ -143,6 +145,8 @@ public class ClientCallImplTest {
|
|||
any(Metadata.class),
|
||||
any(Context.class)))
|
||||
.thenReturn(stream);
|
||||
when(streamTracerFactory.newClientStreamTracer(any(StreamInfo.class), any(Metadata.class)))
|
||||
.thenReturn(new ClientStreamTracer() {});
|
||||
doAnswer(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock in) {
|
||||
|
|
@ -156,7 +160,7 @@ public class ClientCallImplTest {
|
|||
|
||||
@After
|
||||
public void tearDown() {
|
||||
verifyNoInteractions(streamTracerFactory);
|
||||
verifyNoMoreInteractions(streamTracerFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -763,6 +767,7 @@ public class ClientCallImplTest {
|
|||
channelCallTracer, configSelector)
|
||||
.setDecompressorRegistry(decompressorRegistry);
|
||||
call.start(callListener, new Metadata());
|
||||
verify(streamTracerFactory).newClientStreamTracer(any(StreamInfo.class), any(Metadata.class));
|
||||
verify(clientStreamProvider, never())
|
||||
.newStream(
|
||||
(MethodDescriptor<?, ?>) any(MethodDescriptor.class),
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.IntegerMarshaller;
|
||||
import io.grpc.LoadBalancer.PickResult;
|
||||
import io.grpc.LoadBalancer.PickSubchannelArgs;
|
||||
|
|
@ -57,6 +58,7 @@ import org.junit.Test;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
|
|
@ -89,6 +91,9 @@ public class DelayedClientTransportTest {
|
|||
= CallOptions.Key.createWithDefault("shard-id", -1);
|
||||
private static final Status SHUTDOWN_STATUS =
|
||||
Status.UNAVAILABLE.withDescription("shutdown called");
|
||||
private static final ClientStreamTracer[] tracers = new ClientStreamTracer[] {
|
||||
new ClientStreamTracer() {}
|
||||
};
|
||||
|
||||
private final MethodDescriptor<String, Integer> method =
|
||||
MethodDescriptor.<String, Integer>newBuilder()
|
||||
|
|
@ -122,9 +127,13 @@ public class DelayedClientTransportTest {
|
|||
.thenReturn(PickResult.withSubchannel(mockSubchannel));
|
||||
when(mockSubchannel.getInternalSubchannel()).thenReturn(mockInternalSubchannel);
|
||||
when(mockInternalSubchannel.obtainActiveTransport()).thenReturn(mockRealTransport);
|
||||
when(mockRealTransport.newStream(same(method), same(headers), same(callOptions)))
|
||||
when(mockRealTransport.newStream(
|
||||
same(method), same(headers), same(callOptions),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockRealStream);
|
||||
when(mockRealTransport2.newStream(same(method2), same(headers2), same(callOptions2)))
|
||||
when(mockRealTransport2.newStream(
|
||||
same(method2), same(headers2), same(callOptions2),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockRealStream2);
|
||||
delayedTransport.start(transportListener);
|
||||
}
|
||||
|
|
@ -135,7 +144,8 @@ public class DelayedClientTransportTest {
|
|||
|
||||
@Test public void streamStartThenAssignTransport() {
|
||||
assertFalse(delayedTransport.hasPendingStreams());
|
||||
ClientStream stream = delayedTransport.newStream(method, headers, callOptions);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, headers, callOptions, tracers);
|
||||
stream.start(streamListener);
|
||||
assertEquals(1, delayedTransport.getPendingStreamsCount());
|
||||
assertTrue(delayedTransport.hasPendingStreams());
|
||||
|
|
@ -145,7 +155,9 @@ public class DelayedClientTransportTest {
|
|||
assertEquals(0, delayedTransport.getPendingStreamsCount());
|
||||
assertFalse(delayedTransport.hasPendingStreams());
|
||||
assertEquals(1, fakeExecutor.runDueTasks());
|
||||
verify(mockRealTransport).newStream(same(method), same(headers), same(callOptions));
|
||||
verify(mockRealTransport).newStream(
|
||||
same(method), same(headers), same(callOptions),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockRealStream).start(listenerCaptor.capture());
|
||||
verifyNoMoreInteractions(streamListener);
|
||||
listenerCaptor.getValue().onReady();
|
||||
|
|
@ -154,7 +166,7 @@ public class DelayedClientTransportTest {
|
|||
}
|
||||
|
||||
@Test public void newStreamThenAssignTransportThenShutdown() {
|
||||
ClientStream stream = delayedTransport.newStream(method, headers, callOptions);
|
||||
ClientStream stream = delayedTransport.newStream(method, headers, callOptions, tracers);
|
||||
assertEquals(1, delayedTransport.getPendingStreamsCount());
|
||||
assertTrue(stream instanceof DelayedStream);
|
||||
delayedTransport.reprocess(mockPicker);
|
||||
|
|
@ -163,7 +175,9 @@ public class DelayedClientTransportTest {
|
|||
verify(transportListener).transportShutdown(same(SHUTDOWN_STATUS));
|
||||
verify(transportListener).transportTerminated();
|
||||
assertEquals(0, fakeExecutor.runDueTasks());
|
||||
verify(mockRealTransport).newStream(same(method), same(headers), same(callOptions));
|
||||
verify(mockRealTransport).newStream(
|
||||
same(method), same(headers), same(callOptions),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
stream.start(streamListener);
|
||||
verify(mockRealStream).start(same(streamListener));
|
||||
}
|
||||
|
|
@ -181,11 +195,13 @@ public class DelayedClientTransportTest {
|
|||
delayedTransport.shutdown(SHUTDOWN_STATUS);
|
||||
verify(transportListener).transportShutdown(same(SHUTDOWN_STATUS));
|
||||
verify(transportListener).transportTerminated();
|
||||
ClientStream stream = delayedTransport.newStream(method, headers, callOptions);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, headers, callOptions, tracers);
|
||||
assertEquals(0, delayedTransport.getPendingStreamsCount());
|
||||
assertTrue(stream instanceof FailingClientStream);
|
||||
verify(mockRealTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
}
|
||||
|
||||
@Test public void assignTransportThenShutdownNowThenNewStream() {
|
||||
|
|
@ -193,15 +209,18 @@ public class DelayedClientTransportTest {
|
|||
delayedTransport.shutdownNow(Status.UNAVAILABLE);
|
||||
verify(transportListener).transportShutdown(any(Status.class));
|
||||
verify(transportListener).transportTerminated();
|
||||
ClientStream stream = delayedTransport.newStream(method, headers, callOptions);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, headers, callOptions, tracers);
|
||||
assertEquals(0, delayedTransport.getPendingStreamsCount());
|
||||
assertTrue(stream instanceof FailingClientStream);
|
||||
verify(mockRealTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
}
|
||||
|
||||
@Test public void startThenCancelStreamWithoutSetTransport() {
|
||||
ClientStream stream = delayedTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(streamListener);
|
||||
assertEquals(1, delayedTransport.getPendingStreamsCount());
|
||||
stream.cancel(Status.CANCELLED);
|
||||
|
|
@ -213,7 +232,8 @@ public class DelayedClientTransportTest {
|
|||
}
|
||||
|
||||
@Test public void newStreamThenShutdownTransportThenAssignTransport() {
|
||||
ClientStream stream = delayedTransport.newStream(method, headers, callOptions);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, headers, callOptions, tracers);
|
||||
stream.start(streamListener);
|
||||
delayedTransport.shutdown(SHUTDOWN_STATUS);
|
||||
|
||||
|
|
@ -225,7 +245,8 @@ public class DelayedClientTransportTest {
|
|||
// ... and will proceed if a real transport is available
|
||||
delayedTransport.reprocess(mockPicker);
|
||||
fakeExecutor.runDueTasks();
|
||||
verify(mockRealTransport).newStream(method, headers, callOptions);
|
||||
verify(mockRealTransport).newStream(
|
||||
method, headers, callOptions, tracers);
|
||||
verify(mockRealStream).start(any(ClientStreamListener.class));
|
||||
|
||||
// Since no more streams are pending, delayed transport is now terminated
|
||||
|
|
@ -233,7 +254,8 @@ public class DelayedClientTransportTest {
|
|||
verify(transportListener).transportTerminated();
|
||||
|
||||
// Further newStream() will return a failing stream
|
||||
stream = delayedTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
stream = delayedTransport.newStream(
|
||||
method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
verify(streamListener, never()).closed(
|
||||
any(Status.class), any(RpcProgress.class), any(Metadata.class));
|
||||
stream.start(streamListener);
|
||||
|
|
@ -247,7 +269,8 @@ public class DelayedClientTransportTest {
|
|||
}
|
||||
|
||||
@Test public void newStreamThenShutdownTransportThenCancelStream() {
|
||||
ClientStream stream = delayedTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
delayedTransport.shutdown(SHUTDOWN_STATUS);
|
||||
verify(transportListener).transportShutdown(same(SHUTDOWN_STATUS));
|
||||
verify(transportListener, times(0)).transportTerminated();
|
||||
|
|
@ -264,7 +287,8 @@ public class DelayedClientTransportTest {
|
|||
delayedTransport.shutdown(SHUTDOWN_STATUS);
|
||||
verify(transportListener).transportShutdown(same(SHUTDOWN_STATUS));
|
||||
verify(transportListener).transportTerminated();
|
||||
ClientStream stream = delayedTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(streamListener);
|
||||
verify(streamListener).closed(
|
||||
statusCaptor.capture(), any(RpcProgress.class), any(Metadata.class));
|
||||
|
|
@ -272,7 +296,8 @@ public class DelayedClientTransportTest {
|
|||
}
|
||||
|
||||
@Test public void startStreamThenShutdownNow() {
|
||||
ClientStream stream = delayedTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(streamListener);
|
||||
delayedTransport.shutdownNow(Status.UNAVAILABLE);
|
||||
verify(transportListener).transportShutdown(any(Status.class));
|
||||
|
|
@ -286,7 +311,8 @@ public class DelayedClientTransportTest {
|
|||
delayedTransport.shutdownNow(Status.UNAVAILABLE);
|
||||
verify(transportListener).transportShutdown(any(Status.class));
|
||||
verify(transportListener).transportTerminated();
|
||||
ClientStream stream = delayedTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(streamListener);
|
||||
verify(streamListener).closed(
|
||||
statusCaptor.capture(), any(RpcProgress.class), any(Metadata.class));
|
||||
|
|
@ -301,55 +327,59 @@ public class DelayedClientTransportTest {
|
|||
AbstractSubchannel subchannel1 = mock(AbstractSubchannel.class);
|
||||
AbstractSubchannel subchannel2 = mock(AbstractSubchannel.class);
|
||||
AbstractSubchannel subchannel3 = mock(AbstractSubchannel.class);
|
||||
when(mockRealTransport.newStream(any(MethodDescriptor.class), any(Metadata.class),
|
||||
any(CallOptions.class))).thenReturn(mockRealStream);
|
||||
when(mockRealTransport2.newStream(any(MethodDescriptor.class), any(Metadata.class),
|
||||
any(CallOptions.class))).thenReturn(mockRealStream2);
|
||||
when(mockRealTransport.newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockRealStream);
|
||||
when(mockRealTransport2.newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockRealStream2);
|
||||
when(subchannel1.getInternalSubchannel()).thenReturn(newTransportProvider(mockRealTransport));
|
||||
when(subchannel2.getInternalSubchannel()).thenReturn(newTransportProvider(mockRealTransport2));
|
||||
when(subchannel3.getInternalSubchannel()).thenReturn(newTransportProvider(null));
|
||||
|
||||
// Fail-fast streams
|
||||
DelayedStream ff1 = (DelayedStream) delayedTransport.newStream(
|
||||
method, headers, failFastCallOptions);
|
||||
method, headers, failFastCallOptions, tracers);
|
||||
ff1.start(mock(ClientStreamListener.class));
|
||||
ff1.halfClose();
|
||||
PickSubchannelArgsImpl ff1args = new PickSubchannelArgsImpl(method, headers,
|
||||
failFastCallOptions);
|
||||
verify(transportListener).transportInUse(true);
|
||||
DelayedStream ff2 = (DelayedStream) delayedTransport.newStream(
|
||||
method2, headers2, failFastCallOptions);
|
||||
method2, headers2, failFastCallOptions, tracers);
|
||||
PickSubchannelArgsImpl ff2args = new PickSubchannelArgsImpl(method2, headers2,
|
||||
failFastCallOptions);
|
||||
DelayedStream ff3 = (DelayedStream) delayedTransport.newStream(
|
||||
method, headers, failFastCallOptions);
|
||||
method, headers, failFastCallOptions, tracers);
|
||||
PickSubchannelArgsImpl ff3args = new PickSubchannelArgsImpl(method, headers,
|
||||
failFastCallOptions);
|
||||
DelayedStream ff4 = (DelayedStream) delayedTransport.newStream(
|
||||
method2, headers2, failFastCallOptions);
|
||||
method2, headers2, failFastCallOptions, tracers);
|
||||
PickSubchannelArgsImpl ff4args = new PickSubchannelArgsImpl(method2, headers2,
|
||||
failFastCallOptions);
|
||||
|
||||
// Wait-for-ready streams
|
||||
FakeClock wfr3Executor = new FakeClock();
|
||||
DelayedStream wfr1 = (DelayedStream) delayedTransport.newStream(
|
||||
method, headers, waitForReadyCallOptions);
|
||||
method, headers, waitForReadyCallOptions, tracers);
|
||||
PickSubchannelArgsImpl wfr1args = new PickSubchannelArgsImpl(method, headers,
|
||||
waitForReadyCallOptions);
|
||||
DelayedStream wfr2 = (DelayedStream) delayedTransport.newStream(
|
||||
method2, headers2, waitForReadyCallOptions);
|
||||
method2, headers2, waitForReadyCallOptions, tracers);
|
||||
PickSubchannelArgsImpl wfr2args = new PickSubchannelArgsImpl(method2, headers2,
|
||||
waitForReadyCallOptions);
|
||||
CallOptions wfr3callOptions = waitForReadyCallOptions.withExecutor(
|
||||
wfr3Executor.getScheduledExecutorService());
|
||||
DelayedStream wfr3 = (DelayedStream) delayedTransport.newStream(
|
||||
method, headers, wfr3callOptions);
|
||||
method, headers, wfr3callOptions, tracers);
|
||||
wfr3.start(mock(ClientStreamListener.class));
|
||||
wfr3.halfClose();
|
||||
PickSubchannelArgsImpl wfr3args = new PickSubchannelArgsImpl(method, headers,
|
||||
wfr3callOptions);
|
||||
DelayedStream wfr4 = (DelayedStream) delayedTransport.newStream(
|
||||
method2, headers2, waitForReadyCallOptions);
|
||||
method2, headers2, waitForReadyCallOptions, tracers);
|
||||
PickSubchannelArgsImpl wfr4args = new PickSubchannelArgsImpl(method2, headers2,
|
||||
waitForReadyCallOptions);
|
||||
|
||||
|
|
@ -386,8 +416,10 @@ public class DelayedClientTransportTest {
|
|||
// streams are now owned by a real transport (which should prevent the Channel from
|
||||
// terminating).
|
||||
// ff1 and wfr1 went through
|
||||
verify(mockRealTransport).newStream(method, headers, failFastCallOptions);
|
||||
verify(mockRealTransport2).newStream(method, headers, waitForReadyCallOptions);
|
||||
verify(mockRealTransport).newStream(
|
||||
method, headers, failFastCallOptions, tracers);
|
||||
verify(mockRealTransport2).newStream(
|
||||
method, headers, waitForReadyCallOptions, tracers);
|
||||
assertSame(mockRealStream, ff1.getRealStream());
|
||||
assertSame(mockRealStream2, wfr1.getRealStream());
|
||||
verify(mockRealStream).start(any(ClientStreamListener.class));
|
||||
|
|
@ -443,7 +475,7 @@ public class DelayedClientTransportTest {
|
|||
|
||||
// New streams will use the last picker
|
||||
DelayedStream wfr5 = (DelayedStream) delayedTransport.newStream(
|
||||
method, headers, waitForReadyCallOptions);
|
||||
method, headers, waitForReadyCallOptions, tracers);
|
||||
assertNull(wfr5.getRealStream());
|
||||
inOrder.verify(picker).pickSubchannel(
|
||||
new PickSubchannelArgsImpl(method, headers, waitForReadyCallOptions));
|
||||
|
|
@ -474,14 +506,17 @@ public class DelayedClientTransportTest {
|
|||
when(subchannel.getInternalSubchannel()).thenReturn(mockInternalSubchannel);
|
||||
when(picker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(
|
||||
PickResult.withSubchannel(subchannel));
|
||||
when(mockRealTransport.newStream(any(MethodDescriptor.class), any(Metadata.class),
|
||||
any(CallOptions.class))).thenReturn(mockRealStream);
|
||||
when(mockRealTransport.newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockRealStream);
|
||||
delayedTransport.reprocess(picker);
|
||||
verifyNoMoreInteractions(picker);
|
||||
verifyNoMoreInteractions(transportListener);
|
||||
|
||||
// Though picker was not originally used, it will be saved and serve future streams.
|
||||
ClientStream stream = delayedTransport.newStream(method, headers, CallOptions.DEFAULT);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, headers, CallOptions.DEFAULT, tracers);
|
||||
verify(picker).pickSubchannel(new PickSubchannelArgsImpl(method, headers, CallOptions.DEFAULT));
|
||||
verify(mockInternalSubchannel).obtainActiveTransport();
|
||||
assertSame(mockRealStream, stream);
|
||||
|
|
@ -519,7 +554,7 @@ public class DelayedClientTransportTest {
|
|||
@Override
|
||||
public void run() {
|
||||
// Will call pickSubchannel and wait on barrier
|
||||
delayedTransport.newStream(method, headers, callOptions);
|
||||
delayedTransport.newStream(method, headers, callOptions, tracers);
|
||||
}
|
||||
};
|
||||
sideThread.start();
|
||||
|
|
@ -552,7 +587,7 @@ public class DelayedClientTransportTest {
|
|||
@Override
|
||||
public void run() {
|
||||
// Will call pickSubchannel and wait on barrier
|
||||
delayedTransport.newStream(method, headers2, callOptions);
|
||||
delayedTransport.newStream(method, headers2, callOptions, tracers);
|
||||
}
|
||||
};
|
||||
sideThread2.start();
|
||||
|
|
@ -600,7 +635,8 @@ public class DelayedClientTransportTest {
|
|||
// Because there is no pending stream yet, it will do nothing but save the picker.
|
||||
delayedTransport.reprocess(picker);
|
||||
|
||||
ClientStream stream = delayedTransport.newStream(method, headers, callOptions);
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, headers, callOptions, tracers);
|
||||
stream.start(streamListener);
|
||||
assertTrue(delayedTransport.hasPendingStreams());
|
||||
verify(transportListener).transportInUse(true);
|
||||
|
|
@ -609,7 +645,7 @@ public class DelayedClientTransportTest {
|
|||
@Test
|
||||
public void pendingStream_appendTimeoutInsight_waitForReady() {
|
||||
ClientStream stream = delayedTransport.newStream(
|
||||
method, headers, callOptions.withWaitForReady());
|
||||
method, headers, callOptions.withWaitForReady(), tracers);
|
||||
stream.start(streamListener);
|
||||
InsightBuilder insight = new InsightBuilder();
|
||||
stream.appendTimeoutInsight(insight);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.eq;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.internal.ClientStreamListener.RpcProgress;
|
||||
|
|
@ -33,13 +34,16 @@ import org.junit.runners.JUnit4;
|
|||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class FailingClientStreamTest {
|
||||
private static final ClientStreamTracer[] tracers = new ClientStreamTracer[] {
|
||||
new ClientStreamTracer() {}
|
||||
};
|
||||
|
||||
@Test
|
||||
public void processedRpcProgressPopulatedToListener() {
|
||||
ClientStreamListener listener = mock(ClientStreamListener.class);
|
||||
Status status = Status.UNAVAILABLE;
|
||||
|
||||
ClientStream stream = new FailingClientStream(status);
|
||||
ClientStream stream = new FailingClientStream(status, RpcProgress.PROCESSED, tracers);
|
||||
stream.start(listener);
|
||||
verify(listener).closed(eq(status), eq(RpcProgress.PROCESSED), any(Metadata.class));
|
||||
}
|
||||
|
|
@ -49,7 +53,7 @@ public class FailingClientStreamTest {
|
|||
ClientStreamListener listener = mock(ClientStreamListener.class);
|
||||
Status status = Status.UNAVAILABLE;
|
||||
|
||||
ClientStream stream = new FailingClientStream(status, RpcProgress.DROPPED);
|
||||
ClientStream stream = new FailingClientStream(status, RpcProgress.DROPPED, tracers);
|
||||
stream.start(listener);
|
||||
verify(listener).closed(eq(status), eq(RpcProgress.DROPPED), any(Metadata.class));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import static org.mockito.Mockito.mock;
|
|||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.internal.ClientStreamListener.RpcProgress;
|
||||
|
|
@ -41,8 +42,9 @@ public class FailingClientTransportTest {
|
|||
Status error = Status.UNAVAILABLE;
|
||||
RpcProgress rpcProgress = RpcProgress.DROPPED;
|
||||
FailingClientTransport transport = new FailingClientTransport(error, rpcProgress);
|
||||
ClientStream stream = transport
|
||||
.newStream(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT);
|
||||
ClientStream stream = transport.newStream(
|
||||
TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT,
|
||||
new ClientStreamTracer[] { new ClientStreamTracer() {} });
|
||||
ClientStreamListener listener = mock(ClientStreamListener.class);
|
||||
stream.start(listener);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2021 The gRPC Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.internal;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.ForwardingTestUtil;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Unit tests for {@link ForwardingClientStreamTracer}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class ForwardingClientStreamTracerTest {
|
||||
private final ClientStreamTracer mockDelegate = mock(ClientStreamTracer.class);
|
||||
|
||||
@Test
|
||||
public void allMethodsForwarded() throws Exception {
|
||||
ForwardingTestUtil.testMethodsForwarded(
|
||||
ClientStreamTracer.class,
|
||||
mockDelegate,
|
||||
new ForwardingClientStreamTracerTest.TestClientStreamTracer(),
|
||||
Collections.<Method>emptyList());
|
||||
}
|
||||
|
||||
private final class TestClientStreamTracer extends ForwardingClientStreamTracer {
|
||||
@Override
|
||||
protected ClientStreamTracer delegate() {
|
||||
return mockDelegate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package io.grpc.internal;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
|
@ -27,13 +28,17 @@ import static org.mockito.ArgumentMatchers.eq;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.ClientStreamTracer.StreamInfo;
|
||||
import io.grpc.LoadBalancer.PickResult;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.internal.ClientStreamListener.RpcProgress;
|
||||
import io.grpc.internal.GrpcUtil.Http2Error;
|
||||
import io.grpc.testing.TestMethodDescriptors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
|
@ -44,6 +49,10 @@ import org.junit.runners.JUnit4;
|
|||
@RunWith(JUnit4.class)
|
||||
public class GrpcUtilTest {
|
||||
|
||||
private static final ClientStreamTracer[] tracers = new ClientStreamTracer[] {
|
||||
new ClientStreamTracer() {}
|
||||
};
|
||||
|
||||
@SuppressWarnings("deprecation") // https://github.com/grpc/grpc-java/issues/7467
|
||||
@Rule public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
|
|
@ -244,8 +253,9 @@ public class GrpcUtilTest {
|
|||
|
||||
assertNotNull(transport);
|
||||
|
||||
ClientStream stream = transport
|
||||
.newStream(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT);
|
||||
ClientStream stream = transport.newStream(
|
||||
TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT,
|
||||
tracers);
|
||||
ClientStreamListener listener = mock(ClientStreamListener.class);
|
||||
stream.start(listener);
|
||||
|
||||
|
|
@ -260,8 +270,9 @@ public class GrpcUtilTest {
|
|||
|
||||
assertNotNull(transport);
|
||||
|
||||
ClientStream stream = transport
|
||||
.newStream(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT);
|
||||
ClientStream stream = transport.newStream(
|
||||
TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT,
|
||||
tracers);
|
||||
ClientStreamListener listener = mock(ClientStreamListener.class);
|
||||
stream.start(listener);
|
||||
|
||||
|
|
@ -276,11 +287,39 @@ public class GrpcUtilTest {
|
|||
|
||||
assertNotNull(transport);
|
||||
|
||||
ClientStream stream = transport
|
||||
.newStream(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT);
|
||||
ClientStream stream = transport.newStream(
|
||||
TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT,
|
||||
tracers);
|
||||
ClientStreamListener listener = mock(ClientStreamListener.class);
|
||||
stream.start(listener);
|
||||
|
||||
verify(listener).closed(eq(status), eq(RpcProgress.DROPPED), any(Metadata.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clientStreamTracerFactoryBackwardCompatibility() {
|
||||
final AtomicReference<Attributes> transportAttrsRef = new AtomicReference<>();
|
||||
final ClientStreamTracer mockTracer = mock(ClientStreamTracer.class);
|
||||
final Metadata.Key<String> key = Metadata.Key.of("fake-key", Metadata.ASCII_STRING_MARSHALLER);
|
||||
ClientStreamTracer.Factory oldFactoryImpl = new ClientStreamTracer.Factory() {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
|
||||
transportAttrsRef.set(info.getTransportAttrs());
|
||||
headers.put(key, "fake-value");
|
||||
return mockTracer;
|
||||
}
|
||||
};
|
||||
|
||||
StreamInfo info =
|
||||
StreamInfo.newBuilder().setCallOptions(CallOptions.DEFAULT.withWaitForReady()).build();
|
||||
Metadata metadata = new Metadata();
|
||||
Attributes transAttrs =
|
||||
Attributes.newBuilder().set(Attributes.Key.<String>create("foo"), "bar").build();
|
||||
ClientStreamTracer tracer = GrpcUtil.newClientStreamTracer(oldFactoryImpl, info, metadata);
|
||||
tracer.streamCreated(transAttrs, metadata);
|
||||
|
||||
assertThat(transportAttrsRef.get()).isEqualTo(transAttrs);
|
||||
assertThat(metadata.get(key)).isEqualTo("fake-value");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ import io.grpc.ClientCall;
|
|||
import io.grpc.ClientInterceptor;
|
||||
import io.grpc.ClientInterceptors;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.ClientStreamTracer.StreamInfo;
|
||||
import io.grpc.CompositeChannelCredentials;
|
||||
import io.grpc.ConnectivityState;
|
||||
import io.grpc.ConnectivityStateInfo;
|
||||
|
|
@ -151,6 +152,7 @@ import org.junit.Test;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
|
|
@ -225,6 +227,8 @@ public class ManagedChannelImplTest {
|
|||
private ArgumentCaptor<Status> statusCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<CallOptions> callOptionsCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<ClientStreamTracer[]> tracersCaptor;
|
||||
@Mock
|
||||
private LoadBalancer mockLoadBalancer;
|
||||
@Mock
|
||||
|
|
@ -525,7 +529,9 @@ public class ManagedChannelImplTest {
|
|||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
when(mockTransport.newStream(same(method), same(headers), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), same(headers), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
transportListener.transportReady();
|
||||
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class)))
|
||||
|
|
@ -534,7 +540,9 @@ public class ManagedChannelImplTest {
|
|||
executor.runDueTasks();
|
||||
|
||||
ArgumentCaptor<CallOptions> callOptionsCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockTransport).newStream(same(method), same(headers), callOptionsCaptor.capture());
|
||||
verify(mockTransport).newStream(
|
||||
same(method), same(headers), callOptionsCaptor.capture(),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertThat(callOptionsCaptor.getValue().isWaitForReady()).isTrue();
|
||||
verify(mockStream).start(streamListenerCaptor.capture());
|
||||
|
||||
|
|
@ -600,7 +608,9 @@ public class ManagedChannelImplTest {
|
|||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
when(mockTransport.newStream(same(method), same(headers), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), same(headers), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
transportListener.transportReady();
|
||||
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class)))
|
||||
|
|
@ -609,7 +619,9 @@ public class ManagedChannelImplTest {
|
|||
executor.runDueTasks();
|
||||
|
||||
ArgumentCaptor<CallOptions> callOptionsCaptor = ArgumentCaptor.forClass(null);
|
||||
verify(mockTransport).newStream(same(method), same(headers), callOptionsCaptor.capture());
|
||||
verify(mockTransport).newStream(
|
||||
same(method), same(headers), callOptionsCaptor.capture(),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertThat(callOptionsCaptor.getValue().getOption(callOptionsKey)).isEqualTo("fooValue");
|
||||
verify(mockStream).start(streamListenerCaptor.capture());
|
||||
|
||||
|
|
@ -800,9 +812,13 @@ public class ManagedChannelImplTest {
|
|||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
verify(mockTransport).start(any(ManagedClientTransport.Listener.class));
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
when(mockTransport.newStream(same(method), same(headers), same(CallOptions.DEFAULT)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), same(headers), same(CallOptions.DEFAULT),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
when(mockTransport.newStream(same(method), same(headers2), same(CallOptions.DEFAULT)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), same(headers2), same(CallOptions.DEFAULT),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream2);
|
||||
transportListener.transportReady();
|
||||
when(mockPicker.pickSubchannel(
|
||||
|
|
@ -820,14 +836,19 @@ public class ManagedChannelImplTest {
|
|||
any(SocketAddress.class), any(ClientTransportOptions.class), any(ChannelLogger.class));
|
||||
call.start(mockCallListener, headers);
|
||||
|
||||
verify(mockTransport, never())
|
||||
.newStream(same(method), same(headers), same(CallOptions.DEFAULT));
|
||||
verify(mockTransport, never()).newStream(
|
||||
same(method), same(headers), same(CallOptions.DEFAULT),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
// Second RPC, will be assigned to the real transport
|
||||
ClientCall<String, Integer> call2 = channel.newCall(method, CallOptions.DEFAULT);
|
||||
call2.start(mockCallListener2, headers2);
|
||||
verify(mockTransport).newStream(same(method), same(headers2), same(CallOptions.DEFAULT));
|
||||
verify(mockTransport).newStream(same(method), same(headers2), same(CallOptions.DEFAULT));
|
||||
verify(mockTransport).newStream(
|
||||
same(method), same(headers2), same(CallOptions.DEFAULT),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockTransport).newStream(
|
||||
same(method), same(headers2), same(CallOptions.DEFAULT),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockStream2).start(any(ClientStreamListener.class));
|
||||
|
||||
// Shutdown
|
||||
|
|
@ -872,7 +893,9 @@ public class ManagedChannelImplTest {
|
|||
.thenReturn(PickResult.withSubchannel(subchannel));
|
||||
updateBalancingStateSafely(helper, READY, picker2);
|
||||
executor.runDueTasks();
|
||||
verify(mockTransport).newStream(same(method), same(headers), same(CallOptions.DEFAULT));
|
||||
verify(mockTransport).newStream(
|
||||
same(method), same(headers), same(CallOptions.DEFAULT),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockStream).start(any(ClientStreamListener.class));
|
||||
}
|
||||
|
||||
|
|
@ -1021,7 +1044,9 @@ public class ManagedChannelImplTest {
|
|||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
when(mockTransport.newStream(same(method), same(headers), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), same(headers), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
transportListener.transportReady();
|
||||
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class)))
|
||||
|
|
@ -1031,7 +1056,8 @@ public class ManagedChannelImplTest {
|
|||
|
||||
// Real streams are started in the call executor if they were previously buffered.
|
||||
assertEquals(1, callExecutor.runDueTasks());
|
||||
verify(mockTransport).newStream(same(method), same(headers), same(options));
|
||||
verify(mockTransport).newStream(
|
||||
same(method), same(headers), same(options), ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockStream).start(streamListenerCaptor.capture());
|
||||
|
||||
// Call listener callbacks are also run in the call executor
|
||||
|
|
@ -1298,7 +1324,8 @@ public class ManagedChannelImplTest {
|
|||
same(goodAddress), any(ClientTransportOptions.class), any(ChannelLogger.class));
|
||||
MockClientTransportInfo goodTransportInfo = transports.poll();
|
||||
when(goodTransportInfo.transport.newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class)))
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mock(ClientStream.class));
|
||||
|
||||
goodTransportInfo.listener.transportReady();
|
||||
|
|
@ -1310,11 +1337,13 @@ public class ManagedChannelImplTest {
|
|||
// Delayed transport uses the app executor to create real streams.
|
||||
executor.runDueTasks();
|
||||
|
||||
verify(goodTransportInfo.transport).newStream(same(method), same(headers),
|
||||
same(CallOptions.DEFAULT));
|
||||
verify(goodTransportInfo.transport).newStream(
|
||||
same(method), same(headers), same(CallOptions.DEFAULT),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
// The bad transport was never used.
|
||||
verify(badTransportInfo.transport, times(0)).newStream(any(MethodDescriptor.class),
|
||||
any(Metadata.class), any(CallOptions.class));
|
||||
verify(badTransportInfo.transport, times(0)).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1464,10 +1493,12 @@ public class ManagedChannelImplTest {
|
|||
// ... while the wait-for-ready call stays
|
||||
verifyNoMoreInteractions(mockCallListener);
|
||||
// No real stream was ever created
|
||||
verify(transportInfo1.transport, times(0))
|
||||
.newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
verify(transportInfo2.transport, times(0))
|
||||
.newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
verify(transportInfo1.transport, times(0)).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(transportInfo2.transport, times(0)).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1763,8 +1794,9 @@ public class ManagedChannelImplTest {
|
|||
assertEquals(0, balancerRpcExecutor.numPendingTasks());
|
||||
transportInfo.listener.transportReady();
|
||||
assertEquals(1, balancerRpcExecutor.runDueTasks());
|
||||
verify(transportInfo.transport).newStream(same(method), same(headers),
|
||||
same(CallOptions.DEFAULT));
|
||||
verify(transportInfo.transport).newStream(
|
||||
same(method), same(headers), same(CallOptions.DEFAULT),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
// The transport goes away
|
||||
transportInfo.listener.transportShutdown(Status.UNAVAILABLE);
|
||||
|
|
@ -1870,7 +1902,9 @@ public class ManagedChannelImplTest {
|
|||
ClientCall<String, Integer> call = channel.newCall(method, callOptions);
|
||||
call.start(mockCallListener, headers);
|
||||
|
||||
verify(transportInfo.transport).newStream(same(method), same(headers), same(callOptions));
|
||||
verify(transportInfo.transport).newStream(
|
||||
same(method), same(headers), same(callOptions),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertThat(headers.getAll(metadataKey))
|
||||
.containsExactly(channelCredValue, callCredValue).inOrder();
|
||||
|
||||
|
|
@ -1887,7 +1921,9 @@ public class ManagedChannelImplTest {
|
|||
transportInfo.listener.transportReady();
|
||||
balancerRpcExecutor.runDueTasks();
|
||||
|
||||
verify(transportInfo.transport).newStream(same(method), same(headers), same(callOptions));
|
||||
verify(transportInfo.transport).newStream(
|
||||
same(method), same(headers), same(callOptions),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertThat(headers.getAll(metadataKey)).containsExactly(callCredValue);
|
||||
oob.shutdownNow();
|
||||
|
||||
|
|
@ -1919,7 +1955,9 @@ public class ManagedChannelImplTest {
|
|||
call.start(mockCallListener2, headers);
|
||||
|
||||
// CallOptions may contain StreamTracerFactory for census that is added by default.
|
||||
verify(transportInfo.transport).newStream(same(method), same(headers), any(CallOptions.class));
|
||||
verify(transportInfo.transport).newStream(
|
||||
same(method), same(headers), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertThat(headers.getAll(metadataKey)).containsExactly(callCredValue);
|
||||
oob.shutdownNow();
|
||||
}
|
||||
|
|
@ -1962,7 +2000,9 @@ public class ManagedChannelImplTest {
|
|||
ClientCall<String, Integer> call = channel.newCall(method, callOptions);
|
||||
call.start(mockCallListener, headers);
|
||||
|
||||
verify(transportInfo.transport).newStream(same(method), same(headers), same(callOptions));
|
||||
verify(transportInfo.transport).newStream(
|
||||
same(method), same(headers), same(callOptions),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertThat(headers.getAll(metadataKey))
|
||||
.containsExactly(channelCredValue, callCredValue).inOrder();
|
||||
|
||||
|
|
@ -1998,7 +2038,9 @@ public class ManagedChannelImplTest {
|
|||
call.start(mockCallListener2, headers);
|
||||
|
||||
// CallOptions may contain StreamTracerFactory for census that is added by default.
|
||||
verify(transportInfo.transport).newStream(same(method), same(headers), any(CallOptions.class));
|
||||
verify(transportInfo.transport).newStream(
|
||||
same(method), same(headers), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertThat(headers.getAll(metadataKey))
|
||||
.containsExactly(oobChannelCredValue, callCredValue).inOrder();
|
||||
oob.shutdownNow();
|
||||
|
|
@ -2097,7 +2139,9 @@ public class ManagedChannelImplTest {
|
|||
|
||||
ClientCall<String, Integer> call = sChannel.newCall(method, callOptions);
|
||||
call.start(mockCallListener, headers);
|
||||
verify(mockTransport).newStream(same(method), same(headers), callOptionsCaptor.capture());
|
||||
verify(mockTransport).newStream(
|
||||
same(method), same(headers), callOptionsCaptor.capture(),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
CallOptions capturedCallOption = callOptionsCaptor.getValue();
|
||||
assertThat(capturedCallOption.getDeadline()).isSameInstanceAs(callOptions.getDeadline());
|
||||
|
|
@ -2125,7 +2169,8 @@ public class ManagedChannelImplTest {
|
|||
ClientCall<String, Integer> call = sChannel.newCall(method, CallOptions.DEFAULT);
|
||||
call.start(mockCallListener, headers);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
verifyNoInteractions(mockCallListener);
|
||||
assertEquals(1, balancerRpcExecutor.runDueTasks());
|
||||
|
|
@ -2157,7 +2202,8 @@ public class ManagedChannelImplTest {
|
|||
sChannel.newCall(method, CallOptions.DEFAULT.withWaitForReady());
|
||||
call.start(mockCallListener, headers);
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
verifyNoInteractions(mockCallListener);
|
||||
assertEquals(1, balancerRpcExecutor.runDueTasks());
|
||||
|
|
@ -2332,7 +2378,8 @@ public class ManagedChannelImplTest {
|
|||
return mock(ClientStream.class);
|
||||
}
|
||||
}).when(transport).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
verify(creds, never()).applyRequestMetadata(
|
||||
any(RequestInfo.class), any(Executor.class), any(CallCredentials.MetadataApplier.class));
|
||||
|
|
@ -2351,11 +2398,14 @@ public class ManagedChannelImplTest {
|
|||
assertEquals(AUTHORITY, infoCaptor.getValue().getAuthority());
|
||||
assertEquals(SecurityLevel.NONE, infoCaptor.getValue().getSecurityLevel());
|
||||
verify(transport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
// newStream() is called after apply() is called
|
||||
applierCaptor.getValue().apply(new Metadata());
|
||||
verify(transport).newStream(same(method), any(Metadata.class), same(callOptions));
|
||||
verify(transport).newStream(
|
||||
same(method), any(Metadata.class), same(callOptions),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertEquals("testValue", testKey.get(newStreamContexts.poll()));
|
||||
// The context should not live beyond the scope of newStream() and applyRequestMetadata()
|
||||
assertNull(testKey.get());
|
||||
|
|
@ -2374,11 +2424,14 @@ public class ManagedChannelImplTest {
|
|||
assertEquals(SecurityLevel.NONE, infoCaptor.getValue().getSecurityLevel());
|
||||
// This is from the first call
|
||||
verify(transport).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
|
||||
// Still, newStream() is called after apply() is called
|
||||
applierCaptor.getValue().apply(new Metadata());
|
||||
verify(transport, times(2)).newStream(same(method), any(Metadata.class), same(callOptions));
|
||||
verify(transport, times(2)).newStream(
|
||||
same(method), any(Metadata.class), same(callOptions),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
assertEquals("testValue", testKey.get(newStreamContexts.poll()));
|
||||
|
||||
assertNull(testKey.get());
|
||||
|
|
@ -2387,8 +2440,20 @@ public class ManagedChannelImplTest {
|
|||
@Test
|
||||
public void pickerReturnsStreamTracer_noDelay() {
|
||||
ClientStream mockStream = mock(ClientStream.class);
|
||||
ClientStreamTracer.Factory factory1 = mock(ClientStreamTracer.Factory.class);
|
||||
ClientStreamTracer.Factory factory2 = mock(ClientStreamTracer.Factory.class);
|
||||
final ClientStreamTracer tracer1 = new ClientStreamTracer() {};
|
||||
final ClientStreamTracer tracer2 = new ClientStreamTracer() {};
|
||||
ClientStreamTracer.Factory factory1 = new ClientStreamTracer.InternalLimitedInfoFactory() {
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
|
||||
return tracer1;
|
||||
}
|
||||
};
|
||||
ClientStreamTracer.Factory factory2 = new ClientStreamTracer.InternalLimitedInfoFactory() {
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
|
||||
return tracer2;
|
||||
}
|
||||
};
|
||||
createChannel();
|
||||
Subchannel subchannel =
|
||||
createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, subchannelStateListener);
|
||||
|
|
@ -2397,7 +2462,8 @@ public class ManagedChannelImplTest {
|
|||
transportInfo.listener.transportReady();
|
||||
ClientTransport mockTransport = transportInfo.transport;
|
||||
when(mockTransport.newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class)))
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
|
||||
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(
|
||||
|
|
@ -2409,20 +2475,29 @@ public class ManagedChannelImplTest {
|
|||
call.start(mockCallListener, new Metadata());
|
||||
|
||||
verify(mockPicker).pickSubchannel(any(PickSubchannelArgs.class));
|
||||
verify(mockTransport).newStream(same(method), any(Metadata.class), callOptionsCaptor.capture());
|
||||
assertEquals(
|
||||
Arrays.asList(factory1, factory2),
|
||||
callOptionsCaptor.getValue().getStreamTracerFactories());
|
||||
// The factories are safely not stubbed because we do not expect any usage of them.
|
||||
verifyNoInteractions(factory1);
|
||||
verifyNoInteractions(factory2);
|
||||
verify(mockTransport).newStream(
|
||||
same(method), any(Metadata.class), callOptionsCaptor.capture(),
|
||||
tracersCaptor.capture());
|
||||
assertThat(tracersCaptor.getValue()).isEqualTo(new ClientStreamTracer[] {tracer1, tracer2});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pickerReturnsStreamTracer_delayed() {
|
||||
ClientStream mockStream = mock(ClientStream.class);
|
||||
ClientStreamTracer.Factory factory1 = mock(ClientStreamTracer.Factory.class);
|
||||
ClientStreamTracer.Factory factory2 = mock(ClientStreamTracer.Factory.class);
|
||||
final ClientStreamTracer tracer1 = new ClientStreamTracer() {};
|
||||
final ClientStreamTracer tracer2 = new ClientStreamTracer() {};
|
||||
ClientStreamTracer.Factory factory1 = new ClientStreamTracer.InternalLimitedInfoFactory() {
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
|
||||
return tracer1;
|
||||
}
|
||||
};
|
||||
ClientStreamTracer.Factory factory2 = new ClientStreamTracer.InternalLimitedInfoFactory() {
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
|
||||
return tracer2;
|
||||
}
|
||||
};
|
||||
createChannel();
|
||||
|
||||
CallOptions callOptions = CallOptions.DEFAULT.withStreamTracerFactory(factory1);
|
||||
|
|
@ -2436,7 +2511,8 @@ public class ManagedChannelImplTest {
|
|||
transportInfo.listener.transportReady();
|
||||
ClientTransport mockTransport = transportInfo.transport;
|
||||
when(mockTransport.newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class)))
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(
|
||||
PickResult.withSubchannel(subchannel, factory2));
|
||||
|
|
@ -2445,13 +2521,10 @@ public class ManagedChannelImplTest {
|
|||
assertEquals(1, executor.runDueTasks());
|
||||
|
||||
verify(mockPicker).pickSubchannel(any(PickSubchannelArgs.class));
|
||||
verify(mockTransport).newStream(same(method), any(Metadata.class), callOptionsCaptor.capture());
|
||||
assertEquals(
|
||||
Arrays.asList(factory1, factory2),
|
||||
callOptionsCaptor.getValue().getStreamTracerFactories());
|
||||
// The factories are safely not stubbed because we do not expect any usage of them.
|
||||
verifyNoInteractions(factory1);
|
||||
verifyNoInteractions(factory2);
|
||||
verify(mockTransport).newStream(
|
||||
same(method), any(Metadata.class), callOptionsCaptor.capture(),
|
||||
tracersCaptor.capture());
|
||||
assertThat(tracersCaptor.getValue()).isEqualTo(new ClientStreamTracer[] {tracer1, tracer2});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -2818,7 +2891,9 @@ public class ManagedChannelImplTest {
|
|||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
transportListener.transportReady();
|
||||
|
||||
|
|
@ -2829,7 +2904,9 @@ public class ManagedChannelImplTest {
|
|||
executor.runDueTasks();
|
||||
|
||||
// Verify the buffered call was drained
|
||||
verify(mockTransport).newStream(same(method), any(Metadata.class), any(CallOptions.class));
|
||||
verify(mockTransport).newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockStream).start(any(ClientStreamListener.class));
|
||||
}
|
||||
|
||||
|
|
@ -2888,7 +2965,9 @@ public class ManagedChannelImplTest {
|
|||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
transportListener.transportReady();
|
||||
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class)))
|
||||
|
|
@ -2898,7 +2977,9 @@ public class ManagedChannelImplTest {
|
|||
|
||||
// Verify the original call was drained
|
||||
executor.runDueTasks();
|
||||
verify(mockTransport).newStream(same(method), any(Metadata.class), any(CallOptions.class));
|
||||
verify(mockTransport).newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockStream).start(any(ClientStreamListener.class));
|
||||
}
|
||||
|
||||
|
|
@ -2920,7 +3001,9 @@ public class ManagedChannelImplTest {
|
|||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
transportListener.transportReady();
|
||||
|
||||
|
|
@ -2929,8 +3012,9 @@ public class ManagedChannelImplTest {
|
|||
updateBalancingStateSafely(helper, READY, mockPicker);
|
||||
|
||||
executor.runDueTasks();
|
||||
verify(mockTransport, never())
|
||||
.newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class));
|
||||
verify(mockTransport, never()).newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockStream, never()).start(any(ClientStreamListener.class));
|
||||
|
||||
|
||||
|
|
@ -2939,7 +3023,9 @@ public class ManagedChannelImplTest {
|
|||
updateBalancingStateSafely(helper, READY, mockPicker);
|
||||
|
||||
executor.runDueTasks();
|
||||
verify(mockTransport).newStream(same(method), any(Metadata.class), any(CallOptions.class));
|
||||
verify(mockTransport).newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockStream).start(any(ClientStreamListener.class));
|
||||
}
|
||||
|
||||
|
|
@ -2958,7 +3044,9 @@ public class ManagedChannelImplTest {
|
|||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
transportListener.transportReady();
|
||||
|
||||
|
|
@ -2973,7 +3061,9 @@ public class ManagedChannelImplTest {
|
|||
updateBalancingStateSafely(helper, READY, mockPicker);
|
||||
|
||||
executor.runDueTasks();
|
||||
verify(mockTransport).newStream(same(method), any(Metadata.class), any(CallOptions.class));
|
||||
verify(mockTransport).newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any());
|
||||
verify(mockStream).start(any(ClientStreamListener.class));
|
||||
}
|
||||
|
||||
|
|
@ -3405,7 +3495,8 @@ public class ManagedChannelImplTest {
|
|||
transportInfo.listener.transportReady();
|
||||
ClientTransport mockTransport = transportInfo.transport;
|
||||
when(mockTransport.newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class)))
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(
|
||||
PickResult.withSubchannel(subchannel, factory));
|
||||
|
|
@ -3478,7 +3569,9 @@ public class ManagedChannelImplTest {
|
|||
MockClientTransportInfo transportInfo = transports.poll();
|
||||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ManagedClientTransport.Listener transportListener = transportInfo.listener;
|
||||
when(mockTransport.newStream(same(method), same(headers), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), same(headers), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream);
|
||||
|
||||
// subchannel stat bumped when call gets assigned to it
|
||||
|
|
@ -3650,7 +3743,9 @@ public class ManagedChannelImplTest {
|
|||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ClientStream mockStream = mock(ClientStream.class);
|
||||
ClientStream mockStream2 = mock(ClientStream.class);
|
||||
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream).thenReturn(mockStream2);
|
||||
transportInfo.listener.transportReady();
|
||||
updateBalancingStateSafely(helper, READY, mockPicker);
|
||||
|
|
@ -3754,7 +3849,9 @@ public class ManagedChannelImplTest {
|
|||
ConnectionClientTransport mockTransport = transportInfo.transport;
|
||||
ClientStream mockStream = mock(ClientStream.class);
|
||||
ClientStream mockStream2 = mock(ClientStream.class);
|
||||
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
|
||||
when(mockTransport.newStream(
|
||||
same(method), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mockStream).thenReturn(mockStream2);
|
||||
transportInfo.listener.transportReady();
|
||||
updateBalancingStateSafely(helper, READY, mockPicker);
|
||||
|
|
|
|||
|
|
@ -163,9 +163,10 @@ public class RetriableStreamTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
ClientStream newSubstream(ClientStreamTracer.Factory tracerFactory, Metadata metadata) {
|
||||
ClientStream newSubstream(
|
||||
Metadata metadata, ClientStreamTracer.Factory tracerFactory, boolean isTransparentRetry) {
|
||||
bufferSizeTracer =
|
||||
tracerFactory.newClientStreamTracer(STREAM_INFO, new Metadata());
|
||||
tracerFactory.newClientStreamTracer(STREAM_INFO, metadata);
|
||||
int actualPreviousRpcAttemptsInHeader = metadata.get(GRPC_PREVIOUS_RPC_ATTEMPTS) == null
|
||||
? 0 : Integer.valueOf(metadata.get(GRPC_PREVIOUS_RPC_ATTEMPTS));
|
||||
return retriableStreamRecorder.newSubstream(actualPreviousRpcAttemptsInHeader);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ChannelLogger;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.InternalLogId;
|
||||
import io.grpc.LoadBalancer.PickResult;
|
||||
import io.grpc.LoadBalancer.PickSubchannelArgs;
|
||||
|
|
@ -35,6 +36,7 @@ import java.net.SocketAddress;
|
|||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import javax.annotation.Nullable;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
|
|
@ -118,7 +120,8 @@ public final class TestUtils {
|
|||
when(mockTransport.getLogId())
|
||||
.thenReturn(InternalLogId.allocate("mocktransport", /*details=*/ null));
|
||||
when(mockTransport.newStream(
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class)))
|
||||
any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class),
|
||||
ArgumentMatchers.<ClientStreamTracer[]>any()))
|
||||
.thenReturn(mock(ClientStream.class));
|
||||
// Save the listener
|
||||
doAnswer(new Answer<Runnable>() {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ public class ForwardingClientStreamTracerTest {
|
|||
Collections.<Method>emptyList());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private final class TestClientStreamTracer extends ForwardingClientStreamTracer {
|
||||
@Override
|
||||
protected ClientStreamTracer delegate() {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
import com.google.common.util.concurrent.SettableFuture;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
import io.grpc.InternalLogId;
|
||||
import io.grpc.Metadata;
|
||||
|
|
@ -118,7 +119,7 @@ class CronetClientTransport implements ConnectionClientTransport {
|
|||
|
||||
@Override
|
||||
public CronetClientStream newStream(final MethodDescriptor<?, ?> method, final Metadata headers,
|
||||
final CallOptions callOptions) {
|
||||
final CallOptions callOptions, ClientStreamTracer[] tracers) {
|
||||
Preconditions.checkNotNull(method, "method");
|
||||
Preconditions.checkNotNull(headers, "headers");
|
||||
|
||||
|
|
@ -126,7 +127,7 @@ class CronetClientTransport implements ConnectionClientTransport {
|
|||
final String url = "https://" + authority + defaultPath;
|
||||
|
||||
final StatsTraceContext statsTraceCtx =
|
||||
StatsTraceContext.newClientContext(callOptions, attrs, headers);
|
||||
StatsTraceContext.newClientContext(tracers, attrs, headers);
|
||||
class StartCallback implements Runnable {
|
||||
final CronetClientStream clientStream = new CronetClientStream(
|
||||
url, userAgent, executor, headers, CronetClientTransport.this, this, lock, maxMessageSize,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import static org.mockito.Mockito.mock;
|
|||
import android.os.Build;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ChannelLogger;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor;
|
||||
import io.grpc.cronet.CronetChannelBuilder.CronetTransportFactory;
|
||||
|
|
@ -50,6 +51,8 @@ public final class CronetChannelBuilderTest {
|
|||
@Mock private ExperimentalCronetEngine mockEngine;
|
||||
@Mock private ChannelLogger channelLogger;
|
||||
|
||||
private final ClientStreamTracer[] tracers =
|
||||
new ClientStreamTracer[]{ new ClientStreamTracer() {} };
|
||||
private MethodDescriptor<?, ?> method = TestMethodDescriptors.voidMethod();
|
||||
|
||||
@Before
|
||||
|
|
@ -69,7 +72,8 @@ public final class CronetChannelBuilderTest {
|
|||
new InetSocketAddress("localhost", 443),
|
||||
new ClientTransportOptions(),
|
||||
channelLogger);
|
||||
CronetClientStream stream = transport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
CronetClientStream stream = transport.newStream(
|
||||
method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
|
||||
assertTrue(stream.idempotent);
|
||||
}
|
||||
|
|
@ -85,7 +89,8 @@ public final class CronetChannelBuilderTest {
|
|||
new InetSocketAddress("localhost", 443),
|
||||
new ClientTransportOptions(),
|
||||
channelLogger);
|
||||
CronetClientStream stream = transport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
CronetClientStream stream = transport.newStream(
|
||||
method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
|
||||
assertFalse(stream.idempotent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import static org.mockito.Mockito.when;
|
|||
import android.os.Build;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor;
|
||||
import io.grpc.SecurityLevel;
|
||||
|
|
@ -60,6 +61,8 @@ public final class CronetClientTransportTest {
|
|||
private static final Attributes EAG_ATTRS =
|
||||
Attributes.newBuilder().set(EAG_ATTR_KEY, "value").build();
|
||||
|
||||
private final ClientStreamTracer[] tracers =
|
||||
new ClientStreamTracer[]{ new ClientStreamTracer() {} };
|
||||
private CronetClientTransport transport;
|
||||
@Mock private StreamBuilderFactory streamFactory;
|
||||
@Mock private Executor executor;
|
||||
|
|
@ -101,9 +104,9 @@ public final class CronetClientTransportTest {
|
|||
@Test
|
||||
public void shutdownTransport() throws Exception {
|
||||
CronetClientStream stream1 =
|
||||
transport.newStream(descriptor, new Metadata(), CallOptions.DEFAULT);
|
||||
transport.newStream(descriptor, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
CronetClientStream stream2 =
|
||||
transport.newStream(descriptor, new Metadata(), CallOptions.DEFAULT);
|
||||
transport.newStream(descriptor, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
|
||||
// Create a transport and start two streams on it.
|
||||
ArgumentCaptor<BidirectionalStream.Callback> callbackCaptor =
|
||||
|
|
@ -137,7 +140,7 @@ public final class CronetClientTransportTest {
|
|||
@Test
|
||||
public void startStreamAfterShutdown() throws Exception {
|
||||
CronetClientStream stream =
|
||||
transport.newStream(descriptor, new Metadata(), CallOptions.DEFAULT);
|
||||
transport.newStream(descriptor, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
transport.shutdown();
|
||||
BaseClientStreamListener listener = new BaseClientStreamListener();
|
||||
stream.start(listener);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||
* span of an LB stream with the remote load-balancer.
|
||||
*/
|
||||
@ThreadSafe
|
||||
final class GrpclbClientLoadRecorder extends ClientStreamTracer.Factory {
|
||||
final class GrpclbClientLoadRecorder extends ClientStreamTracer.InternalLimitedInfoFactory {
|
||||
|
||||
private static final AtomicLongFieldUpdater<GrpclbClientLoadRecorder> callsStartedUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(GrpclbClientLoadRecorder.class, "callsStarted");
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.google.common.base.Objects;
|
|||
import io.grpc.Attributes;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.internal.ForwardingClientStreamTracer;
|
||||
import io.grpc.internal.GrpcAttributes;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ import javax.annotation.Nullable;
|
|||
* Wraps a {@link ClientStreamTracer.Factory}, retrieves tokens from transport attributes and
|
||||
* attaches them to headers. This is only used in the PICK_FIRST mode.
|
||||
*/
|
||||
final class TokenAttachingTracerFactory extends ClientStreamTracer.Factory {
|
||||
final class TokenAttachingTracerFactory extends ClientStreamTracer.InternalLimitedInfoFactory {
|
||||
private static final ClientStreamTracer NOOP_TRACER = new ClientStreamTracer() {};
|
||||
|
||||
@Nullable
|
||||
|
|
@ -42,19 +43,30 @@ final class TokenAttachingTracerFactory extends ClientStreamTracer.Factory {
|
|||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(
|
||||
ClientStreamTracer.StreamInfo info, Metadata headers) {
|
||||
Attributes transportAttrs = checkNotNull(info.getTransportAttrs(), "transportAttrs");
|
||||
Attributes eagAttrs =
|
||||
checkNotNull(transportAttrs.get(GrpcAttributes.ATTR_CLIENT_EAG_ATTRS), "eagAttrs");
|
||||
String token = eagAttrs.get(GrpclbConstants.TOKEN_ATTRIBUTE_KEY);
|
||||
headers.discardAll(GrpclbConstants.TOKEN_METADATA_KEY);
|
||||
if (token != null) {
|
||||
headers.put(GrpclbConstants.TOKEN_METADATA_KEY, token);
|
||||
}
|
||||
if (delegate != null) {
|
||||
return delegate.newClientStreamTracer(info, headers);
|
||||
} else {
|
||||
if (delegate == null) {
|
||||
return NOOP_TRACER;
|
||||
}
|
||||
final ClientStreamTracer clientStreamTracer = delegate.newClientStreamTracer(info, headers);
|
||||
class TokenPropagationTracer extends ForwardingClientStreamTracer {
|
||||
@Override
|
||||
protected ClientStreamTracer delegate() {
|
||||
return clientStreamTracer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamCreated(Attributes transportAttrs, Metadata headers) {
|
||||
Attributes eagAttrs =
|
||||
checkNotNull(transportAttrs.get(GrpcAttributes.ATTR_CLIENT_EAG_ATTRS), "eagAttrs");
|
||||
String token = eagAttrs.get(GrpclbConstants.TOKEN_ATTRIBUTE_KEY);
|
||||
headers.discardAll(GrpclbConstants.TOKEN_METADATA_KEY);
|
||||
if (token != null) {
|
||||
headers.put(GrpclbConstants.TOKEN_METADATA_KEY, token);
|
||||
}
|
||||
delegate().streamCreated(transportAttrs, headers);
|
||||
}
|
||||
}
|
||||
|
||||
return new TokenPropagationTracer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -481,6 +481,7 @@ public class GrpclbLoadBalancerTest {
|
|||
|
||||
ClientStreamTracer tracer1 =
|
||||
pick1.getStreamTracerFactory().newClientStreamTracer(STREAM_INFO, new Metadata());
|
||||
tracer1.streamCreated(Attributes.EMPTY, new Metadata());
|
||||
|
||||
PickResult pick2 = picker.pickSubchannel(args);
|
||||
assertNull(pick2.getSubchannel());
|
||||
|
|
@ -504,6 +505,7 @@ public class GrpclbLoadBalancerTest {
|
|||
assertSame(getLoadRecorder(), pick3.getStreamTracerFactory());
|
||||
ClientStreamTracer tracer3 =
|
||||
pick3.getStreamTracerFactory().newClientStreamTracer(STREAM_INFO, new Metadata());
|
||||
tracer3.streamCreated(Attributes.EMPTY, new Metadata());
|
||||
|
||||
// pick3 has sent out headers
|
||||
tracer3.outboundHeaders();
|
||||
|
|
@ -541,6 +543,7 @@ public class GrpclbLoadBalancerTest {
|
|||
assertSame(getLoadRecorder(), pick5.getStreamTracerFactory());
|
||||
ClientStreamTracer tracer5 =
|
||||
pick5.getStreamTracerFactory().newClientStreamTracer(STREAM_INFO, new Metadata());
|
||||
tracer5.streamCreated(Attributes.EMPTY, new Metadata());
|
||||
|
||||
// pick3 ended without receiving response headers
|
||||
tracer3.streamClosed(Status.DEADLINE_EXCEEDED);
|
||||
|
|
|
|||
|
|
@ -33,12 +33,23 @@ import org.junit.runners.JUnit4;
|
|||
/** Unit tests for {@link TokenAttachingTracerFactory}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class TokenAttachingTracerFactoryTest {
|
||||
private static final ClientStreamTracer fakeTracer = new ClientStreamTracer() {};
|
||||
private static final class FakeClientStreamTracer extends ClientStreamTracer {
|
||||
Attributes transportAttrs;
|
||||
Metadata headers;
|
||||
|
||||
@Override
|
||||
public void streamCreated(Attributes transportAttrs, Metadata headers) {
|
||||
this.transportAttrs = transportAttrs;
|
||||
this.headers = headers;
|
||||
}
|
||||
}
|
||||
|
||||
private static final FakeClientStreamTracer fakeTracer = new FakeClientStreamTracer();
|
||||
|
||||
private final ClientStreamTracer.Factory delegate = mock(
|
||||
ClientStreamTracer.Factory.class,
|
||||
delegatesTo(
|
||||
new ClientStreamTracer.Factory() {
|
||||
new ClientStreamTracer.InternalLimitedInfoFactory() {
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(
|
||||
ClientStreamTracer.StreamInfo info, Metadata headers) {
|
||||
|
|
@ -51,28 +62,25 @@ public class TokenAttachingTracerFactoryTest {
|
|||
TokenAttachingTracerFactory factory = new TokenAttachingTracerFactory(delegate);
|
||||
Attributes eagAttrs = Attributes.newBuilder()
|
||||
.set(GrpclbConstants.TOKEN_ATTRIBUTE_KEY, "token0001").build();
|
||||
ClientStreamTracer.StreamInfo info = ClientStreamTracer.StreamInfo.newBuilder()
|
||||
.setTransportAttrs(
|
||||
Attributes.newBuilder().set(GrpcAttributes.ATTR_CLIENT_EAG_ATTRS, eagAttrs).build())
|
||||
.build();
|
||||
ClientStreamTracer.StreamInfo info = ClientStreamTracer.StreamInfo.newBuilder().build();
|
||||
Metadata headers = new Metadata();
|
||||
// Preexisting token should be replaced
|
||||
headers.put(GrpclbConstants.TOKEN_METADATA_KEY, "preexisting-token");
|
||||
|
||||
ClientStreamTracer tracer = factory.newClientStreamTracer(info, headers);
|
||||
verify(delegate).newClientStreamTracer(same(info), same(headers));
|
||||
assertThat(tracer).isSameInstanceAs(fakeTracer);
|
||||
Attributes transportAttrs =
|
||||
Attributes.newBuilder().set(GrpcAttributes.ATTR_CLIENT_EAG_ATTRS, eagAttrs).build();
|
||||
tracer.streamCreated(transportAttrs, headers);
|
||||
assertThat(fakeTracer.transportAttrs).isSameInstanceAs(transportAttrs);
|
||||
assertThat(fakeTracer.headers).isSameInstanceAs(headers);
|
||||
assertThat(headers.getAll(GrpclbConstants.TOKEN_METADATA_KEY)).containsExactly("token0001");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noToken() {
|
||||
TokenAttachingTracerFactory factory = new TokenAttachingTracerFactory(delegate);
|
||||
ClientStreamTracer.StreamInfo info = ClientStreamTracer.StreamInfo.newBuilder()
|
||||
.setTransportAttrs(
|
||||
Attributes.newBuilder()
|
||||
.set(GrpcAttributes.ATTR_CLIENT_EAG_ATTRS, Attributes.EMPTY).build())
|
||||
.build();
|
||||
ClientStreamTracer.StreamInfo info = ClientStreamTracer.StreamInfo.newBuilder().build();
|
||||
|
||||
Metadata headers = new Metadata();
|
||||
// Preexisting token should be removed
|
||||
|
|
@ -80,22 +88,25 @@ public class TokenAttachingTracerFactoryTest {
|
|||
|
||||
ClientStreamTracer tracer = factory.newClientStreamTracer(info, headers);
|
||||
verify(delegate).newClientStreamTracer(same(info), same(headers));
|
||||
assertThat(tracer).isSameInstanceAs(fakeTracer);
|
||||
Attributes transportAttrs =
|
||||
Attributes.newBuilder().set(GrpcAttributes.ATTR_CLIENT_EAG_ATTRS, Attributes.EMPTY).build();
|
||||
tracer.streamCreated(transportAttrs, headers);
|
||||
assertThat(fakeTracer.transportAttrs).isSameInstanceAs(transportAttrs);
|
||||
assertThat(fakeTracer.headers).isSameInstanceAs(headers);
|
||||
assertThat(headers.get(GrpclbConstants.TOKEN_METADATA_KEY)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullDelegate() {
|
||||
TokenAttachingTracerFactory factory = new TokenAttachingTracerFactory(null);
|
||||
ClientStreamTracer.StreamInfo info = ClientStreamTracer.StreamInfo.newBuilder()
|
||||
.setTransportAttrs(
|
||||
Attributes.newBuilder()
|
||||
.set(GrpcAttributes.ATTR_CLIENT_EAG_ATTRS, Attributes.EMPTY).build())
|
||||
.build();
|
||||
ClientStreamTracer.StreamInfo info = ClientStreamTracer.StreamInfo.newBuilder().build();
|
||||
|
||||
Metadata headers = new Metadata();
|
||||
|
||||
ClientStreamTracer tracer = factory.newClientStreamTracer(info, headers);
|
||||
tracer.streamCreated(
|
||||
Attributes.newBuilder().set(GrpcAttributes.ATTR_CLIENT_EAG_ATTRS, Attributes.EMPTY).build(),
|
||||
headers);
|
||||
assertThat(tracer).isNotNull();
|
||||
assertThat(headers.get(GrpclbConstants.TOKEN_METADATA_KEY)).isNull();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ public abstract class AbstractInteropTest {
|
|||
new LinkedBlockingQueue<>();
|
||||
|
||||
private final ClientStreamTracer.Factory clientStreamTracerFactory =
|
||||
new ClientStreamTracer.Factory() {
|
||||
new ClientStreamTracer.InternalLimitedInfoFactory() {
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(
|
||||
ClientStreamTracer.StreamInfo info, Metadata headers) {
|
||||
|
|
@ -375,7 +375,8 @@ public abstract class AbstractInteropTest {
|
|||
.getClientInterceptor(
|
||||
tagger, tagContextBinarySerializer, clientStatsRecorder,
|
||||
GrpcUtil.STOPWATCH_SUPPLIER,
|
||||
true, true, true, false /* real-time metrics */);
|
||||
true, true, true,
|
||||
/* recordRealTimeMetrics= */ false);
|
||||
}
|
||||
|
||||
protected final ServerStreamTracer.Factory createCustomCensusTracerFactory() {
|
||||
|
|
@ -1179,6 +1180,7 @@ public abstract class AbstractInteropTest {
|
|||
public void deadlineExceededServerStreaming() throws Exception {
|
||||
// warm up the channel and JVM
|
||||
blockingStub.emptyCall(Empty.getDefaultInstance());
|
||||
assertStatsTrace("grpc.testing.TestService/EmptyCall", Status.Code.OK);
|
||||
ResponseParameters.Builder responseParameters = ResponseParameters.newBuilder()
|
||||
.setSize(1)
|
||||
.setIntervalUs(10000);
|
||||
|
|
@ -1195,7 +1197,6 @@ public abstract class AbstractInteropTest {
|
|||
recorder.awaitCompletion();
|
||||
assertEquals(Status.DEADLINE_EXCEEDED.getCode(),
|
||||
Status.fromThrowable(recorder.getError()).getCode());
|
||||
assertStatsTrace("grpc.testing.TestService/EmptyCall", Status.Code.OK);
|
||||
if (metricsExpected()) {
|
||||
// Stream may not have been created when deadline is exceeded, thus we don't check tracer
|
||||
// stats.
|
||||
|
|
@ -1239,6 +1240,12 @@ public abstract class AbstractInteropTest {
|
|||
|
||||
// warm up the channel
|
||||
blockingStub.emptyCall(Empty.getDefaultInstance());
|
||||
if (metricsExpected()) {
|
||||
// clientStartRecord
|
||||
clientStatsRecorder.pollRecord(5, TimeUnit.SECONDS);
|
||||
// clientEndRecord
|
||||
clientStatsRecorder.pollRecord(5, TimeUnit.SECONDS);
|
||||
}
|
||||
try {
|
||||
blockingStub
|
||||
.withDeadlineAfter(-10, TimeUnit.SECONDS)
|
||||
|
|
@ -1249,7 +1256,6 @@ public abstract class AbstractInteropTest {
|
|||
assertThat(ex.getStatus().getDescription())
|
||||
.startsWith("ClientCall started after deadline exceeded");
|
||||
}
|
||||
assertStatsTrace("grpc.testing.TestService/EmptyCall", Status.Code.OK);
|
||||
if (metricsExpected()) {
|
||||
MetricsRecord clientStartRecord = clientStatsRecorder.pollRecord(5, TimeUnit.SECONDS);
|
||||
checkStartTags(clientStartRecord, "grpc.testing.TestService/EmptyCall", true);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import com.google.common.util.concurrent.SettableFuture;
|
|||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ChannelLogger;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
import io.grpc.InternalLogId;
|
||||
import io.grpc.Metadata;
|
||||
|
|
@ -167,14 +168,15 @@ class NettyClientTransport implements ConnectionClientTransport {
|
|||
|
||||
@Override
|
||||
public ClientStream newStream(
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions) {
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
Preconditions.checkNotNull(method, "method");
|
||||
Preconditions.checkNotNull(headers, "headers");
|
||||
if (channel == null) {
|
||||
return new FailingClientStream(statusExplainingWhyTheChannelIsNull);
|
||||
return new FailingClientStream(statusExplainingWhyTheChannelIsNull, tracers);
|
||||
}
|
||||
StatsTraceContext statsTraceCtx =
|
||||
StatsTraceContext.newClientContext(callOptions, getAttributes(), headers);
|
||||
StatsTraceContext.newClientContext(tracers, getAttributes(), headers);
|
||||
return new NettyClientStream(
|
||||
new NettyClientStream.TransportState(
|
||||
handler,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import com.google.common.util.concurrent.SettableFuture;
|
|||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ChannelLogger;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.InternalChannelz;
|
||||
import io.grpc.Metadata;
|
||||
|
|
@ -828,7 +829,9 @@ public class NettyClientTransportTest {
|
|||
}
|
||||
|
||||
Rpc(NettyClientTransport transport, Metadata headers) {
|
||||
stream = transport.newStream(METHOD, headers, CallOptions.DEFAULT);
|
||||
stream = transport.newStream(
|
||||
METHOD, headers, CallOptions.DEFAULT,
|
||||
new ClientStreamTracer[]{ new ClientStreamTracer() {} });
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
stream.writeMessage(new ByteArrayInputStream(MESSAGE.getBytes(UTF_8)));
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import com.squareup.okhttp.Request;
|
|||
import com.squareup.okhttp.internal.http.StatusLine;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.HttpConnectProxiedSocketAddress;
|
||||
import io.grpc.InternalChannelz;
|
||||
|
|
@ -387,12 +388,13 @@ class OkHttpClientTransport implements ConnectionClientTransport, TransportExcep
|
|||
}
|
||||
|
||||
@Override
|
||||
public OkHttpClientStream newStream(final MethodDescriptor<?, ?> method,
|
||||
final Metadata headers, CallOptions callOptions) {
|
||||
public OkHttpClientStream newStream(
|
||||
MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
|
||||
ClientStreamTracer[] tracers) {
|
||||
Preconditions.checkNotNull(method, "method");
|
||||
Preconditions.checkNotNull(headers, "headers");
|
||||
StatsTraceContext statsTraceCtx =
|
||||
StatsTraceContext.newClientContext(callOptions, attributes, headers);
|
||||
StatsTraceContext statsTraceContext =
|
||||
StatsTraceContext.newClientContext(tracers, getAttributes(), headers);
|
||||
// FIXME: it is likely wrong to pass the transportTracer here as it'll exit the lock's scope
|
||||
synchronized (lock) { // to make @GuardedBy linter happy
|
||||
return new OkHttpClientStream(
|
||||
|
|
@ -406,7 +408,7 @@ class OkHttpClientTransport implements ConnectionClientTransport, TransportExcep
|
|||
initialWindowSize,
|
||||
defaultAuthority,
|
||||
userAgent,
|
||||
statsTraceCtx,
|
||||
statsTraceContext,
|
||||
transportTracer,
|
||||
callOptions,
|
||||
useGetForSafeMethods);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ import com.google.common.util.concurrent.MoreExecutors;
|
|||
import com.google.common.util.concurrent.SettableFuture;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.HttpConnectProxiedSocketAddress;
|
||||
import io.grpc.InternalChannelz.SocketStats;
|
||||
import io.grpc.InternalChannelz.TransportStats;
|
||||
|
|
@ -146,6 +147,9 @@ public class OkHttpClientTransportTest {
|
|||
private static final int DEFAULT_MAX_INBOUND_METADATA_SIZE = Integer.MAX_VALUE;
|
||||
private static final Attributes EAG_ATTRS = Attributes.EMPTY;
|
||||
private static final Logger logger = Logger.getLogger(OkHttpClientTransport.class.getName());
|
||||
private static final ClientStreamTracer[] tracers = new ClientStreamTracer[] {
|
||||
new ClientStreamTracer() {}
|
||||
};
|
||||
|
||||
@Rule public final Timeout globalTimeout = Timeout.seconds(10);
|
||||
|
||||
|
|
@ -299,7 +303,7 @@ public class OkHttpClientTransportTest {
|
|||
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
|
||||
|
|
@ -387,7 +391,7 @@ public class OkHttpClientTransportTest {
|
|||
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
assertContainStream(3);
|
||||
|
|
@ -443,11 +447,11 @@ public class OkHttpClientTransportTest {
|
|||
MockStreamListener listener1 = new MockStreamListener();
|
||||
MockStreamListener listener2 = new MockStreamListener();
|
||||
OkHttpClientStream stream1 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream1.start(listener1);
|
||||
stream1.request(1);
|
||||
OkHttpClientStream stream2 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream2.start(listener2);
|
||||
stream2.request(1);
|
||||
assertEquals(2, activeStreamCount());
|
||||
|
|
@ -477,7 +481,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
assertEquals(1, activeStreamCount());
|
||||
|
|
@ -498,7 +502,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
frameReader.nextFrameAtEndOfStream();
|
||||
|
|
@ -516,7 +520,7 @@ public class OkHttpClientTransportTest {
|
|||
final String message = "Hello Client";
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(numMessages);
|
||||
assertContainStream(3);
|
||||
|
|
@ -566,7 +570,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
assertContainStream(3);
|
||||
|
|
@ -590,7 +594,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
assertContainStream(3);
|
||||
|
|
@ -610,7 +614,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
assertContainStream(3);
|
||||
frameHandler().headers(true, true, 3, 0, grpcResponseTrailers(), HeadersMode.HTTP_20_HEADERS);
|
||||
|
|
@ -624,7 +628,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
assertContainStream(3);
|
||||
frameHandler().rstStream(3, ErrorCode.PROTOCOL_ERROR);
|
||||
|
|
@ -641,7 +645,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
assertContainStream(3);
|
||||
frameHandler().headers(false, false, 3, 0, grpcResponseHeaders(), HeadersMode.HTTP_20_HEADERS);
|
||||
|
|
@ -661,7 +665,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
getStream(3).cancel(Status.CANCELLED);
|
||||
verify(frameWriter, timeout(TIME_OUT_MS)).rstStream(eq(3), eq(ErrorCode.CANCEL));
|
||||
|
|
@ -676,7 +680,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
Header userAgentHeader = new Header(GrpcUtil.USER_AGENT_KEY.name(),
|
||||
GrpcUtil.getGrpcUserAgent("okhttp", null));
|
||||
|
|
@ -695,7 +699,7 @@ public class OkHttpClientTransportTest {
|
|||
startTransport(3, null, true, DEFAULT_MAX_MESSAGE_SIZE, INITIAL_WINDOW_SIZE, "fakeUserAgent");
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
List<Header> expectedHeaders = Arrays.asList(HTTP_SCHEME_HEADER, METHOD_HEADER,
|
||||
new Header(Header.TARGET_AUTHORITY, "notarealauthority:80"),
|
||||
|
|
@ -714,7 +718,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
getStream(3).cancel(Status.DEADLINE_EXCEEDED);
|
||||
verify(frameWriter, timeout(TIME_OUT_MS)).rstStream(eq(3), eq(ErrorCode.CANCEL));
|
||||
|
|
@ -728,7 +732,7 @@ public class OkHttpClientTransportTest {
|
|||
final String message = "Hello Server";
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
InputStream input = new ByteArrayInputStream(message.getBytes(UTF_8));
|
||||
assertEquals(12, input.available());
|
||||
|
|
@ -772,12 +776,12 @@ public class OkHttpClientTransportTest {
|
|||
MockStreamListener listener1 = new MockStreamListener();
|
||||
MockStreamListener listener2 = new MockStreamListener();
|
||||
OkHttpClientStream stream1 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream1.start(listener1);
|
||||
stream1.request(2);
|
||||
|
||||
OkHttpClientStream stream2 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream2.start(listener2);
|
||||
stream2.request(2);
|
||||
assertEquals(2, activeStreamCount());
|
||||
|
|
@ -838,7 +842,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
int messageLength = INITIAL_WINDOW_SIZE / 2 + 1;
|
||||
byte[] fakeMessage = new byte[messageLength];
|
||||
|
|
@ -874,7 +878,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
|
||||
// Outbound window always starts at 65535 until changed by Settings.INITIAL_WINDOW_SIZE
|
||||
|
|
@ -920,7 +924,7 @@ public class OkHttpClientTransportTest {
|
|||
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
|
||||
int messageLength = 75;
|
||||
|
|
@ -963,7 +967,7 @@ public class OkHttpClientTransportTest {
|
|||
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
|
||||
int messageLength = 100000;
|
||||
|
|
@ -999,7 +1003,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
int messageLength = 20;
|
||||
setInitialWindowSize(HEADER_LENGTH + 10);
|
||||
|
|
@ -1045,7 +1049,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
int messageLength = 20;
|
||||
setInitialWindowSize(HEADER_LENGTH + 10);
|
||||
|
|
@ -1080,10 +1084,10 @@ public class OkHttpClientTransportTest {
|
|||
MockStreamListener listener1 = new MockStreamListener();
|
||||
MockStreamListener listener2 = new MockStreamListener();
|
||||
OkHttpClientStream stream1 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream1.start(listener1);
|
||||
OkHttpClientStream stream2 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream2.start(listener2);
|
||||
assertEquals(2, activeStreamCount());
|
||||
clientTransport.shutdown(SHUTDOWN_REASON);
|
||||
|
|
@ -1110,11 +1114,11 @@ public class OkHttpClientTransportTest {
|
|||
MockStreamListener listener1 = new MockStreamListener();
|
||||
MockStreamListener listener2 = new MockStreamListener();
|
||||
OkHttpClientStream stream1 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream1.start(listener1);
|
||||
stream1.request(1);
|
||||
OkHttpClientStream stream2 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream2.start(listener2);
|
||||
stream2.request(1);
|
||||
assertEquals(2, activeStreamCount());
|
||||
|
|
@ -1168,7 +1172,7 @@ public class OkHttpClientTransportTest {
|
|||
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
|
||||
|
|
@ -1204,11 +1208,11 @@ public class OkHttpClientTransportTest {
|
|||
final MockStreamListener listener1 = new MockStreamListener();
|
||||
final MockStreamListener listener2 = new MockStreamListener();
|
||||
OkHttpClientStream stream1 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream1.start(listener1);
|
||||
// The second stream should be pending.
|
||||
OkHttpClientStream stream2 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream2.start(listener2);
|
||||
String sentMessage = "hello";
|
||||
InputStream input = new ByteArrayInputStream(sentMessage.getBytes(UTF_8));
|
||||
|
|
@ -1241,7 +1245,7 @@ public class OkHttpClientTransportTest {
|
|||
setMaxConcurrentStreams(0);
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
waitForStreamPending(1);
|
||||
stream.cancel(Status.CANCELLED);
|
||||
|
|
@ -1260,11 +1264,11 @@ public class OkHttpClientTransportTest {
|
|||
final MockStreamListener listener1 = new MockStreamListener();
|
||||
final MockStreamListener listener2 = new MockStreamListener();
|
||||
OkHttpClientStream stream1 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream1.start(listener1);
|
||||
// The second stream should be pending.
|
||||
OkHttpClientStream stream2 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream2.start(listener2);
|
||||
|
||||
waitForStreamPending(1);
|
||||
|
|
@ -1290,7 +1294,7 @@ public class OkHttpClientTransportTest {
|
|||
final MockStreamListener listener = new MockStreamListener();
|
||||
// The second stream should be pending.
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
waitForStreamPending(1);
|
||||
|
||||
|
|
@ -1314,15 +1318,15 @@ public class OkHttpClientTransportTest {
|
|||
final MockStreamListener listener3 = new MockStreamListener();
|
||||
|
||||
OkHttpClientStream stream1 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream1.start(listener1);
|
||||
|
||||
// The second and third stream should be pending.
|
||||
OkHttpClientStream stream2 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream2.start(listener2);
|
||||
OkHttpClientStream stream3 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream3.start(listener3);
|
||||
|
||||
waitForStreamPending(2);
|
||||
|
|
@ -1346,7 +1350,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
|
||||
|
|
@ -1398,7 +1402,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
verify(frameWriter, timeout(TIME_OUT_MS)).synStream(
|
||||
eq(false), eq(false), eq(3), eq(0), ArgumentMatchers.<Header>anyList());
|
||||
|
|
@ -1415,7 +1419,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
Buffer buffer = createMessageFrame(new byte[1]);
|
||||
|
|
@ -1437,7 +1441,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
Buffer buffer = createMessageFrame(new byte[1]);
|
||||
|
|
@ -1459,7 +1463,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.request(1);
|
||||
Buffer buffer = createMessageFrame(new byte[1000]);
|
||||
|
|
@ -1480,7 +1484,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.cancel(Status.CANCELLED);
|
||||
|
||||
|
|
@ -1507,7 +1511,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
stream.cancel(Status.CANCELLED);
|
||||
// This should be ignored.
|
||||
|
|
@ -1527,7 +1531,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransport();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
assertTrue(stream.isReady());
|
||||
assertTrue(listener.isOnReadyCalled());
|
||||
|
|
@ -1545,7 +1549,7 @@ public class OkHttpClientTransportTest {
|
|||
setInitialWindowSize(0);
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
assertTrue(stream.isReady());
|
||||
// Be notified at the beginning.
|
||||
|
|
@ -1695,7 +1699,7 @@ public class OkHttpClientTransportTest {
|
|||
final String message = "Hello Server";
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
InputStream input = new ByteArrayInputStream(message.getBytes(UTF_8));
|
||||
stream.writeMessage(input);
|
||||
|
|
@ -1720,7 +1724,7 @@ public class OkHttpClientTransportTest {
|
|||
final String message = "Hello Server";
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
InputStream input = new ByteArrayInputStream(message.getBytes(UTF_8));
|
||||
stream.writeMessage(input);
|
||||
|
|
@ -1738,7 +1742,7 @@ public class OkHttpClientTransportTest {
|
|||
initTransportAndDelayConnected();
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
clientTransport.shutdown(SHUTDOWN_REASON);
|
||||
allowTransportConnected();
|
||||
|
|
@ -1810,7 +1814,8 @@ public class OkHttpClientTransportTest {
|
|||
assertTrue(status.getCause().toString(), status.getCause() instanceof IOException);
|
||||
|
||||
MockStreamListener streamListener = new MockStreamListener();
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT).start(streamListener);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers)
|
||||
.start(streamListener);
|
||||
streamListener.waitUntilStreamClosed();
|
||||
assertEquals(Status.UNAVAILABLE.getCode(), streamListener.status.getCode());
|
||||
}
|
||||
|
|
@ -2054,13 +2059,13 @@ public class OkHttpClientTransportTest {
|
|||
MockStreamListener listener2 = new MockStreamListener();
|
||||
MockStreamListener listener3 = new MockStreamListener();
|
||||
OkHttpClientStream stream1 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream1.start(listener1);
|
||||
OkHttpClientStream stream2 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream2.start(listener2);
|
||||
OkHttpClientStream stream3 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream3.start(listener3);
|
||||
waitForStreamPending(1);
|
||||
|
||||
|
|
@ -2094,13 +2099,13 @@ public class OkHttpClientTransportTest {
|
|||
MockStreamListener listener2 = new MockStreamListener();
|
||||
MockStreamListener listener3 = new MockStreamListener();
|
||||
OkHttpClientStream stream1 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream1.start(listener1);
|
||||
OkHttpClientStream stream2 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream2.start(listener2);
|
||||
OkHttpClientStream stream3 =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream3.start(listener3);
|
||||
|
||||
assertEquals(3, activeStreamCount());
|
||||
|
|
@ -2158,7 +2163,7 @@ public class OkHttpClientTransportTest {
|
|||
private void assertNewStreamFail() throws Exception {
|
||||
MockStreamListener listener = new MockStreamListener();
|
||||
OkHttpClientStream stream =
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT);
|
||||
clientTransport.newStream(method, new Metadata(), CallOptions.DEFAULT, tracers);
|
||||
stream.start(listener);
|
||||
listener.waitUntilStreamClosed();
|
||||
assertFalse(listener.status.isOk());
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ import io.grpc.InternalLogId;
|
|||
import io.grpc.LoadBalancer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.internal.ForwardingClientStreamTracer;
|
||||
import io.grpc.internal.ObjectPool;
|
||||
import io.grpc.util.ForwardingClientStreamTracer;
|
||||
import io.grpc.util.ForwardingLoadBalancerHelper;
|
||||
import io.grpc.util.ForwardingSubchannel;
|
||||
import io.grpc.xds.ClusterImplLoadBalancerProvider.ClusterImplConfig;
|
||||
|
|
@ -329,7 +329,8 @@ final class ClusterImplLoadBalancer extends LoadBalancer {
|
|||
}
|
||||
}
|
||||
|
||||
private static final class CountingStreamTracerFactory extends ClientStreamTracer.Factory {
|
||||
private static final class CountingStreamTracerFactory extends
|
||||
ClientStreamTracer.InternalLimitedInfoFactory {
|
||||
private ClusterLocalityStats stats;
|
||||
private final AtomicLong inFlights;
|
||||
@Nullable
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ import io.grpc.ClientStreamTracer;
|
|||
import io.grpc.ClientStreamTracer.StreamInfo;
|
||||
import io.grpc.LoadBalancer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.internal.ForwardingClientStreamTracer;
|
||||
import io.grpc.protobuf.ProtoUtils;
|
||||
import io.grpc.util.ForwardingClientStreamTracer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ import java.util.List;
|
|||
abstract class OrcaPerRequestUtil {
|
||||
private static final ClientStreamTracer NOOP_CLIENT_STREAM_TRACER = new ClientStreamTracer() {};
|
||||
private static final ClientStreamTracer.Factory NOOP_CLIENT_STREAM_TRACER_FACTORY =
|
||||
new ClientStreamTracer.Factory() {
|
||||
new ClientStreamTracer.InternalLimitedInfoFactory() {
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
|
||||
return NOOP_CLIENT_STREAM_TRACER;
|
||||
|
|
@ -189,7 +189,8 @@ abstract class OrcaPerRequestUtil {
|
|||
* per-request ORCA reports and push to registered listeners for calls they trace.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static final class OrcaReportingTracerFactory extends ClientStreamTracer.Factory {
|
||||
static final class OrcaReportingTracerFactory extends
|
||||
ClientStreamTracer.InternalLimitedInfoFactory {
|
||||
|
||||
@VisibleForTesting
|
||||
static final Metadata.Key<OrcaLoadReport> ORCA_ENDPOINT_LOAD_METRICS_KEY =
|
||||
|
|
|
|||
|
|
@ -341,8 +341,8 @@ public class ClusterImplLoadBalancerTest {
|
|||
PickResult result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
|
||||
assertThat(result.getStatus().isOk()).isTrue();
|
||||
ClientStreamTracer.Factory streamTracerFactory = result.getStreamTracerFactory();
|
||||
streamTracerFactory.newClientStreamTracer(ClientStreamTracer.StreamInfo.newBuilder().build(),
|
||||
new Metadata());
|
||||
streamTracerFactory.newClientStreamTracer(
|
||||
ClientStreamTracer.StreamInfo.newBuilder().build(), new Metadata());
|
||||
}
|
||||
ClusterStats clusterStats =
|
||||
Iterables.getOnlyElement(loadStatsManager.getClusterStatsReports(CLUSTER));
|
||||
|
|
@ -429,8 +429,8 @@ public class ClusterImplLoadBalancerTest {
|
|||
PickResult result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
|
||||
assertThat(result.getStatus().isOk()).isTrue();
|
||||
ClientStreamTracer.Factory streamTracerFactory = result.getStreamTracerFactory();
|
||||
streamTracerFactory.newClientStreamTracer(ClientStreamTracer.StreamInfo.newBuilder().build(),
|
||||
new Metadata());
|
||||
streamTracerFactory.newClientStreamTracer(
|
||||
ClientStreamTracer.StreamInfo.newBuilder().build(), new Metadata());
|
||||
}
|
||||
ClusterStats clusterStats =
|
||||
Iterables.getOnlyElement(loadStatsManager.getClusterStatsReports(CLUSTER));
|
||||
|
|
|
|||
Loading…
Reference in New Issue