├── server ├── startserver.sh ├── .settings │ ├── org.eclipse.m2e.core.prefs │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.core.resources.prefs ├── README.md ├── .project ├── src │ └── main │ │ ├── proto │ │ └── helloworld.proto │ │ └── java │ │ └── io │ │ └── grpc │ │ └── examples │ │ └── helloworld │ │ ├── GrpcViews.java │ │ ├── HelloWorldServer.java │ │ └── HelloWorldClient.java ├── .classpath └── pom.xml ├── .gitignore ├── proto └── helloworld.proto ├── client └── main.go └── README.md /server/startserver.sh: -------------------------------------------------------------------------------- 1 | mvn verify && mvn exec:java -Dexec.mainClass=io.grpc.examples.helloworld.HelloWorldServer -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven (examples) 2 | target 3 | 4 | # IntelliJ IDEA 5 | .idea 6 | *.iml 7 | 8 | # OS X 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /server/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /server/README.md: -------------------------------------------------------------------------------- 1 | # QuickStart 2 | 3 | ``` 4 | $ mvn verify 5 | $ # Run the server 6 | $ mvn exec:java -Dexec.mainClass=io.grpc.examples.helloworld.HelloWorldServer 7 | $ # In another terminal run the client 8 | $ mvn exec:java -Dexec.mainClass=io.grpc.examples.helloworld.HelloWorldClient 9 | ``` -------------------------------------------------------------------------------- /server/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 3 | org.eclipse.jdt.core.compiler.compliance=1.5 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.5 6 | -------------------------------------------------------------------------------- /server/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/proto=UTF-8 4 | encoding//target/generated-sources/protobuf/grpc-java=UTF-8 5 | encoding//target/generated-sources/protobuf/java=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /server/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | examples 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2017, OpenCensus Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | option java_multiple_files = true; 18 | option java_package = "io.grpc.examples.helloworld"; 19 | option java_outer_classname = "HelloWorldProto"; 20 | 21 | package helloworld; 22 | 23 | // The greeting service definition. 24 | service Greeter { 25 | // Sends a greeting 26 | rpc SayHello (HelloRequest) returns (HelloReply) {} 27 | } 28 | 29 | // The request message containing the user's name. 30 | message HelloRequest { 31 | string name = 1; 32 | } 33 | 34 | // The response message containing the greetings 35 | message HelloReply { 36 | string message = 1; 37 | } 38 | -------------------------------------------------------------------------------- /server/src/main/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015, gRPC Authors 2 | // All rights reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | syntax = "proto3"; 16 | 17 | option java_multiple_files = true; 18 | option java_package = "io.grpc.examples.helloworld"; 19 | option java_outer_classname = "HelloWorldProto"; 20 | option objc_class_prefix = "HLW"; 21 | 22 | package helloworld; 23 | 24 | // The greeting service definition. 25 | service Greeter { 26 | // Sends a greeting 27 | rpc SayHello (HelloRequest) returns (HelloReply) {} 28 | } 29 | 30 | // The request message containing the user's name. 31 | message HelloRequest { 32 | string name = 1; 33 | } 34 | 35 | // The response message containing the greetings 36 | message HelloReply { 37 | string message = 1; 38 | } 39 | -------------------------------------------------------------------------------- /server/src/main/java/io/grpc/examples/helloworld/GrpcViews.java: -------------------------------------------------------------------------------- 1 | package io.grpc.examples.helloworld; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import io.opencensus.contrib.grpc.metrics.RpcViewConstants; 5 | import io.opencensus.stats.Stats; 6 | import io.opencensus.stats.View; 7 | import java.util.Set; 8 | 9 | final class GrpcViews { 10 | private static final Set RPC_VIEW_SET = 11 | ImmutableSet.of( 12 | RpcViewConstants.RPC_CLIENT_ERROR_COUNT_VIEW, 13 | RpcViewConstants.RPC_CLIENT_ROUNDTRIP_LATENCY_VIEW, 14 | RpcViewConstants.RPC_CLIENT_REQUEST_BYTES_VIEW, 15 | RpcViewConstants.RPC_CLIENT_RESPONSE_BYTES_VIEW, 16 | RpcViewConstants.RPC_CLIENT_REQUEST_COUNT_VIEW, 17 | RpcViewConstants.RPC_CLIENT_RESPONSE_COUNT_VIEW, 18 | RpcViewConstants.RPC_CLIENT_UNCOMPRESSED_REQUEST_BYTES_VIEW, 19 | RpcViewConstants.RPC_CLIENT_UNCOMPRESSED_RESPONSE_BYTES_VIEW, 20 | RpcViewConstants.RPC_CLIENT_SERVER_ELAPSED_TIME_VIEW, 21 | RpcViewConstants.RPC_SERVER_ERROR_COUNT_VIEW, 22 | RpcViewConstants.RPC_SERVER_SERVER_LATENCY_VIEW, 23 | RpcViewConstants.RPC_SERVER_SERVER_ELAPSED_TIME_VIEW, 24 | RpcViewConstants.RPC_SERVER_REQUEST_BYTES_VIEW, 25 | RpcViewConstants.RPC_SERVER_RESPONSE_BYTES_VIEW, 26 | RpcViewConstants.RPC_SERVER_REQUEST_COUNT_VIEW, 27 | RpcViewConstants.RPC_SERVER_RESPONSE_COUNT_VIEW, 28 | RpcViewConstants.RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES_VIEW, 29 | RpcViewConstants.RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES_VIEW); 30 | 31 | static void registerViews() { 32 | for (View view : RPC_VIEW_SET) { 33 | Stats.getViewManager().registerView(view); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /server/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /client/main.go: -------------------------------------------------------------------------------- 1 | // Package client contains a demo gRPC Go client 2 | // with OpenCensus enabled to collect metrics and 3 | // report traces for the outgoing RPCs. 4 | package main 5 | 6 | import ( 7 | "context" 8 | "log" 9 | "math/rand" 10 | "net/http" 11 | "strings" 12 | "time" 13 | 14 | "google.golang.org/grpc" 15 | 16 | "go.opencensus.io/exporter/prometheus" 17 | "go.opencensus.io/exporter/stackdriver" 18 | "go.opencensus.io/plugin/ocgrpc" 19 | "go.opencensus.io/stats/view" 20 | "go.opencensus.io/trace" 21 | "go.opencensus.io/zpages" 22 | 23 | pb "go.opencensus.io/examples/grpc/proto" 24 | ) 25 | 26 | func main() { 27 | prometheusExporter, stackdriverExporter := exporters() 28 | view.RegisterExporter(prometheusExporter) 29 | trace.RegisterExporter(stackdriverExporter) 30 | 31 | // Subscribe to collect client request count as a distribution 32 | // and the count of the errored RPCs. 33 | if err := view.Register( 34 | ocgrpc.ClientRoundTripLatencyView, 35 | ocgrpc.ClientErrorCountView, 36 | ); err != nil { 37 | log.Fatal(err) 38 | } 39 | 40 | go func() { 41 | // Serve the prometheus metrics endpoint at localhost:9999. 42 | http.Handle("/metrics", prometheusExporter) 43 | http.Handle("/debug", http.StripPrefix("/debug/", zpages.Handler)) 44 | log.Fatal(http.ListenAndServe(":9999", nil)) 45 | }() 46 | 47 | view.SetReportingPeriod(1 * time.Second) 48 | 49 | // Set up a connection to the server with the OpenCensus 50 | // stats handler to enable stats and tracing. 51 | conn, err := grpc.Dial( 52 | "localhost:50051", 53 | grpc.WithStatsHandler(&ocgrpc.ClientHandler{}), 54 | grpc.WithInsecure(), 55 | ) 56 | if err != nil { 57 | log.Fatalf("Failed to connect: %v", err) 58 | } 59 | defer conn.Close() 60 | c := pb.NewGreeterClient(conn) 61 | 62 | // For demoing purposes, always sample. 63 | trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) 64 | 65 | ctx := context.Background() 66 | for { 67 | resp, err := c.SayHello(ctx, &pb.HelloRequest{Name: strings.Repeat("*", rand.Intn(1<<16))}) 68 | if err != nil { 69 | log.Printf("Failed to send request: %v", err) 70 | } else { 71 | log.Printf("Recieved %v", resp.Message) 72 | } 73 | time.Sleep(100 * time.Millisecond) 74 | } 75 | } 76 | 77 | func exporters() (*prometheus.Exporter, *stackdriver.Exporter) { 78 | pe, err := prometheus.NewExporter(prometheus.Options{ 79 | Namespace: "kubecon_demo", 80 | }) 81 | if err != nil { 82 | log.Fatal(err) 83 | } 84 | se, err := stackdriver.NewExporter(stackdriver.Options{ 85 | ProjectID: "jbdtalks", 86 | }) 87 | if err != nil { 88 | log.Fatal(err) 89 | } 90 | return pe, se 91 | } 92 | -------------------------------------------------------------------------------- /server/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, gRPC Authors All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.grpc.examples.helloworld; 18 | 19 | import io.grpc.Server; 20 | import io.grpc.ServerBuilder; 21 | import io.grpc.stub.StreamObserver; 22 | import io.opencensus.common.Duration; 23 | import io.opencensus.contrib.zpages.ZPageHandlers; 24 | import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter; 25 | import io.opencensus.exporter.trace.stackdriver.StackdriverExporter; 26 | import java.io.IOException; 27 | import java.util.concurrent.ThreadLocalRandom; 28 | import java.util.logging.Logger; 29 | 30 | /** Server that manages startup/shutdown of a {@code Greeter} server. */ 31 | public class HelloWorldServer { 32 | private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName()); 33 | 34 | private Server server; 35 | 36 | private void start() throws IOException { 37 | /* The port on which the server should run */ 38 | int port = 50051; 39 | server = ServerBuilder.forPort(port).addService(new GreeterImpl()).build().start(); 40 | logger.info("Server started, listening on " + port); 41 | Runtime.getRuntime() 42 | .addShutdownHook( 43 | new Thread() { 44 | @Override 45 | public void run() { 46 | // Use stderr here since the logger may have been reset by its JVM shutdown hook. 47 | System.err.println("*** shutting down gRPC server since JVM is shutting down"); 48 | HelloWorldServer.this.stop(); 49 | System.err.println("*** server shut down"); 50 | } 51 | }); 52 | } 53 | 54 | private void stop() { 55 | if (server != null) { 56 | server.shutdown(); 57 | } 58 | } 59 | 60 | /** Await termination on the main thread since the grpc library uses daemon threads. */ 61 | private void blockUntilShutdown() throws InterruptedException { 62 | if (server != null) { 63 | server.awaitTermination(); 64 | } 65 | } 66 | 67 | /** Main launches the server from the command line. */ 68 | public static void main(String[] args) throws IOException, InterruptedException { 69 | GrpcViews.registerViews(); 70 | ZPageHandlers.startHttpServerAndRegisterAll(60002); 71 | StackdriverExporter.createAndRegisterWithProjectId("jbdtalks"); 72 | StackdriverStatsExporter.createAndRegisterWithProjectId( 73 | "jbdtalks", 74 | Duration.create(10, 0)); 75 | final HelloWorldServer server = new HelloWorldServer(); 76 | server.start(); 77 | server.blockUntilShutdown(); 78 | } 79 | 80 | static class GreeterImpl extends GreeterGrpc.GreeterImplBase { 81 | 82 | @Override 83 | public void sayHello(HelloRequest req, StreamObserver responseObserver) { 84 | try { 85 | int random = ThreadLocalRandom.current().nextInt(0, 30); 86 | Thread.sleep(20 + random); // simulate latency 87 | } catch (InterruptedException e) { 88 | e.printStackTrace(); 89 | } 90 | HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); 91 | responseObserver.onNext(reply); 92 | responseObserver.onCompleted(); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /server/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, gRPC Authors All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.grpc.examples.helloworld; 18 | 19 | import io.grpc.ManagedChannel; 20 | import io.grpc.ManagedChannelBuilder; 21 | import io.grpc.StatusRuntimeException; 22 | import io.opencensus.common.Duration; 23 | import io.opencensus.contrib.zpages.ZPageHandlers; 24 | import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter; 25 | import io.opencensus.exporter.trace.stackdriver.StackdriverExporter; 26 | import java.util.concurrent.TimeUnit; 27 | import java.util.logging.Level; 28 | import java.util.logging.Logger; 29 | 30 | /** A simple client that requests a greeting from the {@link HelloWorldServer}. */ 31 | public class HelloWorldClient { 32 | private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName()); 33 | 34 | private final ManagedChannel channel; 35 | private final GreeterGrpc.GreeterBlockingStub blockingStub; 36 | 37 | /** Construct client connecting to HelloWorld server at {@code host:port}. */ 38 | public HelloWorldClient(String host, int port) { 39 | this( 40 | ManagedChannelBuilder.forAddress(host, port) 41 | // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid 42 | // needing certificates. 43 | .usePlaintext(true) 44 | .build()); 45 | } 46 | 47 | /** Construct client for accessing RouteGuide server using the existing channel. */ 48 | HelloWorldClient(ManagedChannel channel) { 49 | this.channel = channel; 50 | blockingStub = GreeterGrpc.newBlockingStub(channel); 51 | } 52 | 53 | public void shutdown() throws InterruptedException { 54 | channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); 55 | } 56 | 57 | /** Say hello to server. */ 58 | public void greet(String name) throws java.lang.InterruptedException { 59 | logger.info("Will try to greet " + name + " ..."); 60 | HelloRequest request = HelloRequest.newBuilder().setName(name).build(); 61 | HelloReply response; 62 | 63 | // Simulate latency. 64 | Thread.sleep(50); 65 | 66 | try { 67 | response = blockingStub.sayHello(request); 68 | } catch (StatusRuntimeException e) { 69 | logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); 70 | return; 71 | } 72 | logger.info("Greeting: " + response.getMessage()); 73 | } 74 | 75 | /** 76 | * Greet server. If provided, the first element of {@code args} is the name to use in the 77 | * greeting. 78 | */ 79 | public static void main(String[] args) throws Exception { 80 | GrpcViews.registerViews(); 81 | ZPageHandlers.startHttpServerAndRegisterAll(60001); 82 | StackdriverExporter.createAndRegisterWithProjectId("jbdtalks"); 83 | StackdriverStatsExporter.createAndRegisterWithProjectId( 84 | "jbdtalks", 85 | Duration.create(10, 0)); 86 | HelloWorldClient client = new HelloWorldClient("localhost", 50051); 87 | try { 88 | /* Access a service running on the local machine on port 50051 */ 89 | String user = "world"; 90 | if (args.length > 0) { 91 | user = args[0]; /* Use the arg as the name to greet if provided */ 92 | } 93 | client.greet(user); 94 | } finally { 95 | client.shutdown(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gRPC/OpenCensus Demo 2 | 3 | Prerequisites: 4 | 5 | * Running Prometheus server 6 | * Stackdriver Tracing and Monitoring account 7 | 8 | In this demo, we are forking the gRPC hello world server and client. 9 | We will have a Go gRPC client talking to a gRPC server written in Java. 10 | 11 | OpenCensus is vendor agnostic, it can upload data to various 12 | tracing and metric collection backends. For this demo, we will 13 | use both Prometheus and Stackdriver Monitoring, and Stackdriver for tracing. 14 | We could have also used Zipkin for tracing, or any backend with a supported exporter. 15 | 16 | gRPC Java supports OpenCensus instrumentation libraries out 17 | of the box. To enable this, you simply need to subscribe to the metrics that you 18 | want to collect and pass your credentials to your chosen exporter. 19 | 20 | Let's run the gRPC Java server: 21 | 22 | ``` 23 | $ cd server 24 | $ ./startserver.sh 25 | ``` 26 | 27 | Now the server is listening ... Time to start sending some RPCs. 28 | 29 | Let's take a look at the client first, see client/main.go source code. 30 | 31 | You can see we set a Prometheus exporter for stats and a Stackdriver 32 | Tracing exporter for the traces. 33 | 34 | We need to register the Prometheus metrics handler so it can 35 | scrap and read the metrics we collected. 36 | 37 | I am subscribing to some views; so the library collects, 38 | aggregates and exports them. 39 | 40 | Let's run the gRPC Go client: 41 | 42 | ``` 43 | $ go run client/main.go 44 | ``` 45 | 46 | Now, the client is tracing all the outgoing requests and collecting 47 | stats from the outgoing RPCs. Let's see the Prometheus [metrics](http://localhost:9999/metrics) 48 | endpoint to see the exported metrics. 49 | 50 | You can see the exported distribution of latency with grpc method and grpc service labels. 51 | 52 | ![s](https://i.imgur.com/bkaP7an.png) 53 | 54 | I will switch to the Prometheus UI. You can see that :9999/metrics target is 55 | up and has been scraped. We should be retrieving some metrics. 56 | 57 | ![stats](https://i.imgur.com/JpLy8E0.png) 58 | 59 | 60 | See `kubecon_demo_grpc_io_client_request_bytes_cum_bucket` for the current 61 | request size distribution. 62 | 63 | See the 50th percentile: 64 | 65 | ``` 66 | histogram_quantile(0.5, rate(kubecon_demo_grpc_io_client_request_bytes_cumulative_bucket[5m])) 67 | ``` 68 | 69 | And 70th: 70 | 71 | ``` 72 | histogram_quantile(0.7, rate(kubecon_demo_grpc_io_client_request_bytes_cumulative_bucket[5m])) 73 | ``` 74 | 75 | And 90th: 76 | 77 | ``` 78 | histogram_quantile(0.9, rate(kubecon_demo_grpc_io_client_request_bytes_cumulative_bucket[5m])) 79 | ``` 80 | 81 | We are also collecting the roundtrip latency, you can see the distribution as well. 82 | 83 | ![latency](https://i.imgur.com/LEqtb3d.png) 84 | 85 | Metrics will be collected with the labels from the context 86 | and grpc_service and grpc_method will be automatically added. 87 | 88 | You can filter the metrics coming from the "SayHello" service by 89 | filtering by the label: 90 | 91 | ``` 92 | kubecon_demo_grpc_io_client_roundtrip_latency_cumulative_bucket{grpc_service="SayHello"} 93 | ``` 94 | 95 | Talking about latency, we have a multi service system here. 96 | Let's a take a look at the traces we collected to have more granular 97 | understanding of the cause of latency. 98 | 99 | Both gRPC client and server uploads the collected traces to the Stackdriver 100 | Trace service. In the Google Cloud Console, we already can see some traces: 101 | 102 | ![traces](https://i.imgur.com/MB8dRki.png) 103 | 104 | You see the both parts of the RPC call. Sent part is the outgoing 105 | RPC call from the client that too 3ms in total. It took 1 ms for the 106 | server to handle the request and respond, then it takes another 1ms 107 | for the client to handle the response. 108 | 109 | You can also generate reports and analysis from the collected traces and compare them. 110 | 111 | ![report](https://i.imgur.com/ip0LZ4G.png) 112 | 113 | The 95th percentile is 4ms. 114 | 115 | Now back to the gRPC Java server, we can take a look 116 | at the exported metrics. In this demo, we are using Stackdriver Monitoring 117 | to export the server metrics to. You can choose any vendor of your choice. 118 | 119 | The following dashboard displays the mean and 99th percentile 120 | round-trip latency collected from the server. 121 | 122 | ![stackdriver monitoring](https://i.imgur.com/n3CZzNl.png) 123 | 124 | One more thing... 125 | 126 | OpenCensus includes an optional dashboard that displays diagnostic performance information on the host upon which it is running. 127 | This is very useful when diagnosing issues related to a particular host or when you need to inspect unfiltered and unsampled data. 128 | 129 | ![tracez](https://i.imgur.com/iQiprU5.png) 130 | 131 | See http://localhost:9999/debug/tracez for traces. 132 | -------------------------------------------------------------------------------- /server/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | io.grpc 5 | examples 6 | jar 7 | 9 | 1.8.0 10 | examples 11 | http://maven.apache.org 12 | 13 | UTF-8 14 | 1.8.0 15 | 0.10.0 16 | 17 | 18 | 19 | io.grpc 20 | grpc-netty 21 | ${grpc.version} 22 | 23 | 24 | io.grpc 25 | grpc-protobuf 26 | ${grpc.version} 27 | 28 | 29 | io.grpc 30 | grpc-stub 31 | ${grpc.version} 32 | 33 | 34 | io.grpc 35 | grpc-auth 36 | ${grpc.version} 37 | 38 | 39 | io.grpc 40 | grpc-testing 41 | ${grpc.version} 42 | test 43 | 44 | 45 | com.google.guava 46 | guava 47 | 20.0 48 | 49 | 50 | com.google.auth 51 | google-auth-library-credentials 52 | 0.9.0 53 | 54 | 55 | com.google.api 56 | api-common 57 | 1.2.0 58 | 59 | 60 | com.google.code.findbugs 61 | jsr305 62 | 3.0.1 63 | 64 | 65 | com.google.api.grpc 66 | proto-google-common-protos 67 | 1.0.1 68 | 69 | 70 | io.opencensus 71 | opencensus-exporter-trace-stackdriver 72 | ${opencensus.version} 73 | 74 | 75 | io.opencensus 76 | opencensus-exporter-stats-stackdriver 77 | ${opencensus.version} 78 | 79 | 80 | io.opencensus 81 | opencensus-contrib-zpages 82 | ${opencensus.version} 83 | 84 | 85 | io.opencensus 86 | opencensus-impl 87 | ${opencensus.version} 88 | runtime 89 | 90 | 91 | 92 | 93 | 94 | kr.motd.maven 95 | os-maven-plugin 96 | 1.5.0.Final 97 | 98 | 99 | 100 | 101 | org.xolstice.maven.plugins 102 | protobuf-maven-plugin 103 | 0.5.0 104 | 105 | com.google.protobuf:protoc:3.5.0:exe:${os.detected.classifier} 106 | grpc-java 107 | io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} 108 | 109 | 110 | 111 | 112 | compile 113 | compile-custom 114 | 115 | 116 | 117 | 118 | 119 | org.apache.maven.plugins 120 | maven-enforcer-plugin 121 | 1.4.1 122 | 123 | 124 | enforce 125 | 126 | enforce 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | org.apache.maven.plugins 138 | maven-compiler-plugin 139 | 140 | 1.7 141 | 1.7 142 | 143 | 144 | 145 | 146 | 147 | --------------------------------------------------------------------------------