diff options
author | zpencer <spencerfang@google.com> | 2018-03-30 08:48:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-30 08:48:37 -0700 |
commit | 7c37f1d32b9dc11027ff1ba946303f5a11dbfe00 (patch) | |
tree | 8323666a75669ee53e6740a78069539e309beda1 /services | |
parent | 2a95e3825753a455810a93890c36348e7815b4f9 (diff) | |
download | grpc-grpc-java-7c37f1d32b9dc11027ff1ba946303f5a11dbfe00.tar.gz |
core,netty,okhttp,services: expose socket options to channelz (#4228)
For okhttp, expose the standard options from the Socket object.
For netty, expose all the `io.netty.channel.ChannelOption`s of the
`channel.config()`.
Diffstat (limited to 'services')
3 files changed, 205 insertions, 9 deletions
diff --git a/services/src/main/java/io/grpc/services/ChannelzProtoUtil.java b/services/src/main/java/io/grpc/services/ChannelzProtoUtil.java index c9a11ba76..ca8f58228 100644 --- a/services/src/main/java/io/grpc/services/ChannelzProtoUtil.java +++ b/services/src/main/java/io/grpc/services/ChannelzProtoUtil.java @@ -18,8 +18,10 @@ package io.grpc.services; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.ListenableFuture; +import com.google.protobuf.Any; import com.google.protobuf.ByteString; import com.google.protobuf.Int64Value; +import com.google.protobuf.util.Durations; import com.google.protobuf.util.Timestamps; import io.grpc.ConnectivityState; import io.grpc.Status; @@ -39,6 +41,9 @@ import io.grpc.channelz.v1.ServerData; import io.grpc.channelz.v1.ServerRef; import io.grpc.channelz.v1.Socket; import io.grpc.channelz.v1.SocketData; +import io.grpc.channelz.v1.SocketOption; +import io.grpc.channelz.v1.SocketOptionLinger; +import io.grpc.channelz.v1.SocketOptionTimeout; import io.grpc.channelz.v1.SocketRef; import io.grpc.channelz.v1.Subchannel; import io.grpc.channelz.v1.SubchannelRef; @@ -54,6 +59,9 @@ import io.grpc.internal.Instrumented; import io.grpc.internal.WithLogId; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; import java.util.concurrent.ExecutionException; /** @@ -121,7 +129,7 @@ final class ChannelzProtoUtil { .setRef(toSocketRef(obj)) .setRemote(toAddress(socketStats.remote)) .setLocal(toAddress(socketStats.local)) - .setData(toSocketData(socketStats.data)) + .setData(extractSocketData(socketStats)) .build(); } @@ -147,7 +155,8 @@ final class ChannelzProtoUtil { return builder.build(); } - static SocketData toSocketData(TransportStats s) { + static SocketData extractSocketData(SocketStats socketStats) { + TransportStats s = socketStats.data; return SocketData .newBuilder() .setStreamsStarted(s.streamsStarted) @@ -168,9 +177,66 @@ final class ChannelzProtoUtil { Int64Value.newBuilder().setValue(s.localFlowControlWindow).build()) .setRemoteFlowControlWindow( Int64Value.newBuilder().setValue(s.remoteFlowControlWindow).build()) + .addAllOption(toSocketOptionsList(socketStats.socketOptions)) .build(); } + public static final String SO_LINGER = "SO_LINGER"; + public static final String SO_TIMEOUT = "SO_TIMEOUT"; + + static SocketOption toSocketOptionLinger(int lingerSeconds) { + final SocketOptionLinger lingerOpt; + if (lingerSeconds >= 0) { + lingerOpt = SocketOptionLinger + .newBuilder() + .setActive(true) + .setDuration(Durations.fromSeconds(lingerSeconds)) + .build(); + } else { + lingerOpt = SocketOptionLinger.getDefaultInstance(); + } + return SocketOption + .newBuilder() + .setName(SO_LINGER) + .setAdditional(Any.pack(lingerOpt)) + .build(); + } + + static SocketOption toSocketOptionTimeout(String name, int timeoutMillis) { + Preconditions.checkNotNull(name); + return SocketOption + .newBuilder() + .setName(name) + .setAdditional( + Any.pack( + SocketOptionTimeout + .newBuilder() + .setDuration(Durations.fromMillis(timeoutMillis)) + .build())) + .build(); + } + + static SocketOption toSocketOptionAdditional(String name, String value) { + Preconditions.checkNotNull(name); + Preconditions.checkNotNull(value); + return SocketOption.newBuilder().setName(name).setValue(value).build(); + } + + static List<SocketOption> toSocketOptionsList(Channelz.SocketOptions options) { + Preconditions.checkNotNull(options); + List<SocketOption> ret = new ArrayList<SocketOption>(); + if (options.lingerSeconds != null) { + ret.add(toSocketOptionLinger(options.lingerSeconds)); + } + if (options.soTimeoutMillis != null) { + ret.add(toSocketOptionTimeout(SO_TIMEOUT, options.soTimeoutMillis)); + } + for (Entry<String, String> entry : options.others.entrySet()) { + ret.add(toSocketOptionAdditional(entry.getKey(), entry.getValue())); + } + return ret; + } + static Channel toChannel(Instrumented<ChannelStats> channel) { ChannelStats stats = getFuture(channel.getStats()); Channel.Builder channelBuilder = Channel diff --git a/services/src/test/java/io/grpc/services/ChannelzProtoUtilTest.java b/services/src/test/java/io/grpc/services/ChannelzProtoUtilTest.java index 1ce474b8c..83e3c6dad 100644 --- a/services/src/test/java/io/grpc/services/ChannelzProtoUtilTest.java +++ b/services/src/test/java/io/grpc/services/ChannelzProtoUtilTest.java @@ -16,11 +16,14 @@ package io.grpc.services; +import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import com.google.common.collect.ImmutableList; +import com.google.protobuf.Any; import com.google.protobuf.ByteString; import com.google.protobuf.Int64Value; +import com.google.protobuf.util.Durations; import com.google.protobuf.util.Timestamps; import io.grpc.ConnectivityState; import io.grpc.channelz.v1.Address; @@ -39,14 +42,19 @@ import io.grpc.channelz.v1.ServerData; import io.grpc.channelz.v1.ServerRef; import io.grpc.channelz.v1.Socket; import io.grpc.channelz.v1.SocketData; +import io.grpc.channelz.v1.SocketOption; +import io.grpc.channelz.v1.SocketOptionLinger; +import io.grpc.channelz.v1.SocketOptionTimeout; import io.grpc.channelz.v1.SocketRef; 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.RootChannelList; import io.grpc.internal.Channelz.ServerList; import io.grpc.internal.Channelz.ServerSocketsList; import io.grpc.internal.Channelz.ServerStats; +import io.grpc.internal.Channelz.SocketOptions; import io.grpc.internal.Instrumented; import io.grpc.internal.WithLogId; import io.grpc.services.ChannelzTestHelper.TestChannel; @@ -57,6 +65,7 @@ import java.net.Inet4Address; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.Collections; +import java.util.Map.Entry; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -125,13 +134,47 @@ public final class ChannelzProtoUtilTest { .setData(serverData) .build(); + private final SocketOption sockOptLingerDisabled = SocketOption + .newBuilder() + .setName("SO_LINGER") + .setAdditional( + Any.pack(SocketOptionLinger.getDefaultInstance())) + .build(); + + private final SocketOption sockOptlinger10s = SocketOption + .newBuilder() + .setName("SO_LINGER") + .setAdditional( + Any.pack(SocketOptionLinger + .newBuilder() + .setActive(true) + .setDuration(Durations.fromSeconds(10)) + .build())) + .build(); + + private final SocketOption sockOptTimeout200ms = SocketOption + .newBuilder() + .setName("SO_TIMEOUT") + .setAdditional( + Any.pack(SocketOptionTimeout + .newBuilder() + .setDuration(Durations.fromMillis(200)) + .build()) + ).build(); + + private final SocketOption sockOptAdditional = SocketOption + .newBuilder() + .setName("SO_MADE_UP_OPTION") + .setValue("some-made-up-value") + .build(); + private final TestSocket socket = new TestSocket(); private final SocketRef socketRef = SocketRef .newBuilder() .setName(socket.toString()) .setSocketId(socket.getLogId().getId()) .build(); - private final SocketData socketData = SocketData + private final SocketData socketDataNoSockOpts = SocketData .newBuilder() .setStreamsStarted(1) .setLastLocalStreamCreatedTimestamp(Timestamps.fromNanos(2)) @@ -203,16 +246,28 @@ public final class ChannelzProtoUtilTest { .setRef(socketRef) .setLocal(localAddress) .setRemote(remoteAddress) - .setData(socketData) + .setData(socketDataNoSockOpts) .build(), ChannelzProtoUtil.toSocket(socket)); } @Test - public void toSocketData() { + public void extractSocketData() throws Exception { + // no options + assertEquals( + socketDataNoSockOpts, + ChannelzProtoUtil.extractSocketData(socket.getStats().get())); + + // with options + socket.socketOptions = toBuilder(socket.socketOptions) + .setSocketOptionLingerSeconds(10) + .build(); assertEquals( - socketData, - ChannelzProtoUtil.toSocketData(socket.transportStats)); + socketDataNoSockOpts + .toBuilder() + .addOption(sockOptlinger10s) + .build(), + ChannelzProtoUtil.extractSocketData(socket.getStats().get())); } @Test @@ -482,6 +537,64 @@ public final class ChannelzProtoUtilTest { new ServerSocketsList(ImmutableList.<WithLogId>of(socket, socket2), true))); } + @Test + public void toSocketOptionLinger() { + assertEquals(sockOptLingerDisabled, ChannelzProtoUtil.toSocketOptionLinger(-1)); + assertEquals(sockOptlinger10s, ChannelzProtoUtil.toSocketOptionLinger(10)); + } + + @Test + public void toSocketOptionTimeout() { + assertEquals( + sockOptTimeout200ms, ChannelzProtoUtil.toSocketOptionTimeout("SO_TIMEOUT", 200)); + } + + @Test + public void toSocketOptionAdditional() { + assertEquals( + sockOptAdditional, + ChannelzProtoUtil.toSocketOptionAdditional("SO_MADE_UP_OPTION", "some-made-up-value")); + } + + @Test + public void toSocketOptionsList() { + assertThat( + ChannelzProtoUtil.toSocketOptionsList( + new Channelz.SocketOptions.Builder().build())) + .isEmpty(); + + assertThat( + ChannelzProtoUtil.toSocketOptionsList( + new Channelz.SocketOptions.Builder().setSocketOptionLingerSeconds(10).build())) + .containsExactly(sockOptlinger10s); + + assertThat( + ChannelzProtoUtil.toSocketOptionsList( + new Channelz.SocketOptions.Builder().setSocketOptionTimeoutMillis(200).build())) + .containsExactly(sockOptTimeout200ms); + + assertThat( + ChannelzProtoUtil.toSocketOptionsList( + new Channelz.SocketOptions + .Builder() + .addOption("SO_MADE_UP_OPTION", "some-made-up-value") + .build())) + .containsExactly(sockOptAdditional); + + SocketOption otherOption = SocketOption + .newBuilder() + .setName("SO_MADE_UP_OPTION2") + .setValue("some-made-up-value2") + .build(); + assertThat( + ChannelzProtoUtil.toSocketOptionsList( + new Channelz.SocketOptions.Builder() + .addOption("SO_MADE_UP_OPTION", "some-made-up-value") + .addOption("SO_MADE_UP_OPTION2", "some-made-up-value2") + .build())) + .containsExactly(sockOptAdditional, otherOption); + } + private static ChannelStats.Builder toBuilder(ChannelStats stats) { ChannelStats.Builder builder = new ChannelStats.Builder() .setTarget(stats.target) @@ -498,4 +611,14 @@ public final class ChannelzProtoUtilTest { } return builder; } + + private static SocketOptions.Builder toBuilder(SocketOptions options) { + SocketOptions.Builder builder = new SocketOptions.Builder() + .setSocketOptionTimeoutMillis(options.soTimeoutMillis) + .setSocketOptionLingerSeconds(options.lingerSeconds); + for (Entry<String, String> entry : options.others.entrySet()) { + builder.addOption(entry.getKey(), entry.getValue()); + } + return builder; + } } diff --git a/services/src/test/java/io/grpc/services/ChannelzTestHelper.java b/services/src/test/java/io/grpc/services/ChannelzTestHelper.java index ee5697592..baadc10f3 100644 --- a/services/src/test/java/io/grpc/services/ChannelzTestHelper.java +++ b/services/src/test/java/io/grpc/services/ChannelzTestHelper.java @@ -19,6 +19,7 @@ package io.grpc.services; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import io.grpc.ConnectivityState; +import io.grpc.internal.Channelz; import io.grpc.internal.Channelz.ChannelStats; import io.grpc.internal.Channelz.Security; import io.grpc.internal.Channelz.ServerStats; @@ -54,12 +55,18 @@ final class ChannelzTestHelper { /*remoteFlowControlWindow=*/ 12); SocketAddress local = new InetSocketAddress("10.0.0.1", 1000); SocketAddress remote = new InetSocketAddress("10.0.0.2", 1000); - + Channelz.SocketOptions socketOptions = new Channelz.SocketOptions.Builder().build(); @Override public ListenableFuture<SocketStats> getStats() { SettableFuture<SocketStats> ret = SettableFuture.create(); - ret.set(new SocketStats(transportStats, local, remote, new Security())); + ret.set( + new SocketStats( + transportStats, + local, + remote, + socketOptions, + new Security())); return ret; } |