responseObserver) {
+ HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
+ responseObserver.onNext(reply);
+ responseObserver.onCompleted();
+ }
+ }
+}
diff --git a/examples/example-reflection/src/main/proto/helloworld/helloworld.proto b/examples/example-reflection/src/main/proto/helloworld/helloworld.proto
new file mode 100644
index 00000000000..77184aa8326
--- /dev/null
+++ b/examples/example-reflection/src/main/proto/helloworld/helloworld.proto
@@ -0,0 +1,37 @@
+// Copyright 2022 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "io.grpc.examples.helloworld";
+option java_outer_classname = "HelloWorldProto";
+option objc_class_prefix = "HLW";
+
+package helloworld;
+
+// The greeting service definition.
+service Greeter {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply) {}
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+}
+
+// The response message containing the greetings
+message HelloReply {
+ string message = 1;
+}
diff --git a/examples/example-servlet/build.gradle b/examples/example-servlet/build.gradle
index 64b0a8eac10..f6772cda51d 100644
--- a/examples/example-servlet/build.gradle
+++ b/examples/example-servlet/build.gradle
@@ -23,7 +23,7 @@ dependencies {
"io.grpc:grpc-servlet:${grpcVersion}",
"io.grpc:grpc-stub:${grpcVersion}"
- providedImplementation "javax.servlet:javax.servlet-api:4.0.1",
+ compileOnly "javax.servlet:javax.servlet-api:4.0.1",
"org.apache.tomcat:annotations-api:6.0.53"
}
diff --git a/examples/logging.properties b/examples/logging.properties
new file mode 100644
index 00000000000..b807613adcd
--- /dev/null
+++ b/examples/logging.properties
@@ -0,0 +1,8 @@
+# Create a file called logging.properties with the following contents.
+handlers=java.util.logging.ConsoleHandler
+io.grpc.level=FINE
+java.util.logging.ConsoleHandler.level=ALL
+java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
+
+# Pass the location of the file to JVM via this command-line flag
+JAVA_OPTS=-Djava.util.logging.config.file=logging.properties
diff --git a/examples/src/main/java/io/grpc/examples/deadline/DeadlineClient.java b/examples/src/main/java/io/grpc/examples/deadline/DeadlineClient.java
new file mode 100644
index 00000000000..378688ee1cc
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/deadline/DeadlineClient.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2023 The gRPC Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.grpc.examples.deadline;
+
+import io.grpc.Channel;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
+import io.grpc.ManagedChannel;
+import io.grpc.Status;
+import io.grpc.StatusRuntimeException;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+import io.grpc.examples.helloworld.HelloWorldServer;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.SimpleFormatter;
+
+/**
+ * A simple client that requests a greeting from the {@link HelloWorldServer}.
+ *
+ * This is based off the client in the helloworld example with some deadline logic added.
+ */
+public class DeadlineClient {
+ private static final Logger logger = Logger.getLogger(DeadlineClient.class.getName());
+
+ private final GreeterGrpc.GreeterBlockingStub blockingStub;
+
+ /** Construct client for accessing HelloWorld server using the existing channel. */
+ public DeadlineClient(Channel channel) {
+ blockingStub = GreeterGrpc.newBlockingStub(channel);
+ }
+
+ /** Say hello to server. */
+ public Status greet(String name, long timeoutMillis) {
+ logger.info("Will try to greet " + name + " ...");
+ HelloRequest request = HelloRequest.newBuilder().setName(name).build();
+ HelloReply response;
+ try {
+ response = blockingStub.withDeadlineAfter(timeoutMillis, TimeUnit.MILLISECONDS)
+ .sayHello(request);
+ } catch (StatusRuntimeException e) {
+ logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
+ return e.getStatus();
+ }
+ logger.info("Greeting: " + response.getMessage());
+ return Status.OK;
+ }
+
+ /**
+ * Greet server. If provided, the first element of {@code args} is the name to use in the
+ * greeting. The second argument is the target server.
+ */
+ public static void main(String[] args) throws Exception {
+ System.setProperty("java.util.logging.SimpleFormatter.format",
+ "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n");
+
+ // Access a service running on the local machine on port 50051
+ String target = "localhost:50051";
+
+ ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create())
+ .build();
+ try {
+ DeadlineClient client = new DeadlineClient(channel);
+
+ // The server takes 500ms to process the call, so setting a deadline further in the future we
+ // should get a successful response.
+ logger.info("Calling server with a generous deadline, expected to work");
+ client.greet("deadline client", 1000);
+
+ // A smaller deadline will result in us getting a DEADLINE_EXCEEDED error.
+ logger.info(
+ "Calling server with an unrealistic (300ms) deadline, expecting a DEADLINE_EXCEEDED");
+ client.greet("deadline client", 300);
+
+ // Including the "propagate" magic string in the request will cause the server to call itself
+ // to simulate a situation where a server needs to call another server to satisfy the original
+ // request. This will double the time it takes to respond to the client request, but with
+ // an increased deadline we should get a successful response.
+ logger.info("Calling server with propagation and a generous deadline, expected to work");
+ client.greet("deadline client [propagate]", 2000);
+
+ // With this propagated call we reduce the deadline making it impossible for the both the
+ // first server call and the propagated one to succeed. You should see the call fail with
+ // DEADLINE_EXCEEDED, and you should also see DEADLINE_EXCEEDED in the server output as it
+ // runs out of time waiting for the propagated call to finish.
+ logger.info(
+ "Calling server with propagation and a generous deadline, expecting a DEADLINE_EXCEEDED");
+ client.greet("deadline client [propagate]", 1000);
+ } finally {
+ channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
+ }
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/deadline/DeadlineServer.java b/examples/src/main/java/io/grpc/examples/deadline/DeadlineServer.java
new file mode 100644
index 00000000000..49214fc77d5
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/deadline/DeadlineServer.java
@@ -0,0 +1,119 @@
+
+/*
+ * Copyright 2023 The gRPC Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.grpc.examples.deadline;
+
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
+import io.grpc.InsecureServerCredentials;
+import io.grpc.Server;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+import io.grpc.stub.StreamObserver;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+public class DeadlineServer {
+ private static final Logger logger = Logger.getLogger(DeadlineServer.class.getName());
+
+ private Server server;
+
+
+ private void start() throws IOException {
+ int port = 50051;
+ SlowGreeter slowGreeter = new SlowGreeter();
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
+ .addService(slowGreeter)
+ .build()
+ .start();
+ logger.info("Server started, listening on " + port);
+
+ // Create a channel to this same server so we can make a recursive call to demonstrate deadline
+ // propagation.
+ String target = "localhost:50051";
+ slowGreeter.setClientStub(GreeterGrpc.newBlockingStub(
+ Grpc.newChannelBuilder(target, InsecureChannelCredentials.create()).build()));
+
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ // Use stderr here since the logger may have been reset by its JVM shutdown hook.
+ System.err.println("*** shutting down gRPC server since JVM is shutting down");
+ try {
+ DeadlineServer.this.stop();
+ } catch (InterruptedException e) {
+ e.printStackTrace(System.err);
+ }
+ System.err.println("*** server shut down");
+ }
+ });
+ }
+
+ private void stop() throws InterruptedException {
+ if (server != null) {
+ server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
+ }
+ }
+
+ /**
+ * Await termination on the main thread since the grpc library uses daemon threads.
+ */
+ private void blockUntilShutdown() throws InterruptedException {
+ if (server != null) {
+ server.awaitTermination();
+ }
+ }
+
+ /**
+ * Main launches the server from the command line.
+ */
+ public static void main(String[] args) throws IOException, InterruptedException {
+ System.setProperty("java.util.logging.SimpleFormatter.format",
+ "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n");
+
+ final DeadlineServer server = new DeadlineServer();
+ server.start();
+ server.blockUntilShutdown();
+ }
+
+ static class SlowGreeter extends GreeterGrpc.GreeterImplBase {
+ private GreeterGrpc.GreeterBlockingStub clientStub;
+
+ void setClientStub(GreeterGrpc.GreeterBlockingStub clientStub) {
+ this.clientStub = clientStub;
+ }
+
+ @Override
+ public void sayHello(HelloRequest req, StreamObserver responseObserver) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException(e);
+ }
+
+ if (req.getName().contains("propagate")) {
+ clientStub.sayHello(HelloRequest.newBuilder().setName("Server").build());
+ }
+
+ HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
+ responseObserver.onNext(reply);
+ responseObserver.onCompleted();
+ }
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/keepalive/KeepAliveClient.java b/examples/src/main/java/io/grpc/examples/keepalive/KeepAliveClient.java
new file mode 100644
index 00000000000..a7c59c3952f
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/keepalive/KeepAliveClient.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2023 The gRPC Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.grpc.examples.keepalive;
+
+import io.grpc.Channel;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
+import io.grpc.ManagedChannel;
+import io.grpc.StatusRuntimeException;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A simple client that requests a greeting from the {@link KeepAliveServer}.
+ */
+public class KeepAliveClient {
+ private static final Logger logger = Logger.getLogger(KeepAliveClient.class.getName());
+
+ private final GreeterGrpc.GreeterBlockingStub blockingStub;
+
+ /** Construct client for accessing HelloWorld server using the existing channel. */
+ public KeepAliveClient(Channel channel) {
+ // 'channel' here is a Channel, not a ManagedChannel, so it is not this code's responsibility to
+ // shut it down.
+
+ // Passing Channels to code makes code easier to test and makes it easier to reuse Channels.
+ blockingStub = GreeterGrpc.newBlockingStub(channel);
+ }
+
+ /** Say hello to server. */
+ public void greet(String name) {
+ logger.info("Will try to greet " + name + " ...");
+ HelloRequest request = HelloRequest.newBuilder().setName(name).build();
+ HelloReply response;
+ try {
+ response = blockingStub.sayHello(request);
+ } catch (StatusRuntimeException e) {
+ logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
+ return;
+ }
+ logger.info("Greeting: " + response.getMessage());
+ }
+
+ /**
+ * Greet server.
+ */
+ public static void main(String[] args) throws Exception {
+ // Access a service running on the local machine on port 50051
+ String target = "localhost:50051";
+
+ // Create a channel with the following keep alive configurations (demo only, you should set
+ // more appropriate values based on your environment):
+ // keepAliveTime: Send pings every 10 seconds if there is no activity. Set to an appropriate
+ // value in reality, e.g. (5, TimeUnit.MINUTES).
+ // keepAliveTimeout: Wait 1 second for ping ack before considering the connection dead. Set to a
+ // larger value in reality, e.g. (10, TimeUnit.SECONDS). You should only set such a small value,
+ // e.g. (1, TimeUnit.SECONDS) in certain low latency environments.
+ // keepAliveWithoutCalls: Send pings even without active streams. Normally disable it.
+ // Use JAVA_OPTS=-Djava.util.logging.config.file=logging.properties to see the keep alive ping
+ // frames.
+ // More details see: https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md
+ ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create())
+ .keepAliveTime(5, TimeUnit.MINUTES)
+ .keepAliveTime(10, TimeUnit.SECONDS) // Change to a larger value, e.g. 5min.
+ .keepAliveTimeout(1, TimeUnit.SECONDS) // Change to a larger value, e.g. 10s.
+ .keepAliveWithoutCalls(true)// You should normally avoid enabling this.
+ .build();
+
+ try {
+ KeepAliveClient client = new KeepAliveClient(channel);
+ client.greet("Keep-alive Demo");
+ Thread.sleep(30000);
+ } finally {
+ channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
+ }
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/keepalive/KeepAliveServer.java b/examples/src/main/java/io/grpc/examples/keepalive/KeepAliveServer.java
new file mode 100644
index 00000000000..884bbfea532
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/keepalive/KeepAliveServer.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2023 The gRPC Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.grpc.examples.keepalive;
+
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
+import io.grpc.Server;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+import io.grpc.stub.StreamObserver;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+/**
+ * Server that manages startup/shutdown of a keep alive server.
+ */
+public class KeepAliveServer {
+ private static final Logger logger = Logger.getLogger(KeepAliveServer.class.getName());
+
+ private Server server;
+
+ private void start() throws IOException {
+ /* The port on which the server should run */
+ int port = 50051;
+
+ // Start a server with the following configurations (demo only, you should set more appropriate
+ // values based on your real environment):
+ // keepAliveTime: Ping the client if it is idle for 5 seconds to ensure the connection is
+ // still active. Set to an appropriate value in reality, e.g. in minutes.
+ // keepAliveTimeout: Wait 1 second for the ping ack before assuming the connection is dead.
+ // Set to an appropriate value in reality, e.g. (10, TimeUnit.SECONDS).
+ // permitKeepAliveTime: If a client pings more than once every 5 seconds, terminate the
+ // connection.
+ // permitKeepAliveWithoutCalls: Allow pings even when there are no active streams.
+ // maxConnectionIdle: If a client is idle for 15 seconds, send a GOAWAY.
+ // maxConnectionAge: If any connection is alive for more than 30 seconds, send a GOAWAY.
+ // maxConnectionAgeGrace: Allow 5 seconds for pending RPCs to complete before forcibly closing
+ // connections.
+ // Use JAVA_OPTS=-Djava.util.logging.config.file=logging.properties to see keep alive ping
+ // frames.
+ // More details see: https://github.com/grpc/proposal/blob/master/A9-server-side-conn-mgt.md
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
+ .addService(new GreeterImpl())
+ .keepAliveTime(5, TimeUnit.SECONDS)
+ .keepAliveTimeout(1, TimeUnit.SECONDS)
+ .permitKeepAliveTime(5, TimeUnit.SECONDS)
+ .permitKeepAliveWithoutCalls(true)
+ .maxConnectionIdle(15, TimeUnit.SECONDS)
+ .maxConnectionAge(30, TimeUnit.SECONDS)
+ .maxConnectionAgeGrace(5, TimeUnit.SECONDS)
+ .build()
+ .start();
+ logger.info("Server started, listening on " + port);
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ // Use stderr here since the logger may have been reset by its JVM shutdown hook.
+ System.err.println("*** shutting down gRPC server since JVM is shutting down");
+ try {
+ KeepAliveServer.this.stop();
+ } catch (InterruptedException e) {
+ e.printStackTrace(System.err);
+ }
+ System.err.println("*** server shut down");
+ }
+ });
+ }
+
+ private void stop() throws InterruptedException {
+ if (server != null) {
+ server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
+ }
+ }
+
+ /**
+ * Await termination on the main thread since the grpc library uses daemon threads.
+ */
+ private void blockUntilShutdown() throws InterruptedException {
+ if (server != null) {
+ server.awaitTermination();
+ }
+ }
+
+ /**
+ * Main launches the server from the command line.
+ */
+ public static void main(String[] args) throws IOException, InterruptedException {
+ final KeepAliveServer server = new KeepAliveServer();
+ server.start();
+ server.blockUntilShutdown();
+ }
+
+ static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
+
+ @Override
+ public void sayHello(HelloRequest req, StreamObserver responseObserver) {
+ HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
+ responseObserver.onNext(reply);
+ responseObserver.onCompleted();
+ }
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/multiplex/EchoServer.java b/examples/src/main/java/io/grpc/examples/multiplex/EchoServer.java
new file mode 100644
index 00000000000..cf8f6fdb7fe
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/multiplex/EchoServer.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2015 The gRPC Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.grpc.examples.multiplex;
+
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
+import io.grpc.Server;
+import io.grpc.examples.echo.EchoGrpc;
+import io.grpc.examples.echo.EchoRequest;
+import io.grpc.examples.echo.EchoResponse;
+import io.grpc.stub.StreamObserver;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+/**
+ * Server that manages startup/shutdown of a {@code Greeter} server.
+ */
+public class EchoServer extends EchoGrpc.EchoImplBase{
+ private static final Logger logger = Logger.getLogger(EchoServer.class.getName());
+
+ @Override
+ public void unaryEcho(EchoRequest request,
+ StreamObserver responseObserver) {
+ EchoResponse response = EchoResponse.newBuilder().setMessage(request.getMessage()).build();
+ responseObserver.onNext(response);
+ }
+
+ @Override
+ public void serverStreamingEcho(EchoRequest request,
+ StreamObserver responseObserver) {
+ EchoResponse response = EchoResponse.newBuilder().setMessage(request.getMessage()).build();
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public StreamObserver clientStreamingEcho(
+ final StreamObserver responseObserver) {
+ return new StreamObserver() {
+ List requestList = new ArrayList<>();
+
+ @Override
+ public void onNext(EchoRequest request) {
+ requestList.add(request.getMessage());
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ logger.log(Level.WARNING, "echo stream cancelled");
+ }
+
+ @Override
+ public void onCompleted() {
+ String reply = requestList.stream().collect(Collectors.joining(", "));
+ EchoResponse response = EchoResponse.newBuilder().setMessage(reply).build();
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+ }
+ };
+ }
+
+ @Override
+ public StreamObserver bidirectionalStreamingEcho(
+ final StreamObserver responseObserver) {
+ return new StreamObserver() {
+ @Override
+ public void onNext(EchoRequest request) {
+ EchoResponse response = EchoResponse.newBuilder().setMessage(request.getMessage()).build();
+ responseObserver.onNext(response);
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ logger.log(Level.WARNING, "echo stream cancelled");
+ }
+
+ @Override
+ public void onCompleted() {
+ responseObserver.onCompleted();
+ }
+ };
+ }
+}
diff --git a/examples/src/main/java/io/grpc/examples/multiplex/MultiplexingServer.java b/examples/src/main/java/io/grpc/examples/multiplex/MultiplexingServer.java
new file mode 100644
index 00000000000..f5607c287f6
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/multiplex/MultiplexingServer.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 The gRPC Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.grpc.examples.multiplex;
+
+import io.grpc.Grpc;
+import io.grpc.InsecureServerCredentials;
+import io.grpc.Server;
+import io.grpc.ServerBuilder;
+import io.grpc.StatusRuntimeException;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+import io.grpc.examples.echo.EchoGrpc;
+import io.grpc.examples.echo.EchoRequest;
+import io.grpc.examples.echo.EchoResponse;
+import io.grpc.stub.StreamObserver;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+/**
+ * A sample gRPC server that serves both the Greeting and Echo services.
+ */
+public class MultiplexingServer {
+
+ private static final Logger logger = Logger.getLogger(MultiplexingServer.class.getName());
+
+ private final int port;
+ private Server server = null;
+
+ public MultiplexingServer(int port) throws IOException {
+ this.port = port;
+ }
+ private void start() throws IOException {
+ /* The port on which the server should run */
+ server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
+ .addService(new io.grpc.examples.multiplex.MultiplexingServer.GreeterImpl())
+ .addService(new io.grpc.examples.multiplex.EchoServer())
+ .build()
+ .start();
+ logger.info("Server started, listening on " + port);
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ // Use stderr here since the logger may have been reset by its JVM shutdown hook.
+ System.err.println("*** shutting down gRPC server since JVM is shutting down");
+ try {
+ io.grpc.examples.multiplex.MultiplexingServer.this.stop();
+ } catch (InterruptedException e) {
+ e.printStackTrace(System.err);
+ }
+ System.err.println("*** server shut down");
+ }
+ });
+ }
+
+ private void stop() throws InterruptedException {
+ if (server != null) {
+ server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
+ }
+ }
+
+ /**
+ * Await termination on the main thread since the grpc library uses daemon threads.
+ */
+ private void blockUntilShutdown() throws InterruptedException {
+ if (server != null) {
+ server.awaitTermination();
+ }
+ }
+
+ /**
+ * Main launches the server from the command line.
+ */
+ public static void main(String[] args) throws IOException, InterruptedException {
+ final MultiplexingServer server = new MultiplexingServer(50051);
+ server.start();
+ server.blockUntilShutdown();
+ }
+
+ static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
+
+ @Override
+ public void sayHello(HelloRequest req, StreamObserver responseObserver) {
+ HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
+ responseObserver.onNext(reply);
+ responseObserver.onCompleted();
+ }
+ }
+ }
diff --git a/examples/src/main/java/io/grpc/examples/multiplex/SharingClient.java b/examples/src/main/java/io/grpc/examples/multiplex/SharingClient.java
new file mode 100644
index 00000000000..dd087f4a04b
--- /dev/null
+++ b/examples/src/main/java/io/grpc/examples/multiplex/SharingClient.java
@@ -0,0 +1,195 @@
+
+/*
+ * Copyright 2015 The gRPC Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.grpc.examples.multiplex;
+
+import com.google.common.collect.ImmutableList;
+import io.grpc.Channel;
+import io.grpc.Grpc;
+import io.grpc.InsecureChannelCredentials;
+import io.grpc.ManagedChannel;
+import io.grpc.Status;
+import io.grpc.StatusRuntimeException;
+import io.grpc.examples.helloworld.GreeterGrpc;
+import io.grpc.examples.helloworld.HelloReply;
+import io.grpc.examples.helloworld.HelloRequest;
+import io.grpc.examples.echo.EchoGrpc;
+import io.grpc.examples.echo.EchoRequest;
+import io.grpc.examples.echo.EchoResponse;
+import io.grpc.examples.helloworld.HelloWorldClient;
+import io.grpc.stub.StreamObserver;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A client that shares a channel across multiple stubs to a single service and across services
+ * being provided by one server process.
+ */
+public class SharingClient {
+ private static final Logger logger = Logger.getLogger(
+ HelloWorldClient.class.getName());
+
+ private final GreeterGrpc.GreeterBlockingStub greeterStub1;
+ private final GreeterGrpc.GreeterBlockingStub greeterStub2;
+ private final EchoGrpc.EchoStub echoStub;
+
+ private Random random = new Random();
+
+ /** Construct client for accessing HelloWorld server using the existing channel. */
+ public SharingClient(Channel channel) {
+ // 'channel' here is a Channel, not a ManagedChannel, so it is not this code's responsibility to
+ // shut it down.
+
+ // Passing Channels to code makes code easier to test and makes it easier to reuse Channels.
+ greeterStub1 = GreeterGrpc.newBlockingStub(channel);
+ greeterStub2 = GreeterGrpc.newBlockingStub(channel);
+ echoStub = EchoGrpc.newStub(channel);
+ }
+
+ /** Say hello to server. */
+ private void greet(String name, GreeterGrpc.GreeterBlockingStub stub, String stubName) {
+ logger.info("Will try to greet " + name + " using " + stubName);
+ HelloRequest request = HelloRequest.newBuilder().setName(name).build();
+ HelloReply response;
+ try {
+ response = stub.sayHello(request);
+ } catch (StatusRuntimeException e) {
+ logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
+ return;
+ }
+ logger.info("Greeting: " + response.getMessage());
+ }
+
+ public void greet1(String name) {
+ greet(name, greeterStub1, "greeter #1");
+ }
+
+ public void greet2(String name) {
+ greet(name, greeterStub2, "greeter #2");
+ }
+
+ public CountDownLatch initiateEchos(List valuesToSend, final List valuesReceived) {
+ final CountDownLatch finishLatch = new CountDownLatch(1);
+ StreamObserver responseObserver = new StreamObserver() {
+ @Override
+ public void onNext(EchoResponse response) {
+ valuesReceived.add(response.getMessage());
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ logger.warning("Echo Failed: {0}" + Status.fromThrowable(t));
+ finishLatch.countDown();
+ }
+
+ @Override
+ public void onCompleted() {
+ logger.info("Finished RecordRoute");
+ finishLatch.countDown();
+ }
+ };
+
+ StreamObserver requestObserver =
+ echoStub.bidirectionalStreamingEcho(responseObserver);
+ try {
+ for (String curValue : valuesToSend) {
+ EchoRequest req = EchoRequest.newBuilder().setMessage(curValue).build();
+ requestObserver.onNext(req);
+ // Sleep for a bit before sending the next one.
+ Thread.sleep(random.nextInt(1000) + 500);
+ if (finishLatch.getCount() == 0) {
+ // RPC completed or errored before we finished sending.
+ // Sending further requests won't error, but they will just be thrown away.
+ return finishLatch;
+ }
+ }
+ } catch (RuntimeException e) {
+ // Cancel RPC
+ requestObserver.onError(e);
+ throw e;
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ requestObserver.onError(e);
+ }
+ // Mark the end of requests
+ requestObserver.onCompleted();
+
+ return finishLatch;
+ }
+
+ /**
+ * Greet server. If provided, the first element of {@code args} is the name to use in the
+ * greeting. The second argument is the target server.
+ */
+ public static void main(String[] args) throws Exception {
+ String user = "world";
+ // Access a service running on the local machine on port 50051
+ String target = "localhost:50051";
+ // Allow passing in the user and target strings as command line arguments
+ if (args.length > 0) {
+ if ("--help".equals(args[0])) {
+ System.err.println("Usage: [name [target]]");
+ System.err.println("");
+ System.err.println(" name The name you wish to be greeted by. Defaults to " + user);
+ System.err.println(" target The server to connect to. Defaults to " + target);
+ System.exit(1);
+ }
+ user = args[0];
+ }
+ if (args.length > 1) {
+ target = args[1];
+ }
+
+ // Create a communication channel to the server, known as a Channel. Channels are thread-safe
+ // and reusable. It is common to create channels at the beginning of your application and reuse
+ // them until the application shuts down.
+ //
+ // For the example we use plaintext insecure credentials to avoid needing TLS certificates. To
+ // use TLS, use TlsChannelCredentials instead.
+ ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create())
+ .build();
+ List echoInput = ImmutableList.of("some", "thing", "wicked", "this", "way", "comes");
+ List echoOutput = new ArrayList<>();
+ try {
+ SharingClient client = new SharingClient(channel);
+
+ CountDownLatch finishLatch = client.initiateEchos(echoInput, echoOutput);
+ client.greet1(user + " the great");
+ client.greet2(user + " the lesser");
+ client.greet1(user + " the humble");
+ // Receiving happens asynchronously
+ if (!finishLatch.await(1, TimeUnit.MINUTES)) {
+ logger.warning("Echo did not finish within 1 minute");
+ }
+
+ System.out.println("The echo requests and results were:");
+ System.out.println(echoInput.toString());
+ System.out.println(echoOutput.toString());
+ } finally {
+ // ManagedChannels use resources like threads and TCP connections. To prevent leaking these
+ // resources the channel should be shut down when it will no longer be used. If it may be used
+ // again leave it running.
+ channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
+ }
+ }
+}
diff --git a/examples/src/main/proto/echo.proto b/examples/src/main/proto/echo.proto
new file mode 100644
index 00000000000..0668eb55bcc
--- /dev/null
+++ b/examples/src/main/proto/echo.proto
@@ -0,0 +1,48 @@
+/*
+ *
+ * Copyright 2023 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "io.grpc.examples.echo";
+option java_outer_classname = "EchoProto";
+option objc_class_prefix = "ECHO";
+
+package echo;
+
+// EchoRequest is the request for echo.
+message EchoRequest {
+ string message = 1;
+}
+
+// EchoResponse is the response for echo.
+message EchoResponse {
+ string message = 1;
+}
+
+// Echo is the echo service.
+service Echo {
+ // UnaryEcho is unary echo.
+ rpc UnaryEcho(EchoRequest) returns (EchoResponse) {}
+ // ServerStreamingEcho is server side streaming.
+ rpc ServerStreamingEcho(EchoRequest) returns (stream EchoResponse) {}
+ // ClientStreamingEcho is client side streaming.
+ rpc ClientStreamingEcho(stream EchoRequest) returns (EchoResponse) {}
+ // BidirectionalStreamingEcho is bidi streaming.
+ rpc BidirectionalStreamingEcho(stream EchoRequest) returns (stream EchoResponse) {}
+}
\ No newline at end of file
diff --git a/gcp-observability/build.gradle b/gcp-observability/build.gradle
index 85e6e9eeb01..63850efc4e8 100644
--- a/gcp-observability/build.gradle
+++ b/gcp-observability/build.gradle
@@ -20,11 +20,13 @@ tasks.named("compileJava").configure {
}
dependencies {
- def cloudLoggingVersion = '3.6.1'
+ def cloudLoggingVersion = '3.14.5'
annotationProcessor libraries.auto.value
api project(':grpc-api')
-
+
+ // TODO(dnvindhya): Prefer using our own libraries, update the dependencies
+ // in gradle/libs.versions instead
implementation project(':grpc-protobuf'),
project(':grpc-stub'),
project(':grpc-alts'),
@@ -35,12 +37,10 @@ dependencies {
libraries.opencensus.exporter.trace.stackdriver,
project(':grpc-xds'), // Align grpc versions
project(':grpc-services'), // Align grpc versions
- libraries.animalsniffer.annotations, // Prefer our version
- libraries.google.auth.credentials, // Prefer our version
- libraries.protobuf.java.util, // Prefer our version
- libraries.gson, // Prefer our version
- libraries.perfmark.api, // Prefer our version
- libraries.re2j, // Prefer our version
+ ('com.google.protobuf:protobuf-java:3.21.12'),
+ ('com.google.api.grpc:proto-google-common-protos:2.14.2'),
+ ('com.google.auth:google-auth-library-oauth2-http:1.16.0'),
+ ('io.opencensus:opencensus-api:0.31.1'),
('com.google.guava:guava:31.1-jre')
runtimeOnly libraries.opencensus.impl
diff --git a/gcp-observability/src/main/java/io/grpc/gcp/observability/interceptors/LogHelper.java b/gcp-observability/src/main/java/io/grpc/gcp/observability/interceptors/LogHelper.java
index 9b46699efaf..abd44c43650 100644
--- a/gcp-observability/src/main/java/io/grpc/gcp/observability/interceptors/LogHelper.java
+++ b/gcp-observability/src/main/java/io/grpc/gcp/observability/interceptors/LogHelper.java
@@ -23,6 +23,7 @@
import com.google.common.base.Joiner;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
+import com.google.rpc.Code;
import io.grpc.Attributes;
import io.grpc.Deadline;
import io.grpc.Grpc;
@@ -182,7 +183,7 @@ void logTrailer(
PayloadBuilderHelper pair =
createMetadataProto(metadata, maxHeaderBytes);
- pair.payloadBuilder.setStatusCode(status.getCode().value());
+ pair.payloadBuilder.setStatusCode(Code.forNumber(status.getCode().value()));
String statusDescription = status.getDescription();
if (statusDescription != null) {
pair.payloadBuilder.setStatusMessage(statusDescription);
@@ -404,10 +405,10 @@ static Address socketAddressToProto(SocketAddress address) {
if (address instanceof InetSocketAddress) {
InetAddress inetAddress = ((InetSocketAddress) address).getAddress();
if (inetAddress instanceof Inet4Address) {
- builder.setType(Address.Type.TYPE_IPV4)
+ builder.setType(Address.Type.IPV4)
.setAddress(InetAddressUtil.toAddrString(inetAddress));
} else if (inetAddress instanceof Inet6Address) {
- builder.setType(Address.Type.TYPE_IPV6)
+ builder.setType(Address.Type.IPV6)
.setAddress(InetAddressUtil.toAddrString(inetAddress));
} else {
logger.log(Level.SEVERE, "unknown type of InetSocketAddress: {}", address);
@@ -417,7 +418,7 @@ static Address socketAddressToProto(SocketAddress address) {
} else if (address.getClass().getName().equals("io.netty.channel.unix.DomainSocketAddress")) {
// To avoid a compiled time dependency on grpc-netty, we check against the
// runtime class name.
- builder.setType(Address.Type.TYPE_UNIX)
+ builder.setType(Address.Type.UNIX)
.setAddress(address.toString());
} else {
builder.setType(Address.Type.TYPE_UNKNOWN).setAddress(address.toString());
diff --git a/gcp-observability/src/main/java/io/grpc/gcp/observability/logging/GcpLogSink.java b/gcp-observability/src/main/java/io/grpc/gcp/observability/logging/GcpLogSink.java
index e91f310e647..02ff4049eb4 100644
--- a/gcp-observability/src/main/java/io/grpc/gcp/observability/logging/GcpLogSink.java
+++ b/gcp-observability/src/main/java/io/grpc/gcp/observability/logging/GcpLogSink.java
@@ -18,12 +18,15 @@
import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.api.gax.batching.BatchingSettings;
+import com.google.api.gax.batching.FlowController;
import com.google.cloud.MonitoredResource;
import com.google.cloud.logging.LogEntry;
import com.google.cloud.logging.Logging;
import com.google.cloud.logging.LoggingOptions;
import com.google.cloud.logging.Payload.JsonPayload;
import com.google.cloud.logging.Severity;
+import com.google.cloud.logging.v2.stub.LoggingServiceV2StubSettings;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
@@ -41,6 +44,7 @@
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.threeten.bp.Duration;
/**
* Sink for Google Cloud Logging.
@@ -102,6 +106,7 @@ public void write(GrpcLogRecord logProto) {
if (servicesToExclude.contains(logProto.getServiceName())) {
return;
}
+ LogEntry grpcLogEntry = null;
try {
GrpcLogRecord.EventType eventType = logProto.getType();
// TODO(DNVindhya): make sure all (int, long) values are not displayed as double
@@ -117,11 +122,18 @@ public void write(GrpcLogRecord logProto) {
if (!customTags.isEmpty()) {
grpcLogEntryBuilder.setLabels(customTags);
}
- LogEntry grpcLogEntry = grpcLogEntryBuilder.build();
+ grpcLogEntry = grpcLogEntryBuilder.build();
synchronized (this) {
logger.log(Level.FINEST, "Writing gRPC event : {0} to Cloud Logging", eventType);
gcpLoggingClient.write(Collections.singleton(grpcLogEntry));
}
+ } catch (FlowController.FlowControlRuntimeException e) {
+ String grpcLogEntryString = null;
+ if (grpcLogEntry != null) {
+ grpcLogEntryString = grpcLogEntry.toStructuredJsonString();
+ }
+ logger.log(Level.SEVERE, "Limit exceeded while writing log entry to cloud logging");
+ logger.log(Level.SEVERE, "Log entry = ", grpcLogEntryString);
} catch (Exception e) {
logger.log(Level.SEVERE, "Caught exception while writing to Cloud Logging", e);
}
@@ -132,6 +144,16 @@ Logging createLoggingClient() {
if (!Strings.isNullOrEmpty(projectId)) {
builder.setProjectId(projectId);
}
+ BatchingSettings loggingDefaultBatchingSettings = LoggingServiceV2StubSettings.newBuilder()
+ .writeLogEntriesSettings().getBatchingSettings();
+ // Custom batching settings
+ BatchingSettings grpcLoggingVBatchingSettings = loggingDefaultBatchingSettings.toBuilder()
+ .setDelayThreshold(Duration.ofSeconds(1L)).setFlowControlSettings(
+ loggingDefaultBatchingSettings.getFlowControlSettings().toBuilder()
+ .setMaxOutstandingRequestBytes(52428800L) //50 MiB
+ .setLimitExceededBehavior(FlowController.LimitExceededBehavior.ThrowException)
+ .build()).build();
+ builder.setBatchingSettings(grpcLoggingVBatchingSettings);
return builder.build().getService();
}
diff --git a/gcp-observability/src/main/proto/grpc/observabilitylog/v1/observabilitylog.proto b/gcp-observability/src/main/proto/grpc/observabilitylog/v1/observabilitylog.proto
index 85ef00ac2dd..7d278aa08a9 100644
--- a/gcp-observability/src/main/proto/grpc/observabilitylog/v1/observabilitylog.proto
+++ b/gcp-observability/src/main/proto/grpc/observabilitylog/v1/observabilitylog.proto
@@ -20,6 +20,7 @@ package grpc.observabilitylog.v1;
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
+import "google/rpc/code.proto";
option java_multiple_files = true;
option java_package = "io.grpc.observabilitylog.v1";
@@ -97,7 +98,7 @@ message Payload {
// the RPC timeout value
google.protobuf.Duration timeout = 2;
// The gRPC status code
- uint32 status_code = 3;
+ google.rpc.Code status_code = 3;
// The gRPC status message
string status_message = 4;
// The value of the grpc-status-details-bin metadata key, if any.
@@ -115,9 +116,9 @@ message Payload {
message Address {
enum Type {
TYPE_UNKNOWN = 0;
- TYPE_IPV4 = 1; // in 1.2.3.4 form
- TYPE_IPV6 = 2; // IPv6 canonical form (RFC5952 section 4)
- TYPE_UNIX = 3; // UDS string
+ IPV4 = 1; // in 1.2.3.4 form
+ IPV6 = 2; // IPv6 canonical form (RFC5952 section 4)
+ UNIX = 3; // UDS string
}
Type type = 1;
string address = 2;
diff --git a/gcp-observability/src/test/java/io/grpc/gcp/observability/interceptors/LogHelperTest.java b/gcp-observability/src/test/java/io/grpc/gcp/observability/interceptors/LogHelperTest.java
index 73704eb4181..a6d9fab702f 100644
--- a/gcp-observability/src/test/java/io/grpc/gcp/observability/interceptors/LogHelperTest.java
+++ b/gcp-observability/src/test/java/io/grpc/gcp/observability/interceptors/LogHelperTest.java
@@ -29,6 +29,7 @@
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import com.google.protobuf.util.Durations;
+import com.google.rpc.Code;
import io.grpc.Attributes;
import io.grpc.Grpc;
import io.grpc.Metadata;
@@ -94,7 +95,7 @@ public void socketToProto_ipv4() throws Exception {
assertThat(LogHelper.socketAddressToProto(socketAddress))
.isEqualTo(Address
.newBuilder()
- .setType(Address.Type.TYPE_IPV4)
+ .setType(Address.Type.IPV4)
.setAddress("127.0.0.1")
.setIpPort(12345)
.build());
@@ -109,7 +110,7 @@ public void socketToProto_ipv6() throws Exception {
assertThat(LogHelper.socketAddressToProto(socketAddress))
.isEqualTo(Address
.newBuilder()
- .setType(Address.Type.TYPE_IPV6)
+ .setType(Address.Type.IPV6)
.setAddress("2001:db8::2:1") // RFC 5952 section 4: ipv6 canonical form required
.setIpPort(12345)
.build());
@@ -454,7 +455,7 @@ public void logTrailer() throws Exception {
builder.setPeer(LogHelper.socketAddressToProto(peer));
builder.setPayload(
builder.getPayload().toBuilder()
- .setStatusCode(Status.INTERNAL.getCode().value())
+ .setStatusCode(Code.forNumber(Status.INTERNAL.getCode().value()))
.setStatusMessage("test description")
.build());
GrpcLogRecord base = builder.build();