diff --git a/java/rabbitmq-ot/.gradle/5.6.4/executionHistory/executionHistory.bin b/java/rabbitmq-ot/.gradle/5.6.4/executionHistory/executionHistory.bin new file mode 100644 index 00000000..2bcca7f0 Binary files /dev/null and b/java/rabbitmq-ot/.gradle/5.6.4/executionHistory/executionHistory.bin differ diff --git a/java/rabbitmq-ot/.gradle/5.6.4/executionHistory/executionHistory.lock b/java/rabbitmq-ot/.gradle/5.6.4/executionHistory/executionHistory.lock new file mode 100644 index 00000000..c64752f1 Binary files /dev/null and b/java/rabbitmq-ot/.gradle/5.6.4/executionHistory/executionHistory.lock differ diff --git a/java/rabbitmq-ot/.gradle/5.6.4/fileChanges/last-build.bin b/java/rabbitmq-ot/.gradle/5.6.4/fileChanges/last-build.bin new file mode 100644 index 00000000..f76dd238 Binary files /dev/null and b/java/rabbitmq-ot/.gradle/5.6.4/fileChanges/last-build.bin differ diff --git a/java/rabbitmq-ot/.gradle/5.6.4/fileContent/fileContent.lock b/java/rabbitmq-ot/.gradle/5.6.4/fileContent/fileContent.lock new file mode 100644 index 00000000..7c89efe5 Binary files /dev/null and b/java/rabbitmq-ot/.gradle/5.6.4/fileContent/fileContent.lock differ diff --git a/java/rabbitmq-ot/.gradle/5.6.4/fileHashes/fileHashes.bin b/java/rabbitmq-ot/.gradle/5.6.4/fileHashes/fileHashes.bin new file mode 100644 index 00000000..872dee3e Binary files /dev/null and b/java/rabbitmq-ot/.gradle/5.6.4/fileHashes/fileHashes.bin differ diff --git a/java/rabbitmq-ot/.gradle/5.6.4/fileHashes/fileHashes.lock b/java/rabbitmq-ot/.gradle/5.6.4/fileHashes/fileHashes.lock new file mode 100644 index 00000000..a937329c Binary files /dev/null and b/java/rabbitmq-ot/.gradle/5.6.4/fileHashes/fileHashes.lock differ diff --git a/java/rabbitmq-ot/.gradle/5.6.4/gc.properties b/java/rabbitmq-ot/.gradle/5.6.4/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/java/rabbitmq-ot/.gradle/5.6.4/javaCompile/classAnalysis.bin b/java/rabbitmq-ot/.gradle/5.6.4/javaCompile/classAnalysis.bin new file mode 100644 index 00000000..439ddb72 Binary files /dev/null and b/java/rabbitmq-ot/.gradle/5.6.4/javaCompile/classAnalysis.bin differ diff --git a/java/rabbitmq-ot/.gradle/5.6.4/javaCompile/javaCompile.lock b/java/rabbitmq-ot/.gradle/5.6.4/javaCompile/javaCompile.lock new file mode 100644 index 00000000..9d04d28e Binary files /dev/null and b/java/rabbitmq-ot/.gradle/5.6.4/javaCompile/javaCompile.lock differ diff --git a/java/rabbitmq-ot/.gradle/5.6.4/javaCompile/taskHistory.bin b/java/rabbitmq-ot/.gradle/5.6.4/javaCompile/taskHistory.bin new file mode 100644 index 00000000..2f0e8e4b Binary files /dev/null and b/java/rabbitmq-ot/.gradle/5.6.4/javaCompile/taskHistory.bin differ diff --git a/java/rabbitmq-ot/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/java/rabbitmq-ot/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 00000000..260b4e65 Binary files /dev/null and b/java/rabbitmq-ot/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/java/rabbitmq-ot/.gradle/buildOutputCleanup/cache.properties b/java/rabbitmq-ot/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 00000000..397b7a72 --- /dev/null +++ b/java/rabbitmq-ot/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Sun Apr 05 12:42:49 CEST 2020 +gradle.version=5.6.4 diff --git a/java/rabbitmq-ot/.gradle/buildOutputCleanup/outputFiles.bin b/java/rabbitmq-ot/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 00000000..7c7e61f0 Binary files /dev/null and b/java/rabbitmq-ot/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/java/rabbitmq-ot/.gradle/vcs-1/gc.properties b/java/rabbitmq-ot/.gradle/vcs-1/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/java/rabbitmq-ot/README.md b/java/rabbitmq-ot/README.md new file mode 100644 index 00000000..92f6da09 --- /dev/null +++ b/java/rabbitmq-ot/README.md @@ -0,0 +1,94 @@ +## Tracing RabbitMQ Producer / Consumer code example + + +A detailed step-by-step tutorial on how to implement tracing with a RabbitMQ Consumer and Producer using RabbitMQ Java client and Datadog the OpenTracing API. + +### _Preliminary tasks and first time steps_ + +**Install RabbitMQ on mac OSX (tested on High Sierra)** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ brew install rabbitmq +```` + +**Start RabbitMQ** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ brew services start rabbitmq +```` + +Another option is to use the official docker image and run it locally. +Below an examlple of docker-compose file. + + +##### _docker-compose.yml_ +```` +rabbitmq: + image: rabbitmq:management + ports: + - "5672:5672" + - "15672:15672" +```` + +**Spin up the container** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ docker-compose up -d +```` + +### _Administration tasks_ + +**Start RabbitMQ** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ brew services start rabbitmq +```` + +**Stop RabbitMQ** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ brew services stop rabbitmq +```` + +**RabbitMQ UI** + +```` +http://localhost:15672 +```` + +### _Spin up the Datadog Agent (Provide your API key to the belown command_ + + +```` +docker run -d --name datadog_agent -v /var/run/docker.sock:/var/run/docker.sock:ro -v /proc/:/host/proc/:ro -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro -p 127.0.0.1:8126:8126/tcp -e DD_API_KEY= -e DD_APM_ENABLED=true -e DD_APM_IGNORE_RESOURCES="GET /api/random" datadog/agent:latest +```` + +### _Clone the repository and build the application_ + +The project is structured as a main gradle project with two submodules (one for the consumer, the other for the producer) + +```` +COMP10619:RabbitMQ pejman.tabassomi$ git clone https://github.com/ptabasso2/prodconsrbmqdt.git +COMP10619:RabbitMQ pejman.tabassomi$ cd prodconsrbmqdt +COMP10619:prodconsrbmqdt pejman.tabassomi$ ./gradlew shadowjar +```` + + +### _Start the app_ + +Open two terminal windows, one for the producer. The other for the consumer. + +#### Consumer + +```` +COMP10619:RabbitMQ pejman.tabassomi$ java -jar consumer/build/libs/consumer-0.1.0.jar +```` +and then + +#### Producer + +```` +COMP10619:RabbitMQ pejman.tabassomi$ java -jar producer/build/libs/producer-0.1.0.jar +```` + + diff --git a/java/rabbitmq-ot/build.gradle b/java/rabbitmq-ot/build.gradle new file mode 100644 index 00000000..6c5d0bd4 --- /dev/null +++ b/java/rabbitmq-ot/build.gradle @@ -0,0 +1,7 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This is a general purpose Gradle build. + * Learn how to create Gradle builds at https://guides.gradle.org/creating-new-gradle-builds + */ +tasks.getByPath(':consumer:run').shouldRunAfter(':producer:run') diff --git a/java/rabbitmq-ot/consumer/build.gradle b/java/rabbitmq-ot/consumer/build.gradle new file mode 100644 index 00000000..4d307d1f --- /dev/null +++ b/java/rabbitmq-ot/consumer/build.gradle @@ -0,0 +1,40 @@ +plugins { + id 'java' + id 'application' + id "com.github.johnrengelman.shadow" version "5.2.0" +} + +version '0.1.0' + +shadowJar { + archiveFileName = "consumer-${version}.jar" +} + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + compile 'com.rabbitmq:amqp-client:5.8.0' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' + compile group: 'com.datadoghq', name: 'dd-trace-ot', version: '0.47.0' + //compile group: 'io.opentracing.contrib', name: 'opentracing-rabbitmq-client', version: '0.1.9' + compile 'com.squareup.okhttp3:okhttp:4.5.0' + +} + +ext { + javaMainClass = "com.datadog.pej.Main" +} + +application { + mainClassName = javaMainClass +} + +jar { + manifest { + attributes 'Main-Class': 'com.datadog.pej.Main' + } +} \ No newline at end of file diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/com/datadog/pej/EndPoint.class b/java/rabbitmq-ot/consumer/build/classes/java/main/com/datadog/pej/EndPoint.class new file mode 100644 index 00000000..1d9d6036 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/com/datadog/pej/EndPoint.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/com/datadog/pej/Main.class b/java/rabbitmq-ot/consumer/build/classes/java/main/com/datadog/pej/Main.class new file mode 100644 index 00000000..5b1a7a53 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/com/datadog/pej/Main.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/com/datadog/pej/QueueConsumer.class b/java/rabbitmq-ot/consumer/build/classes/java/main/com/datadog/pej/QueueConsumer.class new file mode 100644 index 00000000..a8b3fa31 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/com/datadog/pej/QueueConsumer.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.class b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.class new file mode 100644 index 00000000..ab3d7375 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.class b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.class new file mode 100644 index 00000000..5a61d2b4 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/SpanDecorator.class b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/SpanDecorator.class new file mode 100644 index 00000000..e73a58bb Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/SpanDecorator.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingChannel.class b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingChannel.class new file mode 100644 index 00000000..377c6958 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingChannel.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnection.class b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnection.class new file mode 100644 index 00000000..4a29b2e4 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnection.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.class b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.class new file mode 100644 index 00000000..85c149f1 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConsumer.class b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConsumer.class new file mode 100644 index 00000000..e3024d3e Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConsumer.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.class b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.class new file mode 100644 index 00000000..350bb825 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.class differ diff --git a/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingUtils.class b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingUtils.class new file mode 100644 index 00000000..960eeb0a Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingUtils.class differ diff --git a/java/rabbitmq-ot/consumer/build/libs/consumer-0.1.0.jar b/java/rabbitmq-ot/consumer/build/libs/consumer-0.1.0.jar new file mode 100644 index 00000000..6377dd39 Binary files /dev/null and b/java/rabbitmq-ot/consumer/build/libs/consumer-0.1.0.jar differ diff --git a/java/rabbitmq-ot/consumer/build/tmp/shadowJar/MANIFEST.MF b/java/rabbitmq-ot/consumer/build/tmp/shadowJar/MANIFEST.MF new file mode 100644 index 00000000..6d901297 --- /dev/null +++ b/java/rabbitmq-ot/consumer/build/tmp/shadowJar/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: com.datadog.pej.Main + diff --git a/java/rabbitmq-ot/consumer/src/main/java/com/datadog/pej/EndPoint.java b/java/rabbitmq-ot/consumer/src/main/java/com/datadog/pej/EndPoint.java new file mode 100644 index 00000000..bd78b983 --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/com/datadog/pej/EndPoint.java @@ -0,0 +1,51 @@ +package com.datadog.pej; + + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +/** + * Represents a connection with a queue + * @author syntx + * + */ +public abstract class EndPoint{ + + protected Channel channel; + protected Connection connection; + protected String endPointName; + + public EndPoint(String endpointName) throws IOException, TimeoutException { + this.endPointName = endpointName; + + //Create a connection factory + ConnectionFactory factory = new ConnectionFactory(); + + //hostname of your rabbitmq server + factory.setHost("localhost"); + + //getting a connection + connection = factory.newConnection(); + + //creating a channel + channel = connection.createChannel(); + + //declaring a queue for this channel. If queue does not exist, + //it will be created on the server. + channel.queueDeclare(endpointName, false, false, false, null); + } + + + /** + * Close channel and connection. Not necessary as it happens implicitly any way. + * @throws IOException + */ + public void close() throws IOException, TimeoutException { + this.channel.close(); + this.connection.close(); + } +} \ No newline at end of file diff --git a/java/rabbitmq-ot/consumer/src/main/java/com/datadog/pej/Main.java b/java/rabbitmq-ot/consumer/src/main/java/com/datadog/pej/Main.java new file mode 100644 index 00000000..f2352cb8 --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/com/datadog/pej/Main.java @@ -0,0 +1,38 @@ +package com.datadog.pej; + +import datadog.opentracing.DDTracer; +import datadog.trace.api.DDTags; +import datadog.trace.api.GlobalTracer; +import io.opentracing.Scope; +import io.opentracing.ScopeManager; +import io.opentracing.Span; +import io.opentracing.Tracer; + + +public class Main { + + public static void main(String[] args) throws Exception{ + + + //Tracer tracer = new DDTracer("Consumer"); + Tracer tracer = DDTracer.builder().build(); + GlobalTracer.registerIfAbsent((datadog.trace.api.Tracer) tracer); + + ScopeManager sm = tracer.scopeManager(); + Tracer.SpanBuilder tb = tracer.buildSpan("receiving"); + + Span span = tb.start(); + + try(Scope scope = sm.activate(span)) { + span.setTag(DDTags.SERVICE_NAME, "Consumer"); + span.setTag(DDTags.RESOURCE_NAME, "receive message"); + span.setTag(DDTags.SPAN_TYPE, "web"); + + QueueConsumer consumer = new QueueConsumer("spring-boot", tracer); + Thread consumerThread = new Thread(consumer); + consumerThread.start(); + span.finish(); + } + + } +} \ No newline at end of file diff --git a/java/rabbitmq-ot/consumer/src/main/java/com/datadog/pej/QueueConsumer.java b/java/rabbitmq-ot/consumer/src/main/java/com/datadog/pej/QueueConsumer.java new file mode 100644 index 00000000..e2be6049 --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/com/datadog/pej/QueueConsumer.java @@ -0,0 +1,109 @@ +package com.datadog.pej; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeoutException; + +import datadog.trace.api.DDTags; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.Tracer; +import io.opentracing.contrib.rabbitmq.TracingChannel; +import okhttp3.Call; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.commons.lang3.SerializationUtils; + +import com.rabbitmq.client.AMQP.BasicProperties; +import com.rabbitmq.client.Consumer; +import com.rabbitmq.client.Envelope; +import com.rabbitmq.client.ShutdownSignalException; + + +/** + * The endpoint that consumes messages off of the queue. Happens to be runnable. + * @author syntx + * + */ +public class QueueConsumer extends EndPoint implements Runnable, Consumer{ + + Tracer tracer; + + public QueueConsumer(String endPointName, Tracer tracer) throws IOException, TimeoutException { + super(endPointName); + this.tracer = tracer; + } + + public void run() { + try { + //start consuming messages. Auto acknowledge messages. + TracingChannel tracingChannel = new TracingChannel(channel, tracer); + //channel.basicConsume(endPointName, true,this); + tracingChannel.basicConsume(endPointName, true,this); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Called when consumer is registered. + */ + public void handleConsumeOk(String consumerTag) { + System.out.println("Consumer "+consumerTag +" registered"); + } + + /** + * Called when new message is available. + */ + /*public void handleDelivery(String consumerTag, Envelope env, + BasicProperties props, byte[] body) throws IOException { + Map map = (HashMap)SerializationUtils.deserialize(body); + System.out.println("Message Number "+ map.get("message number") + " received."); + + }*/ + + public void handleDelivery(String consumerTag, Envelope env, + BasicProperties props, byte[] body) throws IOException { + Map map = (HashMap)SerializationUtils.deserialize(body); + System.out.println("Message Number "+ map.get("message number") + " received."); + + Span resultingspan = tracer.activeSpan(); + + + Tracer.SpanBuilder httpspan = tracer.buildSpan("okhttp google").asChildOf(resultingspan); + Span childspan = httpspan.start(); + + try(Scope scope = tracer.activateSpan(childspan)){ + childspan.setTag(DDTags.RESOURCE_NAME, "GET /"); + childspan.setTag(DDTags.SPAN_TYPE, "web"); + childspan.setTag(DDTags.SERVICE_NAME, "Google"); + httpRequest(); + System.out.println("Hello google"); + childspan.finish(); + } + + + } + + + public void httpRequest() throws IOException { + OkHttpClient client = new OkHttpClient(); + Request request = new Request.Builder() + .url("https://www.google.fr") + .build(); + + Call call = client.newCall(request); + Response response = call.execute(); + System.out.println("http response code: " + response.code()); + + } + + + public void handleCancel(String consumerTag) {} + public void handleCancelOk(String consumerTag) {} + public void handleRecoverOk(String consumerTag) {} + public void handleShutdownSignal(String consumerTag, ShutdownSignalException arg1) {} +} \ No newline at end of file diff --git a/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.java b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.java new file mode 100644 index 00000000..bcfb7f8d --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import io.opentracing.propagation.TextMap; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static java.lang.String.valueOf; + +public class HeadersMapExtractAdapter implements TextMap { + + private final Map map = new HashMap<>(); + + public HeadersMapExtractAdapter(Map headers) { + if (headers == null) { + return; + } + for (Map.Entry entry : headers.entrySet()) { + map.put(entry.getKey(), valueOf(entry.getValue())); + } + } + + @Override + public Iterator> iterator() { + return map.entrySet().iterator(); + } + + @Override + public void put(String key, String value) { + throw new UnsupportedOperationException( + "HeadersMapExtractAdapter should only be used with Tracer.extract()"); + } +} diff --git a/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.java b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.java new file mode 100644 index 00000000..5a5ebff7 --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import io.opentracing.propagation.TextMap; + +import java.util.Iterator; +import java.util.Map; + + +public class HeadersMapInjectAdapter implements TextMap { + + private final Map headers; + + public HeadersMapInjectAdapter(Map headers) { + this.headers = headers; + } + + @Override + public Iterator> iterator() { + throw new UnsupportedOperationException("iterator should never be used with Tracer.inject()"); + } + + @Override + public void put(String key, String value) { + headers.put(key, value); + } +} \ No newline at end of file diff --git a/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/SpanDecorator.java b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/SpanDecorator.java new file mode 100644 index 00000000..ca4dcb34 --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/SpanDecorator.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + + +import io.opentracing.Span; +import io.opentracing.tag.Tags; + +public class SpanDecorator { + public static final String COMPONENT_NAME = "java-rabbitmq"; + + public static void onRequest(String exchange, Span span) { + Tags.COMPONENT.set(span, COMPONENT_NAME); + Tags.MESSAGE_BUS_DESTINATION.set(span, exchange); + } + + public static void onResponse(Span span) { + Tags.COMPONENT.set(span, COMPONENT_NAME); + } +} diff --git a/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingChannel.java b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingChannel.java new file mode 100644 index 00000000..6a98c5d6 --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingChannel.java @@ -0,0 +1,654 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.*; +import datadog.trace.api.DDTags; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.Tracer; +import io.opentracing.util.GlobalTracer; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; + +import static io.opentracing.contrib.rabbitmq.TracingUtils.buildSpan; +import static io.opentracing.contrib.rabbitmq.TracingUtils.inject; + + +public class TracingChannel implements Channel { + + private final Channel channel; + private final Tracer tracer; + + public TracingChannel(Channel channel, Tracer tracer) { + this.channel = channel; + this.tracer = tracer; + } + + /** + * GlobalTracer is used to get tracer + */ + public TracingChannel(Channel channel) { + this(channel, GlobalTracer.get()); + } + + @Override + public int getChannelNumber() { + return channel.getChannelNumber(); + } + + @Override + public Connection getConnection() { + return channel.getConnection(); + } + + @Override + public void close() throws IOException, TimeoutException { + channel.close(); + } + + @Override + public void close(int closeCode, String closeMessage) throws IOException, TimeoutException { + channel.close(closeCode, closeMessage); + } + + @Override + public void abort() throws IOException { + channel.abort(); + } + + @Override + public void abort(int closeCode, String closeMessage) throws IOException { + channel.abort(closeCode, closeMessage); + } + + @Override + public void addReturnListener(ReturnListener listener) { + channel.addReturnListener(listener); + } + + @Override + public ReturnListener addReturnListener(ReturnCallback returnCallback) { + return channel.addReturnListener(returnCallback); + } + + @Override + public boolean removeReturnListener(ReturnListener listener) { + return channel.removeReturnListener(listener); + } + + @Override + public void clearReturnListeners() { + channel.clearReturnListeners(); + } + + @Override + public void addConfirmListener(ConfirmListener listener) { + channel.addConfirmListener(listener); + } + + @Override + public ConfirmListener addConfirmListener(ConfirmCallback confirmCallback, + ConfirmCallback confirmCallback1) { + return channel.addConfirmListener(confirmCallback, confirmCallback1); + } + + @Override + public boolean removeConfirmListener(ConfirmListener listener) { + return channel.removeConfirmListener(listener); + } + + @Override + public void clearConfirmListeners() { + channel.clearConfirmListeners(); + } + + @Override + public Consumer getDefaultConsumer() { + return channel.getDefaultConsumer(); + } + + @Override + public void setDefaultConsumer(Consumer consumer) { + channel.setDefaultConsumer(consumer); + } + + @Override + public void basicQos(int prefetchSize, int prefetchCount, boolean global) throws IOException { + channel.basicQos(prefetchSize, prefetchCount, global); + } + + @Override + public void basicQos(int prefetchCount, boolean global) throws IOException { + channel.basicQos(prefetchCount, global); + } + + @Override + public void basicQos(int prefetchCount) throws IOException { + channel.basicQos(prefetchCount); + } + + @Override + public void basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, + byte[] body) throws IOException { + basicPublish(exchange, routingKey, false, false, props, body); + } + + @Override + public void basicPublish(String exchange, String routingKey, boolean mandatory, + AMQP.BasicProperties props, byte[] body) throws IOException { + basicPublish(exchange, routingKey, mandatory, false, props, body); + } + + @Override + public void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, + AMQP.BasicProperties props, byte[] body) throws IOException { + + Span span = buildSpan(exchange, routingKey, props, tracer); + try (Scope ignored = tracer.scopeManager().activate(span)) { + AMQP.BasicProperties properties = inject(props, span, tracer); + channel.basicPublish(exchange, routingKey, mandatory, immediate, properties, body); + } finally { + span.finish(); + } + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type) throws IOException { + return channel.exchangeDeclare(exchange, type); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type) + throws IOException { + return channel.exchangeDeclare(exchange, type); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable) + throws IOException { + return channel.exchangeDeclare(exchange, type, durable); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, + boolean durable) throws IOException { + return channel.exchangeDeclare(exchange, type, durable); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, + boolean autoDelete, Map arguments) throws IOException { + return channel.exchangeDeclare(exchange, type, durable, autoDelete, arguments); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, + boolean durable, boolean autoDelete, Map arguments) throws IOException { + return channel.exchangeDeclare(exchange, type, durable, autoDelete, arguments); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, + boolean autoDelete, boolean internal, Map arguments) throws IOException { + return channel.exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, + boolean durable, boolean autoDelete, boolean internal, Map arguments) + throws IOException { + return channel.exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments); + } + + @Override + public void exchangeDeclareNoWait(String exchange, String type, boolean durable, + boolean autoDelete, boolean internal, Map arguments) throws IOException { + channel.exchangeDeclareNoWait(exchange, type, durable, autoDelete, internal, arguments); + } + + @Override + public void exchangeDeclareNoWait(String exchange, BuiltinExchangeType type, boolean durable, + boolean autoDelete, boolean internal, Map arguments) throws IOException { + channel.exchangeDeclareNoWait(exchange, type, durable, autoDelete, internal, arguments); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclarePassive(String name) throws IOException { + return channel.exchangeDeclarePassive(name); + } + + @Override + public AMQP.Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) + throws IOException { + return channel.exchangeDelete(exchange, ifUnused); + } + + @Override + public void exchangeDeleteNoWait(String exchange, boolean ifUnused) throws IOException { + channel.exchangeDeleteNoWait(exchange, ifUnused); + } + + @Override + public AMQP.Exchange.DeleteOk exchangeDelete(String exchange) throws IOException { + return channel.exchangeDelete(exchange); + } + + @Override + public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey) + throws IOException { + return channel.exchangeBind(destination, source, routingKey); + } + + @Override + public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey, + Map arguments) throws IOException { + return channel.exchangeBind(destination, source, routingKey, arguments); + } + + @Override + public void exchangeBindNoWait(String destination, String source, String routingKey, + Map arguments) throws IOException { + channel.exchangeBindNoWait(destination, source, routingKey, arguments); + } + + @Override + public AMQP.Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey) + throws IOException { + return channel.exchangeUnbind(destination, source, routingKey); + } + + @Override + public AMQP.Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey, + Map arguments) throws IOException { + return channel.exchangeUnbind(destination, source, routingKey, arguments); + } + + @Override + public void exchangeUnbindNoWait(String destination, String source, String routingKey, + Map arguments) throws IOException { + channel.exchangeUnbindNoWait(destination, source, routingKey, arguments); + } + + @Override + public AMQP.Queue.DeclareOk queueDeclare() throws IOException { + return channel.queueDeclare(); + } + + @Override + public AMQP.Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, + boolean autoDelete, Map arguments) throws IOException { + return channel.queueDeclare(queue, durable, exclusive, autoDelete, arguments); + } + + @Override + public void queueDeclareNoWait(String queue, boolean durable, boolean exclusive, + boolean autoDelete, Map arguments) throws IOException { + channel.queueDeclareNoWait(queue, durable, exclusive, autoDelete, arguments); + } + + @Override + public AMQP.Queue.DeclareOk queueDeclarePassive(String queue) throws IOException { + return channel.queueDeclarePassive(queue); + } + + @Override + public AMQP.Queue.DeleteOk queueDelete(String queue) throws IOException { + return channel.queueDelete(queue); + } + + @Override + public AMQP.Queue.DeleteOk queueDelete(String queue, boolean ifUnused, boolean ifEmpty) + throws IOException { + return channel.queueDelete(queue, ifUnused, ifEmpty); + } + + @Override + public void queueDeleteNoWait(String queue, boolean ifUnused, boolean ifEmpty) + throws IOException { + channel.queueDeleteNoWait(queue, ifUnused, ifEmpty); + } + + @Override + public AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey) + throws IOException { + return channel.queueBind(queue, exchange, routingKey); + } + + @Override + public AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey, + Map arguments) throws IOException { + return channel.queueBind(queue, exchange, routingKey, arguments); + } + + @Override + public void queueBindNoWait(String queue, String exchange, String routingKey, + Map arguments) throws IOException { + channel.queueBindNoWait(queue, exchange, routingKey, arguments); + } + + @Override + public AMQP.Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) + throws IOException { + return channel.queueUnbind(queue, exchange, routingKey); + } + + @Override + public AMQP.Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, + Map arguments) throws IOException { + return channel.queueUnbind(queue, exchange, routingKey, arguments); + } + + @Override + public AMQP.Queue.PurgeOk queuePurge(String queue) throws IOException { + return channel.queuePurge(queue); + } + + @Override + public GetResponse basicGet(String queue, boolean autoAck) throws IOException { + GetResponse response = channel.basicGet(queue, autoAck); + if (response != null) { + TracingUtils.buildAndFinishChildSpan(response.getProps(), queue, tracer); + } + return response; + } + + @Override + public void basicAck(long deliveryTag, boolean multiple) throws IOException { + channel.basicAck(deliveryTag, multiple); + } + + @Override + public void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException { + channel.basicNack(deliveryTag, multiple, requeue); + } + + @Override + public void basicReject(long deliveryTag, boolean requeue) throws IOException { + channel.basicReject(deliveryTag, requeue); + } + + @Override + public String basicConsume(String queue, Consumer callback) throws IOException { + return basicConsume(queue, false, "", false, false, null, callback); + } + + @Override + public String basicConsume(String queue, DeliverCallback deliverCallback, + CancelCallback cancelCallback) throws IOException { + return channel + .basicConsume(queue, new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback); + } + + @Override + public String basicConsume(String queue, DeliverCallback deliverCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel.basicConsume(queue, new TracingDeliverCallback(deliverCallback, queue, tracer), + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, DeliverCallback deliverCallback, + CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel + .basicConsume(queue, new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback, + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException { + return basicConsume(queue, autoAck, "", false, false, null, callback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, + CancelCallback cancelCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, new TracingDeliverCallback(deliverCallback, queue, tracer), + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, + CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel + .basicConsume(queue, autoAck, new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback, shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Map arguments, + Consumer callback) throws IOException { + return basicConsume(queue, autoAck, "", false, false, arguments, callback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Map arguments, + DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { + return channel.basicConsume(queue, autoAck, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Map arguments, + DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel.basicConsume(queue, autoAck, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Map arguments, + DeliverCallback deliverCallback, CancelCallback cancelCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback, + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, Consumer callback) + throws IOException { + return basicConsume(queue, autoAck, consumerTag, false, false, null, callback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, + DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { + return channel.basicConsume(queue, autoAck, consumerTag, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, + DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel.basicConsume(queue, autoAck, consumerTag, + new TracingDeliverCallback(deliverCallback, queue, tracer), shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, + DeliverCallback deliverCallback, CancelCallback cancelCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, consumerTag, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback, + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, + boolean exclusive, Map arguments, Consumer callback) throws IOException { + return channel.basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, + new TracingConsumer(callback, queue, tracer)); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, + boolean exclusive, Map arguments, DeliverCallback deliverCallback, + CancelCallback cancelCallback) throws IOException { + return channel.basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, + boolean exclusive, Map arguments, DeliverCallback deliverCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, + boolean exclusive, Map arguments, DeliverCallback deliverCallback, + CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel + .basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback, shutdownSignalCallback); + } + + @Override + public void basicCancel(String consumerTag) throws IOException { + channel.basicCancel(consumerTag); + } + + @Override + public AMQP.Basic.RecoverOk basicRecover() throws IOException { + return channel.basicRecover(); + } + + @Override + public AMQP.Basic.RecoverOk basicRecover(boolean requeue) throws IOException { + return channel.basicRecover(requeue); + } + + @Override + public AMQP.Tx.SelectOk txSelect() throws IOException { + return channel.txSelect(); + } + + @Override + public AMQP.Tx.CommitOk txCommit() throws IOException { + return channel.txCommit(); + } + + @Override + public AMQP.Tx.RollbackOk txRollback() throws IOException { + return channel.txRollback(); + } + + @Override + public AMQP.Confirm.SelectOk confirmSelect() throws IOException { + return channel.confirmSelect(); + } + + @Override + public long getNextPublishSeqNo() { + return channel.getNextPublishSeqNo(); + } + + @Override + public boolean waitForConfirms() throws InterruptedException { + return channel.waitForConfirms(); + } + + @Override + public boolean waitForConfirms(long timeout) throws InterruptedException, TimeoutException { + return channel.waitForConfirms(timeout); + } + + @Override + public void waitForConfirmsOrDie() throws IOException, InterruptedException { + channel.waitForConfirmsOrDie(); + } + + @Override + public void waitForConfirmsOrDie(long timeout) + throws IOException, InterruptedException, TimeoutException { + channel.waitForConfirmsOrDie(timeout); + } + + @Override + public void asyncRpc(Method method) throws IOException { + channel.asyncRpc(method); + } + + @Override + public Command rpc(Method method) throws IOException { + return channel.rpc(method); + } + + @Override + public long messageCount(String queue) throws IOException { + return channel.messageCount(queue); + } + + @Override + public long consumerCount(String queue) throws IOException { + return channel.consumerCount(queue); + } + + @Override + public CompletableFuture asyncCompletableRpc( + Method method) throws IOException { + return channel.asyncCompletableRpc(method); + } + + @Override + public void addShutdownListener(ShutdownListener listener) { + channel.addShutdownListener(listener); + } + + @Override + public void removeShutdownListener(ShutdownListener listener) { + channel.removeShutdownListener(listener); + } + + @Override + public ShutdownSignalException getCloseReason() { + return channel.getCloseReason(); + } + + @Override + public void notifyListeners() { + channel.notifyListeners(); + } + + @Override + public boolean isOpen() { + return channel.isOpen(); + } + +} diff --git a/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnection.java b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnection.java new file mode 100644 index 00000000..e4f349fa --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnection.java @@ -0,0 +1,184 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.*; +import io.opentracing.Tracer; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.Map; + +public class TracingConnection implements Connection { + + private final Connection connection; + + private final Tracer tracer; + + public TracingConnection(Connection connection, Tracer tracer) { + this.connection = connection; + this.tracer = tracer; + } + + @Override + public InetAddress getAddress() { + return connection.getAddress(); + } + + @Override + public int getPort() { + return connection.getPort(); + } + + @Override + public int getChannelMax() { + return connection.getChannelMax(); + } + + @Override + public int getFrameMax() { + return connection.getFrameMax(); + } + + @Override + public int getHeartbeat() { + return connection.getHeartbeat(); + } + + @Override + public Map getClientProperties() { + return connection.getClientProperties(); + } + + @Override + public String getClientProvidedName() { + return connection.getClientProvidedName(); + } + + @Override + public Map getServerProperties() { + return connection.getServerProperties(); + } + + @Override + public Channel createChannel() throws IOException { + return new TracingChannel(connection.createChannel(), tracer); + } + + @Override + public Channel createChannel(int channelNumber) throws IOException { + return new TracingChannel(connection.createChannel(channelNumber), tracer); + } + + @Override + public void close() throws IOException { + connection.close(); + } + + @Override + public void close(int closeCode, String closeMessage) throws IOException { + connection.close(closeCode, closeMessage); + } + + @Override + public void close(int timeout) throws IOException { + connection.close(timeout); + } + + @Override + public void close(int closeCode, String closeMessage, int timeout) throws IOException { + connection.close(closeCode, closeMessage, timeout); + } + + @Override + public void abort() { + connection.abort(); + } + + @Override + public void abort(int closeCode, String closeMessage) { + connection.abort(closeCode, closeMessage); + } + + @Override + public void abort(int timeout) { + connection.abort(timeout); + } + + @Override + public void abort(int closeCode, String closeMessage, int timeout) { + connection.abort(closeCode, closeMessage, timeout); + } + + @Override + public void addBlockedListener(BlockedListener listener) { + connection.addBlockedListener(listener); + } + + @Override + public BlockedListener addBlockedListener(BlockedCallback blockedCallback, + UnblockedCallback unblockedCallback) { + return connection.addBlockedListener(blockedCallback, unblockedCallback); + } + + @Override + public boolean removeBlockedListener(BlockedListener listener) { + return connection.removeBlockedListener(listener); + } + + @Override + public void clearBlockedListeners() { + connection.clearBlockedListeners(); + } + + @Override + public ExceptionHandler getExceptionHandler() { + return connection.getExceptionHandler(); + } + + @Override + public String getId() { + return connection.getId(); + } + + @Override + public void setId(String id) { + connection.setId(id); + } + + @Override + public void addShutdownListener(ShutdownListener listener) { + connection.addShutdownListener(listener); + } + + @Override + public void removeShutdownListener(ShutdownListener listener) { + connection.removeShutdownListener(listener); + } + + @Override + public ShutdownSignalException getCloseReason() { + return connection.getCloseReason(); + } + + @Override + public void notifyListeners() { + connection.notifyListeners(); + } + + @Override + public boolean isOpen() { + return connection.isOpen(); + } +} diff --git a/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.java b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.java new file mode 100644 index 00000000..a8bcfd9b --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.AddressResolver; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import io.opentracing.Tracer; +import io.opentracing.util.GlobalTracer; + +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeoutException; + +public class TracingConnectionFactory extends ConnectionFactory { + + private final Tracer tracer; + + public TracingConnectionFactory(Tracer tracer) { + this.tracer = tracer; + } + + /** + * GlobalTracer is used to get tracer + */ + public TracingConnectionFactory() { + this(GlobalTracer.get()); + } + + @Override + public Connection newConnection( + ExecutorService executor, + AddressResolver addressResolver, + String clientProvidedName + ) throws IOException, TimeoutException { + return new TracingConnection( + super.newConnection(executor, addressResolver, clientProvidedName), + tracer + ); + } +} diff --git a/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConsumer.java b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConsumer.java new file mode 100644 index 00000000..823b119e --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConsumer.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Consumer; +import com.rabbitmq.client.Envelope; +import com.rabbitmq.client.ShutdownSignalException; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.Tracer; + +import java.io.IOException; + + +public class TracingConsumer implements Consumer { + + private final Consumer consumer; + private final String queue; + private final Tracer tracer; + + public TracingConsumer(Consumer consumer, String queue, Tracer tracer) { + this.consumer = consumer; + this.queue = queue; + this.tracer = tracer; + } + + @Override + public void handleConsumeOk(String consumerTag) { + consumer.handleConsumeOk(consumerTag); + } + + @Override + public void handleCancelOk(String consumerTag) { + consumer.handleCancelOk(consumerTag); + + } + + @Override + public void handleCancel(String consumerTag) throws IOException { + consumer.handleCancel(consumerTag); + + } + + @Override + public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { + consumer.handleShutdownSignal(consumerTag, sig); + } + + @Override + public void handleRecoverOk(String consumerTag) { + consumer.handleRecoverOk(consumerTag); + } + + @Override + public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, + byte[] body) throws IOException { + Span child = TracingUtils.buildChildSpan(properties, queue, tracer); + + try (Scope ignored = tracer.scopeManager().activate(child)) { + consumer.handleDelivery(consumerTag, envelope, properties, body); + } finally { + child.finish(); + } + } +} diff --git a/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.java b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.java new file mode 100644 index 00000000..b2d500ea --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.java @@ -0,0 +1,44 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.DeliverCallback; +import com.rabbitmq.client.Delivery; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.Tracer; + +import java.io.IOException; + +public class TracingDeliverCallback implements DeliverCallback { + private final DeliverCallback deliverCallback; + private final String queue; + private final Tracer tracer; + + public TracingDeliverCallback(DeliverCallback deliverCallback, String queue, Tracer tracer) { + this.deliverCallback = deliverCallback; + this.queue = queue; + this.tracer = tracer; + } + + @Override + public void handle(String consumerTag, Delivery message) throws IOException { + Span child = TracingUtils.buildChildSpan(message.getProperties(), queue, tracer); + try (Scope ignored = tracer.scopeManager().activate(child)) { + deliverCallback.handle(consumerTag, message); + } finally { + child.finish(); + } + } +} diff --git a/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingUtils.java b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingUtils.java new file mode 100644 index 00000000..0f0831eb --- /dev/null +++ b/java/rabbitmq-ot/consumer/src/main/java/io/opentracing/contrib/rabbitmq/TracingUtils.java @@ -0,0 +1,152 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.AMQP; +import datadog.trace.api.DDTags; +import io.opentracing.References; +import io.opentracing.Span; +import io.opentracing.SpanContext; +import io.opentracing.Tracer; +import io.opentracing.noop.NoopSpan; +import io.opentracing.propagation.Format.Builtin; +import io.opentracing.tag.Tags; + +import java.util.HashMap; +import java.util.Map; + +public class TracingUtils { + + public static SpanContext extract(AMQP.BasicProperties props, Tracer tracer) { + SpanContext spanContext = tracer + .extract(Builtin.TEXT_MAP, new HeadersMapExtractAdapter(props.getHeaders())); + if (spanContext != null) { + return spanContext; + } + + Span span = tracer.activeSpan(); + if (span != null) { + return span.context(); + } + return null; + } + + public static void buildAndFinishChildSpan(AMQP.BasicProperties props, String queue, + Tracer tracer) { + Span child = buildChildSpan(props, queue, tracer); + if (child != null) { + child.finish(); + } + } + + public static Span buildChildSpan(AMQP.BasicProperties props, String queue, Tracer tracer) { + SpanContext context = TracingUtils.extract(props, tracer); + if (context != null) { + /*Tracer.SpanBuilder spanBuilder = tracer.buildSpan("receive") + .ignoreActiveSpan() + .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER);*/ + + Tracer.SpanBuilder spanBuilder = tracer.buildSpan("amqp command") + .ignoreActiveSpan() + .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) + .withTag(DDTags.RESOURCE_NAME, "receive") + .withTag(DDTags.SPAN_TYPE, "web") + .withTag(DDTags.SERVICE_NAME, "RabbitMQ"); + + if (queue != null) { + spanBuilder.withTag("queue", queue); + } + + spanBuilder.addReference(References.FOLLOWS_FROM, context); + + Span span = spanBuilder.start(); + SpanDecorator.onResponse(span); + + try { + if (props.getHeaders() != null) { + tracer.inject(span.context(), Builtin.TEXT_MAP, + new HeadersMapInjectAdapter(props.getHeaders())); + } + } catch (Exception e) { + // ignore. Waiting for a proper fix. + } + + return span; + } + + return NoopSpan.INSTANCE; + } + + public static Span buildSpan(String exchange, String routingKey, AMQP.BasicProperties props, + Tracer tracer) { + Tracer.SpanBuilder spanBuilder = tracer.buildSpan("send") + .ignoreActiveSpan() + .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) + .withTag("routingKey", routingKey); + + /*Tracer.SpanBuilder spanBuilder = tracer.buildSpan("amqp command") + .ignoreActiveSpan() + .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) + .withTag("routingKey", routingKey) + .withTag(DDTags.RESOURCE_NAME, "send") + .withTag(DDTags.SPAN_TYPE, "web") + .withTag(DDTags.SERVICE_NAME, "RabbitMQ");*/ + + SpanContext spanContext = null; + + if (props != null && props.getHeaders() != null) { + // just in case if span context was injected manually to props in basicPublish + spanContext = tracer.extract(Builtin.TEXT_MAP, + new HeadersMapExtractAdapter(props.getHeaders())); + } + + if (spanContext == null) { + Span parentSpan = tracer.activeSpan(); + if (parentSpan != null) { + spanContext = parentSpan.context(); + } + } + + if (spanContext != null) { + spanBuilder.asChildOf(spanContext); + } + + Span span = spanBuilder.start(); + SpanDecorator.onRequest(exchange, span); + + return span; + } + + public static AMQP.BasicProperties inject(AMQP.BasicProperties properties, Span span, + Tracer tracer) { + + // Headers of AMQP.BasicProperties is unmodifiableMap therefore we build new AMQP.BasicProperties + // with injected span context into headers + Map headers = new HashMap<>(); + + tracer.inject(span.context(), Builtin.TEXT_MAP, new HeadersMapInjectAdapter(headers)); + + if (properties == null) { + return new AMQP.BasicProperties().builder().headers(headers).build(); + } + + if (properties.getHeaders() != null) { + headers.putAll(properties.getHeaders()); + } + + return properties.builder() + .headers(headers) + .build(); + } +} diff --git a/java/rabbitmq-ot/docker-compose.yml b/java/rabbitmq-ot/docker-compose.yml new file mode 100644 index 00000000..9dbda249 --- /dev/null +++ b/java/rabbitmq-ot/docker-compose.yml @@ -0,0 +1,5 @@ +rabbitmq: + image: rabbitmq:management + ports: + - "5672:5672" + - "15672:15672" \ No newline at end of file diff --git a/java/rabbitmq-ot/gradle/wrapper/gradle-wrapper.jar b/java/rabbitmq-ot/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..5c2d1cf0 Binary files /dev/null and b/java/rabbitmq-ot/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/rabbitmq-ot/gradle/wrapper/gradle-wrapper.properties b/java/rabbitmq-ot/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..503ca703 --- /dev/null +++ b/java/rabbitmq-ot/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Apr 05 12:45:54 CEST 2020 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/java/rabbitmq-ot/gradlew b/java/rabbitmq-ot/gradlew new file mode 100755 index 00000000..83f2acfd --- /dev/null +++ b/java/rabbitmq-ot/gradlew @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or 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 +# +# https://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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/java/rabbitmq-ot/producer/build.gradle b/java/rabbitmq-ot/producer/build.gradle new file mode 100644 index 00000000..64631534 --- /dev/null +++ b/java/rabbitmq-ot/producer/build.gradle @@ -0,0 +1,41 @@ +plugins { + id 'java' + id 'application' + id "com.github.johnrengelman.shadow" version "5.2.0" +} + +version '0.1.0' + +shadowJar { + archiveFileName = "producer-${version}.jar" +} + + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + compile 'com.rabbitmq:amqp-client:5.8.0' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' + compile group: 'com.datadoghq', name: 'dd-trace-ot', version: '0.47.0' + //compile group: 'io.opentracing.contrib', name: 'opentracing-rabbitmq-client', version: '0.1.9' + +} + + +ext { + javaMainClass = "com.datadog.pej.Main" +} + +application { + mainClassName = javaMainClass +} + +jar { + manifest { + attributes 'Main-Class': 'com.datadog.pej.Main' + } +} diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/com/datadog/pej/EndPoint.class b/java/rabbitmq-ot/producer/build/classes/java/main/com/datadog/pej/EndPoint.class new file mode 100644 index 00000000..1d9d6036 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/com/datadog/pej/EndPoint.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/com/datadog/pej/Main.class b/java/rabbitmq-ot/producer/build/classes/java/main/com/datadog/pej/Main.class new file mode 100644 index 00000000..e25bc3c1 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/com/datadog/pej/Main.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/com/datadog/pej/Producer.class b/java/rabbitmq-ot/producer/build/classes/java/main/com/datadog/pej/Producer.class new file mode 100644 index 00000000..4254fafa Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/com/datadog/pej/Producer.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.class b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.class new file mode 100644 index 00000000..ab3d7375 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.class b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.class new file mode 100644 index 00000000..5a61d2b4 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/SpanDecorator.class b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/SpanDecorator.class new file mode 100644 index 00000000..e73a58bb Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/SpanDecorator.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingChannel.class b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingChannel.class new file mode 100644 index 00000000..c2dbcb14 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingChannel.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnection.class b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnection.class new file mode 100644 index 00000000..4a29b2e4 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnection.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.class b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.class new file mode 100644 index 00000000..85c149f1 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConsumer.class b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConsumer.class new file mode 100644 index 00000000..e3024d3e Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingConsumer.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.class b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.class new file mode 100644 index 00000000..350bb825 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.class differ diff --git a/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingUtils.class b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingUtils.class new file mode 100644 index 00000000..173a9ec7 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/classes/java/main/io/opentracing/contrib/rabbitmq/TracingUtils.class differ diff --git a/java/rabbitmq-ot/producer/build/libs/producer-0.1.0.jar b/java/rabbitmq-ot/producer/build/libs/producer-0.1.0.jar new file mode 100644 index 00000000..2a78e460 Binary files /dev/null and b/java/rabbitmq-ot/producer/build/libs/producer-0.1.0.jar differ diff --git a/java/rabbitmq-ot/producer/build/tmp/shadowJar/MANIFEST.MF b/java/rabbitmq-ot/producer/build/tmp/shadowJar/MANIFEST.MF new file mode 100644 index 00000000..6d901297 --- /dev/null +++ b/java/rabbitmq-ot/producer/build/tmp/shadowJar/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: com.datadog.pej.Main + diff --git a/java/rabbitmq-ot/producer/src/main/java/com/datadog/pej/EndPoint.java b/java/rabbitmq-ot/producer/src/main/java/com/datadog/pej/EndPoint.java new file mode 100644 index 00000000..64902497 --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/com/datadog/pej/EndPoint.java @@ -0,0 +1,51 @@ +package com.datadog.pej; + + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +/** + * Represents a connection with a queue + * @author syntx + * + */ +public abstract class EndPoint { + + protected Channel channel; + protected Connection connection; + protected String endPointName; + + public EndPoint(String endpointName) throws IOException, TimeoutException { + this.endPointName = endpointName; + + //Create a connection factory + ConnectionFactory factory = new ConnectionFactory(); + + //hostname of your rabbitmq server + factory.setHost("localhost"); + + //getting a connection + connection = factory.newConnection(); + + //creating a channel + channel = connection.createChannel(); + + //declaring a queue for this channel. If queue does not exist, + //it will be created on the server. + channel.queueDeclare(endpointName, false, false, false, null); + } + + + /** + * Close channel and connection. Not necessary as it happens implicitly any way. + * @throws IOException + */ + public void close() throws IOException, TimeoutException { + this.channel.close(); + this.connection.close(); + } +} \ No newline at end of file diff --git a/java/rabbitmq-ot/producer/src/main/java/com/datadog/pej/Main.java b/java/rabbitmq-ot/producer/src/main/java/com/datadog/pej/Main.java new file mode 100644 index 00000000..2e969bf8 --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/com/datadog/pej/Main.java @@ -0,0 +1,41 @@ +package com.datadog.pej; + +import datadog.opentracing.DDTracer; +import datadog.trace.api.DDTags; +import io.opentracing.Scope; +import io.opentracing.ScopeManager; +import io.opentracing.Span; +import io.opentracing.Tracer; + +import java.util.HashMap; + +public class Main { + + + public static void main(String[] args) throws Exception{ + + + Tracer tracer = DDTracer.builder().build(); + Producer producer = new Producer("spring-boot", tracer); + + for (int i = 0; i < 19; i++) { + HashMap message = new HashMap(); + ScopeManager sm = tracer.scopeManager(); + Tracer.SpanBuilder tb = tracer.buildSpan("sending"); + message.put("message number", i); + Span span = tb.start(); + try(Scope scope = sm.activate(span)) { + span.setTag(DDTags.SERVICE_NAME, "client"); + span.setTag(DDTags.RESOURCE_NAME, "send message"); + span.setTag(DDTags.SPAN_TYPE, "web"); + producer.sendMessage(message); + System.out.println("Message Number " + i + " sent."); + Thread.sleep(20); + //scope.close(); + span.finish(); + } + } + + System.exit(0); + } +} \ No newline at end of file diff --git a/java/rabbitmq-ot/producer/src/main/java/com/datadog/pej/Producer.java b/java/rabbitmq-ot/producer/src/main/java/com/datadog/pej/Producer.java new file mode 100644 index 00000000..794682cc --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/com/datadog/pej/Producer.java @@ -0,0 +1,30 @@ +package com.datadog.pej; + +import io.opentracing.Tracer; +import io.opentracing.contrib.rabbitmq.TracingChannel; +import org.apache.commons.lang3.SerializationUtils; + +import java.io.IOException; +import java.io.Serializable; +import java.util.concurrent.TimeoutException; + + +/** + * The producer endpoint that writes to the queue. + * @author syntx + * + */ +public class Producer extends EndPoint{ + + Tracer tracer; + public Producer(String endPointName, Tracer tracer) throws IOException, TimeoutException { + super(endPointName); + this.tracer = tracer; + } + + public void sendMessage(Serializable object) throws IOException { + TracingChannel tracingChannel = new TracingChannel(channel, tracer); + //channel.basicPublish("",endPointName, null, SerializationUtils.serialize(object)); + tracingChannel.basicPublish("",endPointName, null, SerializationUtils.serialize(object)); + } +} diff --git a/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.java b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.java new file mode 100644 index 00000000..bcfb7f8d --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapExtractAdapter.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import io.opentracing.propagation.TextMap; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static java.lang.String.valueOf; + +public class HeadersMapExtractAdapter implements TextMap { + + private final Map map = new HashMap<>(); + + public HeadersMapExtractAdapter(Map headers) { + if (headers == null) { + return; + } + for (Map.Entry entry : headers.entrySet()) { + map.put(entry.getKey(), valueOf(entry.getValue())); + } + } + + @Override + public Iterator> iterator() { + return map.entrySet().iterator(); + } + + @Override + public void put(String key, String value) { + throw new UnsupportedOperationException( + "HeadersMapExtractAdapter should only be used with Tracer.extract()"); + } +} diff --git a/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.java b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.java new file mode 100644 index 00000000..5a5ebff7 --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/HeadersMapInjectAdapter.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import io.opentracing.propagation.TextMap; + +import java.util.Iterator; +import java.util.Map; + + +public class HeadersMapInjectAdapter implements TextMap { + + private final Map headers; + + public HeadersMapInjectAdapter(Map headers) { + this.headers = headers; + } + + @Override + public Iterator> iterator() { + throw new UnsupportedOperationException("iterator should never be used with Tracer.inject()"); + } + + @Override + public void put(String key, String value) { + headers.put(key, value); + } +} \ No newline at end of file diff --git a/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/SpanDecorator.java b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/SpanDecorator.java new file mode 100644 index 00000000..ca4dcb34 --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/SpanDecorator.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + + +import io.opentracing.Span; +import io.opentracing.tag.Tags; + +public class SpanDecorator { + public static final String COMPONENT_NAME = "java-rabbitmq"; + + public static void onRequest(String exchange, Span span) { + Tags.COMPONENT.set(span, COMPONENT_NAME); + Tags.MESSAGE_BUS_DESTINATION.set(span, exchange); + } + + public static void onResponse(Span span) { + Tags.COMPONENT.set(span, COMPONENT_NAME); + } +} diff --git a/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingChannel.java b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingChannel.java new file mode 100644 index 00000000..00788a27 --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingChannel.java @@ -0,0 +1,653 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.*; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.Tracer; +import io.opentracing.util.GlobalTracer; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; + +import static io.opentracing.contrib.rabbitmq.TracingUtils.buildSpan; +import static io.opentracing.contrib.rabbitmq.TracingUtils.inject; + + +public class TracingChannel implements Channel { + + private final Channel channel; + private final Tracer tracer; + + public TracingChannel(Channel channel, Tracer tracer) { + this.channel = channel; + this.tracer = tracer; + } + + /** + * GlobalTracer is used to get tracer + */ + public TracingChannel(Channel channel) { + this(channel, GlobalTracer.get()); + } + + @Override + public int getChannelNumber() { + return channel.getChannelNumber(); + } + + @Override + public Connection getConnection() { + return channel.getConnection(); + } + + @Override + public void close() throws IOException, TimeoutException { + channel.close(); + } + + @Override + public void close(int closeCode, String closeMessage) throws IOException, TimeoutException { + channel.close(closeCode, closeMessage); + } + + @Override + public void abort() throws IOException { + channel.abort(); + } + + @Override + public void abort(int closeCode, String closeMessage) throws IOException { + channel.abort(closeCode, closeMessage); + } + + @Override + public void addReturnListener(ReturnListener listener) { + channel.addReturnListener(listener); + } + + @Override + public ReturnListener addReturnListener(ReturnCallback returnCallback) { + return channel.addReturnListener(returnCallback); + } + + @Override + public boolean removeReturnListener(ReturnListener listener) { + return channel.removeReturnListener(listener); + } + + @Override + public void clearReturnListeners() { + channel.clearReturnListeners(); + } + + @Override + public void addConfirmListener(ConfirmListener listener) { + channel.addConfirmListener(listener); + } + + @Override + public ConfirmListener addConfirmListener(ConfirmCallback confirmCallback, + ConfirmCallback confirmCallback1) { + return channel.addConfirmListener(confirmCallback, confirmCallback1); + } + + @Override + public boolean removeConfirmListener(ConfirmListener listener) { + return channel.removeConfirmListener(listener); + } + + @Override + public void clearConfirmListeners() { + channel.clearConfirmListeners(); + } + + @Override + public Consumer getDefaultConsumer() { + return channel.getDefaultConsumer(); + } + + @Override + public void setDefaultConsumer(Consumer consumer) { + channel.setDefaultConsumer(consumer); + } + + @Override + public void basicQos(int prefetchSize, int prefetchCount, boolean global) throws IOException { + channel.basicQos(prefetchSize, prefetchCount, global); + } + + @Override + public void basicQos(int prefetchCount, boolean global) throws IOException { + channel.basicQos(prefetchCount, global); + } + + @Override + public void basicQos(int prefetchCount) throws IOException { + channel.basicQos(prefetchCount); + } + + @Override + public void basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, + byte[] body) throws IOException { + basicPublish(exchange, routingKey, false, false, props, body); + } + + @Override + public void basicPublish(String exchange, String routingKey, boolean mandatory, + AMQP.BasicProperties props, byte[] body) throws IOException { + basicPublish(exchange, routingKey, mandatory, false, props, body); + } + + @Override + public void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, + AMQP.BasicProperties props, byte[] body) throws IOException { + + Span span = buildSpan(exchange, routingKey, props, tracer); + try (Scope ignored = tracer.scopeManager().activate(span)) { + AMQP.BasicProperties properties = inject(props, span, tracer); + channel.basicPublish(exchange, routingKey, mandatory, immediate, properties, body); + } finally { + span.finish(); + } + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type) throws IOException { + return channel.exchangeDeclare(exchange, type); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type) + throws IOException { + return channel.exchangeDeclare(exchange, type); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable) + throws IOException { + return channel.exchangeDeclare(exchange, type, durable); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, + boolean durable) throws IOException { + return channel.exchangeDeclare(exchange, type, durable); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, + boolean autoDelete, Map arguments) throws IOException { + return channel.exchangeDeclare(exchange, type, durable, autoDelete, arguments); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, + boolean durable, boolean autoDelete, Map arguments) throws IOException { + return channel.exchangeDeclare(exchange, type, durable, autoDelete, arguments); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, + boolean autoDelete, boolean internal, Map arguments) throws IOException { + return channel.exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, + boolean durable, boolean autoDelete, boolean internal, Map arguments) + throws IOException { + return channel.exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments); + } + + @Override + public void exchangeDeclareNoWait(String exchange, String type, boolean durable, + boolean autoDelete, boolean internal, Map arguments) throws IOException { + channel.exchangeDeclareNoWait(exchange, type, durable, autoDelete, internal, arguments); + } + + @Override + public void exchangeDeclareNoWait(String exchange, BuiltinExchangeType type, boolean durable, + boolean autoDelete, boolean internal, Map arguments) throws IOException { + channel.exchangeDeclareNoWait(exchange, type, durable, autoDelete, internal, arguments); + } + + @Override + public AMQP.Exchange.DeclareOk exchangeDeclarePassive(String name) throws IOException { + return channel.exchangeDeclarePassive(name); + } + + @Override + public AMQP.Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) + throws IOException { + return channel.exchangeDelete(exchange, ifUnused); + } + + @Override + public void exchangeDeleteNoWait(String exchange, boolean ifUnused) throws IOException { + channel.exchangeDeleteNoWait(exchange, ifUnused); + } + + @Override + public AMQP.Exchange.DeleteOk exchangeDelete(String exchange) throws IOException { + return channel.exchangeDelete(exchange); + } + + @Override + public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey) + throws IOException { + return channel.exchangeBind(destination, source, routingKey); + } + + @Override + public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey, + Map arguments) throws IOException { + return channel.exchangeBind(destination, source, routingKey, arguments); + } + + @Override + public void exchangeBindNoWait(String destination, String source, String routingKey, + Map arguments) throws IOException { + channel.exchangeBindNoWait(destination, source, routingKey, arguments); + } + + @Override + public AMQP.Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey) + throws IOException { + return channel.exchangeUnbind(destination, source, routingKey); + } + + @Override + public AMQP.Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey, + Map arguments) throws IOException { + return channel.exchangeUnbind(destination, source, routingKey, arguments); + } + + @Override + public void exchangeUnbindNoWait(String destination, String source, String routingKey, + Map arguments) throws IOException { + channel.exchangeUnbindNoWait(destination, source, routingKey, arguments); + } + + @Override + public AMQP.Queue.DeclareOk queueDeclare() throws IOException { + return channel.queueDeclare(); + } + + @Override + public AMQP.Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, + boolean autoDelete, Map arguments) throws IOException { + return channel.queueDeclare(queue, durable, exclusive, autoDelete, arguments); + } + + @Override + public void queueDeclareNoWait(String queue, boolean durable, boolean exclusive, + boolean autoDelete, Map arguments) throws IOException { + channel.queueDeclareNoWait(queue, durable, exclusive, autoDelete, arguments); + } + + @Override + public AMQP.Queue.DeclareOk queueDeclarePassive(String queue) throws IOException { + return channel.queueDeclarePassive(queue); + } + + @Override + public AMQP.Queue.DeleteOk queueDelete(String queue) throws IOException { + return channel.queueDelete(queue); + } + + @Override + public AMQP.Queue.DeleteOk queueDelete(String queue, boolean ifUnused, boolean ifEmpty) + throws IOException { + return channel.queueDelete(queue, ifUnused, ifEmpty); + } + + @Override + public void queueDeleteNoWait(String queue, boolean ifUnused, boolean ifEmpty) + throws IOException { + channel.queueDeleteNoWait(queue, ifUnused, ifEmpty); + } + + @Override + public AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey) + throws IOException { + return channel.queueBind(queue, exchange, routingKey); + } + + @Override + public AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey, + Map arguments) throws IOException { + return channel.queueBind(queue, exchange, routingKey, arguments); + } + + @Override + public void queueBindNoWait(String queue, String exchange, String routingKey, + Map arguments) throws IOException { + channel.queueBindNoWait(queue, exchange, routingKey, arguments); + } + + @Override + public AMQP.Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) + throws IOException { + return channel.queueUnbind(queue, exchange, routingKey); + } + + @Override + public AMQP.Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, + Map arguments) throws IOException { + return channel.queueUnbind(queue, exchange, routingKey, arguments); + } + + @Override + public AMQP.Queue.PurgeOk queuePurge(String queue) throws IOException { + return channel.queuePurge(queue); + } + + @Override + public GetResponse basicGet(String queue, boolean autoAck) throws IOException { + GetResponse response = channel.basicGet(queue, autoAck); + if (response != null) { + TracingUtils.buildAndFinishChildSpan(response.getProps(), queue, tracer); + } + return response; + } + + @Override + public void basicAck(long deliveryTag, boolean multiple) throws IOException { + channel.basicAck(deliveryTag, multiple); + } + + @Override + public void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException { + channel.basicNack(deliveryTag, multiple, requeue); + } + + @Override + public void basicReject(long deliveryTag, boolean requeue) throws IOException { + channel.basicReject(deliveryTag, requeue); + } + + @Override + public String basicConsume(String queue, Consumer callback) throws IOException { + return basicConsume(queue, false, "", false, false, null, callback); + } + + @Override + public String basicConsume(String queue, DeliverCallback deliverCallback, + CancelCallback cancelCallback) throws IOException { + return channel + .basicConsume(queue, new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback); + } + + @Override + public String basicConsume(String queue, DeliverCallback deliverCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel.basicConsume(queue, new TracingDeliverCallback(deliverCallback, queue, tracer), + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, DeliverCallback deliverCallback, + CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel + .basicConsume(queue, new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback, + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException { + return basicConsume(queue, autoAck, "", false, false, null, callback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, + CancelCallback cancelCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, new TracingDeliverCallback(deliverCallback, queue, tracer), + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, + CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel + .basicConsume(queue, autoAck, new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback, shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Map arguments, + Consumer callback) throws IOException { + return basicConsume(queue, autoAck, "", false, false, arguments, callback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Map arguments, + DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { + return channel.basicConsume(queue, autoAck, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Map arguments, + DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel.basicConsume(queue, autoAck, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, Map arguments, + DeliverCallback deliverCallback, CancelCallback cancelCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback, + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, Consumer callback) + throws IOException { + return basicConsume(queue, autoAck, consumerTag, false, false, null, callback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, + DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException { + return channel.basicConsume(queue, autoAck, consumerTag, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, + DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel.basicConsume(queue, autoAck, consumerTag, + new TracingDeliverCallback(deliverCallback, queue, tracer), shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, + DeliverCallback deliverCallback, CancelCallback cancelCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, consumerTag, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback, + shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, + boolean exclusive, Map arguments, Consumer callback) throws IOException { + return channel.basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, + new TracingConsumer(callback, queue, tracer)); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, + boolean exclusive, Map arguments, DeliverCallback deliverCallback, + CancelCallback cancelCallback) throws IOException { + return channel.basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), cancelCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, + boolean exclusive, Map arguments, DeliverCallback deliverCallback, + ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException { + return channel + .basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), shutdownSignalCallback); + } + + @Override + public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, + boolean exclusive, Map arguments, DeliverCallback deliverCallback, + CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) + throws IOException { + return channel + .basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, + new TracingDeliverCallback(deliverCallback, queue, tracer), + cancelCallback, shutdownSignalCallback); + } + + @Override + public void basicCancel(String consumerTag) throws IOException { + channel.basicCancel(consumerTag); + } + + @Override + public AMQP.Basic.RecoverOk basicRecover() throws IOException { + return channel.basicRecover(); + } + + @Override + public AMQP.Basic.RecoverOk basicRecover(boolean requeue) throws IOException { + return channel.basicRecover(requeue); + } + + @Override + public AMQP.Tx.SelectOk txSelect() throws IOException { + return channel.txSelect(); + } + + @Override + public AMQP.Tx.CommitOk txCommit() throws IOException { + return channel.txCommit(); + } + + @Override + public AMQP.Tx.RollbackOk txRollback() throws IOException { + return channel.txRollback(); + } + + @Override + public AMQP.Confirm.SelectOk confirmSelect() throws IOException { + return channel.confirmSelect(); + } + + @Override + public long getNextPublishSeqNo() { + return channel.getNextPublishSeqNo(); + } + + @Override + public boolean waitForConfirms() throws InterruptedException { + return channel.waitForConfirms(); + } + + @Override + public boolean waitForConfirms(long timeout) throws InterruptedException, TimeoutException { + return channel.waitForConfirms(timeout); + } + + @Override + public void waitForConfirmsOrDie() throws IOException, InterruptedException { + channel.waitForConfirmsOrDie(); + } + + @Override + public void waitForConfirmsOrDie(long timeout) + throws IOException, InterruptedException, TimeoutException { + channel.waitForConfirmsOrDie(timeout); + } + + @Override + public void asyncRpc(Method method) throws IOException { + channel.asyncRpc(method); + } + + @Override + public Command rpc(Method method) throws IOException { + return channel.rpc(method); + } + + @Override + public long messageCount(String queue) throws IOException { + return channel.messageCount(queue); + } + + @Override + public long consumerCount(String queue) throws IOException { + return channel.consumerCount(queue); + } + + @Override + public CompletableFuture asyncCompletableRpc( + Method method) throws IOException { + return channel.asyncCompletableRpc(method); + } + + @Override + public void addShutdownListener(ShutdownListener listener) { + channel.addShutdownListener(listener); + } + + @Override + public void removeShutdownListener(ShutdownListener listener) { + channel.removeShutdownListener(listener); + } + + @Override + public ShutdownSignalException getCloseReason() { + return channel.getCloseReason(); + } + + @Override + public void notifyListeners() { + channel.notifyListeners(); + } + + @Override + public boolean isOpen() { + return channel.isOpen(); + } + +} diff --git a/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnection.java b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnection.java new file mode 100644 index 00000000..e4f349fa --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnection.java @@ -0,0 +1,184 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.*; +import io.opentracing.Tracer; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.Map; + +public class TracingConnection implements Connection { + + private final Connection connection; + + private final Tracer tracer; + + public TracingConnection(Connection connection, Tracer tracer) { + this.connection = connection; + this.tracer = tracer; + } + + @Override + public InetAddress getAddress() { + return connection.getAddress(); + } + + @Override + public int getPort() { + return connection.getPort(); + } + + @Override + public int getChannelMax() { + return connection.getChannelMax(); + } + + @Override + public int getFrameMax() { + return connection.getFrameMax(); + } + + @Override + public int getHeartbeat() { + return connection.getHeartbeat(); + } + + @Override + public Map getClientProperties() { + return connection.getClientProperties(); + } + + @Override + public String getClientProvidedName() { + return connection.getClientProvidedName(); + } + + @Override + public Map getServerProperties() { + return connection.getServerProperties(); + } + + @Override + public Channel createChannel() throws IOException { + return new TracingChannel(connection.createChannel(), tracer); + } + + @Override + public Channel createChannel(int channelNumber) throws IOException { + return new TracingChannel(connection.createChannel(channelNumber), tracer); + } + + @Override + public void close() throws IOException { + connection.close(); + } + + @Override + public void close(int closeCode, String closeMessage) throws IOException { + connection.close(closeCode, closeMessage); + } + + @Override + public void close(int timeout) throws IOException { + connection.close(timeout); + } + + @Override + public void close(int closeCode, String closeMessage, int timeout) throws IOException { + connection.close(closeCode, closeMessage, timeout); + } + + @Override + public void abort() { + connection.abort(); + } + + @Override + public void abort(int closeCode, String closeMessage) { + connection.abort(closeCode, closeMessage); + } + + @Override + public void abort(int timeout) { + connection.abort(timeout); + } + + @Override + public void abort(int closeCode, String closeMessage, int timeout) { + connection.abort(closeCode, closeMessage, timeout); + } + + @Override + public void addBlockedListener(BlockedListener listener) { + connection.addBlockedListener(listener); + } + + @Override + public BlockedListener addBlockedListener(BlockedCallback blockedCallback, + UnblockedCallback unblockedCallback) { + return connection.addBlockedListener(blockedCallback, unblockedCallback); + } + + @Override + public boolean removeBlockedListener(BlockedListener listener) { + return connection.removeBlockedListener(listener); + } + + @Override + public void clearBlockedListeners() { + connection.clearBlockedListeners(); + } + + @Override + public ExceptionHandler getExceptionHandler() { + return connection.getExceptionHandler(); + } + + @Override + public String getId() { + return connection.getId(); + } + + @Override + public void setId(String id) { + connection.setId(id); + } + + @Override + public void addShutdownListener(ShutdownListener listener) { + connection.addShutdownListener(listener); + } + + @Override + public void removeShutdownListener(ShutdownListener listener) { + connection.removeShutdownListener(listener); + } + + @Override + public ShutdownSignalException getCloseReason() { + return connection.getCloseReason(); + } + + @Override + public void notifyListeners() { + connection.notifyListeners(); + } + + @Override + public boolean isOpen() { + return connection.isOpen(); + } +} diff --git a/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.java b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.java new file mode 100644 index 00000000..a8bcfd9b --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConnectionFactory.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.AddressResolver; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import io.opentracing.Tracer; +import io.opentracing.util.GlobalTracer; + +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeoutException; + +public class TracingConnectionFactory extends ConnectionFactory { + + private final Tracer tracer; + + public TracingConnectionFactory(Tracer tracer) { + this.tracer = tracer; + } + + /** + * GlobalTracer is used to get tracer + */ + public TracingConnectionFactory() { + this(GlobalTracer.get()); + } + + @Override + public Connection newConnection( + ExecutorService executor, + AddressResolver addressResolver, + String clientProvidedName + ) throws IOException, TimeoutException { + return new TracingConnection( + super.newConnection(executor, addressResolver, clientProvidedName), + tracer + ); + } +} diff --git a/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConsumer.java b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConsumer.java new file mode 100644 index 00000000..823b119e --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingConsumer.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.AMQP; +import com.rabbitmq.client.Consumer; +import com.rabbitmq.client.Envelope; +import com.rabbitmq.client.ShutdownSignalException; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.Tracer; + +import java.io.IOException; + + +public class TracingConsumer implements Consumer { + + private final Consumer consumer; + private final String queue; + private final Tracer tracer; + + public TracingConsumer(Consumer consumer, String queue, Tracer tracer) { + this.consumer = consumer; + this.queue = queue; + this.tracer = tracer; + } + + @Override + public void handleConsumeOk(String consumerTag) { + consumer.handleConsumeOk(consumerTag); + } + + @Override + public void handleCancelOk(String consumerTag) { + consumer.handleCancelOk(consumerTag); + + } + + @Override + public void handleCancel(String consumerTag) throws IOException { + consumer.handleCancel(consumerTag); + + } + + @Override + public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { + consumer.handleShutdownSignal(consumerTag, sig); + } + + @Override + public void handleRecoverOk(String consumerTag) { + consumer.handleRecoverOk(consumerTag); + } + + @Override + public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, + byte[] body) throws IOException { + Span child = TracingUtils.buildChildSpan(properties, queue, tracer); + + try (Scope ignored = tracer.scopeManager().activate(child)) { + consumer.handleDelivery(consumerTag, envelope, properties, body); + } finally { + child.finish(); + } + } +} diff --git a/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.java b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.java new file mode 100644 index 00000000..b2d500ea --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingDeliverCallback.java @@ -0,0 +1,44 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.DeliverCallback; +import com.rabbitmq.client.Delivery; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.Tracer; + +import java.io.IOException; + +public class TracingDeliverCallback implements DeliverCallback { + private final DeliverCallback deliverCallback; + private final String queue; + private final Tracer tracer; + + public TracingDeliverCallback(DeliverCallback deliverCallback, String queue, Tracer tracer) { + this.deliverCallback = deliverCallback; + this.queue = queue; + this.tracer = tracer; + } + + @Override + public void handle(String consumerTag, Delivery message) throws IOException { + Span child = TracingUtils.buildChildSpan(message.getProperties(), queue, tracer); + try (Scope ignored = tracer.scopeManager().activate(child)) { + deliverCallback.handle(consumerTag, message); + } finally { + child.finish(); + } + } +} diff --git a/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingUtils.java b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingUtils.java new file mode 100644 index 00000000..242256d1 --- /dev/null +++ b/java/rabbitmq-ot/producer/src/main/java/io/opentracing/contrib/rabbitmq/TracingUtils.java @@ -0,0 +1,146 @@ +/* + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.rabbitmq; + +import com.rabbitmq.client.AMQP; +import datadog.trace.api.DDTags; +import io.opentracing.References; +import io.opentracing.Span; +import io.opentracing.SpanContext; +import io.opentracing.Tracer; +import io.opentracing.noop.NoopSpan; +import io.opentracing.propagation.Format.Builtin; +import io.opentracing.tag.Tags; + +import java.util.HashMap; +import java.util.Map; + +public class TracingUtils { + + public static SpanContext extract(AMQP.BasicProperties props, Tracer tracer) { + SpanContext spanContext = tracer + .extract(Builtin.TEXT_MAP, new HeadersMapExtractAdapter(props.getHeaders())); + if (spanContext != null) { + return spanContext; + } + + Span span = tracer.activeSpan(); + if (span != null) { + return span.context(); + } + return null; + } + + public static void buildAndFinishChildSpan(AMQP.BasicProperties props, String queue, + Tracer tracer) { + Span child = buildChildSpan(props, queue, tracer); + if (child != null) { + child.finish(); + } + } + + public static Span buildChildSpan(AMQP.BasicProperties props, String queue, Tracer tracer) { + SpanContext context = TracingUtils.extract(props, tracer); + if (context != null) { + Tracer.SpanBuilder spanBuilder = tracer.buildSpan("receive") + .ignoreActiveSpan() + .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER); + + if (queue != null) { + spanBuilder.withTag("queue", queue); + } + + spanBuilder.addReference(References.FOLLOWS_FROM, context); + + Span span = spanBuilder.start(); + SpanDecorator.onResponse(span); + + try { + if (props.getHeaders() != null) { + tracer.inject(span.context(), Builtin.TEXT_MAP, + new HeadersMapInjectAdapter(props.getHeaders())); + } + } catch (Exception e) { + // ignore. Waiting for a proper fix. + } + + return span; + } + + return NoopSpan.INSTANCE; + } + + public static Span buildSpan(String exchange, String routingKey, AMQP.BasicProperties props, + Tracer tracer) { + /*Tracer.SpanBuilder spanBuilder = tracer.buildSpan("send") + .ignoreActiveSpan() + .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) + .withTag("routingKey", routingKey);*/ + + Tracer.SpanBuilder spanBuilder = tracer.buildSpan("amqp command") + .ignoreActiveSpan() + .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) + .withTag("routingKey", routingKey) + .withTag(DDTags.RESOURCE_NAME, "send") + .withTag(DDTags.SPAN_TYPE, "web") + .withTag(DDTags.SERVICE_NAME, "RabbitMQ"); + + + SpanContext spanContext = null; + + if (props != null && props.getHeaders() != null) { + // just in case if span context was injected manually to props in basicPublish + spanContext = tracer.extract(Builtin.TEXT_MAP, + new HeadersMapExtractAdapter(props.getHeaders())); + } + + if (spanContext == null) { + Span parentSpan = tracer.activeSpan(); + if (parentSpan != null) { + spanContext = parentSpan.context(); + } + } + + if (spanContext != null) { + spanBuilder.asChildOf(spanContext); + } + + Span span = spanBuilder.start(); + SpanDecorator.onRequest(exchange, span); + + return span; + } + + public static AMQP.BasicProperties inject(AMQP.BasicProperties properties, Span span, + Tracer tracer) { + + // Headers of AMQP.BasicProperties is unmodifiableMap therefore we build new AMQP.BasicProperties + // with injected span context into headers + Map headers = new HashMap<>(); + + tracer.inject(span.context(), Builtin.TEXT_MAP, new HeadersMapInjectAdapter(headers)); + + if (properties == null) { + return new AMQP.BasicProperties().builder().headers(headers).build(); + } + + if (properties.getHeaders() != null) { + headers.putAll(properties.getHeaders()); + } + + return properties.builder() + .headers(headers) + .build(); + } +} diff --git a/java/rabbitmq-ot/settings.gradle b/java/rabbitmq-ot/settings.gradle new file mode 100644 index 00000000..dbdf5e47 --- /dev/null +++ b/java/rabbitmq-ot/settings.gradle @@ -0,0 +1,14 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/5.6.4/userguide/multi_project_builds.html + */ + +rootProject.name = 'prodconsrbmqdt' +include 'consumer' +include 'producer' +include 'testot' + diff --git a/java/rabbitmq-ot/testot/build.gradle b/java/rabbitmq-ot/testot/build.gradle new file mode 100644 index 00000000..3ed84f0e --- /dev/null +++ b/java/rabbitmq-ot/testot/build.gradle @@ -0,0 +1,44 @@ +plugins { + id 'java' + id 'application' + id "com.github.johnrengelman.shadow" version "5.2.0" +} + +version '0.1.0' + +shadowJar { + archiveFileName = "testot-${version}.jar" +} + + + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + compile group: 'com.datadoghq', name: 'dd-trace-ot', version: '0.47.0' + compileOnly'org.projectlombok:lombok:1.18.10' + annotationProcessor'org.projectlombok:lombok:1.18.10' + compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.30' +} + + +ext { + javaMainClass = "Main" +} + +application { + mainClassName = javaMainClass +} + + +jar { + manifest { + attributes 'Main-Class': 'Main' + } +} + + diff --git a/java/rabbitmq-ot/testot/build/classes/java/main/Main.class b/java/rabbitmq-ot/testot/build/classes/java/main/Main.class new file mode 100644 index 00000000..26493596 Binary files /dev/null and b/java/rabbitmq-ot/testot/build/classes/java/main/Main.class differ diff --git a/java/rabbitmq-ot/testot/build/libs/testot-0.1.0.jar b/java/rabbitmq-ot/testot/build/libs/testot-0.1.0.jar new file mode 100644 index 00000000..171b0482 Binary files /dev/null and b/java/rabbitmq-ot/testot/build/libs/testot-0.1.0.jar differ diff --git a/java/rabbitmq-ot/testot/build/tmp/shadowJar/MANIFEST.MF b/java/rabbitmq-ot/testot/build/tmp/shadowJar/MANIFEST.MF new file mode 100644 index 00000000..5ee19cb0 --- /dev/null +++ b/java/rabbitmq-ot/testot/build/tmp/shadowJar/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: Main + diff --git a/java/rabbitmq-ot/testot/src/main/java/Main.java b/java/rabbitmq-ot/testot/src/main/java/Main.java new file mode 100644 index 00000000..5f4f7abf --- /dev/null +++ b/java/rabbitmq-ot/testot/src/main/java/Main.java @@ -0,0 +1,87 @@ +import datadog.opentracing.DDTracer; +import datadog.trace.api.DDTags; +import io.opentracing.Scope; +import io.opentracing.ScopeManager; +import io.opentracing.Span; +import io.opentracing.Tracer; +import lombok.extern.slf4j.Slf4j; +import okhttp3.Call; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; + +@Slf4j +public class Main { + + static Tracer tracer; + Span parentspan; + + public void doSomeThing() throws InterruptedException, IOException { + + Thread.sleep(120); + ScopeManager sm = tracer.scopeManager(); + Tracer.SpanBuilder tb = tracer.buildSpan("receiving").asChildOf(parentspan); + + Span span = tb.start(); + try(Scope scope = sm.activate(span)) { + span.setTag(DDTags.SERVICE_NAME, "ServiceB"); + span.setTag(DDTags.RESOURCE_NAME, "dosomethingmore"); + span.setTag(DDTags.SPAN_TYPE, "web"); + // + doSomethingMore(); + // + span.finish(); + } + + System.out.println("In doSometThing..."); + } + + + public void doSomethingMore() throws InterruptedException, IOException { + Thread.sleep(250); + System.out.println("In doSomethingMore..."); + httpRequest(); + } + + + + public void httpRequest() throws IOException { + OkHttpClient client = new OkHttpClient(); + Request request = new Request.Builder() + .url("https://www.google.fr") + .build(); + + Call call = client.newCall(request); + Response response = call.execute(); + System.out.println("http response code: " + response.code()); + } + + + public static void main(String[] args) throws InterruptedException, IOException { + + Main mn = new Main(); + //Tracer tracer = new DDTracer("ServiceA"); + + //tracer = new DDTracer.DDTracerBuilder().build(); + tracer = DDTracer.builder().build(); + + + Span span = tracer.buildSpan("sending").start(); + try(Scope scope = tracer.activateSpan(span)){ + span.setTag(DDTags.SERVICE_NAME, "ServiceA"); + span.setTag(DDTags.RESOURCE_NAME, "dosomething"); + span.setTag(DDTags.SPAN_TYPE, "web"); + Thread.sleep(20); + System.out.println("In main..."); + mn.doSomeThing(); + span.finish(); + } + + //System.out.println("hh"); + log.info("Terminating..."); + System.exit(0); + + } +} diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/executionHistory/executionHistory.bin b/java/spring-kafka-ot33v2/.gradle/5.6.2/executionHistory/executionHistory.bin new file mode 100644 index 00000000..4cc9f479 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/executionHistory/executionHistory.bin differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/executionHistory/executionHistory.lock b/java/spring-kafka-ot33v2/.gradle/5.6.2/executionHistory/executionHistory.lock new file mode 100644 index 00000000..9e0c8d11 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/executionHistory/executionHistory.lock differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/fileChanges/last-build.bin b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileChanges/last-build.bin new file mode 100644 index 00000000..f76dd238 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileChanges/last-build.bin differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/fileContent/fileContent.lock b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileContent/fileContent.lock new file mode 100644 index 00000000..8c0a585a Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileContent/fileContent.lock differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/fileHashes/fileHashes.bin b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileHashes/fileHashes.bin new file mode 100644 index 00000000..48b4a7eb Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileHashes/fileHashes.bin differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/fileHashes/fileHashes.lock b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileHashes/fileHashes.lock new file mode 100644 index 00000000..753c18b9 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileHashes/fileHashes.lock differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/fileHashes/resourceHashesCache.bin b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileHashes/resourceHashesCache.bin new file mode 100644 index 00000000..6bffb2c4 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/fileHashes/resourceHashesCache.bin differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/gc.properties b/java/spring-kafka-ot33v2/.gradle/5.6.2/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/classAnalysis.bin b/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/classAnalysis.bin new file mode 100644 index 00000000..51361668 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/classAnalysis.bin differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/jarAnalysis.bin b/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/jarAnalysis.bin new file mode 100644 index 00000000..5c71ecc6 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/jarAnalysis.bin differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/javaCompile.lock b/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/javaCompile.lock new file mode 100644 index 00000000..edb5c994 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/javaCompile.lock differ diff --git a/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/taskHistory.bin b/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/taskHistory.bin new file mode 100644 index 00000000..ee287459 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/5.6.2/javaCompile/taskHistory.bin differ diff --git a/java/spring-kafka-ot33v2/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/java/spring-kafka-ot33v2/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 00000000..6a958b42 Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/java/spring-kafka-ot33v2/.gradle/buildOutputCleanup/cache.properties b/java/spring-kafka-ot33v2/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 00000000..4ea7f13d --- /dev/null +++ b/java/spring-kafka-ot33v2/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Tue Feb 25 09:29:41 CET 2020 +gradle.version=5.6.2 diff --git a/java/spring-kafka-ot33v2/.gradle/buildOutputCleanup/outputFiles.bin b/java/spring-kafka-ot33v2/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 00000000..8f6f469d Binary files /dev/null and b/java/spring-kafka-ot33v2/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/java/spring-kafka-ot33v2/.gradle/vcs-1/gc.properties b/java/spring-kafka-ot33v2/.gradle/vcs-1/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/java/spring-kafka-ot33v2/README.md b/java/spring-kafka-ot33v2/README.md new file mode 100644 index 00000000..131efb66 --- /dev/null +++ b/java/spring-kafka-ot33v2/README.md @@ -0,0 +1,57 @@ +## spring-kafka-ot33v2 + + +A detailed step-by-step tutorial on how to implement an Apache Kafka Consumer and Producer using Spring Kafka and Spring Boot. + +**_Preliminary tasks and first time steps_** + +Install Kafka on mac OSX (High Sierra) + +`COMP10619:Kafka pejman.tabassomi$ brew install kafka` + +Start Zookeeper + +`COMP10619:Kafka pejman.tabassomi$ zookeeper-server-start /usr/local/etc/kafka/zookeeper.properties` + +Start kafka server + +`COMP10619:Kafka pejman.tabassomi$ kafka-server-start /usr/local/etc/kafka/server.properties` + +Create a Topic (First time) + +`COMP10619:Kafka pejman.tabassomi$ kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic users` + + +**_Administration tasks_** + +Start Zookeeper + +`COMP10619:Kafka pejman.tabassomi$ zookeeper-server-start /usr/local/etc/kafka/zookeeper.properties` + +Start kafka server + +`COMP10619:Kafka pejman.tabassomi$ kafka-server-start /usr/local/etc/kafka/server.properties` + +List all Topics + +`COMP10619:Kafka pejman.tabassomi$ kafka-topics --list --zookeeper localhost:2181` + +Check if data is landing in kafka + +`COMP10619:Kafka pejman.tabassomi$ kafka-console-consumer --bootstrap-server localhost:9092 --topic users --from-beginning` + + +**_Spin up the Datadog Agent (Provide your API key to the belown command_** + + +`docker run -d --name datadog_agent -v /var/run/docker.sock:/var/run/docker.sock:ro -v /proc/:/host/proc/:ro -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro -p 127.0.0.1:8126:8126/tcp -e DD_API_KEY= -e DD_APM_ENABLED=true -e DD_APM_IGNORE_RESOURCES="GET /api/random" datadog/agent:latest` + + +**_Start the spring boot app_** + +`COMP10619:spring-kafka-ot33v2 pejman.tabassomi$ java -jar build/libs/spring-kafka-ot33v2.jar` + + +**_Run the tests_** + +`COMP10619:Kafka pejman.tabassomi$ curl localhost:8080/test` diff --git a/java/spring-kafka-ot33v2/build.gradle b/java/spring-kafka-ot33v2/build.gradle new file mode 100644 index 00000000..6ff2c84a --- /dev/null +++ b/java/spring-kafka-ot33v2/build.gradle @@ -0,0 +1,56 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + id 'java' + id 'maven-publish' + id 'org.springframework.boot' version '2.1.8.RELEASE' +} + + + + +repositories { + mavenLocal() + maven { + url = 'https://repo.maven.apache.org/maven2' + } +} + +dependencies { + compile 'org.springframework.boot:spring-boot-starter:2.1.0.RELEASE' + compile 'org.springframework.boot:spring-boot-starter-web:2.1.0.RELEASE' + compile 'org.springframework.kafka:spring-kafka:2.2.0.RELEASE' + compile group: 'io.opentracing.contrib', name: 'opentracing-kafka-spring', version: "0.1.8" + compile group: 'com.datadoghq', name: 'dd-trace-ot', version: "0.37.0" + compileOnly 'org.projectlombok:lombok:1.18.10' + annotationProcessor 'org.projectlombok:lombok:1.18.10' + //compile group: 'io.jaegertracing', name: 'jaeger-client', version: '0.31.0' + //compile group: 'io.jaegertracing', name: 'jaeger-client', version: '0.35.2' +} + +group = 'com.datadog.pej.kafka' +version = '0.0.1-SNAPSHOT' +description = 'spring-kafka' +sourceCompatibility = '1.8' + +bootJar { + archiveFileName = 'spring-kafka-ot33v2.jar' +} + +publishing { + publications { + maven(MavenPublication) { + from(components.java) + } + } +} + +test { + exclude '**/*' +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} diff --git a/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/KafkaController.class b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/KafkaController.class new file mode 100644 index 00000000..27594877 Binary files /dev/null and b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/KafkaController.class differ diff --git a/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/Quote.class b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/Quote.class new file mode 100644 index 00000000..47e1210f Binary files /dev/null and b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/Quote.class differ diff --git a/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/SpringKafkaApplication.class b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/SpringKafkaApplication.class new file mode 100644 index 00000000..38d9a367 Binary files /dev/null and b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/SpringKafkaApplication.class differ diff --git a/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/Value.class b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/Value.class new file mode 100644 index 00000000..a6790418 Binary files /dev/null and b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/Value.class differ diff --git a/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/consumer/Receiver.class b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/consumer/Receiver.class new file mode 100644 index 00000000..76b6b3f1 Binary files /dev/null and b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/consumer/Receiver.class differ diff --git a/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/consumer/ReceiverConfig.class b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/consumer/ReceiverConfig.class new file mode 100644 index 00000000..39251145 Binary files /dev/null and b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/consumer/ReceiverConfig.class differ diff --git a/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/producer/Sender.class b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/producer/Sender.class new file mode 100644 index 00000000..dfa3f502 Binary files /dev/null and b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/producer/Sender.class differ diff --git a/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/producer/SenderConfig.class b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/producer/SenderConfig.class new file mode 100644 index 00000000..bc85211a Binary files /dev/null and b/java/spring-kafka-ot33v2/build/classes/java/main/com/datadog/pej/kafka/producer/SenderConfig.class differ diff --git a/java/spring-kafka-ot33v2/build/libs/spring-kafka-ot33v2.jar b/java/spring-kafka-ot33v2/build/libs/spring-kafka-ot33v2.jar new file mode 100644 index 00000000..4eda4bd3 Binary files /dev/null and b/java/spring-kafka-ot33v2/build/libs/spring-kafka-ot33v2.jar differ diff --git a/java/spring-kafka-ot33v2/build/resources/main/application.yml b/java/spring-kafka-ot33v2/build/resources/main/application.yml new file mode 100644 index 00000000..a9b6da7f --- /dev/null +++ b/java/spring-kafka-ot33v2/build/resources/main/application.yml @@ -0,0 +1,13 @@ +kafka: + bootstrap-servers: localhost:9092 + +logging: + level: + root: info + org.springframework.web: INFO + path: logs + file: ${logging.path}/springkafkaot33.log + pattern: + file: "%d{yyyy-MM-dd HH:mm:ss} %magenta([%thread]) %highlight(%-5level) %yellow(%logger{36}) %X{dd.trace_id:-0} %X{dd.span_id:-0} - %msg%n" + console: "%d{yyyy-MM-dd HH:mm:ss} %magenta([%thread]) %highlight(%-5level) %yellow(%logger{36}) %X{dd.trace_id:-0} %X{dd.span_id:-0} - %msg%n" + diff --git a/java/spring-kafka-ot33v2/build/resources/test/application.yml b/java/spring-kafka-ot33v2/build/resources/test/application.yml new file mode 100644 index 00000000..0c6c7600 --- /dev/null +++ b/java/spring-kafka-ot33v2/build/resources/test/application.yml @@ -0,0 +1,2 @@ +kafka: + bootstrap-servers: ${spring.embedded.kafka.brokers} diff --git a/java/spring-kafka-ot33v2/build/tmp/bootJar/MANIFEST.MF b/java/spring-kafka-ot33v2/build/tmp/bootJar/MANIFEST.MF new file mode 100644 index 00000000..21974e44 --- /dev/null +++ b/java/spring-kafka-ot33v2/build/tmp/bootJar/MANIFEST.MF @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +Main-Class: org.springframework.boot.loader.JarLauncher +Start-Class: com.datadog.pej.kafka.SpringKafkaApplication +Spring-Boot-Version: 2.1.8.RELEASE +Spring-Boot-Classes: BOOT-INF/classes/ +Spring-Boot-Lib: BOOT-INF/lib/ + diff --git a/java/spring-kafka-ot33v2/gradle/wrapper/gradle-wrapper.jar b/java/spring-kafka-ot33v2/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..5c2d1cf0 Binary files /dev/null and b/java/spring-kafka-ot33v2/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/spring-kafka-ot33v2/gradle/wrapper/gradle-wrapper.properties b/java/spring-kafka-ot33v2/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..49c13d2b --- /dev/null +++ b/java/spring-kafka-ot33v2/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Sep 28 10:31:27 CEST 2019 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/java/spring-kafka-ot33v2/gradlew b/java/spring-kafka-ot33v2/gradlew new file mode 100755 index 00000000..83f2acfd --- /dev/null +++ b/java/spring-kafka-ot33v2/gradlew @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or 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 +# +# https://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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/java/spring-kafka-ot33v2/gradlew.bat b/java/spring-kafka-ot33v2/gradlew.bat new file mode 100644 index 00000000..9618d8d9 --- /dev/null +++ b/java/spring-kafka-ot33v2/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java/spring-kafka-ot33v2/settings.gradle b/java/spring-kafka-ot33v2/settings.gradle new file mode 100644 index 00000000..482a0e7a --- /dev/null +++ b/java/spring-kafka-ot33v2/settings.gradle @@ -0,0 +1,5 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'spring-kafka-ot33v2' diff --git a/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/KafkaController.java b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/KafkaController.java new file mode 100644 index 00000000..9a2ddf3f --- /dev/null +++ b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/KafkaController.java @@ -0,0 +1,65 @@ +package com.datadog.pej.kafka; + +import com.datadog.pej.kafka.consumer.Receiver; +import com.datadog.pej.kafka.producer.Sender; +import datadog.trace.api.DDTags; +import io.opentracing.Scope; +import io.opentracing.ScopeManager; +import io.opentracing.Span; +import io.opentracing.Tracer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.concurrent.TimeUnit; + +@RestController +public class KafkaController { + + @Autowired + private Receiver receiver; + + @Autowired + private Sender sender; + + @Autowired + private Tracer tracer; + + @RequestMapping("/test") + public String index() { + + + ScopeManager sm = tracer.scopeManager(); + + Tracer.SpanBuilder tb = tracer.buildSpan("servkafkaa"); + Span span = tb.start(); // ou tb.startActive() + casting => Scope + + + //try(Scope scope = sm.activate(tb.start())) { + /*try(Scope scope = sm.activate(span)) { + //Span span = sm.activeSpan(); + span.setTag(DDTags.RESOURCE_NAME, "GET /test"); + span.setTag(DDTags.SPAN_TYPE, "web"); + sender.send("Un message plus long"); + try { + Thread.sleep(20L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + span.finish(); + + }*/ + + Scope scope = sm.activate(span); + span.setTag(DDTags.RESOURCE_NAME, "GET /test"); + span.setTag(DDTags.SPAN_TYPE, "web"); + sender.send("Un message plus long"); + scope.close(); + span.finish(); + + + return "\ntest"; + } + + +} diff --git a/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/Quote.java b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/Quote.java new file mode 100644 index 00000000..02fbe81a --- /dev/null +++ b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/Quote.java @@ -0,0 +1,37 @@ +package com.datadog.pej.kafka; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Quote { + + private String type; + private Value value; + + public Quote() { + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Value getValue() { + return value; + } + + public void setValue(Value value) { + this.value = value; + } + + @Override + public String toString() { + return "Quote{" + + "type='" + type + '\'' + + ", value=" + value + + '}'; + } +} diff --git a/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/SpringKafkaApplication.java b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/SpringKafkaApplication.java new file mode 100644 index 00000000..c7a1da39 --- /dev/null +++ b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/SpringKafkaApplication.java @@ -0,0 +1,96 @@ +package com.datadog.pej.kafka; + +import com.datadog.pej.kafka.consumer.Receiver; +import com.datadog.pej.kafka.producer.Sender; +//import datadog.opentracing.DDTracer; +//import io.jaegertracing.Configuration; +//import io.jaegertracing.internal.JaegerTracer; + +import datadog.opentracing.DDTracer; +import io.opentracing.Tracer; + +import io.opentracing.util.GlobalTracer; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +import java.util.concurrent.TimeUnit; + + +@Slf4j +@SpringBootApplication +public class SpringKafkaApplication { + + @Autowired + private Receiver receiver; + + @Autowired + private Sender sender; + + public static void main(String[] args) { + SpringApplication.run(SpringKafkaApplication.class, args); + } + + /* To be used with Jaeger and manual instrumentation + + @Bean + public static JaegerTracer initTracer(@Value("ServiceKafka") String service) { + Configuration.SamplerConfiguration samplerConfig = Configuration.SamplerConfiguration.fromEnv().withType("const").withParam(1); + Configuration.ReporterConfiguration reporterConfig = Configuration.ReporterConfiguration.fromEnv().withLogSpans(true); + Configuration config = new Configuration(service).withSampler(samplerConfig).withReporter(reporterConfig); + return config.getTracer(); + } + */ + + + /* To be used without dd-trace-ot.jar and manual instrumentation + */ + + public static Tracer initTracer(@Value("ServiceKafka") String service){ + Tracer tracer = new DDTracer(service); + GlobalTracer.register(tracer); + return tracer; + } + + +/* To be used with the -javaagent + + + public static Tracer initTracer(@Value("ServiceKafka") String service){ + Tracer tracer = GlobalTracer.get(); + return tracer; + } +*/ + + @Bean + public RestTemplate restTemplate(){ + return new RestTemplateBuilder().build(); + } + + + @Bean + public Tracer tracer() { + return initTracer("ServiceKafka"); + } + + + @Bean + public CommandLineRunner run() { + return args -> { + + //sender.send("Un message depuis command line runner"); + //receiver.getLatch().await(10000, TimeUnit.MILLISECONDS); + + log.info("\ntest"); + }; + } + +} diff --git a/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/Value.java b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/Value.java new file mode 100644 index 00000000..c9a7ff8d --- /dev/null +++ b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/Value.java @@ -0,0 +1,37 @@ +package com.datadog.pej.kafka; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Value { + + private Long id; + private String quote; + + public Value() { + } + + public Long getId() { + return this.id; + } + + public String getQuote() { + return this.quote; + } + + public void setId(Long id) { + this.id = id; + } + + public void setQuote(String quote) { + this.quote = quote; + } + + @Override + public String toString() { + return "Value{" + + "id=" + id + + ", quote='" + quote + '\'' + + '}'; + } +} diff --git a/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/consumer/Receiver.java b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/consumer/Receiver.java new file mode 100644 index 00000000..c3c73739 --- /dev/null +++ b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/consumer/Receiver.java @@ -0,0 +1,93 @@ +package com.datadog.pej.kafka.consumer; + +import java.util.concurrent.CountDownLatch; + +import com.datadog.pej.kafka.Quote; +//import datadog.trace.api.DDTags; +import datadog.trace.api.DDTags; +import io.opentracing.*; +import io.opentracing.contrib.kafka.TracingKafkaUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.web.client.RestTemplate; + + +@Slf4j +public class Receiver { + + private CountDownLatch latch = new CountDownLatch(1); + + @Autowired + RestTemplate restTemplate; + + @Autowired + Tracer tracer; + + public CountDownLatch getLatch() { + return latch; + } + + @KafkaListener(topics = "users") + public void receive(String payload, ConsumerRecord cr) { + log.info("received payload='{}'", payload); + + + SpanContext spanContext = TracingKafkaUtils.extractSpanContext(cr.headers(), tracer); + + + ScopeManager sm = tracer.scopeManager(); + + Tracer.SpanBuilder sb0 = tracer.buildSpan("Quote").asChildOf(spanContext); + Span span = sb0.start(); + try(Scope scope = sm.activate(span)) { + span.setTag(DDTags.RESOURCE_NAME, "GET /api/random"); + span.setTag(DDTags.SPAN_TYPE, "web"); + Quote quote = restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class); + log.info(quote.toString()); + span.finish(); + //latch.countDown(); + } + + /* + //new Thread(() -> { + try(Scope scope = tracer.buildSpan("Quote").asChildOf(spanContext).startActive(true)){ + scope.span().setTag(DDTags.RESOURCE_NAME, "GET /api/random"); + scope.span().setTag(DDTags.SPAN_TYPE, "web"); + Quote quote = restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class); + LOGGER.info(quote.toString()); + // latch.countDown(); + } + //}).start(); + */ + + //Tracer.SpanBuilder sbr = tracer.buildSpan("Google"); + + + Tracer.SpanBuilder sb1 = tracer.buildSpan("Google").asChildOf(spanContext); + Span span1 = sb1.start(); + try(Scope scope = sm.activate(span1)) { + span.setTag(DDTags.RESOURCE_NAME, "GET /"); + span.setTag(DDTags.SPAN_TYPE, "web"); + String result = restTemplate.getForObject("https://www.google.fr", String.class); + log.info(result); + latch.countDown(); + span1.finish(); + } + + +/* + try(Scope scope = tracer.buildSpan("Google").asChildOf(spanContext).startActive(true)){ + scope.span().setTag(DDTags.RESOURCE_NAME, "GET /"); + scope.span().setTag(DDTags.SPAN_TYPE, "web"); + String result = restTemplate.getForObject("https://www.google.fr", String.class); + LOGGER.info(result); + latch.countDown(); + } +*/ + + } +} diff --git a/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/consumer/ReceiverConfig.java b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/consumer/ReceiverConfig.java new file mode 100644 index 00000000..79951380 --- /dev/null +++ b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/consumer/ReceiverConfig.java @@ -0,0 +1,71 @@ +package com.datadog.pej.kafka.consumer; + +import java.util.HashMap; +import java.util.Map; + +import io.opentracing.Tracer; +import io.opentracing.contrib.kafka.spring.TracingConsumerFactory; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.config.KafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; +import org.springframework.kafka.listener.ConcurrentMessageListenerContainer; + +@Configuration +@EnableKafka +public class ReceiverConfig { + + @Value("${kafka.bootstrap-servers}") + private String bootstrapServers; + + + @Autowired + private Tracer tracer; + + @Bean + public Map consumerConfigs() { + Map props = new HashMap<>(); + // list of host:port pairs used for establishing the initial connections to the Kafka cluster + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, + bootstrapServers); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, + StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, + StringDeserializer.class); + // allows a pool of processes to divide the work of consuming and processing records + props.put(ConsumerConfig.GROUP_ID_CONFIG, "helloworld"); + // automatically reset the offset to the earliest offset + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + + return props; + } + + + @Bean + public ConsumerFactory consumerFactory() { + //return new DefaultKafkaConsumerFactory<>(consumerConfigs()); + return new TracingConsumerFactory<>(new DefaultKafkaConsumerFactory<>(consumerConfigs()), tracer); + } + + + @Bean + public KafkaListenerContainerFactory> kafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = + new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory()); + + return factory; + } + + @Bean + public Receiver receiver() { + return new Receiver(); + } +} diff --git a/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/producer/Sender.java b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/producer/Sender.java new file mode 100644 index 00000000..0824eded --- /dev/null +++ b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/producer/Sender.java @@ -0,0 +1,20 @@ +package com.datadog.pej.kafka.producer; + +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.KafkaTemplate; + +@Slf4j +public class Sender { + + @Autowired + private KafkaTemplate kafkaTemplate; + + public void send(String payload) { + //LOGGER.info("sending payload='{}'", payload); + log.info("sending payload='{}'", payload); + kafkaTemplate.send("users", payload); + } +} diff --git a/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/producer/SenderConfig.java b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/producer/SenderConfig.java new file mode 100644 index 00000000..ab062c53 --- /dev/null +++ b/java/spring-kafka-ot33v2/src/main/java/com/datadog/pej/kafka/producer/SenderConfig.java @@ -0,0 +1,56 @@ +package com.datadog.pej.kafka.producer; + +import java.util.HashMap; +import java.util.Map; + +import io.opentracing.Tracer; +import io.opentracing.contrib.kafka.spring.TracingProducerFactory; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.serialization.StringSerializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.core.ProducerFactory; + +@Configuration +public class SenderConfig { + + @Value("${kafka.bootstrap-servers}") + private String bootstrapServers; + + @Autowired + Tracer tracer; + + @Bean + public Map producerConfigs() { + Map props = new HashMap<>(); + // list of host:port pairs used for establishing the initial connections to the Kakfa cluster + props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, + bootstrapServers); + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, + StringSerializer.class); + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, + StringSerializer.class); + + return props; + } + + @Bean + public ProducerFactory producerFactory() { + //return new DefaultKafkaProducerFactory<>(producerConfigs()); + return new TracingProducerFactory<>(new DefaultKafkaProducerFactory<>(producerConfigs()), tracer); + } + + @Bean + public KafkaTemplate kafkaTemplate() { + return new KafkaTemplate<>(producerFactory()); + } + + @Bean + public Sender sender() { + return new Sender(); + } +} diff --git a/java/spring-kafka-ot33v2/src/main/resources/application.yml b/java/spring-kafka-ot33v2/src/main/resources/application.yml new file mode 100644 index 00000000..a9b6da7f --- /dev/null +++ b/java/spring-kafka-ot33v2/src/main/resources/application.yml @@ -0,0 +1,13 @@ +kafka: + bootstrap-servers: localhost:9092 + +logging: + level: + root: info + org.springframework.web: INFO + path: logs + file: ${logging.path}/springkafkaot33.log + pattern: + file: "%d{yyyy-MM-dd HH:mm:ss} %magenta([%thread]) %highlight(%-5level) %yellow(%logger{36}) %X{dd.trace_id:-0} %X{dd.span_id:-0} - %msg%n" + console: "%d{yyyy-MM-dd HH:mm:ss} %magenta([%thread]) %highlight(%-5level) %yellow(%logger{36}) %X{dd.trace_id:-0} %X{dd.span_id:-0} - %msg%n" + diff --git a/java/spring-kafka-ot33v2/src/test/resources/application.yml b/java/spring-kafka-ot33v2/src/test/resources/application.yml new file mode 100644 index 00000000..0c6c7600 --- /dev/null +++ b/java/spring-kafka-ot33v2/src/test/resources/application.yml @@ -0,0 +1,2 @@ +kafka: + bootstrap-servers: ${spring.embedded.kafka.brokers} diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/executionHistory/executionHistory.bin b/java/spring-rabbitmq-auto/.gradle/5.6.4/executionHistory/executionHistory.bin new file mode 100644 index 00000000..ec9510ec Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/5.6.4/executionHistory/executionHistory.bin differ diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/executionHistory/executionHistory.lock b/java/spring-rabbitmq-auto/.gradle/5.6.4/executionHistory/executionHistory.lock new file mode 100644 index 00000000..bb19a9c4 Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/5.6.4/executionHistory/executionHistory.lock differ diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/fileChanges/last-build.bin b/java/spring-rabbitmq-auto/.gradle/5.6.4/fileChanges/last-build.bin new file mode 100644 index 00000000..f76dd238 Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/5.6.4/fileChanges/last-build.bin differ diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/fileContent/fileContent.lock b/java/spring-rabbitmq-auto/.gradle/5.6.4/fileContent/fileContent.lock new file mode 100644 index 00000000..f31bd9f3 Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/5.6.4/fileContent/fileContent.lock differ diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/fileHashes/fileHashes.bin b/java/spring-rabbitmq-auto/.gradle/5.6.4/fileHashes/fileHashes.bin new file mode 100644 index 00000000..29476552 Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/5.6.4/fileHashes/fileHashes.bin differ diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/fileHashes/fileHashes.lock b/java/spring-rabbitmq-auto/.gradle/5.6.4/fileHashes/fileHashes.lock new file mode 100644 index 00000000..eb7db126 Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/5.6.4/fileHashes/fileHashes.lock differ diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/gc.properties b/java/spring-rabbitmq-auto/.gradle/5.6.4/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/javaCompile/classAnalysis.bin b/java/spring-rabbitmq-auto/.gradle/5.6.4/javaCompile/classAnalysis.bin new file mode 100644 index 00000000..ae7ff89b Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/5.6.4/javaCompile/classAnalysis.bin differ diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/javaCompile/javaCompile.lock b/java/spring-rabbitmq-auto/.gradle/5.6.4/javaCompile/javaCompile.lock new file mode 100644 index 00000000..1e1ff29e Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/5.6.4/javaCompile/javaCompile.lock differ diff --git a/java/spring-rabbitmq-auto/.gradle/5.6.4/javaCompile/taskHistory.bin b/java/spring-rabbitmq-auto/.gradle/5.6.4/javaCompile/taskHistory.bin new file mode 100644 index 00000000..704fc0ba Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/5.6.4/javaCompile/taskHistory.bin differ diff --git a/java/spring-rabbitmq-auto/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/java/spring-rabbitmq-auto/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 00000000..6d45021b Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/java/spring-rabbitmq-auto/.gradle/buildOutputCleanup/cache.properties b/java/spring-rabbitmq-auto/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 00000000..98541157 --- /dev/null +++ b/java/spring-rabbitmq-auto/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Sat Apr 04 14:43:48 CEST 2020 +gradle.version=5.6.4 diff --git a/java/spring-rabbitmq-auto/.gradle/buildOutputCleanup/outputFiles.bin b/java/spring-rabbitmq-auto/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 00000000..140dbff2 Binary files /dev/null and b/java/spring-rabbitmq-auto/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/java/spring-rabbitmq-auto/.gradle/vcs-1/gc.properties b/java/spring-rabbitmq-auto/.gradle/vcs-1/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/java/spring-rabbitmq-auto/README.md b/java/spring-rabbitmq-auto/README.md new file mode 100644 index 00000000..8cadc231 --- /dev/null +++ b/java/spring-rabbitmq-auto/README.md @@ -0,0 +1,100 @@ +## SpringBoot RabbitMQ Producer / Consumer code example + + +A simple project based on SpringBoot and RabbitMQ meant to use automatic instrumentation with a Consumer and Producer using RabbitMQ. +It is also intended to show how the RabbitMQ Spring API is used and instrumented (RabbitTemplate / RabbitListener) + +### _Preliminary tasks and first time steps_ + +**Install RabbitMQ on mac OSX (tested on High Sierra)** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ brew install rabbitmq +```` + +**Start RabbitMQ** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ brew services start rabbitmq +```` + +Another option is to use the official docker image and run it locally. +Below an example of docker-compose file. + + +##### _docker-compose.yml_ +```` +rabbitmq: + image: rabbitmq:management + ports: + - "5672:5672" + - "15672:15672" +```` + +**Spin up the container** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ docker-compose up -d +```` + +### _Administration tasks_ + +**Start RabbitMQ** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ brew services start rabbitmq +```` + +**Stop RabbitMQ** + +```` +COMP10619:RabbitMQ pejman.tabassomi$ brew services stop rabbitmq +```` + +**RabbitMQ UI** + +```` +http://localhost:15672 +```` + +### _Spin up the Datadog Agent (Provide your API key to the belown command_ + + +```` +docker run -d --name datadog_agent -v /var/run/docker.sock:/var/run/docker.sock:ro -v /proc/:/host/proc/:ro -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro -p 127.0.0.1:8126:8126/tcp -e DD_API_KEY= -e DD_APM_ENABLED=true -e DD_APM_IGNORE_RESOURCES="GET /api/random" datadog/agent:latest +```` + +### _Clone the repository and build the application_ + +The project is structured as a main gradle project with two submodules (one for the consumer, the other for the producer) + +```` +COMP10619:RabbitMQ pejman.tabassomi$ git clone https://github.com/ptabasso2/prodconsrbmq.git +COMP10619:RabbitMQ pejman.tabassomi$ cd prodconsrbmq +COMP10619:prodconsrbmq pejman.tabassomi$ ./gradlew build +```` + + +### _Start the app_ + +Open three terminal windows, one for the producer. The second for the consumer and the third for testing. + +#### Consumer + +```` +COMP10619:prodconsrbmq pejman.tabassomi$ java -jar consumer/build/libs/consumer-0.0.1-SNAPSHOT.jar --server.port=8081 +```` +and then + +#### Producer + +```` +COMP10619:prodconsrbmq pejman.tabassomi$ java -jar producer/build/libs/producer-0.0.1-SNAPSHOT.jar --server.port=8082 +```` + +### _Test the app_ + +```` +COMP10619:prodconsrbmq pejman.tabassomi$ curl localhost:8082/test +```` + diff --git a/java/spring-rabbitmq-auto/build.gradle b/java/spring-rabbitmq-auto/build.gradle new file mode 100644 index 00000000..d323ee3c --- /dev/null +++ b/java/spring-rabbitmq-auto/build.gradle @@ -0,0 +1,6 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This is a general purpose Gradle build. + * Learn how to create Gradle builds at https://guides.gradle.org/creating-new-gradle-builds + */ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileChanges/last-build.bin b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileChanges/last-build.bin new file mode 100644 index 00000000..f76dd238 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileChanges/last-build.bin differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileContent/fileContent.lock b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileContent/fileContent.lock new file mode 100644 index 00000000..cb6a7247 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileContent/fileContent.lock differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileHashes/fileHashes.bin b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileHashes/fileHashes.bin new file mode 100644 index 00000000..8aee3590 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileHashes/fileHashes.bin differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileHashes/fileHashes.lock b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileHashes/fileHashes.lock new file mode 100644 index 00000000..b41c85a8 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileHashes/fileHashes.lock differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileHashes/resourceHashesCache.bin b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileHashes/resourceHashesCache.bin new file mode 100644 index 00000000..79eb4a0e Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/fileHashes/resourceHashesCache.bin differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/gc.properties b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/classAnalysis.bin b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/classAnalysis.bin new file mode 100644 index 00000000..fa1735bc Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/classAnalysis.bin differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/jarAnalysis.bin b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/jarAnalysis.bin new file mode 100644 index 00000000..146929f0 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/jarAnalysis.bin differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/javaCompile.lock b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/javaCompile.lock new file mode 100644 index 00000000..5647ce9f Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/javaCompile.lock differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/taskHistory.bin b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/taskHistory.bin new file mode 100644 index 00000000..5dc79744 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/javaCompile/taskHistory.bin differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/taskHistory/taskHistory.bin b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/taskHistory/taskHistory.bin new file mode 100644 index 00000000..f0c3d821 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/taskHistory/taskHistory.bin differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/taskHistory/taskHistory.lock b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/taskHistory/taskHistory.lock new file mode 100644 index 00000000..a5cba492 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/4.10.3/taskHistory/taskHistory.lock differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/java/spring-rabbitmq-auto/consumer/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 00000000..ea0e91a1 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/buildOutputCleanup/cache.properties b/java/spring-rabbitmq-auto/consumer/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 00000000..0be19378 --- /dev/null +++ b/java/spring-rabbitmq-auto/consumer/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Fri Apr 03 18:13:00 CEST 2020 +gradle.version=4.10.3 diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/buildOutputCleanup/outputFiles.bin b/java/spring-rabbitmq-auto/consumer/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 00000000..db51bef6 Binary files /dev/null and b/java/spring-rabbitmq-auto/consumer/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/java/spring-rabbitmq-auto/consumer/.gradle/vcs-1/gc.properties b/java/spring-rabbitmq-auto/consumer/.gradle/vcs-1/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/java/spring-rabbitmq-auto/consumer/.idea/.name b/java/spring-rabbitmq-auto/consumer/.idea/.name new file mode 100644 index 00000000..31dd3491 --- /dev/null +++ b/java/spring-rabbitmq-auto/consumer/.idea/.name @@ -0,0 +1 @@ +messaging-rabbitmq \ No newline at end of file diff --git a/java/spring-rabbitmq-auto/consumer/.idea/codeStyles/codeStyleConfig.xml b/java/spring-rabbitmq-auto/consumer/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..a55e7a17 --- /dev/null +++ b/java/spring-rabbitmq-auto/consumer/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/java/spring-rabbitmq-auto/consumer/.idea/gradle.xml b/java/spring-rabbitmq-auto/consumer/.idea/gradle.xml new file mode 100644 index 00000000..62e68313 --- /dev/null +++ b/java/spring-rabbitmq-auto/consumer/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/java/spring-rabbitmq-auto/consumer/.idea/misc.xml b/java/spring-rabbitmq-auto/consumer/.idea/misc.xml new file mode 100644 index 00000000..efc86773 --- /dev/null +++ b/java/spring-rabbitmq-auto/consumer/.idea/misc.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/java/spring-rabbitmq-auto/consumer/.idea/vcs.xml b/java/spring-rabbitmq-auto/consumer/.idea/vcs.xml new file mode 100644 index 00000000..6c0b8635 --- /dev/null +++ b/java/spring-rabbitmq-auto/consumer/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/java/spring-rabbitmq-auto/consumer/.idea/workspace.xml b/java/spring-rabbitmq-auto/consumer/.idea/workspace.xml new file mode 100644 index 00000000..db404324 --- /dev/null +++ b/java/spring-rabbitmq-auto/consumer/.idea/workspace.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + 1585930560955 + + + + + + + + + + + + + file://$PROJECT_DIR$/src/main/java/com/example/messagingrabbitmq/Receiver.java + 17 + + + file://$PROJECT_DIR$/src/main/java/com/example/messagingrabbitmq/RabbitmqController.java + 17 + + + + + \ No newline at end of file diff --git a/java/spring-rabbitmq-auto/producer/apikeyfile b/java/spring-rabbitmq-auto/producer/apikeyfile new file mode 100644 index 00000000..69dd19db --- /dev/null +++ b/java/spring-rabbitmq-auto/producer/apikeyfile @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/java/spring-rabbitmq-auto/producer/build.gradle b/java/spring-rabbitmq-auto/producer/build.gradle new file mode 100644 index 00000000..d33b0a83 --- /dev/null +++ b/java/spring-rabbitmq-auto/producer/build.gradle @@ -0,0 +1,21 @@ +plugins { + id 'org.springframework.boot' version '2.2.0.RELEASE' + id 'io.spring.dependency-management' version '1.0.8.RELEASE' + id 'java' +} + +group = 'com.example' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '1.8' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-amqp' + compile 'org.springframework.boot:spring-boot-starter:2.1.0.RELEASE' + compile 'org.springframework.boot:spring-boot-starter-web:2.1.0.RELEASE' +} + + diff --git a/java/spring-rabbitmq-auto/producer/build/classes/java/main/com/example/messagingrabbitmq/MessagingRabbitmqApplication.class b/java/spring-rabbitmq-auto/producer/build/classes/java/main/com/example/messagingrabbitmq/MessagingRabbitmqApplication.class new file mode 100644 index 00000000..2aaccffa Binary files /dev/null and b/java/spring-rabbitmq-auto/producer/build/classes/java/main/com/example/messagingrabbitmq/MessagingRabbitmqApplication.class differ diff --git a/java/spring-rabbitmq-auto/producer/build/classes/java/main/com/example/messagingrabbitmq/RabbitmqController.class b/java/spring-rabbitmq-auto/producer/build/classes/java/main/com/example/messagingrabbitmq/RabbitmqController.class new file mode 100644 index 00000000..3bdce155 Binary files /dev/null and b/java/spring-rabbitmq-auto/producer/build/classes/java/main/com/example/messagingrabbitmq/RabbitmqController.class differ diff --git a/java/spring-rabbitmq-auto/producer/build/libs/producer-0.0.1-SNAPSHOT.jar b/java/spring-rabbitmq-auto/producer/build/libs/producer-0.0.1-SNAPSHOT.jar new file mode 100644 index 00000000..8c5ae560 Binary files /dev/null and b/java/spring-rabbitmq-auto/producer/build/libs/producer-0.0.1-SNAPSHOT.jar differ diff --git a/java/spring-rabbitmq-auto/producer/build/tmp/bootJar/MANIFEST.MF b/java/spring-rabbitmq-auto/producer/build/tmp/bootJar/MANIFEST.MF new file mode 100644 index 00000000..bd594973 --- /dev/null +++ b/java/spring-rabbitmq-auto/producer/build/tmp/bootJar/MANIFEST.MF @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +Main-Class: org.springframework.boot.loader.JarLauncher +Start-Class: com.example.messagingrabbitmq.MessagingRabbitmqApplication +Spring-Boot-Version: 2.2.0.RELEASE +Spring-Boot-Classes: BOOT-INF/classes/ +Spring-Boot-Lib: BOOT-INF/lib/ + diff --git a/java/spring-rabbitmq-auto/producer/dd-java-agent-0.47.0.jar b/java/spring-rabbitmq-auto/producer/dd-java-agent-0.47.0.jar new file mode 100644 index 00000000..3cbbf9c9 Binary files /dev/null and b/java/spring-rabbitmq-auto/producer/dd-java-agent-0.47.0.jar differ diff --git a/java/spring-rabbitmq-auto/producer/docker-compose.yml b/java/spring-rabbitmq-auto/producer/docker-compose.yml new file mode 100644 index 00000000..1a53d6e0 --- /dev/null +++ b/java/spring-rabbitmq-auto/producer/docker-compose.yml @@ -0,0 +1,5 @@ +rabbitmq: + image: rabbitmq:management + ports: + - "5672:5672" + - "15672:15672" diff --git a/java/spring-rabbitmq-auto/producer/gradle/wrapper/gradle-wrapper.jar b/java/spring-rabbitmq-auto/producer/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..5c2d1cf0 Binary files /dev/null and b/java/spring-rabbitmq-auto/producer/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/spring-rabbitmq-auto/producer/gradle/wrapper/gradle-wrapper.properties b/java/spring-rabbitmq-auto/producer/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..ae45383b --- /dev/null +++ b/java/spring-rabbitmq-auto/producer/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/java/spring-rabbitmq-auto/producer/gradlew b/java/spring-rabbitmq-auto/producer/gradlew new file mode 100755 index 00000000..83f2acfd --- /dev/null +++ b/java/spring-rabbitmq-auto/producer/gradlew @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or 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 +# +# https://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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/java/spring-rabbitmq-auto/producer/settings.gradle b/java/spring-rabbitmq-auto/producer/settings.gradle new file mode 100644 index 00000000..01f34362 --- /dev/null +++ b/java/spring-rabbitmq-auto/producer/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'base' diff --git a/java/spring-rabbitmq-auto/producer/src/main/java/com/example/messagingrabbitmq/MessagingRabbitmqApplication.java b/java/spring-rabbitmq-auto/producer/src/main/java/com/example/messagingrabbitmq/MessagingRabbitmqApplication.java new file mode 100644 index 00000000..2e21433c --- /dev/null +++ b/java/spring-rabbitmq-auto/producer/src/main/java/com/example/messagingrabbitmq/MessagingRabbitmqApplication.java @@ -0,0 +1,44 @@ +package com.example.messagingrabbitmq; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; +import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +@SpringBootApplication +public class MessagingRabbitmqApplication { + + static final String topicExchangeName = "spring-boot-exchange"; + + static final String queueName = "spring-boot"; + + @Bean + Queue queue() { + return new Queue(queueName, false); + } + + @Bean + TopicExchange exchange() { + return new TopicExchange(topicExchangeName); + } + + @Bean + Binding binding(Queue queue, TopicExchange exchange) { + return BindingBuilder.bind(queue).to(exchange).with("foo.bar.#"); + } + + + public static void main(String[] args) throws InterruptedException { + //SpringApplication.run(MessagingRabbitmqApplication.class, args).close(); + SpringApplication.run(MessagingRabbitmqApplication.class, args); + } + +} diff --git a/java/spring-rabbitmq-auto/producer/src/main/java/com/example/messagingrabbitmq/RabbitmqController.java b/java/spring-rabbitmq-auto/producer/src/main/java/com/example/messagingrabbitmq/RabbitmqController.java new file mode 100644 index 00000000..0807282b --- /dev/null +++ b/java/spring-rabbitmq-auto/producer/src/main/java/com/example/messagingrabbitmq/RabbitmqController.java @@ -0,0 +1,22 @@ +package com.example.messagingrabbitmq; + +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class RabbitmqController { + + + @Autowired + RabbitTemplate rabbitTemplate; + + @RequestMapping("/test") + public String index() { + System.out.println("Sending message from controller..."); + rabbitTemplate.convertAndSend(MessagingRabbitmqApplication.topicExchangeName, "foo.bar.baz", "Hello from RabbitMQ!"); + return "\ntest"; + } + +} diff --git a/java/spring-rabbitmq-auto/settings.gradle b/java/spring-rabbitmq-auto/settings.gradle new file mode 100644 index 00000000..210f81d6 --- /dev/null +++ b/java/spring-rabbitmq-auto/settings.gradle @@ -0,0 +1,12 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/5.6.4/userguide/multi_project_builds.html + */ + +rootProject.name = 'prodconsrmq' +include 'producer' +include 'consumer'