aboutsummaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorzpencer <spencerfang@google.com>2018-03-30 08:48:37 -0700
committerGitHub <noreply@github.com>2018-03-30 08:48:37 -0700
commit7c37f1d32b9dc11027ff1ba946303f5a11dbfe00 (patch)
tree8323666a75669ee53e6740a78069539e309beda1 /services
parent2a95e3825753a455810a93890c36348e7815b4f9 (diff)
downloadgrpc-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')
-rw-r--r--services/src/main/java/io/grpc/services/ChannelzProtoUtil.java70
-rw-r--r--services/src/test/java/io/grpc/services/ChannelzProtoUtilTest.java133
-rw-r--r--services/src/test/java/io/grpc/services/ChannelzTestHelper.java11
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;
}