From 8bce79cde63190d3703af222782871533f7ea1a8 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Sat, 17 Mar 2018 16:53:41 -0700 Subject: Add a gRPC Hello World example. (#1044) --- examples/BUILD.bazel | 3 +- examples/README.md | 30 ++++ examples/build.gradle | 72 ++++++++- examples/pom.xml | 74 +++++++++ .../examples/grpc/helloworld/HelloWorldClient.java | 151 ++++++++++++++++++ .../examples/grpc/helloworld/HelloWorldServer.java | 176 +++++++++++++++++++++ .../examples/grpc/helloworld/HelloWorldUtils.java | 50 ++++++ examples/src/main/proto/helloworld.proto | 39 +++++ 8 files changed, 590 insertions(+), 5 deletions(-) create mode 100644 examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldClient.java create mode 100644 examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldServer.java create mode 100644 examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldUtils.java create mode 100644 examples/src/main/proto/helloworld.proto (limited to 'examples') diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel index 82f322e7..6245c0a3 100644 --- a/examples/BUILD.bazel +++ b/examples/BUILD.bazel @@ -4,7 +4,8 @@ opencensus_java_libraries() java_library( name = "opencensus_examples", srcs = glob( - ["src/main/java/**/*.java"] + ["src/main/java/**/*.java"], + exclude = ["src/main/java/io/opencensus/examples/grpc/**/*.java"], ), deps = [ "@io_opencensus_opencensus_api//jar", diff --git a/examples/README.md b/examples/README.md index e7a270c4..62324f20 100644 --- a/examples/README.md +++ b/examples/README.md @@ -78,3 +78,33 @@ $ ./target/appassembler/bin/QuickStart ``` $ ./bazel-bin/QuickStart ``` + +## To run "gRPC Hello World" example use + +Please note all the arguments are optional. If you do not specify these arguments, default values +will be used: + +* host and serverPort will be "localhost:50051" +* user will be "world" +* cloudProjectId will be null (which means no stats/spans will be exported to Stackdriver) +* server zPagePort will be 3000 +* client zPagePort will be 3001 +* Prometheus port will be 9090 + + +However, if you want to specify any of these arguements, please make sure they are in order. + +### Gradle +``` +$ ./build/install/opencensus-examples/bin/HelloWorldServer serverPort cloudProjectId zPagePort prometheusPort +$ ./build/install/opencensus-examples/bin/HelloWorldClient user host serverPort cloudProjectId zPagePort +``` + +### Maven +``` +$ ./target/appassembler/bin/HelloWorldServer serverPort cloudProjectId zPagePort prometheusPort +$ ./target/appassembler/bin/HelloWorldClient user host serverPort cloudProjectId zPagePort +``` + +### Bazel +TODO \ No newline at end of file diff --git a/examples/build.gradle b/examples/build.gradle index ab5de34a..163b0b80 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -10,12 +10,14 @@ buildscript { } dependencies { classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.6" + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.3' } } apply plugin: 'checkstyle' apply plugin: 'idea' apply plugin: 'java' +apply plugin: 'com.google.protobuf' // Plugins that require java8 if (JavaVersion.current().isJava8Compatible()) { apply plugin: 'com.github.sherter.google-java-format' @@ -30,6 +32,8 @@ group = "io.opencensus" version = "0.13.0-SNAPSHOT" // CURRENT_OPENCENSUS_VERSION def opencensusVersion = "0.12.2" // LATEST_OPENCENSUS_RELEASE_VERSION +def grpcVersion = "1.9.0" // CURRENT_GRPC_VERSION +def prometheusVersion = "0.3.0" checkstyle { configFile = file("$rootDir/../buildscripts/checkstyle.xml") @@ -41,6 +45,11 @@ checkstyle { configProperties["rootDir"] = file("$rootDir/../") } +checkstyleMain { + // This skips proto generated files beucasue they are in gen_gradle/src/main/** + source = fileTree(dir: "src/main", include: "**/*.java") +} + // Google formatter works only on java8. if (JavaVersion.current().isJava8Compatible()) { googleJavaFormat { @@ -49,12 +58,14 @@ if (JavaVersion.current().isJava8Compatible()) { afterEvaluate { // Allow subproject to add more source sets. tasks.googleJavaFormat { - source = sourceSets*.allJava + // This skips proto generated files beucasue they are in gen_gradle/src/main/** + source = "src/main" include '**/*.java' } tasks.verifyGoogleJavaFormat { - source = sourceSets*.allJava + // This skips proto generated files beucasue they are in gen_gradle/src/main/** + source = "src/main" include '**/*.java' } } @@ -66,13 +77,50 @@ tasks.withType(JavaCompile) { } dependencies { - compile "io.opencensus:opencensus-api:${opencensusVersion}", + compile "com.google.api.grpc:proto-google-common-protos:1.0.5", + "io.opencensus:opencensus-api:${opencensusVersion}", "io.opencensus:opencensus-contrib-zpages:${opencensusVersion}", - "io.opencensus:opencensus-exporter-trace-logging:${opencensusVersion}" + "io.opencensus:opencensus-contrib-grpc-metrics:${opencensusVersion}", + "io.opencensus:opencensus-exporter-stats-prometheus:${opencensusVersion}", + "io.opencensus:opencensus-exporter-stats-stackdriver:${opencensusVersion}", + "io.opencensus:opencensus-exporter-trace-stackdriver:${opencensusVersion}", + "io.opencensus:opencensus-exporter-trace-logging:${opencensusVersion}", + "io.grpc:grpc-protobuf:${grpcVersion}", + "io.grpc:grpc-stub:${grpcVersion}", + "io.grpc:grpc-netty:${grpcVersion}", + "io.prometheus:simpleclient_httpserver:${prometheusVersion}" runtime "io.opencensus:opencensus-impl:${opencensusVersion}" } +protobuf { + protoc { + artifact = 'com.google.protobuf:protoc:3.5.1-1' + } + plugins { + grpc { + artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" + } + } + generateProtoTasks { + all()*.plugins { + grpc {} + } + ofSourceSet('main') + } +} + +// Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code. +sourceSets { + main { + java { + srcDir 'src' + srcDirs 'build/generated/source/proto/main/grpc' + srcDirs 'build/generated/source/proto/main/java' + } + } +} + // Provide convenience executables for trying out the examples. apply plugin: 'application' @@ -120,6 +168,20 @@ task quickStart(type: CreateStartScripts) { classpath = jar.outputs.files + project.configurations.runtime } +task helloWorldServer(type: CreateStartScripts) { + mainClassName = 'io.opencensus.examples.grpc.helloworld.HelloWorldServer' + applicationName = 'HelloWorldServer' + outputDir = new File(project.buildDir, 'tmp') + classpath = jar.outputs.files + project.configurations.runtime +} + +task helloWorldClient(type: CreateStartScripts) { + mainClassName = 'io.opencensus.examples.grpc.helloworld.HelloWorldClient' + applicationName = 'HelloWorldClient' + outputDir = new File(project.buildDir, 'tmp') + classpath = jar.outputs.files + project.configurations.runtime +} + applicationDistribution.into('bin') { from(multiSpansTracing) from(multiSpansScopedTracing) @@ -127,5 +189,7 @@ applicationDistribution.into('bin') { from(statsRunner) from(zPagesTester) from(quickStart) + from(helloWorldServer) + from(helloWorldClient) fileMode = 0755 } diff --git a/examples/pom.xml b/examples/pom.xml index 468f9774..38c6d6d0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -11,6 +11,7 @@ UTF-8 0.12.2 + 1.9.0 @@ -18,16 +19,56 @@ opencensus-api ${opencensus.version} + + io.opencensus + opencensus-contrib-grpc-metrics + ${opencensus.version} + io.opencensus opencensus-contrib-zpages ${opencensus.version} + + io.opencensus + opencensus-exporter-stats-stackdriver + ${opencensus.version} + + + io.opencensus + opencensus-exporter-stats-prometheus + ${opencensus.version} + + + io.opencensus + opencensus-exporter-trace-stackdriver + ${opencensus.version} + io.opencensus opencensus-exporter-trace-logging ${opencensus.version} + + io.grpc + grpc-netty + ${grpc.version} + + + io.grpc + grpc-protobuf + ${grpc.version} + + + io.grpc + grpc-stub + ${grpc.version} + + + io.prometheus + simpleclient_httpserver + 0.3.0 + io.opencensus opencensus-impl @@ -36,6 +77,13 @@ + + + kr.motd.maven + os-maven-plugin + 1.5.0.Final + + @@ -80,9 +128,35 @@ QuickStart io.opencensus.examples.helloworld.QuickStart + + HelloWorldClient + io.opencensus.examples.grpc.helloworld.HelloWorldClient + + + HelloWorldServer + io.opencensus.examples.grpc.helloworld.HelloWorldServer + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.5.0 + + com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier} + grpc-java + io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} + + + + + compile + compile-custom + + + + diff --git a/examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldClient.java b/examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldClient.java new file mode 100644 index 00000000..30e41633 --- /dev/null +++ b/examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldClient.java @@ -0,0 +1,151 @@ +/* + * Copyright 2018, OpenCensus 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.opencensus.examples.grpc.helloworld; + +import static io.opencensus.examples.grpc.helloworld.HelloWorldUtils.getPortOrDefaultFromArgs; +import static io.opencensus.examples.grpc.helloworld.HelloWorldUtils.getStringOrDefaultFromArgs; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.StatusRuntimeException; +import io.opencensus.common.Duration; +import io.opencensus.common.Scope; +import io.opencensus.contrib.grpc.metrics.RpcViews; +import io.opencensus.contrib.zpages.ZPageHandlers; +import io.opencensus.exporter.stats.prometheus.PrometheusStatsCollector; +import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration; +import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter; +import io.opencensus.exporter.trace.logging.LoggingTraceExporter; +import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration; +import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter; +import io.opencensus.trace.SpanBuilder; +import io.opencensus.trace.Status.CanonicalCode; +import io.opencensus.trace.Tracer; +import io.opencensus.trace.Tracing; +import io.opencensus.trace.samplers.Samplers; +import java.io.IOException; +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 HelloWorldServer}. */ +public class HelloWorldClient { + private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName()); + + private static final Tracer tracer = Tracing.getTracer(); + + private final ManagedChannel channel; + private final GreeterGrpc.GreeterBlockingStub blockingStub; + + /** Construct client connecting to HelloWorld server at {@code host:port}. */ + public HelloWorldClient(String host, int port) { + this( + ManagedChannelBuilder.forAddress(host, port) + // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid + // needing certificates. + .usePlaintext(true) + .build()); + } + + /** Construct client for accessing RouteGuide server using the existing channel. */ + HelloWorldClient(ManagedChannel channel) { + this.channel = channel; + blockingStub = GreeterGrpc.newBlockingStub(channel); + } + + public void shutdown() throws InterruptedException { + channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + + /** 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; + + SpanBuilder spanBuilder = + tracer.spanBuilder("client").setRecordEvents(true).setSampler(Samplers.alwaysSample()); + try (Scope scope = spanBuilder.startScopedSpan()) { + tracer.getCurrentSpan().addAnnotation("Saying Hello to Server."); + response = blockingStub.sayHello(request); + tracer.getCurrentSpan().addAnnotation("Received response from Server."); + } catch (StatusRuntimeException e) { + tracer + .getCurrentSpan() + .setStatus( + CanonicalCode.valueOf(e.getStatus().getCode().name()) + .toStatus() + .withDescription(e.getMessage())); + logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); + return; + } + logger.info("Greeting: " + response.getMessage()); + } + + /** + * Greet server. If provided, the first element of {@code args} is the name to use in the + * greeting. + */ + public static void main(String[] args) throws IOException, InterruptedException { + // Add final keyword to pass checkStyle. + final String user = getStringOrDefaultFromArgs(args, 0, "world"); + final String host = getStringOrDefaultFromArgs(args, 1, "localhost"); + final int serverPort = getPortOrDefaultFromArgs(args, 2, 50051); + final String cloudProjectId = getStringOrDefaultFromArgs(args, 3, null); + final int zPagePort = getPortOrDefaultFromArgs(args, 4, 3001); + + // Registers all RPC views. + RpcViews.registerAllViews(); + + // Starts a HTTP server and registers all Zpages to it. + ZPageHandlers.startHttpServerAndRegisterAll(zPagePort); + logger.info("ZPages server starts at localhost:" + zPagePort); + + // Registers logging trace exporter. + LoggingTraceExporter.register(); + + // Registers Stackdriver exporters. + if (cloudProjectId != null) { + StackdriverTraceExporter.createAndRegister( + StackdriverTraceConfiguration.builder().setProjectId(cloudProjectId).build()); + StackdriverStatsExporter.createAndRegister( + StackdriverStatsConfiguration.builder() + .setProjectId(cloudProjectId) + .setExportInterval(Duration.create(15, 0)) + .build()); + } + + // Register Prometheus exporters and export metrics to a Prometheus HTTPServer. + PrometheusStatsCollector.createAndRegister(); + + HelloWorldClient client = new HelloWorldClient(host, serverPort); + try { + client.greet(user); + } finally { + client.shutdown(); + } + + logger.info("Client sleeping, ^C to exit. Meanwhile you can view stats and spans on zpages."); + while (true) { + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + logger.info("Exiting HelloWorldClient..."); + } + } + } +} diff --git a/examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldServer.java b/examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldServer.java new file mode 100644 index 00000000..15a0a896 --- /dev/null +++ b/examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldServer.java @@ -0,0 +1,176 @@ +/* + * Copyright 2018, OpenCensus 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.opencensus.examples.grpc.helloworld; + +import static io.opencensus.examples.grpc.helloworld.HelloWorldUtils.getPortOrDefaultFromArgs; +import static io.opencensus.examples.grpc.helloworld.HelloWorldUtils.getStringOrDefaultFromArgs; + +import com.google.common.collect.ImmutableMap; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.stub.StreamObserver; +import io.opencensus.common.Duration; +import io.opencensus.common.Scope; +import io.opencensus.contrib.grpc.metrics.RpcViews; +import io.opencensus.contrib.zpages.ZPageHandlers; +import io.opencensus.exporter.stats.prometheus.PrometheusStatsCollector; +import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration; +import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter; +import io.opencensus.exporter.trace.logging.LoggingTraceExporter; +import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration; +import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanBuilder; +import io.opencensus.trace.Status; +import io.opencensus.trace.Tracer; +import io.opencensus.trace.Tracing; +import io.opencensus.trace.samplers.Samplers; +import io.prometheus.client.exporter.HTTPServer; +import java.io.IOException; +import java.util.logging.Logger; + +/** Server that manages startup/shutdown of a {@code Greeter} server. */ +public class HelloWorldServer { + private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName()); + + private static final Tracer tracer = Tracing.getTracer(); + + private final int serverPort; + private Server server; + + private HelloWorldServer(int serverPort) { + this.serverPort = serverPort; + } + + // A helper function that performs some work in its own Span. + private static void performWork(Span parent) { + SpanBuilder spanBuilder = + tracer + .spanBuilderWithExplicitParent("internal_work", parent) + .setRecordEvents(true) + .setSampler(Samplers.alwaysSample()); + try (Scope scope = spanBuilder.startScopedSpan()) { + Span span = tracer.getCurrentSpan(); + span.putAttribute("my_attribute", AttributeValue.stringAttributeValue("blue")); + span.addAnnotation("Performing work."); + sleepFor(20); // Working hard here. + span.addAnnotation("Done work."); + } + } + + private static void sleepFor(int milliseconds) { + try { + Thread.sleep(milliseconds); + } catch (InterruptedException e) { + Span span = tracer.getCurrentSpan(); + span.addAnnotation("Exception thrown when performing work " + e.getMessage()); + span.setStatus(Status.UNKNOWN); + } + } + + private void start() throws IOException { + server = ServerBuilder.forPort(serverPort).addService(new GreeterImpl()).build().start(); + logger.info("Server started, listening on " + serverPort); + 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"); + HelloWorldServer.this.stop(); + System.err.println("*** server shut down"); + } + }); + } + + private void stop() { + if (server != null) { + server.shutdown(); + } + } + + /** 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 { + // Add final keyword to pass checkStyle. + final int serverPort = getPortOrDefaultFromArgs(args, 0, 50051); + final String cloudProjectId = getStringOrDefaultFromArgs(args, 1, null); + final int zPagePort = getPortOrDefaultFromArgs(args, 2, 3000); + final int prometheusPort = getPortOrDefaultFromArgs(args, 3, 9090); + + // Registers all RPC views. + RpcViews.registerAllViews(); + + // Registers logging trace exporter. + LoggingTraceExporter.register(); + + // Starts a HTTP server and registers all Zpages to it. + ZPageHandlers.startHttpServerAndRegisterAll(zPagePort); + logger.info("ZPages server starts at localhost:" + zPagePort); + + // Registers Stackdriver exporters. + if (cloudProjectId != null) { + StackdriverTraceExporter.createAndRegister( + StackdriverTraceConfiguration.builder().setProjectId(cloudProjectId).build()); + StackdriverStatsExporter.createAndRegister( + StackdriverStatsConfiguration.builder() + .setProjectId(cloudProjectId) + .setExportInterval(Duration.create(15, 0)) + .build()); + } + + // Register Prometheus exporters and export metrics to a Prometheus HTTPServer. + PrometheusStatsCollector.createAndRegister(); + HTTPServer prometheusServer = new HTTPServer(prometheusPort, true); + + // Start the RPC server. You shouldn't see any output from gRPC before this. + logger.info("gRPC starting."); + final HelloWorldServer server = new HelloWorldServer(serverPort); + server.start(); + server.blockUntilShutdown(); + } + + static class GreeterImpl extends GreeterGrpc.GreeterImplBase { + + @Override + public void sayHello(HelloRequest req, StreamObserver responseObserver) { + Span span = tracer.getCurrentSpan(); + span.putAttribute("my_attribute", AttributeValue.stringAttributeValue("red")); + span.addAnnotation( + "Constructing greeting.", + ImmutableMap.of( + "name", AttributeValue.stringAttributeValue(req.getName()), + "name length", AttributeValue.longAttributeValue(req.getName().length()))); + sleepFor(10); + performWork(span); + span.addAnnotation("Sleeping."); + sleepFor(30); + HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + logger.info("SayHello RPC handled."); + } + } +} diff --git a/examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldUtils.java b/examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldUtils.java new file mode 100644 index 00000000..f6dcdaab --- /dev/null +++ b/examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldUtils.java @@ -0,0 +1,50 @@ +/* + * Copyright 2018, OpenCensus 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.opencensus.examples.grpc.helloworld; + +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** Util methods. */ +final class HelloWorldUtils { + + private static Logger logger = Logger.getLogger(HelloWorldUtils.class.getName()); + + static int getPortOrDefaultFromArgs(String[] args, int index, int defaultPort) { + int portNumber = defaultPort; + if (index < args.length) { + try { + portNumber = Integer.parseInt(args[index]); + } catch (NumberFormatException e) { + logger.warning( + String.format("Port %s is invalid, use default port %d.", args[index], defaultPort)); + } + } + return portNumber; + } + + static String getStringOrDefaultFromArgs( + String[] args, int index, @Nullable String defaultString) { + String s = defaultString; + if (index < args.length) { + s = args[index]; + } + return s; + } + + private HelloWorldUtils() {} +} diff --git a/examples/src/main/proto/helloworld.proto b/examples/src/main/proto/helloworld.proto new file mode 100644 index 00000000..1bd79300 --- /dev/null +++ b/examples/src/main/proto/helloworld.proto @@ -0,0 +1,39 @@ +/* + * Copyright 2018, OpenCensus 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.opencensus.examples.grpc.helloworld"; +option java_outer_classname = "HelloWorldProto"; + +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; +} -- cgit v1.2.3