diff --git a/java/.gitignore b/java/.gitignore index d11829c..dba179d 100644 --- a/java/.gitignore +++ b/java/.gitignore @@ -2,3 +2,5 @@ .project .settings/ target/ +.idea +*.iml diff --git a/java/pom.xml b/java/pom.xml index 6b6822f..4f72a66 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -46,5 +46,11 @@ logback-classic ${logback.version} + + + io.opentracing.contrib + opentracing-okhttp3 + 0.1.1-SNAPSHOT + diff --git a/java/src/main/java/lesson05/README.md b/java/src/main/java/lesson05/README.md new file mode 100644 index 0000000..7863629 --- /dev/null +++ b/java/src/main/java/lesson05/README.md @@ -0,0 +1,23 @@ +# Lesson 5 - Using Existing Open Source Instrumentation + +## Objectives + +* Using Okhttp Open Source Instrumentation + + +### Walkthrough + + +### okhttp + +Adding manual instrumentation to okhttp like we did in [Lesson 3](../lesson03) +is tedious. Fortunately, we don't need to do that because that instrumentation itself already exists +as open source modules: + + * https://github.com/opentracing-contrib/java-okhttp + +For an extra credit, try to use these modules to avoid instrumenting your code manually. + + + + diff --git a/java/src/main/java/lesson05/solution/Formatter.java b/java/src/main/java/lesson05/solution/Formatter.java new file mode 100644 index 0000000..c79badb --- /dev/null +++ b/java/src/main/java/lesson05/solution/Formatter.java @@ -0,0 +1,58 @@ +package lesson05.solution; + +import com.google.common.collect.ImmutableMap; +import io.dropwizard.Application; +import io.dropwizard.Configuration; +import io.dropwizard.setup.Environment; +import io.jaegertracing.internal.JaegerTracer; +import io.opentracing.Scope; +import io.opentracing.Tracer; +import lib.Tracing; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; + +public class Formatter extends Application { + + private final Tracer tracer; + + private Formatter(Tracer tracer) { + this.tracer = tracer; + } + + @Path("/format") + @Produces(MediaType.TEXT_PLAIN) + public class FormatterResource { + + @GET + public String format(@QueryParam("helloTo") String helloTo, @Context HttpHeaders httpHeaders) { + try (Scope scope = Tracing.startServerSpan(tracer, httpHeaders, "format")) { + String greeting = scope.span().getBaggageItem("greeting"); + if (greeting == null) { + greeting = "Hello"; + } + String helloStr = String.format("%s, %s!", greeting, helloTo); + scope.span().log(ImmutableMap.of("event", "string-format", "value", helloStr)); + return helloStr; + } + } + } + + @Override + public void run(Configuration configuration, Environment environment) throws Exception { + environment.jersey().register(new FormatterResource()); + } + + public static void main(String[] args) throws Exception { + System.setProperty("dw.server.applicationConnectors[0].port", "8081"); + System.setProperty("dw.server.adminConnectors[0].port", "9081"); + try (JaegerTracer tracer = Tracing.init("formatter")) { + new Formatter(tracer).run(args); + } + } +} diff --git a/java/src/main/java/lesson05/solution/Hello.java b/java/src/main/java/lesson05/solution/Hello.java new file mode 100644 index 0000000..29513a7 --- /dev/null +++ b/java/src/main/java/lesson05/solution/Hello.java @@ -0,0 +1,79 @@ +package lesson05.solution; + +import com.google.common.collect.ImmutableMap; +import io.jaegertracing.internal.JaegerTracer; +import io.opentracing.Scope; +import io.opentracing.Tracer; +import io.opentracing.contrib.okhttp3.TracingCallFactory; +import lib.Tracing; +import okhttp3.Call; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; + +public class Hello { + + private final Tracer tracer; + private final Call.Factory traceClient; + + private Hello(Tracer tracer) { + this.tracer = tracer; + traceClient = new TracingCallFactory(new OkHttpClient(), tracer); + } + + private String getHttp(int port, String path, String param, String value) { + try { + HttpUrl url = new HttpUrl.Builder().scheme("http").host("localhost").port(port).addPathSegment(path) + .addQueryParameter(param, value).build(); + Request.Builder requestBuilder = new Request.Builder().url(url); + Request request = requestBuilder.build(); + Response response = traceClient.newCall(request).execute(); + tracer.activeSpan().setTag("invoked", "okhttptracer"); + if (response.code() != 200) { + throw new RuntimeException("Bad HTTP result: " + response); + } + return response.body().string(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void sayHello(String helloTo, String greeting) { + try (Scope scope = tracer.buildSpan("say-hello").startActive(true)) { + scope.span().setTag("hello-to", helloTo); + scope.span().setBaggageItem("greeting", greeting); + + String helloStr = formatString(helloTo); + printHello(helloStr); + } + } + + private String formatString(String helloTo) { + try (Scope scope = tracer.buildSpan("formatString").startActive(true)) { + String helloStr = getHttp(8081, "format", "helloTo", helloTo); + scope.span().log(ImmutableMap.of("event", "string-format", "value", helloStr)); + return helloStr; + } + } + + private void printHello(String helloStr) { + try (Scope scope = tracer.buildSpan("printHello").startActive(true)) { + getHttp(8082, "publish", "helloStr", helloStr); + scope.span().log(ImmutableMap.of("event", "println")); + } + } + + public static void main(String[] args) { + if (args.length != 2) { + throw new IllegalArgumentException("Expecting two arguments, helloTo and greeting"); + } + String helloTo = args[0]; + String greeting = args[1]; + try (JaegerTracer tracer = Tracing.init("hello-world")) { + new Hello(tracer).sayHello(helloTo, greeting); + } + } +} diff --git a/java/src/main/java/lesson05/solution/Publisher.java b/java/src/main/java/lesson05/solution/Publisher.java new file mode 100644 index 0000000..5ff56f8 --- /dev/null +++ b/java/src/main/java/lesson05/solution/Publisher.java @@ -0,0 +1,54 @@ +package lesson05.solution; + +import com.google.common.collect.ImmutableMap; +import io.dropwizard.Application; +import io.dropwizard.Configuration; +import io.dropwizard.setup.Environment; +import io.jaegertracing.internal.JaegerTracer; +import io.opentracing.Scope; +import io.opentracing.Tracer; +import lib.Tracing; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; + +public class Publisher extends Application { + + private final Tracer tracer; + + private Publisher(Tracer tracer) { + this.tracer = tracer; + } + + @Path("/publish") + @Produces(MediaType.TEXT_PLAIN) + public class PublisherResource { + + @GET + public String format(@QueryParam("helloStr") String helloStr, @Context HttpHeaders httpHeaders) { + try (Scope scope = Tracing.startServerSpan(tracer, httpHeaders, "publish")) { + System.out.println(helloStr); + scope.span().log(ImmutableMap.of("event", "println", "value", helloStr)); + return "published"; + } + } + } + + @Override + public void run(Configuration configuration, Environment environment) throws Exception { + environment.jersey().register(new PublisherResource()); + } + + public static void main(String[] args) throws Exception { + System.setProperty("dw.server.applicationConnectors[0].port", "8082"); + System.setProperty("dw.server.adminConnectors[0].port", "9082"); + try (JaegerTracer tracer = Tracing.init("publisher")) { + new Publisher(tracer).run(args); + } + } +}