mirror of https://github.com/grpc/grpc-java.git
core,grpclb: use denser atomics for census
This commit is contained in:
parent
72f6d9bc08
commit
95a2723ea5
|
|
@ -46,9 +46,9 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
|
@ -115,7 +115,7 @@ final class CensusStatsModule {
|
|||
*/
|
||||
@VisibleForTesting
|
||||
ClientCallTracer newClientCallTracer(StatsContext parentCtx, String fullMethodName) {
|
||||
return new ClientCallTracer(parentCtx, fullMethodName);
|
||||
return new ClientCallTracer(this, parentCtx, fullMethodName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -133,57 +133,81 @@ final class CensusStatsModule {
|
|||
}
|
||||
|
||||
private static final class ClientTracer extends ClientStreamTracer {
|
||||
final AtomicLong outboundMessageCount = new AtomicLong();
|
||||
final AtomicLong inboundMessageCount = new AtomicLong();
|
||||
final AtomicLong outboundWireSize = new AtomicLong();
|
||||
final AtomicLong inboundWireSize = new AtomicLong();
|
||||
final AtomicLong outboundUncompressedSize = new AtomicLong();
|
||||
final AtomicLong inboundUncompressedSize = new AtomicLong();
|
||||
|
||||
private static final AtomicLongFieldUpdater<ClientTracer> outboundMessageCountUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ClientTracer.class, "outboundMessageCount");
|
||||
private static final AtomicLongFieldUpdater<ClientTracer> inboundMessageCountUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ClientTracer.class, "inboundMessageCount");
|
||||
private static final AtomicLongFieldUpdater<ClientTracer> outboundWireSizeUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ClientTracer.class, "outboundWireSize");
|
||||
private static final AtomicLongFieldUpdater<ClientTracer> inboundWireSizeUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ClientTracer.class, "inboundWireSize");
|
||||
private static final AtomicLongFieldUpdater<ClientTracer> outboundUncompressedSizeUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ClientTracer.class, "outboundUncompressedSize");
|
||||
private static final AtomicLongFieldUpdater<ClientTracer> inboundUncompressedSizeUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ClientTracer.class, "inboundUncompressedSize");
|
||||
|
||||
volatile long outboundMessageCount;
|
||||
volatile long inboundMessageCount;
|
||||
volatile long outboundWireSize;
|
||||
volatile long inboundWireSize;
|
||||
volatile long outboundUncompressedSize;
|
||||
volatile long inboundUncompressedSize;
|
||||
|
||||
@Override
|
||||
public void outboundWireSize(long bytes) {
|
||||
outboundWireSize.addAndGet(bytes);
|
||||
outboundWireSizeUpdater.getAndAdd(this, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundWireSize(long bytes) {
|
||||
inboundWireSize.addAndGet(bytes);
|
||||
inboundWireSizeUpdater.getAndAdd(this, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundUncompressedSize(long bytes) {
|
||||
outboundUncompressedSize.addAndGet(bytes);
|
||||
outboundUncompressedSizeUpdater.getAndAdd(this, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundUncompressedSize(long bytes) {
|
||||
inboundUncompressedSize.addAndGet(bytes);
|
||||
inboundUncompressedSizeUpdater.getAndAdd(this, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundMessage(int seqNo) {
|
||||
inboundMessageCount.incrementAndGet();
|
||||
inboundMessageCountUpdater.getAndIncrement(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundMessage(int seqNo) {
|
||||
outboundMessageCount.incrementAndGet();
|
||||
outboundMessageCountUpdater.getAndIncrement(this);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
final class ClientCallTracer extends ClientStreamTracer.Factory {
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
static final class ClientCallTracer extends ClientStreamTracer.Factory {
|
||||
private static final AtomicReferenceFieldUpdater<ClientCallTracer, ClientTracer>
|
||||
streamTracerUpdater =
|
||||
AtomicReferenceFieldUpdater.newUpdater(
|
||||
ClientCallTracer.class, ClientTracer.class, "streamTracer");
|
||||
private static final AtomicIntegerFieldUpdater<ClientCallTracer> callEndedUpdater =
|
||||
AtomicIntegerFieldUpdater.newUpdater(ClientCallTracer.class, "callEnded");
|
||||
|
||||
private final CensusStatsModule module;
|
||||
private final String fullMethodName;
|
||||
private final Stopwatch stopwatch;
|
||||
private final AtomicReference<ClientTracer> streamTracer = new AtomicReference<ClientTracer>();
|
||||
private final AtomicBoolean callEnded = new AtomicBoolean(false);
|
||||
private volatile ClientTracer streamTracer;
|
||||
private volatile int callEnded;
|
||||
private final StatsContext parentCtx;
|
||||
|
||||
ClientCallTracer(StatsContext parentCtx, String fullMethodName) {
|
||||
ClientCallTracer(CensusStatsModule module, StatsContext parentCtx, String fullMethodName) {
|
||||
this.module = module;
|
||||
this.parentCtx = checkNotNull(parentCtx, "parentCtx");
|
||||
this.fullMethodName = checkNotNull(fullMethodName, "fullMethodName");
|
||||
this.stopwatch = stopwatchSupplier.get().start();
|
||||
this.stopwatch = module.stopwatchSupplier.get().start();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -191,12 +215,13 @@ final class CensusStatsModule {
|
|||
ClientTracer tracer = new ClientTracer();
|
||||
// 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.
|
||||
checkState(streamTracer.compareAndSet(null, tracer),
|
||||
checkState(
|
||||
streamTracerUpdater.compareAndSet(this, null, tracer),
|
||||
"Are you creating multiple streams per call? This class doesn't yet support this case.");
|
||||
if (propagateTags) {
|
||||
headers.discardAll(statsHeader);
|
||||
if (parentCtx != statsCtxFactory.getDefault()) {
|
||||
headers.put(statsHeader, parentCtx);
|
||||
if (module.propagateTags) {
|
||||
headers.discardAll(module.statsHeader);
|
||||
if (parentCtx != module.statsCtxFactory.getDefault()) {
|
||||
headers.put(module.statsHeader, parentCtx);
|
||||
}
|
||||
}
|
||||
return tracer;
|
||||
|
|
@ -209,28 +234,28 @@ final class CensusStatsModule {
|
|||
* is a no-op.
|
||||
*/
|
||||
void callEnded(Status status) {
|
||||
if (!callEnded.compareAndSet(false, true)) {
|
||||
if (callEndedUpdater.getAndSet(this, 1) != 0) {
|
||||
return;
|
||||
}
|
||||
stopwatch.stop();
|
||||
long roundtripNanos = stopwatch.elapsed(TimeUnit.NANOSECONDS);
|
||||
ClientTracer tracer = streamTracer.get();
|
||||
ClientTracer tracer = streamTracer;
|
||||
if (tracer == null) {
|
||||
tracer = BLANK_CLIENT_TRACER;
|
||||
}
|
||||
MeasurementMap.Builder builder = MeasurementMap.builder()
|
||||
// The metrics are in double
|
||||
.put(RpcConstants.RPC_CLIENT_ROUNDTRIP_LATENCY, roundtripNanos / NANOS_PER_MILLI)
|
||||
.put(RpcConstants.RPC_CLIENT_REQUEST_COUNT, tracer.outboundMessageCount.get())
|
||||
.put(RpcConstants.RPC_CLIENT_RESPONSE_COUNT, tracer.inboundMessageCount.get())
|
||||
.put(RpcConstants.RPC_CLIENT_REQUEST_BYTES, tracer.outboundWireSize.get())
|
||||
.put(RpcConstants.RPC_CLIENT_RESPONSE_BYTES, tracer.inboundWireSize.get())
|
||||
.put(RpcConstants.RPC_CLIENT_REQUEST_COUNT, tracer.outboundMessageCount)
|
||||
.put(RpcConstants.RPC_CLIENT_RESPONSE_COUNT, tracer.inboundMessageCount)
|
||||
.put(RpcConstants.RPC_CLIENT_REQUEST_BYTES, tracer.outboundWireSize)
|
||||
.put(RpcConstants.RPC_CLIENT_RESPONSE_BYTES, tracer.inboundWireSize)
|
||||
.put(
|
||||
RpcConstants.RPC_CLIENT_UNCOMPRESSED_REQUEST_BYTES,
|
||||
tracer.outboundUncompressedSize.get())
|
||||
tracer.outboundUncompressedSize)
|
||||
.put(
|
||||
RpcConstants.RPC_CLIENT_UNCOMPRESSED_RESPONSE_BYTES,
|
||||
tracer.inboundUncompressedSize.get());
|
||||
tracer.inboundUncompressedSize);
|
||||
if (!status.isOk()) {
|
||||
builder.put(RpcConstants.RPC_CLIENT_ERROR_COUNT, 1.0);
|
||||
}
|
||||
|
|
@ -242,53 +267,74 @@ final class CensusStatsModule {
|
|||
}
|
||||
}
|
||||
|
||||
private final class ServerTracer extends ServerStreamTracer {
|
||||
private static final class ServerTracer extends ServerStreamTracer {
|
||||
private static final AtomicIntegerFieldUpdater<ServerTracer> streamClosedUpdater =
|
||||
AtomicIntegerFieldUpdater.newUpdater(ServerTracer.class, "streamClosed");
|
||||
private static final AtomicLongFieldUpdater<ServerTracer> outboundMessageCountUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ServerTracer.class, "outboundMessageCount");
|
||||
private static final AtomicLongFieldUpdater<ServerTracer> inboundMessageCountUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ServerTracer.class, "inboundMessageCount");
|
||||
private static final AtomicLongFieldUpdater<ServerTracer> outboundWireSizeUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ServerTracer.class, "outboundWireSize");
|
||||
private static final AtomicLongFieldUpdater<ServerTracer> inboundWireSizeUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ServerTracer.class, "inboundWireSize");
|
||||
private static final AtomicLongFieldUpdater<ServerTracer> outboundUncompressedSizeUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ServerTracer.class, "outboundUncompressedSize");
|
||||
private static final AtomicLongFieldUpdater<ServerTracer> inboundUncompressedSizeUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(ServerTracer.class, "inboundUncompressedSize");
|
||||
|
||||
private final String fullMethodName;
|
||||
@Nullable
|
||||
private final StatsContext parentCtx;
|
||||
private final AtomicBoolean streamClosed = new AtomicBoolean(false);
|
||||
private volatile int streamClosed;
|
||||
private final Stopwatch stopwatch;
|
||||
private final AtomicLong outboundMessageCount = new AtomicLong();
|
||||
private final AtomicLong inboundMessageCount = new AtomicLong();
|
||||
private final AtomicLong outboundWireSize = new AtomicLong();
|
||||
private final AtomicLong inboundWireSize = new AtomicLong();
|
||||
private final AtomicLong outboundUncompressedSize = new AtomicLong();
|
||||
private final AtomicLong inboundUncompressedSize = new AtomicLong();
|
||||
private final StatsContextFactory statsCtxFactory;
|
||||
private volatile long outboundMessageCount;
|
||||
private volatile long inboundMessageCount;
|
||||
private volatile long outboundWireSize;
|
||||
private volatile long inboundWireSize;
|
||||
private volatile long outboundUncompressedSize;
|
||||
private volatile long inboundUncompressedSize;
|
||||
|
||||
ServerTracer(String fullMethodName, StatsContext parentCtx) {
|
||||
ServerTracer(
|
||||
String fullMethodName,
|
||||
StatsContext parentCtx,
|
||||
Supplier<Stopwatch> stopwatchSupplier,
|
||||
StatsContextFactory statsCtxFactory) {
|
||||
this.fullMethodName = checkNotNull(fullMethodName, "fullMethodName");
|
||||
this.parentCtx = checkNotNull(parentCtx, "parentCtx");
|
||||
this.stopwatch = stopwatchSupplier.get().start();
|
||||
this.statsCtxFactory = statsCtxFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundWireSize(long bytes) {
|
||||
outboundWireSize.addAndGet(bytes);
|
||||
outboundWireSizeUpdater.getAndAdd(this, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundWireSize(long bytes) {
|
||||
inboundWireSize.addAndGet(bytes);
|
||||
inboundWireSizeUpdater.getAndAdd(this, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundUncompressedSize(long bytes) {
|
||||
outboundUncompressedSize.addAndGet(bytes);
|
||||
outboundUncompressedSizeUpdater.getAndAdd(this, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundUncompressedSize(long bytes) {
|
||||
inboundUncompressedSize.addAndGet(bytes);
|
||||
inboundUncompressedSizeUpdater.getAndAdd(this, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundMessage(int seqNo) {
|
||||
inboundMessageCount.incrementAndGet();
|
||||
inboundMessageCountUpdater.getAndIncrement(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outboundMessage(int seqNo) {
|
||||
outboundMessageCount.incrementAndGet();
|
||||
outboundMessageCountUpdater.getAndIncrement(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -299,7 +345,7 @@ final class CensusStatsModule {
|
|||
*/
|
||||
@Override
|
||||
public void streamClosed(Status status) {
|
||||
if (!streamClosed.compareAndSet(false, true)) {
|
||||
if (streamClosedUpdater.getAndSet(this, 1) != 0) {
|
||||
return;
|
||||
}
|
||||
stopwatch.stop();
|
||||
|
|
@ -307,16 +353,12 @@ final class CensusStatsModule {
|
|||
MeasurementMap.Builder builder = MeasurementMap.builder()
|
||||
// The metrics are in double
|
||||
.put(RpcConstants.RPC_SERVER_SERVER_LATENCY, elapsedTimeNanos / NANOS_PER_MILLI)
|
||||
.put(RpcConstants.RPC_SERVER_RESPONSE_COUNT, outboundMessageCount.get())
|
||||
.put(RpcConstants.RPC_SERVER_REQUEST_COUNT, inboundMessageCount.get())
|
||||
.put(RpcConstants.RPC_SERVER_RESPONSE_BYTES, outboundWireSize.get())
|
||||
.put(RpcConstants.RPC_SERVER_REQUEST_BYTES, inboundWireSize.get())
|
||||
.put(
|
||||
RpcConstants.RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES,
|
||||
outboundUncompressedSize.get())
|
||||
.put(
|
||||
RpcConstants.RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES,
|
||||
inboundUncompressedSize.get());
|
||||
.put(RpcConstants.RPC_SERVER_RESPONSE_COUNT, outboundMessageCount)
|
||||
.put(RpcConstants.RPC_SERVER_REQUEST_COUNT, inboundMessageCount)
|
||||
.put(RpcConstants.RPC_SERVER_RESPONSE_BYTES, outboundWireSize)
|
||||
.put(RpcConstants.RPC_SERVER_REQUEST_BYTES, inboundWireSize)
|
||||
.put(RpcConstants.RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES, outboundUncompressedSize)
|
||||
.put(RpcConstants.RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES, inboundUncompressedSize);
|
||||
if (!status.isOk()) {
|
||||
builder.put(RpcConstants.RPC_SERVER_ERROR_COUNT, 1.0);
|
||||
}
|
||||
|
|
@ -344,7 +386,7 @@ final class CensusStatsModule {
|
|||
parentCtx = statsCtxFactory.getDefault();
|
||||
}
|
||||
parentCtx = parentCtx.with(RpcConstants.RPC_SERVER_METHOD, TagValue.create(fullMethodName));
|
||||
return new ServerTracer(fullMethodName, parentCtx);
|
||||
return new ServerTracer(fullMethodName, parentCtx, stopwatchSupplier, statsCtxFactory);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import io.opencensus.trace.export.SampledSpanStore;
|
|||
import io.opencensus.trace.propagation.BinaryFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
|
@ -63,6 +63,10 @@ import javax.annotation.Nullable;
|
|||
*/
|
||||
final class CensusTracingModule {
|
||||
private static final Logger logger = Logger.getLogger(CensusTracingModule.class.getName());
|
||||
private static final AtomicIntegerFieldUpdater<ClientCallTracer> callEndedUpdater =
|
||||
AtomicIntegerFieldUpdater.newUpdater(ClientCallTracer.class, "callEnded");
|
||||
private static final AtomicIntegerFieldUpdater<ServerTracer> streamClosedUpdater =
|
||||
AtomicIntegerFieldUpdater.newUpdater(ServerTracer.class, "streamClosed");
|
||||
|
||||
private final Tracer censusTracer;
|
||||
@VisibleForTesting
|
||||
|
|
@ -216,8 +220,8 @@ final class CensusTracingModule {
|
|||
|
||||
@VisibleForTesting
|
||||
final class ClientCallTracer extends ClientStreamTracer.Factory {
|
||||
volatile int callEnded;
|
||||
|
||||
private final AtomicBoolean callEnded = new AtomicBoolean(false);
|
||||
private final Span span;
|
||||
|
||||
ClientCallTracer(@Nullable Span parentSpan, String fullMethodName) {
|
||||
|
|
@ -245,7 +249,7 @@ final class CensusTracingModule {
|
|||
* is a no-op.
|
||||
*/
|
||||
void callEnded(io.grpc.Status status) {
|
||||
if (!callEnded.compareAndSet(false, true)) {
|
||||
if (callEndedUpdater.getAndSet(this, 1) != 0) {
|
||||
return;
|
||||
}
|
||||
span.end(createEndSpanOptions(status));
|
||||
|
|
@ -274,9 +278,10 @@ final class CensusTracingModule {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private final class ServerTracer extends ServerStreamTracer {
|
||||
private final Span span;
|
||||
private final AtomicBoolean streamClosed = new AtomicBoolean(false);
|
||||
volatile int streamClosed;
|
||||
|
||||
ServerTracer(String fullMethodName, @Nullable SpanContext remoteSpan) {
|
||||
checkNotNull(fullMethodName, "fullMethodName");
|
||||
|
|
@ -297,7 +302,7 @@ final class CensusTracingModule {
|
|||
*/
|
||||
@Override
|
||||
public void streamClosed(io.grpc.Status status) {
|
||||
if (!streamClosed.compareAndSet(false, true)) {
|
||||
if (streamClosedUpdater.getAndSet(this, 1) != 0) {
|
||||
return;
|
||||
}
|
||||
span.end(createEndSpanOptions(status));
|
||||
|
|
|
|||
|
|
@ -23,10 +23,11 @@ import io.grpc.CallOptions;
|
|||
import io.grpc.ClientStreamTracer;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.Status;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
|
|
@ -36,17 +37,35 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||
*/
|
||||
@ThreadSafe
|
||||
final class GrpclbClientLoadRecorder extends ClientStreamTracer.Factory {
|
||||
|
||||
private static final AtomicLongFieldUpdater<GrpclbClientLoadRecorder> callsStartedUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(GrpclbClientLoadRecorder.class, "callsStarted");
|
||||
private static final AtomicLongFieldUpdater<GrpclbClientLoadRecorder> callsFinishedUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(GrpclbClientLoadRecorder.class, "callsFinished");
|
||||
private static final AtomicLongFieldUpdater<GrpclbClientLoadRecorder> callsFailedToSendUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(GrpclbClientLoadRecorder.class, "callsFailedToSend");
|
||||
private static final AtomicLongFieldUpdater<GrpclbClientLoadRecorder>
|
||||
callsFinishedKnownReceivedUpdater =
|
||||
AtomicLongFieldUpdater.newUpdater(
|
||||
GrpclbClientLoadRecorder.class, "callsFinishedKnownReceived");
|
||||
|
||||
private final TimeProvider time;
|
||||
private final AtomicLong callsStarted = new AtomicLong();
|
||||
private final AtomicLong callsFinished = new AtomicLong();
|
||||
@SuppressWarnings("unused")
|
||||
private volatile long callsStarted;
|
||||
@SuppressWarnings("unused")
|
||||
private volatile long callsFinished;
|
||||
|
||||
private static final class LongHolder {
|
||||
long num;
|
||||
}
|
||||
|
||||
// Specific finish types
|
||||
// Access to it should be protected by lock. Contention is not an issue for these counts, because
|
||||
// normally only a small portion of all RPCs are dropped.
|
||||
@GuardedBy("this")
|
||||
private HashMap<String, AtomicLong> callsDroppedPerToken = new HashMap<String, AtomicLong>();
|
||||
private final AtomicLong callsFailedToSend = new AtomicLong();
|
||||
private final AtomicLong callsFinishedKnownReceived = new AtomicLong();
|
||||
private Map<String, LongHolder> callsDroppedPerToken = new HashMap<String, LongHolder>(1);
|
||||
@SuppressWarnings("unused")
|
||||
private volatile long callsFailedToSend;
|
||||
@SuppressWarnings("unused")
|
||||
private volatile long callsFinishedKnownReceived;
|
||||
|
||||
GrpclbClientLoadRecorder(TimeProvider time) {
|
||||
this.time = checkNotNull(time, "time provider");
|
||||
|
|
@ -54,7 +73,7 @@ final class GrpclbClientLoadRecorder extends ClientStreamTracer.Factory {
|
|||
|
||||
@Override
|
||||
public ClientStreamTracer newClientStreamTracer(CallOptions callOptions, Metadata headers) {
|
||||
callsStarted.incrementAndGet();
|
||||
callsStartedUpdater.getAndIncrement(this);
|
||||
return new StreamTracer();
|
||||
}
|
||||
|
||||
|
|
@ -62,17 +81,15 @@ final class GrpclbClientLoadRecorder extends ClientStreamTracer.Factory {
|
|||
* Records that a request has been dropped as instructed by the remote balancer.
|
||||
*/
|
||||
void recordDroppedRequest(String token) {
|
||||
callsStarted.incrementAndGet();
|
||||
callsFinished.incrementAndGet();
|
||||
callsStartedUpdater.getAndIncrement(this);
|
||||
callsFinishedUpdater.getAndIncrement(this);
|
||||
|
||||
synchronized (this) {
|
||||
AtomicLong count = callsDroppedPerToken.get(token);
|
||||
if (count == null) {
|
||||
count = new AtomicLong(1);
|
||||
callsDroppedPerToken.put(token, count);
|
||||
} else {
|
||||
count.incrementAndGet();
|
||||
LongHolder holder;
|
||||
if ((holder = callsDroppedPerToken.get(token)) == null) {
|
||||
callsDroppedPerToken.put(token, (holder = new LongHolder()));
|
||||
}
|
||||
holder.num++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,52 +100,55 @@ final class GrpclbClientLoadRecorder extends ClientStreamTracer.Factory {
|
|||
ClientStats.Builder statsBuilder =
|
||||
ClientStats.newBuilder()
|
||||
.setTimestamp(Timestamps.fromMillis(time.currentTimeMillis()))
|
||||
.setNumCallsStarted(callsStarted.getAndSet(0))
|
||||
.setNumCallsFinished(callsFinished.getAndSet(0))
|
||||
.setNumCallsFinishedWithClientFailedToSend(callsFailedToSend.getAndSet(0))
|
||||
.setNumCallsFinishedKnownReceived(callsFinishedKnownReceived.getAndSet(0));
|
||||
HashMap<String, AtomicLong> savedCallsDroppedPerToken;
|
||||
.setNumCallsStarted(callsStartedUpdater.getAndSet(this, 0))
|
||||
.setNumCallsFinished(callsFinishedUpdater.getAndSet(this, 0))
|
||||
.setNumCallsFinishedWithClientFailedToSend(callsFailedToSendUpdater.getAndSet(this, 0))
|
||||
.setNumCallsFinishedKnownReceived(callsFinishedKnownReceivedUpdater.getAndSet(this, 0));
|
||||
|
||||
Map<String, LongHolder> localCallsDroppedPerToken = Collections.emptyMap();
|
||||
synchronized (this) {
|
||||
savedCallsDroppedPerToken = callsDroppedPerToken;
|
||||
callsDroppedPerToken = new HashMap<String, AtomicLong>();
|
||||
if (!callsDroppedPerToken.isEmpty()) {
|
||||
localCallsDroppedPerToken = callsDroppedPerToken;
|
||||
callsDroppedPerToken = new HashMap<String, LongHolder>(localCallsDroppedPerToken.size());
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, AtomicLong> dropCount : savedCallsDroppedPerToken.entrySet()) {
|
||||
for (Entry<String, LongHolder> entry : localCallsDroppedPerToken.entrySet()) {
|
||||
statsBuilder.addCallsFinishedWithDrop(
|
||||
ClientStatsPerToken.newBuilder()
|
||||
.setLoadBalanceToken(dropCount.getKey())
|
||||
.setNumCalls(dropCount.getValue().get())
|
||||
.setLoadBalanceToken(entry.getKey())
|
||||
.setNumCalls(entry.getValue().num)
|
||||
.build());
|
||||
}
|
||||
return statsBuilder.build();
|
||||
}
|
||||
|
||||
private class StreamTracer extends ClientStreamTracer {
|
||||
final AtomicBoolean headersSent = new AtomicBoolean();
|
||||
final AtomicBoolean anythingReceived = new AtomicBoolean();
|
||||
private volatile boolean headersSent;
|
||||
private volatile boolean anythingReceived;
|
||||
|
||||
@Override
|
||||
public void outboundHeaders() {
|
||||
headersSent.set(true);
|
||||
headersSent = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundHeaders() {
|
||||
anythingReceived.set(true);
|
||||
anythingReceived = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inboundMessage(int seqNo) {
|
||||
anythingReceived.set(true);
|
||||
anythingReceived = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamClosed(Status status) {
|
||||
callsFinished.incrementAndGet();
|
||||
if (!headersSent.get()) {
|
||||
callsFailedToSend.incrementAndGet();
|
||||
callsFinishedUpdater.getAndIncrement(GrpclbClientLoadRecorder.this);
|
||||
if (!headersSent) {
|
||||
callsFailedToSendUpdater.getAndIncrement(GrpclbClientLoadRecorder.this);
|
||||
}
|
||||
if (anythingReceived.get()) {
|
||||
callsFinishedKnownReceived.incrementAndGet();
|
||||
if (anythingReceived) {
|
||||
callsFinishedKnownReceivedUpdater.getAndIncrement(GrpclbClientLoadRecorder.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue