diff --git a/dd-java-agent-ittests/pom.xml b/dd-java-agent-ittests/pom.xml
index ab40e0100a0..bb97ac7da68 100644
--- a/dd-java-agent-ittests/pom.xml
+++ b/dd-java-agent-ittests/pom.xml
@@ -169,6 +169,28 @@
test
+
+
+
+ javax.jms
+ javax.jms-api
+ 2.0.1
+ test
+
+
+ org.apache.activemq.tooling
+ activemq-junit
+ 5.14.5
+ test
+
+
+ org.apache.activemq
+ activemq-broker
+ 5.14.5
+ test
+
+
+
diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/instrument/JMSInstrumentationTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/instrument/JMSInstrumentationTest.java
new file mode 100644
index 00000000000..56e685c0e5b
--- /dev/null
+++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/instrument/JMSInstrumentationTest.java
@@ -0,0 +1,48 @@
+package com.datadoghq.trace.instrument;
+
+import io.opentracing.contrib.jms.TracingMessageProducer;
+import io.opentracing.contrib.jms.common.TracingMessageConsumer;
+import org.apache.activemq.ActiveMQConnectionFactory;
+import org.apache.activemq.command.ActiveMQQueue;
+import org.apache.activemq.junit.EmbeddedActiveMQBroker;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import javax.jms.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JMSInstrumentationTest {
+
+
+ @ClassRule
+ public static EmbeddedActiveMQBroker broker = new EmbeddedActiveMQBroker();
+ private static Session session;
+ private static ActiveMQQueue destination;
+
+ @BeforeClass
+ public static void start() throws JMSException {
+
+ broker.start();
+ ActiveMQConnectionFactory connectionFactory = broker.createConnectionFactory();
+
+ destination = new ActiveMQQueue("someQueue");
+ Connection connection = connectionFactory.createConnection();
+ connection.start();
+ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ }
+
+ @Test
+ public void test() throws Exception {
+
+
+ MessageProducer producer = session.createProducer(destination);
+ MessageConsumer consumer = session.createConsumer(destination);
+
+ assertThat(producer).isInstanceOf(TracingMessageProducer.class);
+ assertThat(consumer).isInstanceOf(TracingMessageConsumer.class);
+ }
+
+}
diff --git a/dd-java-agent/pom.xml b/dd-java-agent/pom.xml
index d8f8236497e..6defb66d7eb 100644
--- a/dd-java-agent/pom.xml
+++ b/dd-java-agent/pom.xml
@@ -27,6 +27,7 @@
0.0.2
0.0.2
0.0.2
+ 0.0.3
1.7
@@ -139,6 +140,25 @@
provided
+
+
+ io.opentracing.contrib
+ opentracing-jms-2
+ ${ot.contrib.jms.version}
+
+
+ javax.jms
+ javax.jms-api
+
+
+
+
+ javax.jms
+ javax.jms-api
+ 2.0.1
+ provided
+
+
io.opentracing.contrib
@@ -216,6 +236,32 @@
+
+
+ io.opentracing
+ opentracing-mock
+ ${opentracing.version}
+ test
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.assertj
+ assertj-core
+ 3.6.2
+ test
+
+
+ org.mockito
+ mockito-core
+ 2.7.22
+ test
+
+
${project.artifactId}
diff --git a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/InstrumentationChecker.java b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/InstrumentationChecker.java
new file mode 100644
index 00000000000..be20cbcad45
--- /dev/null
+++ b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/InstrumentationChecker.java
@@ -0,0 +1,137 @@
+package io.opentracing.contrib.agent;
+
+import com.datadoghq.trace.resolver.FactoryUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * Utility class to check the validity of the classpath concerning the java automated instrumentations
+ */
+public class InstrumentationChecker {
+
+ private static final String CONFIG_FILE = "dd-trace-supported-framework.yaml";
+ private final Map>> rules;
+ private final Map frameworks;
+
+ private static InstrumentationChecker INSTANCE;
+
+ /* For testing purpose */
+ InstrumentationChecker(Map>> rules, Map frameworks) {
+ this.rules = rules;
+ this.frameworks = frameworks;
+ INSTANCE = this;
+ }
+
+ private InstrumentationChecker() {
+ rules = FactoryUtils.loadConfigFromResource(CONFIG_FILE, Map.class);
+ frameworks = scanLoadedLibraries();
+
+ }
+
+ /**
+ * Return a list of unsupported rules regarding loading deps
+ *
+ * @return the list of unsupported rules
+ */
+ public synchronized static List getUnsupportedRules() {
+
+ if (INSTANCE == null) {
+ INSTANCE = new InstrumentationChecker();
+ }
+
+ return INSTANCE.doGetUnsupportedRules();
+ }
+
+ private List doGetUnsupportedRules() {
+
+ List unsupportedRules = new ArrayList<>();
+ for (String rule : rules.keySet()) {
+
+ // Check rules
+ boolean supported = false;
+ for (Map check : rules.get(rule)) {
+ if (frameworks.containsKey(check.get("artifact"))) {
+ boolean matched = Pattern.matches(check.get("supported_version"), frameworks.get(check.get("artifact")));
+ if (!matched) {
+ supported = false;
+ break;
+ }
+ supported = true;
+ }
+ }
+
+ if (!supported) {
+ unsupportedRules.add(rule);
+ }
+ }
+
+ return unsupportedRules;
+
+ }
+
+
+ private static Map scanLoadedLibraries() {
+
+ Map frameworks = new HashMap<>();
+
+ // Scan classpath provided jars
+ List jars = getJarFiles(System.getProperty("java.class.path"));
+ for (File file : jars) {
+
+ String jarName = file.getName();
+ String version = extractJarVersion(jarName);
+
+ if (version != null) {
+
+ // Extract artifactId
+ String artifactId = file.getName().substring(0, jarName.indexOf(version) - 1);
+
+ // Store it
+ frameworks.put(artifactId, version);
+ }
+ }
+
+ return frameworks;
+ }
+
+
+ private static List getJarFiles(String paths) {
+ List filesList = new ArrayList();
+ for (final String path : paths.split(File.pathSeparator)) {
+ final File file = new File(path);
+ if (file.isDirectory()) {
+ recurse(filesList, file);
+ } else {
+ if (file.getName().endsWith(".jar")) {
+ filesList.add(file);
+ }
+ }
+ }
+ return filesList;
+ }
+
+ private static void recurse(List filesList, File f) {
+ File list[] = f.listFiles();
+ for (File file : list) {
+ getJarFiles(file.getPath());
+ }
+ }
+
+ private static String extractJarVersion(String jarName) {
+
+ Pattern versionPattern = Pattern.compile("-(\\d+\\..+)\\.jar");
+ Matcher matcher = versionPattern.matcher(jarName);
+ if (matcher.find()) {
+ return matcher.group(1);
+ } else {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/JarVersionsChecker.java b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/JarVersionsChecker.java
deleted file mode 100644
index 959a0b06ed3..00000000000
--- a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/JarVersionsChecker.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package io.opentracing.contrib.agent;
-
-import com.datadoghq.trace.resolver.FactoryUtils;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-/**
- * Utility class to check the validity of the classpath concerning the java automated instrumentations
- */
-public class JarVersionsChecker {
-
- private static Logger log = Logger.getLogger(JarVersionsChecker.class.getName());
-
- public static String AUTHORIZED_VERSIONS_CONFIG = "dd-trace-authorized-versions.yaml";
-
- /**
- * Retrieves all the jars from the classpath
- */
- private static List getJarsFromClasspath() {
- return JarVersionsChecker.getJarFiles(System.getProperty("java.class.path"));
- }
-
- /**
- * list files in the given directory and subdirs (with recursion)
- *
- * @param paths
- * @return
- */
- public static List getJarFiles(String paths) {
- List filesList = new ArrayList();
- for (final String path : paths.split(File.pathSeparator)) {
- final File file = new File(path);
- if (file.isDirectory()) {
- recurse(filesList, file);
- } else {
- if (file.getName().endsWith(".jar")) {
- filesList.add(file);
- }
- }
- }
- return filesList;
- }
-
- private static void recurse(List filesList, File f) {
- File list[] = f.listFiles();
- for (File file : list) {
- getJarFiles(file.getPath());
- }
- }
-
- public static Pattern versionPattern = Pattern.compile("-(\\d+\\..+)\\.jar");
-
- public static String extractJarVersion(String jarName) {
- Matcher matcher = versionPattern.matcher(jarName);
- if (matcher.find())
- return matcher.group(1);
- else
- return null;
-
- }
-
-
- public static void main(String args[]) throws Exception {
- checkJarVersions();
- }
-
- /**
- * Check all Jar versions in the classpath
- *
- * @return the list of jar keys that have been detected as potential issues
- */
- @SuppressWarnings("unchecked")
- public static List checkJarVersions() {
- List potentialIssues = new ArrayList<>();
-
- //Load instrumentations versions
- Map> versions = FactoryUtils.loadConfigFromResource(AUTHORIZED_VERSIONS_CONFIG, Map.class);
- if (versions == null) {
- log.log(Level.WARNING, "DD agent: Authorized versions configuration file {} not found in classpath. Cannot proceed to the Jar versions check.", AUTHORIZED_VERSIONS_CONFIG);
- return potentialIssues;
- }
-
- //Scan classpath provided jars
- List jars = getJarsFromClasspath();
- for (File file : jars) {
- String jarName = file.getName();
- String versionRestrictions = extractJarVersion(jarName);
-
- if (versionRestrictions != null) {
- //Extract artifactId
- String artifactId = file.getName().substring(0, jarName.indexOf(versionRestrictions) - 1);
- Map restrictions = versions.get(artifactId);
- if (restrictions != null) {
- String versionPattern = restrictions.get("valid_versions");
- if (versionPattern != null) {
- if (!Pattern.matches(versionPattern, versionRestrictions)) {
- String key = restrictions.get("key");
- if (key != null) {
- potentialIssues.add(key);
- }
- log.log(Level.WARNING, "DD agent: The JAR {0} has been found in the classpath. It may create some intrumentation issue, some rules are about to get disabled.", jarName);
- }
- }
- }
- }
- }
- return potentialIssues;
- }
-
-
-}
\ No newline at end of file
diff --git a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/TraceAnnotationsManager.java b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/TraceAnnotationsManager.java
index 9ba98ab60e4..06da8e3ad44 100644
--- a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/TraceAnnotationsManager.java
+++ b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/TraceAnnotationsManager.java
@@ -56,7 +56,7 @@ public static void initialize(Retransformer trans) throws Exception {
List loadedScripts = loadRules(ClassLoader.getSystemClassLoader());
//Check if some rules have to be uninstalled
- List uninstallScripts = new ArrayList<>();
+ List uninstallScripts = InstrumentationChecker.getUnsupportedRules();
if(agentTracerConfig != null){
List disabledInstrumentations = agentTracerConfig.getDisabledInstrumentations();
if(disabledInstrumentations!=null && !disabledInstrumentations.isEmpty()){
diff --git a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/DDAgentTracingHelper.java b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/DDAgentTracingHelper.java
index dd67f43b50d..f888dad53a4 100644
--- a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/DDAgentTracingHelper.java
+++ b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/DDAgentTracingHelper.java
@@ -11,9 +11,9 @@
/**
* This class provides helpfull stuff in order to easy patch object using Byteman rules
*
- * @param The type of the object to patch
+ * @param The type of the object to patch
*/
-public abstract class DDAgentTracingHelper extends OpenTracingHelper {
+public abstract class DDAgentTracingHelper extends OpenTracingHelper {
private static final Logger LOGGER = Logger.getLogger(DDAgentTracingHelper.class.getCanonicalName());
@@ -48,15 +48,22 @@ public abstract class DDAgentTracingHelper extends OpenTracingHelper
* @param args The object to patch, the type is defined by the subclass instantiation
* @return The object patched
*/
- public ObjectType patch(ObjectType args) {
+ public T patch(T args) {
- info("Try to patch " + args.getClass().getName());
- ObjectType patched;
+ if (args == null) {
+ info("Skipping " + rule.getName() + "' rule because the input arg is null");
+ return args;
+ }
+
+ String className = args.getClass().getName();
+ info("Try to patch " + className);
+
+ T patched;
try {
patched = doPatch(args);
- info(args.getClass().getName() + " patched");
+ info(className + " patched");
} catch (Throwable e) {
- warning("Failed to patch" + args.getClass().getName() + ", reason: " + e.getMessage());
+ warning("Failed to patch" + className + ", reason: " + e.getMessage());
logStackTrace(e.getMessage(), e);
patched = args;
}
@@ -70,7 +77,7 @@ public ObjectType patch(ObjectType args) {
* @return the object patched
* @throws Exception The exceptions are managed directly to the patch method
*/
- abstract protected ObjectType doPatch(ObjectType obj) throws Exception;
+ abstract protected T doPatch(T obj) throws Exception;
/**
diff --git a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/JMSMessageConsumerHelper.java b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/JMSMessageConsumerHelper.java
new file mode 100644
index 00000000000..3f674f6c051
--- /dev/null
+++ b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/JMSMessageConsumerHelper.java
@@ -0,0 +1,34 @@
+package io.opentracing.contrib.agent.helper;
+
+import io.opentracing.contrib.jms.common.TracingMessageConsumer;
+import org.jboss.byteman.rule.Rule;
+
+import javax.jms.MessageConsumer;
+
+public class JMSMessageConsumerHelper extends DDAgentTracingHelper {
+
+ public JMSMessageConsumerHelper(Rule rule) {
+ super(rule);
+ }
+
+
+ @Override
+ public MessageConsumer patch(MessageConsumer args) {
+ return super.patch(args);
+ }
+
+ /**
+ * Strategy: Wrapper the instance into a new one.
+ *
+ * @param consumer The JMS instance
+ * @return A new instance with the old one wrapped
+ * @throws Exception
+ */
+ protected MessageConsumer doPatch(MessageConsumer consumer) throws Exception {
+ if (consumer instanceof TracingMessageConsumer) {
+ return consumer;
+ }
+ return new TracingMessageConsumer(consumer, tracer);
+ }
+
+}
\ No newline at end of file
diff --git a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/JMSMessageProducerHelper.java b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/JMSMessageProducerHelper.java
new file mode 100644
index 00000000000..fee56b6bb29
--- /dev/null
+++ b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/JMSMessageProducerHelper.java
@@ -0,0 +1,32 @@
+package io.opentracing.contrib.agent.helper;
+
+import io.opentracing.contrib.jms.TracingMessageProducer;
+import org.jboss.byteman.rule.Rule;
+
+import javax.jms.MessageProducer;
+
+public class JMSMessageProducerHelper extends DDAgentTracingHelper {
+
+ public JMSMessageProducerHelper(Rule rule) {
+ super(rule);
+ }
+
+ @Override
+ public MessageProducer patch(MessageProducer args) {
+ return super.patch(args);
+ }
+
+ /**
+ * Strategy: Wrapper the instance into a new one.
+ *
+ * @param producer The JMS instance
+ * @return A new instance with the old one wrapped
+ * @throws Exception
+ */
+ protected MessageProducer doPatch(MessageProducer producer) throws Exception {
+ if (producer instanceof TracingMessageProducer) {
+ return producer;
+ }
+ return new TracingMessageProducer(producer, tracer);
+ }
+}
\ No newline at end of file
diff --git a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/MongoHelper.java b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/MongoHelper.java
index de1531fe091..4497a8171c1 100644
--- a/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/MongoHelper.java
+++ b/dd-java-agent/src/main/java/io/opentracing/contrib/agent/helper/MongoHelper.java
@@ -28,6 +28,8 @@ protected MongoClientOptions.Builder doPatch(MongoClientOptions.Builder builder)
TracingCommandListener listener = new TracingCommandListener(tracer);
builder.addCommandListener(listener);
+ setState(builder, 1);
+
return builder;
}
diff --git a/dd-java-agent/src/main/resources/dd-trace-supported-framework.yaml b/dd-java-agent/src/main/resources/dd-trace-supported-framework.yaml
new file mode 100644
index 00000000000..170f2b13597
--- /dev/null
+++ b/dd-java-agent/src/main/resources/dd-trace-supported-framework.yaml
@@ -0,0 +1,61 @@
+### This file define all supported libraries
+### Syntax:
+### : # the rule name defined in the otarules.btm
+### - check: # a list of tests, if one not matched, thus the rule is removed
+### articfact: # the artifact name to be tested
+### supported_version: # a regex expression to express the version required by the rule
+### - check: ...
+
+opentracing-apache-httpclient:
+ - check:
+ artifact: httpclient
+ supported_version: 4\.[3|4|5]\..*
+ - check:
+ artifact: commons-httpclient
+ supported_version: none
+
+opentracing-aws-sdk:
+ - check:
+ artifact: aws-java-sdk
+ supported_version: 1\.11\..*
+
+opentracing-elasticsearch-client:
+ - check:
+ artifact: transport
+ supported_version: 5\.4\..*
+
+opentracing-cassandra-driver:
+ - check:
+ artifact: cassandra-driver-core
+ supported_version: 3\.2.*
+
+opentracing-web-servlet-filter:
+ - check:
+ artifact: jetty-server
+ supported_version: (8\.|9\.).*
+ - check:
+ artifact: tomcat_catalina
+ supported_version: (8\.|9\.).*
+ - check:
+ artifact: tomcat-embed-core
+ supported_version: (8\.|9\.).*
+
+opentracing-okhttp3:
+ - check:
+ artifact: okhttp
+ supported_version: 3\..*
+
+# For rules opentracing-jms-2_{consumer,producer}
+opentracing-jms-2:
+ - check:
+ artifact: jms-api
+ supported_version: 2\..*
+
+opentracing-mongo-driver:
+ - check:
+ artifact: mongo-java-driver
+ supported_version: 3\..*
+ - check:
+ artifact: mongodb-driver-async
+ supported_version: 3\..*
+
diff --git a/dd-java-agent/src/main/resources/otarules.btm b/dd-java-agent/src/main/resources/otarules.btm
index 1eae62a3af6..981d83efe61 100644
--- a/dd-java-agent/src/main/resources/otarules.btm
+++ b/dd-java-agent/src/main/resources/otarules.btm
@@ -1,11 +1,21 @@
+### The contributions are injected using this file and byteman
+###
+### Helpers are a DD specific, they are defined in the current project
+### The rule names provided (RULE ) are also used in the configuration.
+### The name is used to remove the script if there is no support of the framework
+###
+### So, ensure that the rule name is correct defined both here and in the dd-trace-supported-framework.yaml
+###
+
+
# Instrument Mongo client
# ========================
-RULE mongo
+RULE opentracing-mongo-driver
CLASS com.mongodb.MongoClientOptions$Builder
METHOD build
HELPER io.opentracing.contrib.agent.helper.MongoHelper
AT ENTRY
-IF TRUE
+IF getState($0) == 0
DO
patch($this);
ENDRULE
@@ -13,7 +23,7 @@ ENDRULE
# Instrument AWS SDK client
# ==========================
-RULE awsclient
+RULE opentracing-aws-sdk
CLASS ^com.amazonaws.client.builder.AwsClientBuilder
METHOD build()
HELPER io.opentracing.contrib.agent.helper.AWSClientHelper
@@ -23,9 +33,10 @@ DO
patch($this);
ENDRULE
+
# Instrument Apache HTTP Client
# =============================
-RULE apache http
+RULE opentracing-apache-httpclient
CLASS org.apache.http.impl.client.HttpClientBuilder
METHOD create()
HELPER io.opentracing.contrib.agent.helper.ApacheHTTPClientHelper
@@ -35,9 +46,10 @@ DO
$! = patch($!);
ENDRULE
+
# Instrument Elasticsearch Transport Client
# ==========================================
-RULE elasticsearch
+RULE opentracing-elasticsearch-client
INTERFACE org.elasticsearch.client.ElasticsearchClient
METHOD execute(org.elasticsearch.action.Action,org.elasticsearch.action.ActionRequest,org.elasticsearch.action.ActionListener)
HELPER io.opentracing.contrib.agent.helper.ElasticsearchHelper
@@ -48,9 +60,10 @@ DO
$3 = patch($3);
ENDRULE
+
# Instrument Cassandra client
# ===========================
-RULE cassandra
+RULE opentracing-cassandra-driver
CLASS com.datastax.driver.core.Cluster$Manager
METHOD newSession()
HELPER io.opentracing.contrib.agent.helper.CassandraHelper
@@ -61,12 +74,11 @@ DO
ENDRULE
-
# Instrument Jetty
# ===========================
# State 0 - no filter installed
# State 1 - filter installed
-RULE jetty
+RULE opentracing-web-servlet-filter_jetty
CLASS org.eclipse.jetty.servlet.ServletContextHandler
METHOD
HELPER io.opentracing.contrib.agent.helper.JettyServletHelper
@@ -79,7 +91,7 @@ ENDRULE
# Instrument Tomcat
# ===========================
-RULE tomcat
+RULE opentracing-web-servlet-filter_tomcat
CLASS org.apache.catalina.core.ApplicationContext
METHOD
HELPER io.opentracing.contrib.agent.helper.TomcatServletHelper
@@ -90,10 +102,9 @@ DO
ENDRULE
-
# Instrument OkHttp
# ===========================
-RULE okhttp
+RULE opentracing-okhttp3
CLASS okhttp3.OkHttpClient$Builder
METHOD build()
HELPER io.opentracing.contrib.agent.helper.OkHttpHelper
@@ -102,3 +113,28 @@ IF TRUE
DO
patch($this)
ENDRULE
+
+
+# Instrument JMS
+# ===========================
+RULE opentracing-jms-2_producer
+INTERFACE javax.jms.Session
+METHOD createProducer
+HELPER io.opentracing.contrib.agent.helper.JMSMessageProducerHelper
+AT EXIT
+IF TRUE
+DO
+ $! = patch($!);
+ENDRULE
+
+
+RULE opentracing-jms-2_consumer
+INTERFACE javax.jms.Session
+METHOD createConsumer
+HELPER io.opentracing.contrib.agent.helper.JMSMessageConsumerHelper
+AT EXIT
+IF TRUE
+DO
+ $! = patch($!);
+ENDRULE
+
diff --git a/dd-java-agent/src/test/java/io/opentracing/contrib/agent/InstrumentationCheckerTest.java b/dd-java-agent/src/test/java/io/opentracing/contrib/agent/InstrumentationCheckerTest.java
new file mode 100644
index 00000000000..1f84e5b8bc1
--- /dev/null
+++ b/dd-java-agent/src/test/java/io/opentracing/contrib/agent/InstrumentationCheckerTest.java
@@ -0,0 +1,40 @@
+package io.opentracing.contrib.agent;
+
+import com.datadoghq.trace.resolver.FactoryUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+
+public class InstrumentationCheckerTest {
+
+
+ @Before
+ public void setup() {
+ Map>> rules = FactoryUtils.loadConfigFromResource("supported-version-test.yaml", Map.class);
+ Map frameworks = new HashMap() {{
+ put("artifact-1", "1.2.3.1232");
+ put("artifact-2", "4.y.z");
+ put("artifact-3", "5.123-1");
+ }};
+
+ new InstrumentationChecker(rules, frameworks);
+ }
+
+
+ @Test
+ public void testRules() throws Exception {
+
+
+ List rules = InstrumentationChecker.getUnsupportedRules();
+ assertThat(rules.size()).isEqualTo(3);
+ assertThat(rules).containsExactlyInAnyOrder("unsupportedRuleOne", "unsupportedRuleTwo", "unsupportedRuleThree");
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/dd-java-agent/src/test/resources/supported-version-test.yaml b/dd-java-agent/src/test/resources/supported-version-test.yaml
new file mode 100644
index 00000000000..d19e82a4153
--- /dev/null
+++ b/dd-java-agent/src/test/resources/supported-version-test.yaml
@@ -0,0 +1,26 @@
+unsupportedRuleOne:
+ - check:
+ artifact: artifact-1
+ supported_version: 1\.2\.3\..*
+ - check:
+ artifact: artifact-2
+ supported_version: none
+unsupportedRuleTwo:
+ - check:
+ artifact: artifact-1
+ supported_version: 2\.3\.
+supportedRuleOne:
+ - check:
+ artifact: artifact-3
+ supported_version: 5\..*
+supportedRuleTwo:
+ - check:
+ artifact: artifact-1
+ supported_version: 1\.2\.3\..*
+ - check:
+ artifact: artifact-2
+ supported_version: 4\..*
+unsupportedRuleThree:
+ - check:
+ artifact: foo
+ supported_version: 1
diff --git a/dd-trace-examples/dropwizard-mongo-client/src/main/resources/dd-trace.yaml b/dd-trace-examples/dropwizard-mongo-client/src/main/resources/dd-trace.yaml
index bc6406af2f0..beb8b2b734f 100644
--- a/dd-trace-examples/dropwizard-mongo-client/src/main/resources/dd-trace.yaml
+++ b/dd-trace-examples/dropwizard-mongo-client/src/main/resources/dd-trace.yaml
@@ -12,7 +12,7 @@ writer:
host: localhost
port: 8126
-# The sampler to use.
+# The sampling to use.
# Could be: AllSampler (default) or RateSampler
sampler:
# AllSampler: all spans are reported to the writer
diff --git a/dd-trace/pom.xml b/dd-trace/pom.xml
index d518f6c784e..38dc586304d 100644
--- a/dd-trace/pom.xml
+++ b/dd-trace/pom.xml
@@ -14,10 +14,6 @@
Datadog core library
https://github.com/datadog/dd-trace-java
-
- 1.6
-
-
diff --git a/dd-trace/src/main/java/com/datadoghq/trace/DDSpanContext.java b/dd-trace/src/main/java/com/datadoghq/trace/DDSpanContext.java
index dbe5307f9a7..dd6bde94f2f 100644
--- a/dd-trace/src/main/java/com/datadoghq/trace/DDSpanContext.java
+++ b/dd-trace/src/main/java/com/datadoghq/trace/DDSpanContext.java
@@ -3,6 +3,7 @@
import com.datadoghq.trace.integration.DDSpanContextDecorator;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.common.collect.Maps;
import io.opentracing.tag.Tags;
import java.util.*;
@@ -21,6 +22,8 @@ public class DDSpanContext implements io.opentracing.SpanContext {
private final long traceId;
private final long spanId;
private final long parentId;
+ private final String threadName = Thread.currentThread().getName();
+ private final long threadId = Thread.currentThread().getId();
private Map baggageItems;
// DD attributes
@@ -126,7 +129,7 @@ public String getResourceName() {
public boolean getErrorFlag() {
return errorFlag;
}
-
+
public void setErrorFlag(boolean errorFlag) {
this.errorFlag = errorFlag;
}
@@ -193,6 +196,11 @@ public synchronized void setTag(String tag, Object value) {
}
public synchronized Map getTags() {
+ if(tags.isEmpty()) {
+ tags = Maps.newHashMapWithExpectedSize(2);
+ }
+ tags.put(DDTags.THREAD_NAME, threadName);
+ tags.put(DDTags.THREAD_ID, threadId);
return Collections.unmodifiableMap(tags);
}
diff --git a/dd-trace/src/main/java/com/datadoghq/trace/DDTags.java b/dd-trace/src/main/java/com/datadoghq/trace/DDTags.java
index 5b49c4dd566..1b8920c4fb7 100644
--- a/dd-trace/src/main/java/com/datadoghq/trace/DDTags.java
+++ b/dd-trace/src/main/java/com/datadoghq/trace/DDTags.java
@@ -4,4 +4,6 @@ public class DDTags {
public static final String SPAN_TYPE = "span-type";
public static final String SERVICE_NAME = "service-name";
public static final String RESOURCE_NAME = "resource-name";
+ public static final String THREAD_NAME = "thread-name";
+ public static final String THREAD_ID = "thread-id";
}
diff --git a/dd-trace/src/main/java/com/datadoghq/trace/propagation/HTTPCodec.java b/dd-trace/src/main/java/com/datadoghq/trace/propagation/HTTPCodec.java
index e440ef9c5be..c3d6e12a2d7 100644
--- a/dd-trace/src/main/java/com/datadoghq/trace/propagation/HTTPCodec.java
+++ b/dd-trace/src/main/java/com/datadoghq/trace/propagation/HTTPCodec.java
@@ -1,7 +1,6 @@
package com.datadoghq.trace.propagation;
import com.datadoghq.trace.DDSpanContext;
-
import io.opentracing.propagation.TextMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,86 +17,86 @@
*/
public class HTTPCodec implements Codec {
- private static final String OT_PREFIX = "ot-tracer-";
- private static final String OT_BAGGAGE_PREFIX = "ot-baggage-";
- private static final String TRACE_ID_KEY = OT_PREFIX + "traceid";
- private static final String SPAN_ID_KEY = OT_PREFIX + "spanid";
-
- private static final Logger logger = LoggerFactory.getLogger(HTTPCodec.class);
-
- @Override
- public void inject(DDSpanContext context, TextMap carrier) {
-
- carrier.put(TRACE_ID_KEY, String.valueOf(context.getTraceId()));
- carrier.put(SPAN_ID_KEY, String.valueOf(context.getSpanId()));
-
- for (Map.Entry entry : context.baggageItems()) {
- carrier.put(OT_BAGGAGE_PREFIX + entry.getKey(), encode(entry.getValue()));
- }
- }
-
- @Override
- public DDSpanContext extract(TextMap carrier) {
-
- Map baggage = Collections.emptyMap();
- Long traceId = 0L;
- Long spanId = 0L;
-
- for (Map.Entry entry : carrier) {
-
- if (entry.getKey().equals(TRACE_ID_KEY)) {
- traceId = Long.parseLong(entry.getValue());
- } else if (entry.getKey().equals(SPAN_ID_KEY)) {
- spanId = Long.parseLong(entry.getValue());
- } else if (entry.getKey().startsWith(OT_BAGGAGE_PREFIX)) {
- if (baggage.isEmpty()) {
- baggage = new HashMap();
- }
- baggage.put(entry.getKey(), decode(entry.getValue()));
- }
- }
- DDSpanContext context = null;
- if (traceId != 0L) {
-
- context = new DDSpanContext(
- traceId,
- spanId,
- 0L,
- null,
- null,
- null,
- baggage,
- false,
- null,
- null,
- null,
- null);
-
- logger.debug("{} - Parent context extracted", context);
- }
-
- return context;
- }
-
-
- private String encode(String value) {
- String encoded = value;
- try {
- encoded = URLEncoder.encode(value, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- logger.info("Failed to encode value - {}", value);
- }
- return encoded;
- }
-
- private String decode(String value) {
- String decoded = value;
- try {
- decoded = URLDecoder.decode(value, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- logger.info("Failed to decode value - {}", value);
- }
- return decoded;
- }
+ private static final String OT_PREFIX = "ot-tracer-";
+ private static final String OT_BAGGAGE_PREFIX = "ot-baggage-";
+ private static final String TRACE_ID_KEY = OT_PREFIX + "traceid";
+ private static final String SPAN_ID_KEY = OT_PREFIX + "spanid";
+
+ private static final Logger logger = LoggerFactory.getLogger(HTTPCodec.class);
+
+ @Override
+ public void inject(DDSpanContext context, TextMap carrier) {
+
+ carrier.put(TRACE_ID_KEY, String.valueOf(context.getTraceId()));
+ carrier.put(SPAN_ID_KEY, String.valueOf(context.getSpanId()));
+
+ for (Map.Entry entry : context.baggageItems()) {
+ carrier.put(OT_BAGGAGE_PREFIX + entry.getKey(), encode(entry.getValue()));
+ }
+ }
+
+ @Override
+ public DDSpanContext extract(TextMap carrier) {
+
+ Map baggage = Collections.emptyMap();
+ Long traceId = 0L;
+ Long spanId = 0L;
+
+ for (Map.Entry entry : carrier) {
+
+ if (entry.getKey().equals(TRACE_ID_KEY)) {
+ traceId = Long.parseLong(entry.getValue());
+ } else if (entry.getKey().equals(SPAN_ID_KEY)) {
+ spanId = Long.parseLong(entry.getValue());
+ } else if (entry.getKey().startsWith(OT_BAGGAGE_PREFIX)) {
+ if (baggage.isEmpty()) {
+ baggage = new HashMap();
+ }
+ baggage.put(entry.getKey().replace(OT_BAGGAGE_PREFIX, ""), decode(entry.getValue()));
+ }
+ }
+ DDSpanContext context = null;
+ if (traceId != 0L) {
+
+ context = new DDSpanContext(
+ traceId,
+ spanId,
+ 0L,
+ null,
+ null,
+ null,
+ baggage,
+ false,
+ null,
+ null,
+ null,
+ null);
+
+ logger.debug("{} - Parent context extracted", context);
+ }
+
+ return context;
+ }
+
+
+ private String encode(String value) {
+ String encoded = value;
+ try {
+ encoded = URLEncoder.encode(value, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ logger.info("Failed to encode value - {}", value);
+ }
+ return encoded;
+ }
+
+ private String decode(String value) {
+ String decoded = value;
+ try {
+ decoded = URLDecoder.decode(value, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ logger.info("Failed to decode value - {}", value);
+ }
+ return decoded;
+ }
}
diff --git a/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDTracerFactory.java b/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDTracerFactory.java
index 59a9ee8fbaa..1680167661f 100644
--- a/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDTracerFactory.java
+++ b/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDTracerFactory.java
@@ -1,7 +1,7 @@
package com.datadoghq.trace.resolver;
import com.datadoghq.trace.DDTracer;
-import com.datadoghq.trace.sampling.ASampler;
+import com.datadoghq.trace.sampling.AbstractSampler;
import com.datadoghq.trace.sampling.AllSampler;
import com.datadoghq.trace.sampling.RateSampler;
import com.datadoghq.trace.sampling.Sampler;
@@ -74,8 +74,8 @@ public static DDTracer create(TracerConfig config) {
//Add sampled tags
Map skipTagsPatterns = config.getSampler().getSkipTagsPatterns();
- if (skipTagsPatterns != null && sampler instanceof ASampler) {
- ASampler aSampler = (ASampler) sampler;
+ if (skipTagsPatterns != null && sampler instanceof AbstractSampler) {
+ AbstractSampler aSampler = (AbstractSampler) sampler;
for (Map.Entry entry : skipTagsPatterns.entrySet()) {
aSampler.addSkipTagPattern(entry.getKey(), Pattern.compile(entry.getValue()));
}
diff --git a/dd-trace/src/main/java/com/datadoghq/trace/sampling/ASampler.java b/dd-trace/src/main/java/com/datadoghq/trace/sampling/AbstractSampler.java
similarity index 94%
rename from dd-trace/src/main/java/com/datadoghq/trace/sampling/ASampler.java
rename to dd-trace/src/main/java/com/datadoghq/trace/sampling/AbstractSampler.java
index 38d00be2b08..442d156521e 100644
--- a/dd-trace/src/main/java/com/datadoghq/trace/sampling/ASampler.java
+++ b/dd-trace/src/main/java/com/datadoghq/trace/sampling/AbstractSampler.java
@@ -1,13 +1,13 @@
package com.datadoghq.trace.sampling;
+import com.datadoghq.trace.DDBaseSpan;
+
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
-import com.datadoghq.trace.DDBaseSpan;
-
-public abstract class ASampler implements Sampler{
+public abstract class AbstractSampler implements Sampler {
/**
* Sample tags
diff --git a/dd-trace/src/main/java/com/datadoghq/trace/sampling/AllSampler.java b/dd-trace/src/main/java/com/datadoghq/trace/sampling/AllSampler.java
index 25bd06e8fe0..ec195d9d784 100644
--- a/dd-trace/src/main/java/com/datadoghq/trace/sampling/AllSampler.java
+++ b/dd-trace/src/main/java/com/datadoghq/trace/sampling/AllSampler.java
@@ -5,7 +5,7 @@
/**
* Sampler that always says yes...
*/
-public class AllSampler extends ASampler {
+public class AllSampler extends AbstractSampler {
@Override
public boolean doSample(DDBaseSpan> span) {
diff --git a/dd-trace/src/main/java/com/datadoghq/trace/sampling/RateSampler.java b/dd-trace/src/main/java/com/datadoghq/trace/sampling/RateSampler.java
index 48b718299ea..dd33797f61e 100644
--- a/dd-trace/src/main/java/com/datadoghq/trace/sampling/RateSampler.java
+++ b/dd-trace/src/main/java/com/datadoghq/trace/sampling/RateSampler.java
@@ -1,11 +1,10 @@
package com.datadoghq.trace.sampling;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.datadoghq.trace.DDBaseSpan;
import com.google.auto.service.AutoService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
@@ -15,7 +14,7 @@
* It samples randomly, its main purpose is to reduce the instrumentation footprint.
*/
@AutoService(Sampler.class)
-public class RateSampler extends ASampler {
+public class RateSampler extends AbstractSampler {
private final static Logger logger = LoggerFactory.getLogger(RateSampler.class);
diff --git a/dd-trace/src/test/java/ExampleWithDDAgentWriter.java b/dd-trace/src/test/java/ExampleWithDDAgentWriter.java
deleted file mode 100644
index 70eeb9e911c..00000000000
--- a/dd-trace/src/test/java/ExampleWithDDAgentWriter.java
+++ /dev/null
@@ -1,54 +0,0 @@
-import com.datadoghq.trace.DDTracer;
-import com.datadoghq.trace.sampling.AllSampler;
-import com.datadoghq.trace.sampling.Sampler;
-import com.datadoghq.trace.writer.DDAgentWriter;
-import com.datadoghq.trace.writer.Writer;
-
-import io.opentracing.Span;
-
-public class ExampleWithDDAgentWriter {
-
- public static void main(String[] args) throws Exception {
-
- // Instantiate the DDWriter
- // By default, traces are written to localhost:8126 (the ddagent)
- Writer writer = new DDAgentWriter();
-
- // Instantiate the proper Sampler
- // - RateSampler if you want to keep `ratio` traces
- // - AllSampler to keep all traces
- Sampler sampler = new AllSampler();
-
-
- // Create the tracer
- DDTracer tracer = new DDTracer(writer, sampler);
-
-
- Span parent = tracer
- .buildSpan("hello-world")
- .withServiceName("service-name")
- .withSpanType("web")
- .start();
-
- Thread.sleep(100);
-
- parent.setBaggageItem("a-baggage", "value");
-
- Span child = tracer
- .buildSpan("hello-world")
- .asChildOf(parent)
- .withResourceName("resource-name")
- .start();
-
- Thread.sleep(100);
-
- child.finish();
-
- Thread.sleep(100);
-
- parent.finish();
-
- writer.close();
-
- }
-}
\ No newline at end of file
diff --git a/dd-trace/src/test/java/com/datadoghq/trace/AllSamplerTest.java b/dd-trace/src/test/java/com/datadoghq/trace/AllSamplerTest.java
deleted file mode 100644
index de9268cc30a..00000000000
--- a/dd-trace/src/test/java/com/datadoghq/trace/AllSamplerTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.datadoghq.trace;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-import org.junit.Test;
-
-import com.datadoghq.trace.sampling.AllSampler;
-
-public class AllSamplerTest {
-
-
- @Test
- public void testAllSampler() {
-
-
-
- AllSampler sampler = new AllSampler();
- sampler.addSkipTagPattern("http.url", Pattern.compile(".*/hello"));
-
- DDSpan mockSpan = mock(DDSpan.class);
- Map tags = new HashMap();
- tags.put("http.url", "http://a/hello");
- when(mockSpan.getTags()).thenReturn(tags).thenReturn(tags);
-
- assertThat(sampler.sample(mockSpan)).isEqualTo(false);
-
- tags.put("http.url", "http://a/hello2");
-
- assertThat(sampler.sample(mockSpan)).isEqualTo(true);
-
- }
-}
\ No newline at end of file
diff --git a/dd-trace/src/test/java/com/datadoghq/trace/DDSpanBuilderTest.java b/dd-trace/src/test/java/com/datadoghq/trace/DDSpanBuilderTest.java
index 642b16aad69..6e6d6dabd84 100644
--- a/dd-trace/src/test/java/com/datadoghq/trace/DDSpanBuilderTest.java
+++ b/dd-trace/src/test/java/com/datadoghq/trace/DDSpanBuilderTest.java
@@ -66,7 +66,7 @@ public void shouldBuildMoreComplexSpan() {
.start();
assertThat(span.getTags()).isNotNull();
- assertThat(span.getTags()).isEmpty();
+ assertThat(span.getTags().size()).isEqualTo(2);
// with all custom fields provided
final String expectedResource = "fakeResource";
@@ -88,7 +88,8 @@ public void shouldBuildMoreComplexSpan() {
assertThat(actualContext.getErrorFlag()).isTrue();
assertThat(actualContext.getServiceName()).isEqualTo(expectedService);
assertThat(actualContext.getSpanType()).isEqualTo(expectedType);
-
+ assertThat(actualContext.getTags().get(DDTags.THREAD_NAME)).isEqualTo(Thread.currentThread().getName());
+ assertThat(actualContext.getTags().get(DDTags.THREAD_ID)).isEqualTo(Thread.currentThread().getId());
}
diff --git a/dd-trace/src/test/java/com/datadoghq/trace/DDSpanSerializationTest.java b/dd-trace/src/test/java/com/datadoghq/trace/DDSpanSerializationTest.java
index ff7cbc5dc0f..cb55e784032 100644
--- a/dd-trace/src/test/java/com/datadoghq/trace/DDSpanSerializationTest.java
+++ b/dd-trace/src/test/java/com/datadoghq/trace/DDSpanSerializationTest.java
@@ -5,6 +5,7 @@
import java.util.HashMap;
import java.util.Map;
+import com.google.common.collect.Maps;
import org.junit.Before;
import org.junit.Test;
@@ -16,15 +17,28 @@ public class DDSpanSerializationTest {
ObjectMapper serializer;
DDSpan span;
DDActiveSpan activeSpan;
+ Map expected = Maps.newHashMap();
@Before
public void setUp() throws Exception {
- Map baggage = new HashMap();
+ Map baggage = new HashMap<>();
baggage.put("a-baggage", "value");
- Map tags = new HashMap();
+ Map tags = new HashMap<>();
baggage.put("k1", "v1");
+ expected.put("meta", baggage);
+ expected.put("service", "service");
+ expected.put("error", 0);
+ expected.put("type", "type");
+ expected.put("name", "operation");
+ expected.put("duration", 33000);
+ expected.put("resource", "operation");
+ expected.put("start", 100000);
+ expected.put("span_id", 2l);
+ expected.put("parent_id", 0l);
+ expected.put("trace_id", 1l);
+
DDSpanContext context = new DDSpanContext(
1L,
@@ -33,13 +47,16 @@ public void setUp() throws Exception {
"service",
"operation",
null,
- baggage,
+ new HashMap(baggage),
false,
"type",
tags,
null,
null);
+ baggage.put("thread-name", Thread.currentThread().getName());
+ baggage.put("thread-id", String.valueOf(Thread.currentThread().getId()));
+
span = new DDSpan(
100L,
context);
@@ -52,22 +69,7 @@ public void setUp() throws Exception {
@Test
public void test() throws Exception {
-
-
- String expected = "{\"meta\":{\"a-baggage\":\"value\",\"k1\":\"v1\"},\"service\":\"service\",\"error\":0,\"type\":\"type\",\"name\":\"operation\",\"duration\":33000,\"resource\":\"operation\",\"start\":100000,\"span_id\":2,\"parent_id\":0,\"trace_id\":1}";
- // FIXME At the moment, just compare the string sizes
- try {
- assertThat(serializer.writeValueAsString(span).length()).isEqualTo(expected.length());
-
- } catch (AssertionError e) {
- assertThat(serializer.writeValueAsString(span)).isEqualTo(expected);
- }
-
-// try {
-// assertThat(serializer.writeValueAsString(activeSpan).length()).isEqualTo(expected.length());
-// } catch (AssertionError e) {
-// assertThat(serializer.writeValueAsString(activeSpan)).isEqualTo(expected);
-// }
+ assertThat(serializer.readTree(serializer.writeValueAsString(span)))
+ .isEqualTo(serializer.readTree(serializer.writeValueAsString(expected)));
}
-
}
diff --git a/dd-trace/src/test/java/com/datadoghq/trace/propagation/HTTPCodecTest.java b/dd-trace/src/test/java/com/datadoghq/trace/propagation/HTTPCodecTest.java
new file mode 100644
index 00000000000..1dd61d3d3e9
--- /dev/null
+++ b/dd-trace/src/test/java/com/datadoghq/trace/propagation/HTTPCodecTest.java
@@ -0,0 +1,84 @@
+package com.datadoghq.trace.propagation;
+
+import com.datadoghq.trace.DDSpanContext;
+import io.opentracing.propagation.TextMapExtractAdapter;
+import io.opentracing.propagation.TextMapInjectAdapter;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+
+/**
+ * Created by gpolaert on 6/23/17.
+ */
+public class HTTPCodecTest {
+
+
+ private static final String OT_PREFIX = "ot-tracer-";
+ private static final String OT_BAGGAGE_PREFIX = "ot-baggage-";
+ private static final String TRACE_ID_KEY = OT_PREFIX + "traceid";
+ private static final String SPAN_ID_KEY = OT_PREFIX + "spanid";
+
+
+ @Test
+ public void shoudAddHttpHeaders() {
+
+ DDSpanContext mockedContext = new DDSpanContext(
+ 1L,
+ 2L,
+ 0L,
+ "fakeService",
+ "fakeOperation",
+ "fakeResource",
+ new HashMap() {{
+ put("k1", "v1");
+ put("k2", "v2");
+ }},
+ false,
+ "fakeType",
+ null,
+ null,
+ null);
+
+ Map carrier = new HashMap<>();
+
+ HTTPCodec codec = new HTTPCodec();
+ codec.inject(mockedContext, new TextMapInjectAdapter(carrier));
+
+
+ assertThat(carrier.get(TRACE_ID_KEY)).isEqualTo("1");
+ assertThat(carrier.get(SPAN_ID_KEY)).isEqualTo("2");
+ assertThat(carrier.get(OT_BAGGAGE_PREFIX + "k1")).isEqualTo("v1");
+ assertThat(carrier.get(OT_BAGGAGE_PREFIX + "k2")).isEqualTo("v2");
+
+
+ }
+
+
+ @Test
+ public void shoudReadHttpHeaders() {
+
+
+ Map actual = new HashMap() {{
+ put(TRACE_ID_KEY, "1");
+ put(SPAN_ID_KEY, "2");
+ put(OT_BAGGAGE_PREFIX + "k1", "v1");
+ put(OT_BAGGAGE_PREFIX + "k2", "v2");
+ }};
+
+
+ HTTPCodec codec = new HTTPCodec();
+ DDSpanContext context = codec.extract(new TextMapExtractAdapter(actual));
+
+ assertThat(context.getTraceId()).isEqualTo(1l);
+ assertThat(context.getSpanId()).isEqualTo(2l);
+ assertThat(context.getBaggageItem("k1")).isEqualTo("v1");
+ assertThat(context.getBaggageItem("k2")).isEqualTo("v2");
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/dd-trace/src/test/java/com/datadoghq/trace/sampling/AllSamplerTest.java b/dd-trace/src/test/java/com/datadoghq/trace/sampling/AllSamplerTest.java
new file mode 100644
index 00000000000..e0a6d7bed50
--- /dev/null
+++ b/dd-trace/src/test/java/com/datadoghq/trace/sampling/AllSamplerTest.java
@@ -0,0 +1,47 @@
+package com.datadoghq.trace.sampling;
+
+import com.datadoghq.trace.DDSpan;
+import org.junit.Test;
+import org.mockito.Mock;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class AllSamplerTest {
+
+ @Mock
+ DDSpan mockSpan;
+
+ private final AllSampler sampler = new AllSampler();
+
+
+ @Test
+ public void testAllSampler() {
+
+ for (int i = 0; i < 500; i++) {
+ assertThat(sampler.doSample(mockSpan)).isTrue();
+ }
+ }
+
+ @Test
+ public void testSkipTagPatternSampler() {
+
+ Map tags = new HashMap<>();
+ mockSpan = mock(DDSpan.class);
+ when(mockSpan.getTags()).thenReturn(tags).thenReturn(tags);
+
+ sampler.addSkipTagPattern("http.url", Pattern.compile(".*/hello"));
+
+ tags.put("http.url", "http://a/hello");
+ assertThat(sampler.sample(mockSpan)).isFalse();
+
+ tags.put("http.url", "http://a/hello2");
+ assertThat(sampler.sample(mockSpan)).isTrue();
+
+ }
+}
\ No newline at end of file
diff --git a/dd-trace/src/test/java/com/datadoghq/trace/sampling/ExampleWithDDAgentWriter.java b/dd-trace/src/test/java/com/datadoghq/trace/sampling/ExampleWithDDAgentWriter.java
new file mode 100644
index 00000000000..b98ceb7c65d
--- /dev/null
+++ b/dd-trace/src/test/java/com/datadoghq/trace/sampling/ExampleWithDDAgentWriter.java
@@ -0,0 +1,53 @@
+package com.datadoghq.trace.sampling;
+
+import com.datadoghq.trace.DDTracer;
+import com.datadoghq.trace.writer.DDAgentWriter;
+import com.datadoghq.trace.writer.Writer;
+import io.opentracing.Span;
+
+public class ExampleWithDDAgentWriter {
+
+ public static void main(String[] args) throws Exception {
+
+ // Instantiate the DDWriter
+ // By default, traces are written to localhost:8126 (the ddagent)
+ Writer writer = new DDAgentWriter();
+
+ // Instantiate the proper Sampler
+ // - RateSampler if you want to keep `ratio` traces
+ // - AllSampler to keep all traces
+ Sampler sampler = new AllSampler();
+
+
+ // Create the tracer
+ DDTracer tracer = new DDTracer(writer, sampler);
+
+
+ Span parent = tracer
+ .buildSpan("hello-world")
+ .withServiceName("service-name")
+ .withSpanType("web")
+ .start();
+
+ Thread.sleep(100);
+
+ parent.setBaggageItem("a-baggage", "value");
+
+ Span child = tracer
+ .buildSpan("hello-world")
+ .asChildOf(parent)
+ .withResourceName("resource-name")
+ .start();
+
+ Thread.sleep(100);
+
+ child.finish();
+
+ Thread.sleep(100);
+
+ parent.finish();
+
+ writer.close();
+
+ }
+}
\ No newline at end of file