aboutsummaryrefslogtreecommitdiff
path: root/netty
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 /netty
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 'netty')
-rw-r--r--netty/src/main/java/io/grpc/netty/NettyClientTransport.java2
-rw-r--r--netty/src/main/java/io/grpc/netty/NettyServerTransport.java2
-rw-r--r--netty/src/main/java/io/grpc/netty/Utils.java37
-rw-r--r--netty/src/test/java/io/grpc/netty/UtilsTest.java49
4 files changed, 90 insertions, 0 deletions
diff --git a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java
index 87b11ddf9..0b3c48b41 100644
--- a/netty/src/main/java/io/grpc/netty/NettyClientTransport.java
+++ b/netty/src/main/java/io/grpc/netty/NettyClientTransport.java
@@ -323,6 +323,7 @@ class NettyClientTransport implements ConnectionClientTransport {
transportTracer.getStats(),
channel.localAddress(),
channel.remoteAddress(),
+ Utils.getSocketOptions(channel),
new Security()));
return result;
}
@@ -335,6 +336,7 @@ class NettyClientTransport implements ConnectionClientTransport {
transportTracer.getStats(),
channel.localAddress(),
channel.remoteAddress(),
+ Utils.getSocketOptions(channel),
new Security()));
}
});
diff --git a/netty/src/main/java/io/grpc/netty/NettyServerTransport.java b/netty/src/main/java/io/grpc/netty/NettyServerTransport.java
index 73c748b1b..fe905bb2d 100644
--- a/netty/src/main/java/io/grpc/netty/NettyServerTransport.java
+++ b/netty/src/main/java/io/grpc/netty/NettyServerTransport.java
@@ -206,6 +206,7 @@ class NettyServerTransport implements ServerTransport {
transportTracer.getStats(),
channel.localAddress(),
channel.remoteAddress(),
+ Utils.getSocketOptions(channel),
/*security=*/ null));
return result;
}
@@ -218,6 +219,7 @@ class NettyServerTransport implements ServerTransport {
transportTracer.getStats(),
channel.localAddress(),
channel.remoteAddress(),
+ Utils.getSocketOptions(channel),
/*security=*/ null));
}
});
diff --git a/netty/src/main/java/io/grpc/netty/Utils.java b/netty/src/main/java/io/grpc/netty/Utils.java
index 5dda2ad80..473a4c8ef 100644
--- a/netty/src/main/java/io/grpc/netty/Utils.java
+++ b/netty/src/main/java/io/grpc/netty/Utils.java
@@ -19,6 +19,8 @@ package io.grpc.netty;
import static io.grpc.internal.GrpcUtil.CONTENT_TYPE_KEY;
import static io.grpc.internal.TransportFrameUtil.toHttp2Headers;
import static io.grpc.internal.TransportFrameUtil.toRawSerializedHeaders;
+import static io.netty.channel.ChannelOption.SO_LINGER;
+import static io.netty.channel.ChannelOption.SO_TIMEOUT;
import static io.netty.util.CharsetUtil.UTF_8;
import com.google.common.annotations.VisibleForTesting;
@@ -26,9 +28,13 @@ import com.google.common.base.Preconditions;
import io.grpc.InternalMetadata;
import io.grpc.Metadata;
import io.grpc.Status;
+import io.grpc.internal.Channelz;
import io.grpc.internal.GrpcUtil;
import io.grpc.internal.SharedResourceHolder.Resource;
import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2InboundHeaders;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelConfig;
+import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.codec.http2.Http2Exception;
@@ -38,6 +44,7 @@ import io.netty.util.concurrent.DefaultThreadFactory;
import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@@ -201,6 +208,36 @@ class Utils {
}
}
+ static Channelz.SocketOptions getSocketOptions(Channel channel) {
+ ChannelConfig config = channel.config();
+ Channelz.SocketOptions.Builder b = new Channelz.SocketOptions.Builder();
+
+ // The API allows returning null but not sure if it can happen in practice.
+ // Let's be paranoid and do null checking just in case.
+ Integer lingerSeconds = config.getOption(SO_LINGER);
+ if (lingerSeconds != null) {
+ b.setSocketOptionLingerSeconds(lingerSeconds);
+ }
+
+ Integer timeoutMillis = config.getOption(SO_TIMEOUT);
+ if (timeoutMillis != null) {
+ // in java, SO_TIMEOUT only applies to receiving
+ b.setSocketOptionTimeoutMillis(timeoutMillis);
+ }
+
+ for (Entry<ChannelOption<?>, Object> opt : config.getOptions().entrySet()) {
+ ChannelOption<?> key = opt.getKey();
+ // Constants are pooled, so there should only be one instance of each constant
+ if (key.equals(SO_LINGER) || key.equals(SO_TIMEOUT)) {
+ continue;
+ }
+ Object value = opt.getValue();
+ // zpencer: Can a netty option be null?
+ b.addOption(key.name(), String.valueOf(value));
+ }
+ return b.build();
+ }
+
private Utils() {
// Prevents instantiation
}
diff --git a/netty/src/test/java/io/grpc/netty/UtilsTest.java b/netty/src/test/java/io/grpc/netty/UtilsTest.java
index ead175667..372c451c6 100644
--- a/netty/src/test/java/io/grpc/netty/UtilsTest.java
+++ b/netty/src/test/java/io/grpc/netty/UtilsTest.java
@@ -17,14 +17,23 @@
package io.grpc.netty;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import com.google.common.base.MoreObjects;
import com.google.common.truth.Truth;
import io.grpc.Metadata;
import io.grpc.Status;
+import io.grpc.internal.Channelz;
+import io.grpc.internal.Channelz.SocketOptions;
import io.grpc.internal.GrpcUtil;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelOption;
import io.netty.channel.ConnectTimeoutException;
+import io.netty.channel.WriteBufferWaterMark;
+import io.netty.channel.embedded.EmbeddedChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.channel.socket.oio.OioSocketChannel;
import io.netty.handler.codec.http2.DefaultHttp2Headers;
import io.netty.handler.codec.http2.Http2Error;
import io.netty.handler.codec.http2.Http2Exception;
@@ -118,6 +127,46 @@ public class UtilsTest {
assertEquals(Utils.CONTENT_TYPE_GRPC, headers.get(GrpcUtil.CONTENT_TYPE_KEY.name()));
}
+ @Test
+ public void channelOptionsTest_noLinger() {
+ Channel channel = new EmbeddedChannel();
+ assertNull(channel.config().getOption(ChannelOption.SO_LINGER));
+ Channelz.SocketOptions socketOptions = Utils.getSocketOptions(channel);
+ assertNull(socketOptions.lingerSeconds);
+ }
+
+ @Test
+ public void channelOptionsTest_oio() {
+ Channel channel = new OioSocketChannel();
+ SocketOptions socketOptions = setAndValidateGeneric(channel);
+ assertEquals(250, (int) socketOptions.soTimeoutMillis);
+ }
+
+ @Test
+ public void channelOptionsTest_nio() {
+ Channel channel = new NioSocketChannel();
+ SocketOptions socketOptions = setAndValidateGeneric(channel);
+ assertNull(socketOptions.soTimeoutMillis);
+ }
+
+ private static Channelz.SocketOptions setAndValidateGeneric(Channel channel) {
+ channel.config().setOption(ChannelOption.SO_LINGER, 3);
+ // only applicable for OIO channels:
+ channel.config().setOption(ChannelOption.SO_TIMEOUT, 250);
+ // Test some arbitrarily chosen options with a non numeric values
+ channel.config().setOption(ChannelOption.SO_KEEPALIVE, true);
+ WriteBufferWaterMark writeBufWaterMark = new WriteBufferWaterMark(10, 20);
+ channel.config().setOption(ChannelOption.WRITE_BUFFER_WATER_MARK, writeBufWaterMark);
+
+ Channelz.SocketOptions socketOptions = Utils.getSocketOptions(channel);
+ assertEquals(3, (int) socketOptions.lingerSeconds);
+ assertEquals("true", socketOptions.others.get("SO_KEEPALIVE"));
+ assertEquals(
+ writeBufWaterMark.toString(),
+ socketOptions.others.get(ChannelOption.WRITE_BUFFER_WATER_MARK.toString()));
+ return socketOptions;
+ }
+
private static void assertStatusEquals(Status expected, Status actual) {
assertEquals(expected.getCode(), actual.getCode());
Truth.assertThat(MoreObjects.firstNonNull(actual.getDescription(), ""))