diff options
author | ZHANG Dapeng <zdapeng@google.com> | 2018-05-15 11:33:44 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-15 11:33:44 -0700 |
commit | 561583be1476e54f37812246329be43470262a55 (patch) | |
tree | af71d75ef5cd65ea4f0a31b5ccf5667519ad7609 | |
parent | 04a90bcad2044b78390da2d29c9166361bf84b59 (diff) | |
download | grpc-grpc-java-561583be1476e54f37812246329be43470262a55.tar.gz |
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)
4 files changed, 253 insertions, 30 deletions
diff --git a/core/src/main/java/io/grpc/internal/Channelz.java b/core/src/main/java/io/grpc/internal/Channelz.java index 9d78b691f..3c993725f 100644 --- a/core/src/main/java/io/grpc/internal/Channelz.java +++ b/core/src/main/java/io/grpc/internal/Channelz.java @@ -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; } diff --git a/services/src/main/java/io/grpc/services/ChannelzProtoUtil.java b/services/src/main/java/io/grpc/services/ChannelzProtoUtil.java index 0403bf0b7..431a0ce9d 100644 --- a/services/src/main/java/io/grpc/services/ChannelzProtoUtil.java +++ b/services/src/main/java/io/grpc/services/ChannelzProtoUtil.java @@ -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; diff --git a/services/src/test/java/io/grpc/services/ChannelzProtoUtilTest.java b/services/src/test/java/io/grpc/services/ChannelzProtoUtilTest.java index 407d8734b..8bdbb15f2 100644 --- a/services/src/test/java/io/grpc/services/ChannelzProtoUtilTest.java +++ b/services/src/test/java/io/grpc/services/ChannelzProtoUtilTest.java @@ -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) diff --git a/services/src/test/java/io/grpc/services/ChannelzTestHelper.java b/services/src/test/java/io/grpc/services/ChannelzTestHelper.java index b326fa0bc..0acdd0287 100644 --- a/services/src/test/java/io/grpc/services/ChannelzTestHelper.java +++ b/services/src/test/java/io/grpc/services/ChannelzTestHelper.java @@ -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() { |