aboutsummaryrefslogtreecommitdiff
path: root/examples/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'examples/src/main')
-rw-r--r--examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldClient.java151
-rw-r--r--examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldServer.java176
-rw-r--r--examples/src/main/java/io/opencensus/examples/grpc/helloworld/HelloWorldUtils.java50
-rw-r--r--examples/src/main/java/io/opencensus/examples/helloworld/QuickStart.java111
-rw-r--r--examples/src/main/java/io/opencensus/examples/tags/TagContextExample.java77
-rw-r--r--examples/src/main/java/io/opencensus/examples/trace/MultiSpansContextTracing.java89
-rw-r--r--examples/src/main/java/io/opencensus/examples/trace/MultiSpansScopedTracing.java85
-rw-r--r--examples/src/main/java/io/opencensus/examples/trace/MultiSpansTracing.java72
-rw-r--r--examples/src/main/java/io/opencensus/examples/trace/Utils.java37
-rw-r--r--examples/src/main/java/io/opencensus/examples/zpages/ZPagesTester.java108
-rw-r--r--examples/src/main/proto/helloworld.proto39
11 files changed, 995 insertions, 0 deletions
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<HelloReply> 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..55d6c225
--- /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 final 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/java/io/opencensus/examples/helloworld/QuickStart.java b/examples/src/main/java/io/opencensus/examples/helloworld/QuickStart.java
new file mode 100644
index 00000000..c71e0f3e
--- /dev/null
+++ b/examples/src/main/java/io/opencensus/examples/helloworld/QuickStart.java
@@ -0,0 +1,111 @@
+/*
+ * 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.helloworld;
+
+import io.opencensus.common.Scope;
+import io.opencensus.exporter.trace.logging.LoggingTraceExporter;
+import io.opencensus.stats.Aggregation;
+import io.opencensus.stats.BucketBoundaries;
+import io.opencensus.stats.Measure.MeasureLong;
+import io.opencensus.stats.Stats;
+import io.opencensus.stats.StatsRecorder;
+import io.opencensus.stats.View;
+import io.opencensus.stats.ViewData;
+import io.opencensus.stats.ViewManager;
+import io.opencensus.tags.TagContextBuilder;
+import io.opencensus.tags.TagKey;
+import io.opencensus.tags.TagValue;
+import io.opencensus.tags.Tagger;
+import io.opencensus.tags.Tags;
+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 java.util.Arrays;
+import java.util.Collections;
+import java.util.Random;
+import java.util.logging.Logger;
+
+/** Simple program that collects data for video size. */
+public final class QuickStart {
+
+ private static final Logger logger = Logger.getLogger(QuickStart.class.getName());
+
+ private static final Tagger tagger = Tags.getTagger();
+ private static final ViewManager viewManager = Stats.getViewManager();
+ private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
+ private static final Tracer tracer = Tracing.getTracer();
+
+ // frontendKey allows us to break down the recorded data.
+ private static final TagKey FRONTEND_KEY = TagKey.create("my.org/keys/frontend");
+
+ // videoSize will measure the size of processed videos.
+ private static final MeasureLong VIDEO_SIZE =
+ MeasureLong.create("my.org/measure/video_size", "size of processed videos", "By");
+
+ private static final long MiB = 1 << 20;
+
+ // Create view to see the processed video size distribution broken down by frontend.
+ // The view has bucket boundaries (0, 16 * MiB, 65536 * MiB) that will group measure
+ // values into histogram buckets.
+ private static final View.Name VIDEO_SIZE_VIEW_NAME = View.Name.create("my.org/views/video_size");
+ private static final View VIDEO_SIZE_VIEW =
+ View.create(
+ VIDEO_SIZE_VIEW_NAME,
+ "processed video size over time",
+ VIDEO_SIZE,
+ Aggregation.Distribution.create(
+ BucketBoundaries.create(Arrays.asList(0.0, 16.0 * MiB, 256.0 * MiB))),
+ Collections.singletonList(FRONTEND_KEY));
+
+ /** Main launcher for the QuickStart example. */
+ public static void main(String[] args) throws InterruptedException {
+ TagContextBuilder tagContextBuilder =
+ tagger.currentBuilder().put(FRONTEND_KEY, TagValue.create("mobile-ios9.3.5"));
+ SpanBuilder spanBuilder =
+ tracer
+ .spanBuilder("my.org/ProcessVideo")
+ .setRecordEvents(true)
+ .setSampler(Samplers.alwaysSample());
+ viewManager.registerView(VIDEO_SIZE_VIEW);
+ LoggingTraceExporter.register();
+
+ // Process video.
+ // Record the processed video size.
+ try (Scope scopedTags = tagContextBuilder.buildScoped();
+ Scope scopedSpan = spanBuilder.startScopedSpan()) {
+ tracer.getCurrentSpan().addAnnotation("Start processing video.");
+ // Sleep for [0,10] milliseconds to fake work.
+ Thread.sleep(new Random().nextInt(10) + 1);
+ statsRecorder.newMeasureMap().put(VIDEO_SIZE, 25 * MiB).record();
+ tracer.getCurrentSpan().addAnnotation("Finished processing video.");
+ } catch (Exception e) {
+ tracer.getCurrentSpan().addAnnotation("Exception thrown when processing video.");
+ tracer.getCurrentSpan().setStatus(Status.UNKNOWN);
+ logger.severe(e.getMessage());
+ }
+
+ logger.info("Wait longer than the reporting duration...");
+ // Wait for a duration longer than reporting duration (5s) to ensure spans are exported.
+ // TODO(songya): remove the gap once we add a shutdown hook for exporting unflushed spans.
+ Thread.sleep(5100);
+ ViewData viewData = viewManager.getView(VIDEO_SIZE_VIEW_NAME);
+ logger.info(
+ String.format("Recorded stats for %s:\n %s", VIDEO_SIZE_VIEW_NAME.asString(), viewData));
+ }
+}
diff --git a/examples/src/main/java/io/opencensus/examples/tags/TagContextExample.java b/examples/src/main/java/io/opencensus/examples/tags/TagContextExample.java
new file mode 100644
index 00000000..727c5fbb
--- /dev/null
+++ b/examples/src/main/java/io/opencensus/examples/tags/TagContextExample.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016-17, 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.tags;
+
+import io.opencensus.common.Scope;
+import io.opencensus.stats.Measure.MeasureDouble;
+import io.opencensus.stats.Stats;
+import io.opencensus.stats.StatsRecorder;
+import io.opencensus.tags.TagContext;
+import io.opencensus.tags.TagKey;
+import io.opencensus.tags.TagValue;
+import io.opencensus.tags.Tagger;
+import io.opencensus.tags.Tags;
+
+/** Simple program that uses {@link TagContext}. */
+public class TagContextExample {
+
+ private static final TagKey K1 = TagKey.create("k1");
+ private static final TagKey K2 = TagKey.create("k2");
+ private static final TagKey K3 = TagKey.create("k3");
+ private static final TagKey K4 = TagKey.create("k4");
+
+ private static final TagValue V1 = TagValue.create("v1");
+ private static final TagValue V2 = TagValue.create("v2");
+ private static final TagValue V3 = TagValue.create("v3");
+ private static final TagValue V4 = TagValue.create("v4");
+
+ private static final String UNIT = "1";
+ private static final MeasureDouble M1 = MeasureDouble.create("m1", "1st test metric", UNIT);
+ private static final MeasureDouble M2 = MeasureDouble.create("m2", "2nd test metric", UNIT);
+
+ private static final Tagger tagger = Tags.getTagger();
+ private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
+
+ private TagContextExample() {}
+
+ /**
+ * Main method.
+ *
+ * @param args the main arguments.
+ */
+ public static void main(String[] args) {
+ System.out.println("Hello Stats World");
+ System.out.println("Default Tags: " + tagger.empty());
+ System.out.println("Current Tags: " + tagger.getCurrentTagContext());
+ TagContext tags1 = tagger.emptyBuilder().put(K1, V1).put(K2, V2).build();
+ try (Scope scopedTagCtx1 = tagger.withTagContext(tags1)) {
+ System.out.println(" Current Tags: " + tagger.getCurrentTagContext());
+ System.out.println(
+ " Current == Default + tags1: " + tagger.getCurrentTagContext().equals(tags1));
+ TagContext tags2 = tagger.toBuilder(tags1).put(K3, V3).put(K4, V4).build();
+ try (Scope scopedTagCtx2 = tagger.withTagContext(tags2)) {
+ System.out.println(" Current Tags: " + tagger.getCurrentTagContext());
+ System.out.println(
+ " Current == Default + tags1 + tags2: "
+ + tagger.getCurrentTagContext().equals(tags2));
+ statsRecorder.newMeasureMap().put(M1, 0.2).put(M2, 0.4).record();
+ }
+ }
+ System.out.println(
+ "Current == Default: " + tagger.getCurrentTagContext().equals(tagger.empty()));
+ }
+}
diff --git a/examples/src/main/java/io/opencensus/examples/trace/MultiSpansContextTracing.java b/examples/src/main/java/io/opencensus/examples/trace/MultiSpansContextTracing.java
new file mode 100644
index 00000000..c8df144f
--- /dev/null
+++ b/examples/src/main/java/io/opencensus/examples/trace/MultiSpansContextTracing.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2017, 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.trace;
+
+import static io.opencensus.examples.trace.Utils.sleep;
+
+import io.opencensus.common.Scope;
+import io.opencensus.exporter.trace.logging.LoggingTraceExporter;
+import io.opencensus.trace.Span;
+import io.opencensus.trace.Tracer;
+import io.opencensus.trace.Tracing;
+import io.opencensus.trace.config.TraceConfig;
+import io.opencensus.trace.samplers.Samplers;
+
+/**
+ * Example showing how to create a child {@link Span}, install it to the current context and add
+ * annotations.
+ */
+public final class MultiSpansContextTracing {
+ // Per class Tracer.
+ private static final Tracer tracer = Tracing.getTracer();
+
+ private MultiSpansContextTracing() {}
+
+ private static void doSomeOtherWork() {
+ tracer.getCurrentSpan().addAnnotation("Annotation to the child Span");
+ }
+
+ private static void doSomeMoreWork() {
+ // Create a child Span of the current Span.
+ Span span = tracer.spanBuilder("MyChildSpan").startSpan();
+ try (Scope ws = tracer.withSpan(span)) {
+ doSomeOtherWork();
+ }
+ span.end();
+ }
+
+ private static void doWork() {
+ tracer.getCurrentSpan().addAnnotation("Annotation to the root Span before child is created.");
+ doSomeMoreWork();
+ tracer.getCurrentSpan().addAnnotation("Annotation to the root Span after child is ended.");
+ }
+
+ /**
+ * Main method.
+ *
+ * @param args the main arguments.
+ */
+ public static void main(String[] args) {
+
+ // WARNING: Be careful before you set sampler value to always sample, especially in
+ // production environment. Trace data is often very large in size and is expensive to
+ // collect. This is why rather than collecting traces for every request(i.e. alwaysSample),
+ // downsampling is prefered.
+ //
+ // By default, OpenCensus provides a probabilistic sampler that will trace once in every
+ // 10,000 requests, that's why if default probabilistic sampler is used
+ // you might not see trace data printed or exported and this is expected behavior.
+
+ TraceConfig traceConfig = Tracing.getTraceConfig();
+ traceConfig.updateActiveTraceParams(
+ traceConfig.getActiveTraceParams().toBuilder().setSampler(Samplers.alwaysSample()).build());
+
+ LoggingTraceExporter.register();
+ Span span = tracer.spanBuilderWithExplicitParent("MyRootSpan", null).startSpan();
+ try (Scope ws = tracer.withSpan(span)) {
+ doWork();
+ }
+ span.end();
+
+ // Wait for a duration longer than reporting duration (5s) to ensure spans are exported.
+ // Spans are exported every 5 seconds
+ sleep(5100);
+ }
+}
diff --git a/examples/src/main/java/io/opencensus/examples/trace/MultiSpansScopedTracing.java b/examples/src/main/java/io/opencensus/examples/trace/MultiSpansScopedTracing.java
new file mode 100644
index 00000000..5cfc9dfc
--- /dev/null
+++ b/examples/src/main/java/io/opencensus/examples/trace/MultiSpansScopedTracing.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017, 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.trace;
+
+import static io.opencensus.examples.trace.Utils.sleep;
+
+import io.opencensus.common.Scope;
+import io.opencensus.exporter.trace.logging.LoggingTraceExporter;
+import io.opencensus.trace.Span;
+import io.opencensus.trace.Tracer;
+import io.opencensus.trace.Tracing;
+import io.opencensus.trace.config.TraceConfig;
+import io.opencensus.trace.samplers.Samplers;
+
+/**
+ * Example showing how to create a child {@link Span} using scoped Spans, install it in the current
+ * context, and add annotations.
+ */
+public final class MultiSpansScopedTracing {
+ // Per class Tracer.
+ private static final Tracer tracer = Tracing.getTracer();
+
+ private MultiSpansScopedTracing() {}
+
+ private static void doSomeOtherWork() {
+ tracer.getCurrentSpan().addAnnotation("Annotation to the child Span");
+ }
+
+ private static void doSomeMoreWork() {
+ // Create a child Span of the current Span.
+ try (Scope ss = tracer.spanBuilder("MyChildSpan").startScopedSpan()) {
+ doSomeOtherWork();
+ }
+ }
+
+ private static void doWork() {
+ tracer.getCurrentSpan().addAnnotation("Annotation to the root Span before child is created.");
+ doSomeMoreWork();
+ tracer.getCurrentSpan().addAnnotation("Annotation to the root Span after child is ended.");
+ }
+
+ /**
+ * Main method.
+ *
+ * @param args the main arguments.
+ */
+ public static void main(String[] args) {
+
+ // WARNING: Be careful before you set sampler value to always sample, especially in
+ // production environment. Trace data is often very large in size and is expensive to
+ // collect. This is why rather than collecting traces for every request(i.e. alwaysSample),
+ // downsampling is prefered.
+ //
+ // By default, OpenCensus provides a probabilistic sampler that will trace once in every
+ // 10,000 requests, that's why if default probabilistic sampler is used
+ // you might not see trace data printed or exported and this is expected behavior.
+
+ TraceConfig traceConfig = Tracing.getTraceConfig();
+ traceConfig.updateActiveTraceParams(
+ traceConfig.getActiveTraceParams().toBuilder().setSampler(Samplers.alwaysSample()).build());
+
+ LoggingTraceExporter.register();
+ try (Scope ss = tracer.spanBuilderWithExplicitParent("MyRootSpan", null).startScopedSpan()) {
+ doWork();
+ }
+
+ // Wait for a duration longer than reporting duration (5s) to ensure spans are exported.
+ // Spans are exported every 5 seconds
+ sleep(5100);
+ }
+}
diff --git a/examples/src/main/java/io/opencensus/examples/trace/MultiSpansTracing.java b/examples/src/main/java/io/opencensus/examples/trace/MultiSpansTracing.java
new file mode 100644
index 00000000..fae4e3ff
--- /dev/null
+++ b/examples/src/main/java/io/opencensus/examples/trace/MultiSpansTracing.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017, 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.trace;
+
+import static io.opencensus.examples.trace.Utils.sleep;
+
+import io.opencensus.exporter.trace.logging.LoggingTraceExporter;
+import io.opencensus.trace.Span;
+import io.opencensus.trace.Tracer;
+import io.opencensus.trace.Tracing;
+import io.opencensus.trace.config.TraceConfig;
+import io.opencensus.trace.samplers.Samplers;
+
+/** Example showing how to directly create a child {@link Span} and add annotations. */
+public final class MultiSpansTracing {
+ // Per class Tracer.
+ private static final Tracer tracer = Tracing.getTracer();
+
+ private MultiSpansTracing() {}
+
+ private static void doWork() {
+ Span rootSpan = tracer.spanBuilderWithExplicitParent("MyRootSpan", null).startSpan();
+ rootSpan.addAnnotation("Annotation to the root Span before child is created.");
+ Span childSpan = tracer.spanBuilderWithExplicitParent("MyChildSpan", rootSpan).startSpan();
+ childSpan.addAnnotation("Annotation to the child Span");
+ childSpan.end();
+ rootSpan.addAnnotation("Annotation to the root Span after child is ended.");
+ rootSpan.end();
+ }
+
+ /**
+ * Main method.
+ *
+ * @param args the main arguments.
+ */
+ public static void main(String[] args) {
+
+ // WARNING: Be careful before you set sampler value to always sample, especially in
+ // production environment. Trace data is often very large in size and is expensive to
+ // collect. This is why rather than collecting traces for every request(i.e. alwaysSample),
+ // downsampling is prefered.
+ //
+ // By default, OpenCensus provides a probabilistic sampler that will trace once in every
+ // 10,000 requests, that's why if default probabilistic sampler is used
+ // you might not see trace data printed or exported and this is expected behavior.
+
+ TraceConfig traceConfig = Tracing.getTraceConfig();
+ traceConfig.updateActiveTraceParams(
+ traceConfig.getActiveTraceParams().toBuilder().setSampler(Samplers.alwaysSample()).build());
+
+ LoggingTraceExporter.register();
+ doWork();
+
+ // Wait for a duration longer than reporting duration (5s) to ensure spans are exported.
+ // Spans are exported every 5 seconds
+ sleep(5100);
+ }
+}
diff --git a/examples/src/main/java/io/opencensus/examples/trace/Utils.java b/examples/src/main/java/io/opencensus/examples/trace/Utils.java
new file mode 100644
index 00000000..9f0338af
--- /dev/null
+++ b/examples/src/main/java/io/opencensus/examples/trace/Utils.java
@@ -0,0 +1,37 @@
+/*
+ * 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.trace;
+
+import java.util.logging.Logger;
+
+/** Util methods. */
+final class Utils {
+
+ private static final Logger logger = Logger.getLogger(Utils.class.getName());
+
+ static void sleep(int ms) {
+ // A helper to avoid try-catch when invoking Thread.sleep so that
+ // sleeps can be succinct and not permeated by exception handling.
+ try {
+ Thread.sleep(ms);
+ } catch (Exception e) {
+ logger.warning((String.format("Failed to sleep for %dms. Exception: %s", ms, e)));
+ }
+ }
+
+ private Utils() {}
+}
diff --git a/examples/src/main/java/io/opencensus/examples/zpages/ZPagesTester.java b/examples/src/main/java/io/opencensus/examples/zpages/ZPagesTester.java
new file mode 100644
index 00000000..282b40ec
--- /dev/null
+++ b/examples/src/main/java/io/opencensus/examples/zpages/ZPagesTester.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2017, 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.zpages;
+
+import io.opencensus.common.Scope;
+import io.opencensus.contrib.grpc.metrics.RpcMeasureConstants;
+import io.opencensus.contrib.grpc.metrics.RpcViews;
+import io.opencensus.contrib.zpages.ZPageHandlers;
+import io.opencensus.stats.MeasureMap;
+import io.opencensus.stats.Stats;
+import io.opencensus.stats.StatsRecorder;
+import io.opencensus.tags.TagValue;
+import io.opencensus.tags.Tagger;
+import io.opencensus.tags.Tags;
+import io.opencensus.trace.SpanBuilder;
+import io.opencensus.trace.Tracer;
+import io.opencensus.trace.Tracing;
+import io.opencensus.trace.samplers.Samplers;
+import java.util.Collections;
+
+/** Testing only class for the UI. */
+public class ZPagesTester {
+
+ private ZPagesTester() {}
+
+ private static final Tagger tagger = Tags.getTagger();
+ private static final Tracer tracer = Tracing.getTracer();
+ private static final StatsRecorder statsRecorder = Stats.getStatsRecorder();
+
+ private static final String SPAN_NAME = "ExampleSpan";
+ private static final TagValue METHOD = TagValue.create("ExampleMethod");
+
+ private static void recordExampleData() throws InterruptedException {
+ Tracing.getExportComponent()
+ .getSampledSpanStore()
+ .registerSpanNamesForCollection(Collections.singletonList(SPAN_NAME));
+ RpcViews.registerAllViews(); // Use old RPC constants to get interval stats.
+ SpanBuilder spanBuilder =
+ tracer.spanBuilder(SPAN_NAME).setRecordEvents(true).setSampler(Samplers.alwaysSample());
+
+ try (Scope scope = spanBuilder.startScopedSpan()) {
+ tracer.getCurrentSpan().addAnnotation("Starts recording.");
+ MeasureMap measureMap =
+ statsRecorder
+ .newMeasureMap()
+ // Client measurements.
+ .put(RpcMeasureConstants.RPC_CLIENT_STARTED_COUNT, 1)
+ .put(RpcMeasureConstants.RPC_CLIENT_FINISHED_COUNT, 1)
+ .put(RpcMeasureConstants.RPC_CLIENT_ROUNDTRIP_LATENCY, 1.0)
+ .put(RpcMeasureConstants.RPC_CLIENT_REQUEST_COUNT, 1)
+ .put(RpcMeasureConstants.RPC_CLIENT_RESPONSE_COUNT, 1)
+ .put(RpcMeasureConstants.RPC_CLIENT_REQUEST_BYTES, 1e5)
+ .put(RpcMeasureConstants.RPC_CLIENT_RESPONSE_BYTES, 1e5)
+ .put(RpcMeasureConstants.RPC_CLIENT_UNCOMPRESSED_REQUEST_BYTES, 1e5)
+ .put(RpcMeasureConstants.RPC_CLIENT_UNCOMPRESSED_RESPONSE_BYTES, 1e5)
+ // Server measurements.
+ .put(RpcMeasureConstants.RPC_SERVER_STARTED_COUNT, 1)
+ .put(RpcMeasureConstants.RPC_SERVER_FINISHED_COUNT, 1)
+ .put(RpcMeasureConstants.RPC_SERVER_SERVER_LATENCY, 1.0)
+ .put(RpcMeasureConstants.RPC_SERVER_REQUEST_COUNT, 1)
+ .put(RpcMeasureConstants.RPC_SERVER_RESPONSE_COUNT, 1)
+ .put(RpcMeasureConstants.RPC_SERVER_REQUEST_BYTES, 1e5)
+ .put(RpcMeasureConstants.RPC_SERVER_RESPONSE_BYTES, 1e5)
+ .put(RpcMeasureConstants.RPC_SERVER_UNCOMPRESSED_REQUEST_BYTES, 1e5)
+ .put(RpcMeasureConstants.RPC_SERVER_UNCOMPRESSED_RESPONSE_BYTES, 1e5);
+ measureMap.record(
+ tagger
+ .currentBuilder()
+ .put(RpcMeasureConstants.RPC_STATUS, TagValue.create("OK"))
+ .put(RpcMeasureConstants.RPC_METHOD, METHOD)
+ .build());
+ MeasureMap measureMapErrors =
+ statsRecorder
+ .newMeasureMap()
+ .put(RpcMeasureConstants.RPC_CLIENT_ERROR_COUNT, 1)
+ .put(RpcMeasureConstants.RPC_SERVER_ERROR_COUNT, 1);
+ measureMapErrors.record(
+ tagger
+ .currentBuilder()
+ .put(RpcMeasureConstants.RPC_STATUS, TagValue.create("UNKNOWN"))
+ .put(RpcMeasureConstants.RPC_METHOD, METHOD)
+ .build());
+
+ Thread.sleep(200); // sleep for fake work.
+ tracer.getCurrentSpan().addAnnotation("Finish recording.");
+ }
+ }
+
+ /** Main method. */
+ public static void main(String[] args) throws Exception {
+ ZPageHandlers.startHttpServerAndRegisterAll(8080);
+ recordExampleData();
+ }
+}
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;
+}