mirror of https://github.com/grpc/grpc-java.git
core,services: Add ChannelTracing data object
Added `ChannelTrace` as an inner class of `Channelz`. This is in preparation for the implementation of [Channel Tracing](https://github.com/grpc/proposal/blob/master/A3-channel-tracing.md)
This commit is contained in:
parent
04a90bcad2
commit
561583be14
|
@ -16,6 +16,9 @@
|
|||
|
||||
package io.grpc.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.grpc.ConnectivityState;
|
||||
|
@ -244,7 +247,7 @@ public final class Channelz {
|
|||
|
||||
/** Creates an instance. */
|
||||
public RootChannelList(List<Instrumented<ChannelStats>> channels, boolean end) {
|
||||
this.channels = Preconditions.checkNotNull(channels);
|
||||
this.channels = checkNotNull(channels);
|
||||
this.end = end;
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +258,7 @@ public final class Channelz {
|
|||
|
||||
/** Creates an instance. */
|
||||
public ServerList(List<Instrumented<ServerStats>> servers, boolean end) {
|
||||
this.servers = Preconditions.checkNotNull(servers);
|
||||
this.servers = checkNotNull(servers);
|
||||
this.end = end;
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +295,7 @@ public final class Channelz {
|
|||
this.callsSucceeded = callsSucceeded;
|
||||
this.callsFailed = callsFailed;
|
||||
this.lastCallStartedMillis = lastCallStartedMillis;
|
||||
this.listenSockets = Preconditions.checkNotNull(listenSockets);
|
||||
this.listenSockets = checkNotNull(listenSockets);
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
|
@ -324,7 +327,7 @@ public final class Channelz {
|
|||
|
||||
/** Sets the listen sockets. */
|
||||
public Builder setListenSockets(List<Instrumented<SocketStats>> listenSockets) {
|
||||
Preconditions.checkNotNull(listenSockets);
|
||||
checkNotNull(listenSockets);
|
||||
this.listenSockets = Collections.unmodifiableList(
|
||||
new ArrayList<Instrumented<SocketStats>>(listenSockets));
|
||||
return this;
|
||||
|
@ -351,6 +354,7 @@ public final class Channelz {
|
|||
public static final class ChannelStats {
|
||||
public final String target;
|
||||
public final ConnectivityState state;
|
||||
@Nullable public final ChannelTrace channelTrace;
|
||||
public final long callsStarted;
|
||||
public final long callsSucceeded;
|
||||
public final long callsFailed;
|
||||
|
@ -361,9 +365,10 @@ public final class Channelz {
|
|||
/**
|
||||
* Creates an instance.
|
||||
*/
|
||||
public ChannelStats(
|
||||
private ChannelStats(
|
||||
String target,
|
||||
ConnectivityState state,
|
||||
@Nullable ChannelTrace channelTrace,
|
||||
long callsStarted,
|
||||
long callsSucceeded,
|
||||
long callsFailed,
|
||||
|
@ -376,17 +381,19 @@ public final class Channelz {
|
|||
+ "neither can have both");
|
||||
this.target = target;
|
||||
this.state = state;
|
||||
this.channelTrace = channelTrace;
|
||||
this.callsStarted = callsStarted;
|
||||
this.callsSucceeded = callsSucceeded;
|
||||
this.callsFailed = callsFailed;
|
||||
this.lastCallStartedMillis = lastCallStartedMillis;
|
||||
this.subchannels = Preconditions.checkNotNull(subchannels);
|
||||
this.sockets = Preconditions.checkNotNull(sockets);
|
||||
this.subchannels = checkNotNull(subchannels);
|
||||
this.sockets = checkNotNull(sockets);
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String target;
|
||||
private ConnectivityState state;
|
||||
private ChannelTrace channelTrace;
|
||||
private long callsStarted;
|
||||
private long callsSucceeded;
|
||||
private long callsFailed;
|
||||
|
@ -404,6 +411,11 @@ public final class Channelz {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setChannelTrace(ChannelTrace channelTrace) {
|
||||
this.channelTrace = channelTrace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCallsStarted(long callsStarted) {
|
||||
this.callsStarted = callsStarted;
|
||||
return this;
|
||||
|
@ -427,14 +439,14 @@ public final class Channelz {
|
|||
/** Sets the subchannels. */
|
||||
public Builder setSubchannels(List<WithLogId> subchannels) {
|
||||
Preconditions.checkState(sockets.isEmpty());
|
||||
this.subchannels = Collections.unmodifiableList(Preconditions.checkNotNull(subchannels));
|
||||
this.subchannels = Collections.unmodifiableList(checkNotNull(subchannels));
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the sockets. */
|
||||
public Builder setSockets(List<WithLogId> sockets) {
|
||||
Preconditions.checkState(subchannels.isEmpty());
|
||||
this.sockets = Collections.unmodifiableList(Preconditions.checkNotNull(sockets));
|
||||
this.sockets = Collections.unmodifiableList(checkNotNull(sockets));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -445,6 +457,7 @@ public final class Channelz {
|
|||
return new ChannelStats(
|
||||
target,
|
||||
state,
|
||||
channelTrace,
|
||||
callsStarted,
|
||||
callsSucceeded,
|
||||
callsFailed,
|
||||
|
@ -455,6 +468,109 @@ public final class Channelz {
|
|||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static final class ChannelTrace {
|
||||
public final long numEventsLogged;
|
||||
public final long creationTimeNanos;
|
||||
public final List<Event> events;
|
||||
|
||||
private ChannelTrace(long numEventsLogged, long creationTimeNanos, List<Event> events) {
|
||||
this.numEventsLogged = numEventsLogged;
|
||||
this.creationTimeNanos = creationTimeNanos;
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private long numEventsLogged;
|
||||
private long creationTimeNanos;
|
||||
private List<Event> events = Collections.emptyList();
|
||||
|
||||
public Builder setNumEventsLogged(long numEventsLogged) {
|
||||
this.numEventsLogged = numEventsLogged;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCreationTimeNanos(long creationTimeNanos) {
|
||||
this.creationTimeNanos = creationTimeNanos;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEvents(List<Event> events) {
|
||||
this.events = Collections.unmodifiableList(new ArrayList<Event>(events));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChannelTrace build() {
|
||||
return new ChannelTrace(numEventsLogged, creationTimeNanos, events);
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static final class Event {
|
||||
public final String description;
|
||||
public final Severity severity;
|
||||
public final long timestampNanos;
|
||||
|
||||
// the oneof child_ref field in proto: one of channelRef and channelRef
|
||||
@Nullable public final WithLogId channelRef;
|
||||
@Nullable public final WithLogId subchannelRef;
|
||||
|
||||
public enum Severity {
|
||||
CT_UNKNOWN, CT_INFO, CT_WARNING, CT_ERROR
|
||||
}
|
||||
|
||||
private Event(
|
||||
String description, Severity severity, long timestampNanos,
|
||||
@Nullable WithLogId channelRef, @Nullable WithLogId subchannelRef) {
|
||||
checkArgument(
|
||||
channelRef == null || subchannelRef == null,
|
||||
"at least one of channelRef and subchannelRef must be null");
|
||||
this.description = checkNotNull(description, "description");
|
||||
this.severity = checkNotNull(severity, "severity");
|
||||
this.timestampNanos = timestampNanos;
|
||||
this.channelRef = channelRef;
|
||||
this.subchannelRef = subchannelRef;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String description;
|
||||
private Severity severity;
|
||||
private long timestampNanos;
|
||||
private WithLogId channelRef;
|
||||
private WithLogId subchannelRef;
|
||||
|
||||
public Builder setDescription(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTimestampNaonos(long timestampNanos) {
|
||||
this.timestampNanos = timestampNanos;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSeverity(Severity severity) {
|
||||
this.severity = severity;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setChannelRef(WithLogId channelRef) {
|
||||
this.channelRef = channelRef;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSubchannelRef(WithLogId subchannelRef) {
|
||||
this.subchannelRef = subchannelRef;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Event build() {
|
||||
return new Event(description, severity, timestampNanos, channelRef, subchannelRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Security {
|
||||
@Nullable
|
||||
public final Tls tls;
|
||||
|
@ -462,13 +578,13 @@ public final class Channelz {
|
|||
public final OtherSecurity other;
|
||||
|
||||
public Security(Tls tls) {
|
||||
this.tls = Preconditions.checkNotNull(tls);
|
||||
this.tls = checkNotNull(tls);
|
||||
this.other = null;
|
||||
}
|
||||
|
||||
public Security(OtherSecurity other) {
|
||||
this.tls = null;
|
||||
this.other = Preconditions.checkNotNull(other);
|
||||
this.other = checkNotNull(other);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -483,7 +599,7 @@ public final class Channelz {
|
|||
* @param any a com.google.protobuf.Any object
|
||||
*/
|
||||
public OtherSecurity(String name, @Nullable Object any) {
|
||||
this.name = Preconditions.checkNotNull(name);
|
||||
this.name = checkNotNull(name);
|
||||
Preconditions.checkState(
|
||||
any == null || any.getClass().getName().endsWith("com.google.protobuf.Any"),
|
||||
"the 'any' object must be of type com.google.protobuf.Any");
|
||||
|
@ -553,9 +669,9 @@ public final class Channelz {
|
|||
SocketOptions socketOptions,
|
||||
Security security) {
|
||||
this.data = data;
|
||||
this.local = Preconditions.checkNotNull(local, "local socket");
|
||||
this.local = checkNotNull(local, "local socket");
|
||||
this.remote = remote;
|
||||
this.socketOptions = Preconditions.checkNotNull(socketOptions);
|
||||
this.socketOptions = checkNotNull(socketOptions);
|
||||
this.security = security;
|
||||
}
|
||||
}
|
||||
|
@ -827,7 +943,7 @@ public final class Channelz {
|
|||
@Nullable Integer lingerSeconds,
|
||||
@Nullable TcpInfo tcpInfo,
|
||||
Map<String, String> others) {
|
||||
Preconditions.checkNotNull(others);
|
||||
checkNotNull(others);
|
||||
this.soTimeoutMillis = timeoutMillis;
|
||||
this.lingerSeconds = lingerSeconds;
|
||||
this.tcpInfo = tcpInfo;
|
||||
|
@ -861,7 +977,7 @@ public final class Channelz {
|
|||
}
|
||||
|
||||
public Builder addOption(String name, String value) {
|
||||
others.put(name, Preconditions.checkNotNull(value));
|
||||
others.put(name, checkNotNull(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ import io.grpc.channelz.v1.ChannelConnectivityState;
|
|||
import io.grpc.channelz.v1.ChannelConnectivityState.State;
|
||||
import io.grpc.channelz.v1.ChannelData;
|
||||
import io.grpc.channelz.v1.ChannelRef;
|
||||
import io.grpc.channelz.v1.ChannelTrace;
|
||||
import io.grpc.channelz.v1.ChannelTraceEvent;
|
||||
import io.grpc.channelz.v1.ChannelTraceEvent.Severity;
|
||||
import io.grpc.channelz.v1.GetServerSocketsResponse;
|
||||
import io.grpc.channelz.v1.GetServersResponse;
|
||||
import io.grpc.channelz.v1.GetTopChannelsResponse;
|
||||
|
@ -55,6 +58,7 @@ import io.grpc.channelz.v1.Subchannel;
|
|||
import io.grpc.channelz.v1.SubchannelRef;
|
||||
import io.grpc.internal.Channelz;
|
||||
import io.grpc.internal.Channelz.ChannelStats;
|
||||
import io.grpc.internal.Channelz.ChannelTrace.Event;
|
||||
import io.grpc.internal.Channelz.RootChannelList;
|
||||
import io.grpc.internal.Channelz.ServerList;
|
||||
import io.grpc.internal.Channelz.ServerSocketsList;
|
||||
|
@ -67,6 +71,7 @@ import java.net.InetSocketAddress;
|
|||
import java.net.SocketAddress;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
@ -348,21 +353,49 @@ final class ChannelzProtoUtil {
|
|||
}
|
||||
|
||||
static ChannelData extractChannelData(Channelz.ChannelStats stats) {
|
||||
return ChannelData
|
||||
.newBuilder()
|
||||
.setTarget(stats.target)
|
||||
ChannelData.Builder builder = ChannelData.newBuilder();
|
||||
builder.setTarget(stats.target)
|
||||
.setState(toChannelConnectivityState(stats.state))
|
||||
.setCallsStarted(stats.callsStarted)
|
||||
.setCallsSucceeded(stats.callsSucceeded)
|
||||
.setCallsFailed(stats.callsFailed)
|
||||
.setLastCallStartedTimestamp(Timestamps.fromMillis(stats.lastCallStartedMillis))
|
||||
.build();
|
||||
.setLastCallStartedTimestamp(Timestamps.fromMillis(stats.lastCallStartedMillis));
|
||||
if (stats.channelTrace != null) {
|
||||
builder.setTrace(toChannelTrace(stats.channelTrace));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static ChannelConnectivityState toChannelConnectivityState(ConnectivityState s) {
|
||||
return ChannelConnectivityState.newBuilder().setState(toState(s)).build();
|
||||
}
|
||||
|
||||
private static ChannelTrace toChannelTrace(Channelz.ChannelTrace channelTrace) {
|
||||
return ChannelTrace.newBuilder()
|
||||
.setNumEventsLogged(channelTrace.numEventsLogged)
|
||||
.setCreationTimestamp(Timestamps.fromNanos(channelTrace.creationTimeNanos))
|
||||
.addAllEvents(toChannelTraceEvents(channelTrace.events))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static List<ChannelTraceEvent> toChannelTraceEvents(List<Event> events) {
|
||||
List<ChannelTraceEvent> channelTraceEvents = new ArrayList<ChannelTraceEvent>();
|
||||
for (Event event : events) {
|
||||
ChannelTraceEvent.Builder builder = ChannelTraceEvent.newBuilder()
|
||||
.setDescription(event.description)
|
||||
.setSeverity(Severity.valueOf(event.severity.name()))
|
||||
.setTimestamp(Timestamps.fromNanos(event.timestampNanos));
|
||||
if (event.channelRef != null) {
|
||||
builder.setChannelRef(toChannelRef(event.channelRef));
|
||||
}
|
||||
if (event.subchannelRef != null) {
|
||||
builder.setSubchannelRef(toSubchannelRef(event.subchannelRef));
|
||||
}
|
||||
channelTraceEvents.add(builder.build());
|
||||
}
|
||||
return Collections.unmodifiableList(channelTraceEvents);
|
||||
}
|
||||
|
||||
static State toState(ConnectivityState state) {
|
||||
if (state == null) {
|
||||
return State.UNKNOWN;
|
||||
|
|
|
@ -41,6 +41,8 @@ import io.grpc.channelz.v1.ChannelConnectivityState;
|
|||
import io.grpc.channelz.v1.ChannelConnectivityState.State;
|
||||
import io.grpc.channelz.v1.ChannelData;
|
||||
import io.grpc.channelz.v1.ChannelRef;
|
||||
import io.grpc.channelz.v1.ChannelTrace;
|
||||
import io.grpc.channelz.v1.ChannelTraceEvent;
|
||||
import io.grpc.channelz.v1.GetChannelRequest;
|
||||
import io.grpc.channelz.v1.GetServerSocketsResponse;
|
||||
import io.grpc.channelz.v1.GetServersResponse;
|
||||
|
@ -62,6 +64,8 @@ import io.grpc.channelz.v1.Subchannel;
|
|||
import io.grpc.channelz.v1.SubchannelRef;
|
||||
import io.grpc.internal.Channelz;
|
||||
import io.grpc.internal.Channelz.ChannelStats;
|
||||
import io.grpc.internal.Channelz.ChannelTrace.Event;
|
||||
import io.grpc.internal.Channelz.ChannelTrace.Event.Severity;
|
||||
import io.grpc.internal.Channelz.RootChannelList;
|
||||
import io.grpc.internal.Channelz.ServerList;
|
||||
import io.grpc.internal.Channelz.ServerSocketsList;
|
||||
|
@ -79,6 +83,7 @@ import java.net.Inet4Address;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map.Entry;
|
||||
import org.junit.Test;
|
||||
|
@ -310,6 +315,12 @@ public final class ChannelzProtoUtilTest {
|
|||
.setPort(1000))
|
||||
.build();
|
||||
|
||||
private final ChannelTrace channelTrace = ChannelTrace
|
||||
.newBuilder()
|
||||
.setNumEventsLogged(1234)
|
||||
.setCreationTimestamp(Timestamps.fromNanos(1000))
|
||||
.build();
|
||||
|
||||
@Test
|
||||
public void toChannelRef() {
|
||||
assertEquals(channelRef, ChannelzProtoUtil.toChannelRef(channel));
|
||||
|
@ -832,6 +843,68 @@ public final class ChannelzProtoUtilTest {
|
|||
.containsExactly(sockOptAdditional, otherOption);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void channelTrace_withoutEvents() {
|
||||
ChannelStats stats = toBuilder(channel.stats)
|
||||
.setChannelTrace(new Channelz.ChannelTrace.Builder()
|
||||
.setNumEventsLogged(1234)
|
||||
.setCreationTimeNanos(1000)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
ChannelData protoStats = channelData.toBuilder().setTrace(channelTrace).build();
|
||||
assertEquals(ChannelzProtoUtil.extractChannelData(stats), protoStats);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void channelTrace_withEvents() {
|
||||
Event event1 = new Event.Builder()
|
||||
.setDescription("event1")
|
||||
.setSeverity(Severity.CT_ERROR)
|
||||
.setTimestampNaonos(12)
|
||||
.setSubchannelRef(subchannel)
|
||||
.build();
|
||||
Event event2 = new Event.Builder()
|
||||
.setDescription("event2")
|
||||
.setTimestampNaonos(34)
|
||||
.setSeverity(Severity.CT_INFO)
|
||||
.setChannelRef(channel)
|
||||
.build();
|
||||
|
||||
ChannelStats stats =
|
||||
toBuilder(channel.stats)
|
||||
.setChannelTrace(
|
||||
new Channelz.ChannelTrace.Builder()
|
||||
.setNumEventsLogged(1234)
|
||||
.setCreationTimeNanos(1000)
|
||||
.setEvents(Arrays.asList(event1, event2))
|
||||
.build())
|
||||
.build();
|
||||
|
||||
ChannelTraceEvent protoEvent1 = ChannelTraceEvent
|
||||
.newBuilder()
|
||||
.setDescription("event1")
|
||||
.setTimestamp(Timestamps.fromNanos(12))
|
||||
.setSeverity(ChannelTraceEvent.Severity.CT_ERROR)
|
||||
.setSubchannelRef(subchannelRef)
|
||||
.build();
|
||||
ChannelTraceEvent protoEvent2 = ChannelTraceEvent
|
||||
.newBuilder()
|
||||
.setDescription("event2")
|
||||
.setTimestamp(Timestamps.fromNanos(34))
|
||||
.setSeverity(ChannelTraceEvent.Severity.CT_INFO)
|
||||
.setChannelRef(channelRef)
|
||||
.build();
|
||||
ChannelData protoStats = channelData
|
||||
.toBuilder()
|
||||
.setTrace(channelTrace
|
||||
.toBuilder()
|
||||
.addAllEvents(Arrays.asList(protoEvent1, protoEvent2))
|
||||
.build())
|
||||
.build();
|
||||
assertEquals(ChannelzProtoUtil.extractChannelData(stats), protoStats);
|
||||
}
|
||||
|
||||
private static ChannelStats.Builder toBuilder(ChannelStats stats) {
|
||||
ChannelStats.Builder builder = new ChannelStats.Builder()
|
||||
.setTarget(stats.target)
|
||||
|
|
|
@ -148,15 +148,16 @@ final class ChannelzTestHelper {
|
|||
static final class TestChannel implements Instrumented<ChannelStats> {
|
||||
private final LogId id = LogId.allocate("channel-or-subchannel");
|
||||
|
||||
ChannelStats stats = new ChannelStats(
|
||||
/*target=*/ "sometarget",
|
||||
/*state=*/ ConnectivityState.READY,
|
||||
/*callsStarted=*/ 1,
|
||||
/*callsSucceeded=*/ 2,
|
||||
/*callsFailed=*/ 3,
|
||||
/*lastCallStartedMillis=*/ 4,
|
||||
/*subchannels=*/ Collections.<WithLogId>emptyList(),
|
||||
/*sockets=*/ Collections.<WithLogId>emptyList());
|
||||
ChannelStats stats = new ChannelStats.Builder()
|
||||
.setTarget("sometarget")
|
||||
.setState(ConnectivityState.READY)
|
||||
.setCallsStarted(1)
|
||||
.setCallsSucceeded(2)
|
||||
.setCallsFailed(3)
|
||||
.setLastCallStartedMillis(4)
|
||||
.setSubchannels(Collections.<WithLogId>emptyList())
|
||||
.setSockets(Collections.<WithLogId>emptyList())
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public ListenableFuture<ChannelStats> getStats() {
|
||||
|
|
Loading…
Reference in New Issue