1 /* 2 * Copyright 2018, OpenCensus Authors 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.opencensus.examples.grpc.helloworld; 18 19 import static io.opencensus.examples.grpc.helloworld.HelloWorldUtils.getPortOrDefaultFromArgs; 20 import static io.opencensus.examples.grpc.helloworld.HelloWorldUtils.getStringOrDefaultFromArgs; 21 22 import io.grpc.ManagedChannel; 23 import io.grpc.ManagedChannelBuilder; 24 import io.grpc.StatusRuntimeException; 25 import io.opencensus.common.Duration; 26 import io.opencensus.common.Scope; 27 import io.opencensus.contrib.grpc.metrics.RpcViews; 28 import io.opencensus.contrib.zpages.ZPageHandlers; 29 import io.opencensus.exporter.stats.prometheus.PrometheusStatsCollector; 30 import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration; 31 import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter; 32 import io.opencensus.exporter.trace.logging.LoggingTraceExporter; 33 import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration; 34 import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter; 35 import io.opencensus.trace.SpanBuilder; 36 import io.opencensus.trace.Status.CanonicalCode; 37 import io.opencensus.trace.Tracer; 38 import io.opencensus.trace.Tracing; 39 import io.opencensus.trace.samplers.Samplers; 40 import java.io.IOException; 41 import java.util.concurrent.TimeUnit; 42 import java.util.logging.Level; 43 import java.util.logging.Logger; 44 45 /** A simple client that requests a greeting from the {@link HelloWorldServer}. */ 46 public class HelloWorldClient { 47 private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName()); 48 49 private static final Tracer tracer = Tracing.getTracer(); 50 51 private final ManagedChannel channel; 52 private final GreeterGrpc.GreeterBlockingStub blockingStub; 53 54 /** Construct client connecting to HelloWorld server at {@code host:port}. */ HelloWorldClient(String host, int port)55 public HelloWorldClient(String host, int port) { 56 this( 57 ManagedChannelBuilder.forAddress(host, port) 58 // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid 59 // needing certificates. 60 .usePlaintext(true) 61 .build()); 62 } 63 64 /** Construct client for accessing RouteGuide server using the existing channel. */ HelloWorldClient(ManagedChannel channel)65 HelloWorldClient(ManagedChannel channel) { 66 this.channel = channel; 67 blockingStub = GreeterGrpc.newBlockingStub(channel); 68 } 69 shutdown()70 public void shutdown() throws InterruptedException { 71 channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); 72 } 73 74 /** Say hello to server. */ greet(String name)75 public void greet(String name) { 76 logger.info("Will try to greet " + name + " ..."); 77 HelloRequest request = HelloRequest.newBuilder().setName(name).build(); 78 HelloReply response; 79 80 SpanBuilder spanBuilder = 81 tracer.spanBuilder("client").setRecordEvents(true).setSampler(Samplers.alwaysSample()); 82 try (Scope scope = spanBuilder.startScopedSpan()) { 83 tracer.getCurrentSpan().addAnnotation("Saying Hello to Server."); 84 response = blockingStub.sayHello(request); 85 tracer.getCurrentSpan().addAnnotation("Received response from Server."); 86 } catch (StatusRuntimeException e) { 87 tracer 88 .getCurrentSpan() 89 .setStatus( 90 CanonicalCode.valueOf(e.getStatus().getCode().name()) 91 .toStatus() 92 .withDescription(e.getMessage())); 93 logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); 94 return; 95 } 96 logger.info("Greeting: " + response.getMessage()); 97 } 98 99 /** 100 * Greet server. If provided, the first element of {@code args} is the name to use in the 101 * greeting. 102 */ main(String[] args)103 public static void main(String[] args) throws IOException, InterruptedException { 104 // Add final keyword to pass checkStyle. 105 final String user = getStringOrDefaultFromArgs(args, 0, "world"); 106 final String host = getStringOrDefaultFromArgs(args, 1, "localhost"); 107 final int serverPort = getPortOrDefaultFromArgs(args, 2, 50051); 108 final String cloudProjectId = getStringOrDefaultFromArgs(args, 3, null); 109 final int zPagePort = getPortOrDefaultFromArgs(args, 4, 3001); 110 111 // Registers all RPC views. 112 RpcViews.registerAllViews(); 113 114 // Starts a HTTP server and registers all Zpages to it. 115 ZPageHandlers.startHttpServerAndRegisterAll(zPagePort); 116 logger.info("ZPages server starts at localhost:" + zPagePort); 117 118 // Registers logging trace exporter. 119 LoggingTraceExporter.register(); 120 121 // Registers Stackdriver exporters. 122 if (cloudProjectId != null) { 123 StackdriverTraceExporter.createAndRegister( 124 StackdriverTraceConfiguration.builder().setProjectId(cloudProjectId).build()); 125 StackdriverStatsExporter.createAndRegister( 126 StackdriverStatsConfiguration.builder() 127 .setProjectId(cloudProjectId) 128 .setExportInterval(Duration.create(15, 0)) 129 .build()); 130 } 131 132 // Register Prometheus exporters and export metrics to a Prometheus HTTPServer. 133 PrometheusStatsCollector.createAndRegister(); 134 135 HelloWorldClient client = new HelloWorldClient(host, serverPort); 136 try { 137 client.greet(user); 138 } finally { 139 client.shutdown(); 140 } 141 142 logger.info("Client sleeping, ^C to exit. Meanwhile you can view stats and spans on zpages."); 143 while (true) { 144 try { 145 Thread.sleep(10000); 146 } catch (InterruptedException e) { 147 logger.info("Exiting HelloWorldClient..."); 148 } 149 } 150 } 151 } 152