diff --git a/build.gradle b/build.gradle index f49372ea6fe..d4e8c529d83 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,8 @@ subprojects { task packageSources(type: Jar) { classifier = 'sources' - from sourceSets.main.allSource\ + from sourceSets.main.allSource \ + } artifacts.archives packageSources repositories { diff --git a/dd-java-agent-ittests/pom.xml b/dd-java-agent-ittests/pom.xml index 80da6e78f4a..a178dcb3a9d 100644 --- a/dd-java-agent-ittests/pom.xml +++ b/dd-java-agent-ittests/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/SayTracedHello.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/SayTracedHello.java index b79b99f6b48..2cdd6950847 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/SayTracedHello.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/SayTracedHello.java @@ -7,23 +7,23 @@ public class SayTracedHello { - @Trace(operationName="SAY_HELLO") - public static String sayHello(){ - new StringTag(DDTags.SERVICE_NAME).set(GlobalTracer.get().activeSpan(), "test"); - return "hello!"; - } - - @Trace(operationName="SAY_HA") - public static String sayHA(){ - new StringTag(DDTags.SERVICE_NAME).set(GlobalTracer.get().activeSpan(), "test"); - new StringTag(DDTags.SPAN_TYPE).set(GlobalTracer.get().activeSpan(), "DB"); - return "HA!!"; - } - - @Trace(operationName="NEW_TRACE") - public static String sayHELLOsayHA(){ - new StringTag(DDTags.SERVICE_NAME).set(GlobalTracer.get().activeSpan(), "test2"); - return sayHello()+sayHA(); - } - + @Trace(operationName = "SAY_HELLO") + public static String sayHello() { + new StringTag(DDTags.SERVICE_NAME).set(GlobalTracer.get().activeSpan(), "test"); + return "hello!"; + } + + @Trace(operationName = "SAY_HA") + public static String sayHA() { + new StringTag(DDTags.SERVICE_NAME).set(GlobalTracer.get().activeSpan(), "test"); + new StringTag(DDTags.SPAN_TYPE).set(GlobalTracer.get().activeSpan(), "DB"); + return "HA!!"; + } + + @Trace(operationName = "NEW_TRACE") + public static String sayHELLOsayHA() { + new StringTag(DDTags.SERVICE_NAME).set(GlobalTracer.get().activeSpan(), "test2"); + return sayHello() + sayHA(); + } + } diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/TraceAnnotationsManagerTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/TraceAnnotationsManagerTest.java index 8073cabc43e..156b3a3f232 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/TraceAnnotationsManagerTest.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/TraceAnnotationsManagerTest.java @@ -2,48 +2,47 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.datadoghq.trace.agent.integration.AAgentIntegration; import org.junit.Before; import org.junit.Test; -import com.datadoghq.trace.agent.integration.AAgentIntegration; +public class TraceAnnotationsManagerTest extends AAgentIntegration { + + @Before + public void beforeTest() throws Exception { + super.beforeTest(); + } + + @Test + public void testAnnotations() { + //Test single span in new trace + SayTracedHello.sayHello(); + + assertThat(writer.firstTrace().size()).isEqualTo(1); + assertThat(writer.firstTrace().get(0).getOperationName()).isEqualTo("SAY_HELLO"); + assertThat(writer.firstTrace().get(0).getServiceName()).isEqualTo("test"); + + writer.start(); + + //Test new trace with 2 children spans + SayTracedHello.sayHELLOsayHA(); + assertThat(writer.firstTrace().size()).isEqualTo(3); + long parentId = writer.firstTrace().get(0).context().getTraceId(); + + assertThat(writer.firstTrace().get(0).getOperationName()).isEqualTo("NEW_TRACE"); + assertThat(writer.firstTrace().get(0).getParentId()).isEqualTo(0);//ROOT / no parent + assertThat(writer.firstTrace().get(0).context().getParentId()).isEqualTo(0); + assertThat(writer.firstTrace().get(0).getServiceName()).isEqualTo("test2"); + + assertThat(writer.firstTrace().get(1).getOperationName()).isEqualTo("SAY_HELLO"); + assertThat(writer.firstTrace().get(1).getServiceName()).isEqualTo("test"); + assertThat(writer.firstTrace().get(1).getParentId()).isEqualTo(parentId); + + assertThat(writer.firstTrace().get(2).getOperationName()).isEqualTo("SAY_HA"); + assertThat(writer.firstTrace().get(2).getParentId()).isEqualTo(parentId); + assertThat(writer.firstTrace().get(2).context().getSpanType()).isEqualTo("DB"); -public class TraceAnnotationsManagerTest extends AAgentIntegration{ - - @Before - public void beforeTest() throws Exception { - super.beforeTest(); - } - - @Test - public void testAnnotations() { - //Test single span in new trace - SayTracedHello.sayHello(); - - assertThat(writer.firstTrace().size()).isEqualTo(1); - assertThat(writer.firstTrace().get(0).getOperationName()).isEqualTo("SAY_HELLO"); - assertThat(writer.firstTrace().get(0).getServiceName()).isEqualTo("test"); - - writer.start(); - - //Test new trace with 2 children spans - SayTracedHello.sayHELLOsayHA(); - assertThat(writer.firstTrace().size()).isEqualTo(3); - long parentId = writer.firstTrace().get(0).context().getTraceId(); - - assertThat(writer.firstTrace().get(0).getOperationName()).isEqualTo("NEW_TRACE"); - assertThat(writer.firstTrace().get(0).getParentId()).isEqualTo(0);//ROOT / no parent - assertThat(writer.firstTrace().get(0).context().getParentId()).isEqualTo(0); - assertThat(writer.firstTrace().get(0).getServiceName()).isEqualTo("test2"); - - assertThat(writer.firstTrace().get(1).getOperationName()).isEqualTo("SAY_HELLO"); - assertThat(writer.firstTrace().get(1).getServiceName()).isEqualTo("test"); - assertThat(writer.firstTrace().get(1).getParentId()).isEqualTo(parentId); - - assertThat(writer.firstTrace().get(2).getOperationName()).isEqualTo("SAY_HA"); - assertThat(writer.firstTrace().get(2).getParentId()).isEqualTo(parentId); - assertThat(writer.firstTrace().get(2).context().getSpanType()).isEqualTo("DB"); - - writer.start(); - } + writer.start(); + } } \ No newline at end of file diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/AAgentIntegration.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/AAgentIntegration.java index bef110b9310..8beac968d45 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/AAgentIntegration.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/AAgentIntegration.java @@ -1,25 +1,23 @@ package com.datadoghq.trace.agent.integration; -import org.junit.Before; - import com.datadoghq.trace.DDTracer; import com.datadoghq.trace.writer.ListWriter; - import io.opentracing.util.GlobalTracer; +import org.junit.Before; public class AAgentIntegration { - protected static ListWriter writer = new ListWriter(); - protected static DDTracer tracer = new DDTracer(writer); + protected static ListWriter writer = new ListWriter(); + protected static DDTracer tracer = new DDTracer(writer); + + @Before + public void beforeTest() throws Exception { + try { + GlobalTracer.register(tracer); + } catch (Exception e) { + //DO NOTHING IF ALREADY REGISTERED + } + writer.start(); + } - @Before - public void beforeTest() throws Exception { - try{ - GlobalTracer.register(tracer); - }catch(Exception e){ - //DO NOTHING IF ALREADY REGISTERED - } - writer.start(); - } - } diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/AWSInstrumentationTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/AWSInstrumentationTest.java index f134a2eb22c..fbe1b916b32 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/AWSInstrumentationTest.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/AWSInstrumentationTest.java @@ -1,25 +1,25 @@ package com.datadoghq.trace.agent.integration; +import static org.assertj.core.api.Assertions.assertThat; + import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import io.opentracing.contrib.aws.TracingRequestHandler; import org.junit.Test; -import static org.assertj.core.api.Assertions.assertThat; - public class AWSInstrumentationTest { - @Test - public void test() { + @Test + public void test() { - // Build AWS client with TracingRequestHandler e.g. - AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard(); - builder.withRegion(Regions.US_EAST_1); - builder.build(); + // Build AWS client with TracingRequestHandler e.g. + AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard(); + builder.withRegion(Regions.US_EAST_1); + builder.build(); - assertThat(builder.getRequestHandlers()).isNotNull(); - assertThat(builder.getRequestHandlers().size()).isEqualTo(1); - assertThat(builder.getRequestHandlers().get(0).getClass()).isEqualTo(TracingRequestHandler.class); - } + assertThat(builder.getRequestHandlers()).isNotNull(); + assertThat(builder.getRequestHandlers().size()).isEqualTo(1); + assertThat(builder.getRequestHandlers().get(0).getClass()).isEqualTo(TracingRequestHandler.class); + } } diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/ApacheHTTPClientTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/ApacheHTTPClientTest.java index bc9a6d8b002..07a3e07474e 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/ApacheHTTPClientTest.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/ApacheHTTPClientTest.java @@ -1,18 +1,18 @@ package com.datadoghq.trace.agent.integration; +import static org.assertj.core.api.Assertions.assertThat; + import io.opentracing.contrib.apache.http.client.TracingHttpClientBuilder; import org.apache.http.impl.client.HttpClientBuilder; import org.junit.Test; -import static org.assertj.core.api.Assertions.assertThat; - public class ApacheHTTPClientTest extends AAgentIntegration { - @Test - public void test() throws Exception { + @Test + public void test() throws Exception { - HttpClientBuilder builder = HttpClientBuilder.create(); - assertThat(builder).isInstanceOf(TracingHttpClientBuilder.class); + HttpClientBuilder builder = HttpClientBuilder.create(); + assertThat(builder).isInstanceOf(TracingHttpClientBuilder.class); // HttpClient client = builder.build(); // HttpGet request = new HttpGet("http://apache.org"); @@ -33,6 +33,6 @@ public void test() throws Exception { // } // assertThat(writer.firstTrace().size()).isEqualTo(2); - } + } } diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/CassandraIntegrationTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/CassandraIntegrationTest.java index 6c9e5787a32..d0086241ea0 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/CassandraIntegrationTest.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/CassandraIntegrationTest.java @@ -1,7 +1,11 @@ package com.datadoghq.trace.agent.integration; +import static org.assertj.core.api.Assertions.assertThat; + import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Session; +import java.io.IOException; +import java.util.concurrent.ExecutionException; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.thrift.transport.TTransportException; import org.cassandraunit.utils.EmbeddedCassandraServerHelper; @@ -9,43 +13,38 @@ import org.junit.Before; import org.junit.Test; -import java.io.IOException; -import java.util.concurrent.ExecutionException; - -import static org.assertj.core.api.Assertions.assertThat; - /** * Created by gpolaert on 6/2/17. */ public class CassandraIntegrationTest { - @Before - public void start() throws InterruptedException, TTransportException, ConfigurationException, IOException { - EmbeddedCassandraServerHelper.startEmbeddedCassandra(20000L); - } + @Before + public void start() throws InterruptedException, TTransportException, ConfigurationException, IOException { + EmbeddedCassandraServerHelper.startEmbeddedCassandra(20000L); + } - @After - public void stop() { - EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); - } + @After + public void stop() { + EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); + } - @Test - public void testNewSessionSync() throws ClassNotFoundException { - Cluster cluster = EmbeddedCassandraServerHelper.getCluster(); - Session session = cluster.newSession(); - assertThat(session).isInstanceOf(Class.forName("io.opentracing.contrib.cassandra.TracingSession")); + @Test + public void testNewSessionSync() throws ClassNotFoundException { + Cluster cluster = EmbeddedCassandraServerHelper.getCluster(); + Session session = cluster.newSession(); + assertThat(session).isInstanceOf(Class.forName("io.opentracing.contrib.cassandra.TracingSession")); - } + } - @Test - public void testNewSessionAsync() throws ClassNotFoundException, ExecutionException, InterruptedException { - Cluster cluster = EmbeddedCassandraServerHelper.getCluster(); - Session session = cluster.connectAsync().get(); - assertThat(session).isInstanceOf(Class.forName("io.opentracing.contrib.cassandra.TracingSession")); + @Test + public void testNewSessionAsync() throws ClassNotFoundException, ExecutionException, InterruptedException { + Cluster cluster = EmbeddedCassandraServerHelper.getCluster(); + Session session = cluster.connectAsync().get(); + assertThat(session).isInstanceOf(Class.forName("io.opentracing.contrib.cassandra.TracingSession")); - } + } } diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/JMSInstrumentationTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/JMSInstrumentationTest.java index a094dbe2edb..bec923167be 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/JMSInstrumentationTest.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/JMSInstrumentationTest.java @@ -1,7 +1,14 @@ package com.datadoghq.trace.agent.integration; +import static org.assertj.core.api.Assertions.assertThat; + import io.opentracing.contrib.jms.TracingMessageProducer; import io.opentracing.contrib.jms.common.TracingMessageConsumer; +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import org.apache.activemq.junit.EmbeddedActiveMQBroker; @@ -9,40 +16,35 @@ 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 { + @ClassRule + public static EmbeddedActiveMQBroker broker = new EmbeddedActiveMQBroker(); + private static Session session; + private static ActiveMQQueue destination; - broker.start(); - ActiveMQConnectionFactory connectionFactory = broker.createConnectionFactory(); + @BeforeClass + public static void start() throws JMSException { - destination = new ActiveMQQueue("someQueue"); - Connection connection = connectionFactory.createConnection(); - connection.start(); - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + 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 { + } + @Test + public void test() throws Exception { - MessageProducer producer = session.createProducer(destination); - MessageConsumer consumer = session.createConsumer(destination); + MessageProducer producer = session.createProducer(destination); + MessageConsumer consumer = session.createConsumer(destination); - assertThat(producer).isInstanceOf(TracingMessageProducer.class); - assertThat(consumer).isInstanceOf(TracingMessageConsumer.class); - } + assertThat(producer).isInstanceOf(TracingMessageProducer.class); + assertThat(consumer).isInstanceOf(TracingMessageConsumer.class); + } } diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/JettyServletInstrumentationTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/JettyServletInstrumentationTest.java index 61f639b4d61..fd73b6e481f 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/JettyServletInstrumentationTest.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/JettyServletInstrumentationTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; - import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.junit.After; @@ -15,29 +14,29 @@ */ public class JettyServletInstrumentationTest { - private Server jettyServer; - private ServletContextHandler servletContext; - - @Before - public void beforeTest() throws Exception { - servletContext = new ServletContextHandler(); - servletContext.setContextPath("/"); - // servletContext.addServlet(TestServlet.class, "/hello"); - - jettyServer = new Server(0); - jettyServer.setHandler(servletContext); - jettyServer.start(); - } - - @Test - public void testIsTracingFilterPresent() throws IOException { - assertThat( servletContext.getServletContext().getFilterRegistration("tracingFilter")).isNotNull(); - } - - @After - public void afterTest() throws Exception { - jettyServer.stop(); - jettyServer.join(); - } + private Server jettyServer; + private ServletContextHandler servletContext; + + @Before + public void beforeTest() throws Exception { + servletContext = new ServletContextHandler(); + servletContext.setContextPath("/"); + // servletContext.addServlet(TestServlet.class, "/hello"); + + jettyServer = new Server(0); + jettyServer.setHandler(servletContext); + jettyServer.start(); + } + + @Test + public void testIsTracingFilterPresent() throws IOException { + assertThat(servletContext.getServletContext().getFilterRegistration("tracingFilter")).isNotNull(); + } + + @After + public void afterTest() throws Exception { + jettyServer.stop(); + jettyServer.join(); + } } diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/MongoClientInstrumentationTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/MongoClientInstrumentationTest.java index aeabff751e7..981ce0914f2 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/MongoClientInstrumentationTest.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/MongoClientInstrumentationTest.java @@ -2,22 +2,20 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; - import com.mongodb.MongoClient; - import io.opentracing.contrib.mongo.TracingCommandListener; +import org.junit.Test; public class MongoClientInstrumentationTest { - - @Test - public void test() { - MongoClient mongoClient = new MongoClient(); - - assertThat(mongoClient.getMongoClientOptions().getCommandListeners().size()).isEqualTo(1); - assertThat(mongoClient.getMongoClientOptions().getCommandListeners().get(0).getClass()).isEqualTo(TracingCommandListener.class); - - mongoClient.close(); - } + + @Test + public void test() { + MongoClient mongoClient = new MongoClient(); + + assertThat(mongoClient.getMongoClientOptions().getCommandListeners().size()).isEqualTo(1); + assertThat(mongoClient.getMongoClientOptions().getCommandListeners().get(0).getClass()).isEqualTo(TracingCommandListener.class); + + mongoClient.close(); + } } diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/OkHTTPInstrumentationTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/OkHTTPInstrumentationTest.java index 8afd2fc1803..2331ebb1c14 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/OkHTTPInstrumentationTest.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/OkHTTPInstrumentationTest.java @@ -2,19 +2,18 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; - import io.opentracing.contrib.okhttp3.TracingInterceptor; import okhttp3.OkHttpClient; +import org.junit.Test; public class OkHTTPInstrumentationTest { - @Test - public void test() { - OkHttpClient client = new OkHttpClient().newBuilder().build(); - - assertThat(client.interceptors().size()).isEqualTo(1); - assertThat(client.interceptors().get(0).getClass()).isEqualTo(TracingInterceptor.class); - } + @Test + public void test() { + OkHttpClient client = new OkHttpClient().newBuilder().build(); + + assertThat(client.interceptors().size()).isEqualTo(1); + assertThat(client.interceptors().get(0).getClass()).isEqualTo(TracingInterceptor.class); + } } diff --git a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/TomcatServletInstrumentationTest.java b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/TomcatServletInstrumentationTest.java index 99e6b01b04c..de7e2360663 100644 --- a/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/TomcatServletInstrumentationTest.java +++ b/dd-java-agent-ittests/src/test/java/com/datadoghq/trace/agent/integration/TomcatServletInstrumentationTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.File; - import org.apache.catalina.Context; import org.apache.catalina.startup.Tomcat; import org.junit.After; @@ -12,39 +11,39 @@ public class TomcatServletInstrumentationTest { - private int serverPort = 9786; + private int serverPort = 9786; - protected Tomcat tomcatServer; - Context appContext; + protected Tomcat tomcatServer; + Context appContext; - @Before - public void beforeTest() throws Exception { - tomcatServer = new Tomcat(); - tomcatServer.setPort(serverPort); + @Before + public void beforeTest() throws Exception { + tomcatServer = new Tomcat(); + tomcatServer.setPort(serverPort); - File baseDir = new File("tomcat"); - tomcatServer.setBaseDir(baseDir.getAbsolutePath()); + File baseDir = new File("tomcat"); + tomcatServer.setBaseDir(baseDir.getAbsolutePath()); - File applicationDir = new File(baseDir + "/webapps", "/ROOT"); - if (!applicationDir.exists()) { - applicationDir.mkdirs(); - } - appContext = tomcatServer.addWebapp("", applicationDir.getAbsolutePath()); - // Tomcat.addServlet(appContext, "helloWorldServlet", new TestServlet()); - // appContext.addServletMappingDecoded("/hello", "helloWorldServlet"); + File applicationDir = new File(baseDir + "/webapps", "/ROOT"); + if (!applicationDir.exists()) { + applicationDir.mkdirs(); + } + appContext = tomcatServer.addWebapp("", applicationDir.getAbsolutePath()); + // Tomcat.addServlet(appContext, "helloWorldServlet", new TestServlet()); + // appContext.addServletMappingDecoded("/hello", "helloWorldServlet"); - tomcatServer.start(); - System.out.println("Tomcat server: http://" + tomcatServer.getHost().getName() + ":" + serverPort + "/"); - } + tomcatServer.start(); + System.out.println("Tomcat server: http://" + tomcatServer.getHost().getName() + ":" + serverPort + "/"); + } - @Test - public void test() { - assertThat( appContext.getServletContext().getFilterRegistration("tracingFilter")).isNotNull(); - } + @Test + public void test() { + assertThat(appContext.getServletContext().getFilterRegistration("tracingFilter")).isNotNull(); + } - @After - public void afterTest() throws Exception { - tomcatServer.stop(); - } + @After + public void afterTest() throws Exception { + tomcatServer.stop(); + } } diff --git a/dd-java-agent-ittests/src/test/resources/log4j2.properties b/dd-java-agent-ittests/src/test/resources/log4j2.properties index 4e65a2c244b..3f0daaafe8e 100644 --- a/dd-java-agent-ittests/src/test/resources/log4j2.properties +++ b/dd-java-agent-ittests/src/test/resources/log4j2.properties @@ -1,7 +1,5 @@ - -appender.console.type = Console -appender.console.name = console -appender.console.layout.type = PatternLayout - -rootLogger.level = debug -rootLogger.appenderRef.console.ref = console \ No newline at end of file +appender.console.type=Console +appender.console.name=console +appender.console.layout.type=PatternLayout +rootLogger.level=debug +rootLogger.appenderRef.console.ref=console \ No newline at end of file diff --git a/dd-java-agent/pom.xml b/dd-java-agent/pom.xml index 085b04136f4..d7f7ef2bb9e 100644 --- a/dd-java-agent/pom.xml +++ b/dd-java-agent/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/AgentTracerConfig.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/AgentTracerConfig.java index 4d25368a992..be59f9ee5c1 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/AgentTracerConfig.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/AgentTracerConfig.java @@ -1,7 +1,6 @@ package com.datadoghq.trace.agent; import com.datadoghq.trace.resolver.TracerConfig; - import java.util.ArrayList; import java.util.List; @@ -9,25 +8,25 @@ * Configuration POJO for the agent */ public class AgentTracerConfig extends TracerConfig { - - private List disabledInstrumentations = new ArrayList(); - - private String[] enableCustomAnnotationTracingOver = {}; - - public String[] getEnableCustomAnnotationTracingOver() { - return enableCustomAnnotationTracingOver; - } - - public void setEnableCustomAnnotationTracingOver(String[] enableCustomAnnotationTracingOver) { - this.enableCustomAnnotationTracingOver = enableCustomAnnotationTracingOver; - } - - public List getDisabledInstrumentations() { - return disabledInstrumentations; - } - - public void setDisabledInstrumentations(List uninstallContributions) { - this.disabledInstrumentations = uninstallContributions; - } + + private List disabledInstrumentations = new ArrayList(); + + private String[] enableCustomAnnotationTracingOver = {}; + + public String[] getEnableCustomAnnotationTracingOver() { + return enableCustomAnnotationTracingOver; + } + + public void setEnableCustomAnnotationTracingOver(String[] enableCustomAnnotationTracingOver) { + this.enableCustomAnnotationTracingOver = enableCustomAnnotationTracingOver; + } + + public List getDisabledInstrumentations() { + return disabledInstrumentations; + } + + public void setDisabledInstrumentations(List uninstallContributions) { + this.disabledInstrumentations = uninstallContributions; + } } diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/AnnotationsTracingAgent.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/AnnotationsTracingAgent.java index 30def10f4a7..74a5f370ec8 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/AnnotationsTracingAgent.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/AnnotationsTracingAgent.java @@ -17,7 +17,6 @@ package com.datadoghq.trace.agent; import io.opentracing.contrib.agent.OpenTracingAgent; - import java.lang.instrument.Instrumentation; /** diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/InstrumentationChecker.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/InstrumentationChecker.java index d22536ea176..0ff1a6d19ff 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/InstrumentationChecker.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/InstrumentationChecker.java @@ -1,7 +1,6 @@ package com.datadoghq.trace.agent; import com.datadoghq.trace.resolver.FactoryUtils; - import java.io.File; import java.util.ArrayList; import java.util.HashMap; @@ -16,122 +15,122 @@ */ public class InstrumentationChecker { - private static final String CONFIG_FILE = "dd-trace-supported-framework.yaml"; - private final Map>> rules; - private final Map frameworks; + private static final String CONFIG_FILE = "dd-trace-supported-framework.yaml"; + private final Map>> rules; + private final Map frameworks; - private static InstrumentationChecker INSTANCE; + private static InstrumentationChecker INSTANCE; - /* For testing purpose */ - InstrumentationChecker(Map>> rules, Map frameworks) { - this.rules = rules; - this.frameworks = frameworks; - INSTANCE = this; - } + /* 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; - } - } + 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/com/datadoghq/trace/agent/TraceAnnotationsManager.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/TraceAnnotationsManager.java index a5631e383a7..8794ed7f53f 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/TraceAnnotationsManager.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/TraceAnnotationsManager.java @@ -3,19 +3,6 @@ import com.datadoghq.trace.Trace; import com.datadoghq.trace.resolver.DDTracerFactory; import com.datadoghq.trace.resolver.FactoryUtils; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.CtMethod; -import javassist.bytecode.Descriptor; -import org.jboss.byteman.agent.Location; -import org.jboss.byteman.agent.LocationType; -import org.jboss.byteman.agent.Retransformer; -import org.jboss.byteman.agent.RuleScript; -import org.reflections.Reflections; -import org.reflections.scanners.MethodAnnotationsScanner; -import org.reflections.util.ConfigurationBuilder; -import org.reflections.util.FilterBuilder; - import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; @@ -24,243 +11,261 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.bytecode.Descriptor; +import org.jboss.byteman.agent.Location; +import org.jboss.byteman.agent.LocationType; +import org.jboss.byteman.agent.Retransformer; +import org.jboss.byteman.agent.RuleScript; +import org.reflections.Reflections; +import org.reflections.scanners.MethodAnnotationsScanner; +import org.reflections.util.ConfigurationBuilder; +import org.reflections.util.FilterBuilder; /** * This manager is loaded at pre-main. - * + * * It loads all the scripts contained in all the 'oatrules.btm' resource files then instrument all the methods annoted with the @Trace. */ public class TraceAnnotationsManager { - private static Logger log = Logger.getLogger(TraceAnnotationsManager.class.getName()); - - private static Retransformer transformer; - - private static final String AGENT_RULES = "otarules.btm"; - - /** - * This method initializes the manager. - * - * @param trans The ByteMan retransformer - * @throws Exception - */ - public static void initialize(Retransformer trans) throws Exception { - transformer = trans; - //Load configuration - AgentTracerConfig agentTracerConfig = FactoryUtils.loadConfigFromFilePropertyOrResource(DDTracerFactory.SYSTEM_PROPERTY_CONFIG_PATH,DDTracerFactory.CONFIG_PATH, AgentTracerConfig.class); - - List loadedScripts = loadRules(ClassLoader.getSystemClassLoader()); - - //Check if some rules have to be uninstalled - List uninstallScripts = InstrumentationChecker.getUnsupportedRules(); - if(agentTracerConfig != null){ - List disabledInstrumentations = agentTracerConfig.getDisabledInstrumentations(); - if(disabledInstrumentations!=null && !disabledInstrumentations.isEmpty()){ - uninstallScripts.addAll(disabledInstrumentations); - } - } - uninstallScripts(loadedScripts,uninstallScripts); - - //Check if annotations are enabled - if(agentTracerConfig != null - && agentTracerConfig.getEnableCustomAnnotationTracingOver()!=null - && agentTracerConfig.getEnableCustomAnnotationTracingOver().length>0){ - loadAnnotationsRules(agentTracerConfig.getEnableCustomAnnotationTracingOver()); - } - } - - /** - * Uninstall some scripts from a list of patterns. - * All the rules that contain the pattern will be uninstalled - * - * @param installedScripts - * @param patterns not case sensitive (eg. "mongo", "apache http", "elasticsearch", etc...]) - */ - public static void uninstallScripts(List installedScripts, List patterns) throws Exception{ - Set rulesToRemove = new HashSet(); - - for(String strPattern : patterns){ - Pattern pattern = Pattern.compile("(?i)RULE [^\n]*"+strPattern+"[^\n]*\n"); - for(String loadedScript : installedScripts){ - Matcher matcher = pattern.matcher(loadedScript); - while(matcher.find()){ - rulesToRemove.add(matcher.group()); - } - } - } - - if(!rulesToRemove.isEmpty()){ - StringWriter sw = new StringWriter(); - try(PrintWriter pr = new PrintWriter(sw)){ - transformer.removeScripts(new ArrayList(rulesToRemove), pr); - } - log.log(Level.INFO, sw.toString()); - } - } - - /** - * This method loads any OpenTracing Agent rules (otarules.btm) found as resources - * within the supplied classloader. - * - * @param classLoader The classloader - */ - public static List loadRules(ClassLoader classLoader) { - List scripts = new ArrayList<>(); - if (transformer == null) { - log.severe("Attempt to load OpenTracing agent rules before transformer initialized"); - return scripts; - } - - List scriptNames = new ArrayList<>(); - - // Load default and custom rules - try { - Enumeration iter = classLoader.getResources(AGENT_RULES); - while (iter.hasMoreElements()) { - loadRules(iter.nextElement().toURI(), scriptNames, scripts); - } - - StringWriter sw=new StringWriter(); - try (PrintWriter writer = new PrintWriter(sw)) { - try { - transformer.installScript(scripts, scriptNames, writer); - } catch (Exception e) { - log.log(Level.SEVERE, "Failed to install scripts", e); - } - } - if (log.isLoggable(Level.FINEST)) { - log.finest(sw.toString()); - } - } catch (IOException | URISyntaxException e) { - log.log(Level.SEVERE, "Failed to load OpenTracing agent rules", e); - } - - if (log.isLoggable(Level.FINE)) { - log.fine("OpenTracing Agent rules loaded"); - } - return scripts; - } - - /** - * Find all the methods annoted with @Trace and inject rules - * @param scannedPackages - */ - public static void loadAnnotationsRules(String... scannedPackages) { - - log.info("Looking for annotations over the following packages: "+Arrays.asList(scannedPackages)); - long cur = System.currentTimeMillis(); - - Reflections reflections = new Reflections(new ConfigurationBuilder() - .forPackages(scannedPackages) - .filterInputsBy(new FilterBuilder().includePackage(scannedPackages).include(".*\\.class")) - .setScanners(new MethodAnnotationsScanner())); - - Set methods = reflections.getMethodsAnnotatedWith(Trace.class); - - StringBuilder generatedScripts = new StringBuilder(); - for(Method method : methods){ - try{ - ClassPool pool = ClassPool.getDefault(); - CtClass cc = pool.get(method.getDeclaringClass().getCanonicalName()); - CtMethod javassistMethod = cc.getDeclaredMethod(method.getName()); - - //AT ENTRY: child of current case - String ruleText = - CURRENT_SPAN_EXISTS+ - buildSpan(javassistMethod)+ - START; - RuleScript script = createRuleScript("Start Active Span ",cc, javassistMethod, Location.create(LocationType.ENTRY,""),ruleText); - generatedScripts.append(script).append("\n"); - - //AT EXIT - script = createRuleScript("Close span ",cc, javassistMethod, Location.create(LocationType.EXIT,""),EXIT_RULE); - generatedScripts.append(script).append("\n"); - - }catch(Exception e){ - log.log(Level.SEVERE,"Could not create rule for method "+method+". Proceed to next annoted method.",e); - } - } - try { - StringWriter sw = new StringWriter(); - try(PrintWriter pr = new PrintWriter(sw)){ - transformer.installScript(Arrays.asList(generatedScripts.toString()),Arrays.asList("@Trace annotations"),pr); - } - log.log(Level.FINE, sw.toString()); - } catch (Exception e) { - log.log(Level.SEVERE,"Could not install annotation scripts.",e); - } - - log.info("Finished annotation scanning in " + (System.currentTimeMillis() - cur) +" ms. You can accelerate this process by refining the packages you want to scan with `scannedPackages` in the dd-trace.yaml configuration file."); - } - - private static RuleScript createRuleScript( - String ruleNamePrefix, - CtClass cc, - CtMethod javassistMethod, - Location loc, - String ruleText) { - int lineNumber = javassistMethod.getMethodInfo().getLineNumber(0); - String[] imports = new String[0]; - - - RuleScript ruleScript = new RuleScript( - ruleNamePrefix+loc+" "+javassistMethod.getLongName(), - cc.getName(), - false, - false, - javassistMethod.getName() + Descriptor.toString(javassistMethod.getSignature()), - "io.opentracing.contrib.agent.OpenTracingHelper", - imports, - loc, - ruleText, - lineNumber, - "", - false); - return ruleScript; - } - - private static void loadRules(URI uri, final List scriptNames, - final List scripts) throws IOException { - if (log.isLoggable(Level.FINE)) { - log.fine("Load rules from URI = " + uri); - } - - StringBuilder str=new StringBuilder(); - try (InputStream is = uri.toURL().openStream()) { - byte[] b = new byte[10240]; - int len; - while ((len = is.read(b)) != -1) { - str.append(new String(b, 0, len)); - } - } - scripts.add(str.toString()); - scriptNames.add(uri.toString()); - } - - private static String CURRENT_SPAN_EXISTS = "IF TRUE\n"; - - private static String BUILD_SPAN = "DO\n"+"getTracer().buildSpan(\""; - private static String CLOSE_PARENTHESIS = "\")"; - - private static String START = ".startActive();"; - - private static String EXIT_RULE = "IF getTracer().activeSpan() != null\n"+ - "DO\n"+ - "getTracer().activeSpan().deactivate();\n"; - - private static String buildSpan(CtMethod javassistMethod){ - try { - Trace trace = (Trace) javassistMethod.getAnnotation(Trace.class); - if(trace.operationName()!=null & !trace.operationName().isEmpty()){ - return BUILD_SPAN+trace.operationName()+CLOSE_PARENTHESIS; - } - } catch (Exception e) { - log.log(Level.WARNING, "Error when building injection rule on method " + javassistMethod + ". Fallback on default value.", e); - } - return BUILD_SPAN+javassistMethod.getName()+CLOSE_PARENTHESIS; - } + + private static Logger log = Logger.getLogger(TraceAnnotationsManager.class.getName()); + + private static Retransformer transformer; + + private static final String AGENT_RULES = "otarules.btm"; + + /** + * This method initializes the manager. + * + * @param trans The ByteMan retransformer + */ + public static void initialize(Retransformer trans) throws Exception { + transformer = trans; + //Load configuration + AgentTracerConfig agentTracerConfig = FactoryUtils + .loadConfigFromFilePropertyOrResource(DDTracerFactory.SYSTEM_PROPERTY_CONFIG_PATH, DDTracerFactory.CONFIG_PATH, + AgentTracerConfig.class); + + List loadedScripts = loadRules(ClassLoader.getSystemClassLoader()); + + //Check if some rules have to be uninstalled + List uninstallScripts = InstrumentationChecker.getUnsupportedRules(); + if (agentTracerConfig != null) { + List disabledInstrumentations = agentTracerConfig.getDisabledInstrumentations(); + if (disabledInstrumentations != null && !disabledInstrumentations.isEmpty()) { + uninstallScripts.addAll(disabledInstrumentations); + } + } + uninstallScripts(loadedScripts, uninstallScripts); + + //Check if annotations are enabled + if (agentTracerConfig != null + && agentTracerConfig.getEnableCustomAnnotationTracingOver() != null + && agentTracerConfig.getEnableCustomAnnotationTracingOver().length > 0) { + loadAnnotationsRules(agentTracerConfig.getEnableCustomAnnotationTracingOver()); + } + } + + /** + * Uninstall some scripts from a list of patterns. + * All the rules that contain the pattern will be uninstalled + * + * @param patterns not case sensitive (eg. "mongo", "apache http", "elasticsearch", etc...]) + */ + public static void uninstallScripts(List installedScripts, List patterns) throws Exception { + Set rulesToRemove = new HashSet(); + + for (String strPattern : patterns) { + Pattern pattern = Pattern.compile("(?i)RULE [^\n]*" + strPattern + "[^\n]*\n"); + for (String loadedScript : installedScripts) { + Matcher matcher = pattern.matcher(loadedScript); + while (matcher.find()) { + rulesToRemove.add(matcher.group()); + } + } + } + + if (!rulesToRemove.isEmpty()) { + StringWriter sw = new StringWriter(); + try (PrintWriter pr = new PrintWriter(sw)) { + transformer.removeScripts(new ArrayList(rulesToRemove), pr); + } + log.log(Level.INFO, sw.toString()); + } + } + + /** + * This method loads any OpenTracing Agent rules (otarules.btm) found as resources + * within the supplied classloader. + * + * @param classLoader The classloader + */ + public static List loadRules(ClassLoader classLoader) { + List scripts = new ArrayList<>(); + if (transformer == null) { + log.severe("Attempt to load OpenTracing agent rules before transformer initialized"); + return scripts; + } + + List scriptNames = new ArrayList<>(); + + // Load default and custom rules + try { + Enumeration iter = classLoader.getResources(AGENT_RULES); + while (iter.hasMoreElements()) { + loadRules(iter.nextElement().toURI(), scriptNames, scripts); + } + + StringWriter sw = new StringWriter(); + try (PrintWriter writer = new PrintWriter(sw)) { + try { + transformer.installScript(scripts, scriptNames, writer); + } catch (Exception e) { + log.log(Level.SEVERE, "Failed to install scripts", e); + } + } + if (log.isLoggable(Level.FINEST)) { + log.finest(sw.toString()); + } + } catch (IOException | URISyntaxException e) { + log.log(Level.SEVERE, "Failed to load OpenTracing agent rules", e); + } + + if (log.isLoggable(Level.FINE)) { + log.fine("OpenTracing Agent rules loaded"); + } + return scripts; + } + + /** + * Find all the methods annoted with @Trace and inject rules + */ + public static void loadAnnotationsRules(String... scannedPackages) { + + log.info("Looking for annotations over the following packages: " + Arrays.asList(scannedPackages)); + long cur = System.currentTimeMillis(); + + Reflections reflections = new Reflections(new ConfigurationBuilder() + .forPackages(scannedPackages) + .filterInputsBy(new FilterBuilder().includePackage(scannedPackages).include(".*\\.class")) + .setScanners(new MethodAnnotationsScanner())); + + Set methods = reflections.getMethodsAnnotatedWith(Trace.class); + + StringBuilder generatedScripts = new StringBuilder(); + for (Method method : methods) { + try { + ClassPool pool = ClassPool.getDefault(); + CtClass cc = pool.get(method.getDeclaringClass().getCanonicalName()); + CtMethod javassistMethod = cc.getDeclaredMethod(method.getName()); + + //AT ENTRY: child of current case + String ruleText = + CURRENT_SPAN_EXISTS + + buildSpan(javassistMethod) + + START; + RuleScript script = createRuleScript("Start Active Span ", cc, javassistMethod, Location.create(LocationType.ENTRY, ""), + ruleText); + generatedScripts.append(script).append("\n"); + + //AT EXIT + script = createRuleScript("Close span ", cc, javassistMethod, Location.create(LocationType.EXIT, ""), EXIT_RULE); + generatedScripts.append(script).append("\n"); + + } catch (Exception e) { + log.log(Level.SEVERE, "Could not create rule for method " + method + ". Proceed to next annoted method.", e); + } + } + try { + StringWriter sw = new StringWriter(); + try (PrintWriter pr = new PrintWriter(sw)) { + transformer.installScript(Arrays.asList(generatedScripts.toString()), Arrays.asList("@Trace annotations"), pr); + } + log.log(Level.FINE, sw.toString()); + } catch (Exception e) { + log.log(Level.SEVERE, "Could not install annotation scripts.", e); + } + + log.info("Finished annotation scanning in " + (System.currentTimeMillis() - cur) + + " ms. You can accelerate this process by refining the packages you want to scan with `scannedPackages` in the dd-trace.yaml configuration file."); + } + + private static RuleScript createRuleScript( + String ruleNamePrefix, + CtClass cc, + CtMethod javassistMethod, + Location loc, + String ruleText) { + int lineNumber = javassistMethod.getMethodInfo().getLineNumber(0); + String[] imports = new String[0]; + + RuleScript ruleScript = new RuleScript( + ruleNamePrefix + loc + " " + javassistMethod.getLongName(), + cc.getName(), + false, + false, + javassistMethod.getName() + Descriptor.toString(javassistMethod.getSignature()), + "io.opentracing.contrib.agent.OpenTracingHelper", + imports, + loc, + ruleText, + lineNumber, + "", + false); + return ruleScript; + } + + private static void loadRules(URI uri, final List scriptNames, + final List scripts) throws IOException { + if (log.isLoggable(Level.FINE)) { + log.fine("Load rules from URI = " + uri); + } + + StringBuilder str = new StringBuilder(); + try (InputStream is = uri.toURL().openStream()) { + byte[] b = new byte[10240]; + int len; + while ((len = is.read(b)) != -1) { + str.append(new String(b, 0, len)); + } + } + scripts.add(str.toString()); + scriptNames.add(uri.toString()); + } + + private static String CURRENT_SPAN_EXISTS = "IF TRUE\n"; + + private static String BUILD_SPAN = "DO\n" + "getTracer().buildSpan(\""; + private static String CLOSE_PARENTHESIS = "\")"; + + private static String START = ".startActive();"; + + private static String EXIT_RULE = "IF getTracer().activeSpan() != null\n" + + "DO\n" + + "getTracer().activeSpan().deactivate();\n"; + + private static String buildSpan(CtMethod javassistMethod) { + try { + Trace trace = (Trace) javassistMethod.getAnnotation(Trace.class); + if (trace.operationName() != null & !trace.operationName().isEmpty()) { + return BUILD_SPAN + trace.operationName() + CLOSE_PARENTHESIS; + } + } catch (Exception e) { + log.log(Level.WARNING, "Error when building injection rule on method " + javassistMethod + ". Fallback on default value.", e); + } + return BUILD_SPAN + javassistMethod.getName() + CLOSE_PARENTHESIS; + } } diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/AWSClientHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/AWSClientHelper.java index 5dea5574ed6..61830f0df30 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/AWSClientHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/AWSClientHelper.java @@ -3,11 +3,10 @@ import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.handlers.RequestHandler2; import io.opentracing.contrib.aws.TracingRequestHandler; -import org.jboss.byteman.rule.Rule; - import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; +import org.jboss.byteman.rule.Rule; /** * Patch the AWS Client during the building steps. @@ -16,36 +15,35 @@ public class AWSClientHelper extends DDAgentTracingHelper { - public AWSClientHelper(Rule rule) { - super(rule); - } - - /** - * Strategy: we add a tracing handler to the client when it has just been built. We intercept the return value of - * the com.amazonaws.client.builder.AwsClientBuilder.build() method and add the handler. - * - * @param client The fresh AWS client instance - * @return The same instance, but patched - * @throws Exception - */ - protected AwsClientBuilder doPatch(AwsClientBuilder client) throws Exception { - - RequestHandler2 handler = new TracingRequestHandler(tracer); - - Field field = AwsClientBuilder.class.getDeclaredField("requestHandlers"); - field.setAccessible(true); - List handlers = (List) field.get(client); - - if (handlers == null || handlers.isEmpty()) { - handlers = Arrays.asList(handler); - } else { - // Check if we already added the handler - if (!(handlers.get(0) instanceof TracingRequestHandler)) { - handlers.add(0, handler); - } - } - client.setRequestHandlers((RequestHandler2[]) handlers.toArray()); - return client; - } + public AWSClientHelper(Rule rule) { + super(rule); + } + + /** + * Strategy: we add a tracing handler to the client when it has just been built. We intercept the return value of + * the com.amazonaws.client.builder.AwsClientBuilder.build() method and add the handler. + * + * @param client The fresh AWS client instance + * @return The same instance, but patched + */ + protected AwsClientBuilder doPatch(AwsClientBuilder client) throws Exception { + + RequestHandler2 handler = new TracingRequestHandler(tracer); + + Field field = AwsClientBuilder.class.getDeclaredField("requestHandlers"); + field.setAccessible(true); + List handlers = (List) field.get(client); + + if (handlers == null || handlers.isEmpty()) { + handlers = Arrays.asList(handler); + } else { + // Check if we already added the handler + if (!(handlers.get(0) instanceof TracingRequestHandler)) { + handlers.add(0, handler); + } + } + client.setRequestHandlers((RequestHandler2[]) handlers.toArray()); + return client; + } } \ No newline at end of file diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/ApacheHTTPClientHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/ApacheHTTPClientHelper.java index b680a04551d..5ff93a062c3 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/ApacheHTTPClientHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/ApacheHTTPClientHelper.java @@ -9,27 +9,26 @@ */ public class ApacheHTTPClientHelper extends DDAgentTracingHelper { - public ApacheHTTPClientHelper(Rule rule) { - super(rule); - } - - - @Override - public HttpClientBuilder patch(HttpClientBuilder builder) { - return super.patch(builder); - } - - - /** - * Strategy: We replace the legacy builder by a new instance providing by the opentracing contribution when - * the builder is instantiate. @see org.apache.http.impl.client.HttpClientBuilder.create() method - * - * @param builder The legacy builder instance - * @return A tracing builder instance (new reference) - * @throws Exception - */ - protected HttpClientBuilder doPatch(HttpClientBuilder builder) throws Exception { - return new TracingHttpClientBuilder(); - } + public ApacheHTTPClientHelper(Rule rule) { + super(rule); + } + + + @Override + public HttpClientBuilder patch(HttpClientBuilder builder) { + return super.patch(builder); + } + + + /** + * Strategy: We replace the legacy builder by a new instance providing by the opentracing contribution when + * the builder is instantiate. @see org.apache.http.impl.client.HttpClientBuilder.create() method + * + * @param builder The legacy builder instance + * @return A tracing builder instance (new reference) + */ + protected HttpClientBuilder doPatch(HttpClientBuilder builder) throws Exception { + return new TracingHttpClientBuilder(); + } } \ No newline at end of file diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/CassandraHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/CassandraHelper.java index b6cbec787f8..a1c4a6455da 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/CassandraHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/CassandraHelper.java @@ -2,9 +2,8 @@ import com.datastax.driver.core.Session; import io.opentracing.Tracer; -import org.jboss.byteman.rule.Rule; - import java.lang.reflect.Constructor; +import org.jboss.byteman.rule.Rule; /** * Patch each new sessions created when trying to connect to a Cassandra cluster. @@ -12,39 +11,37 @@ public class CassandraHelper extends DDAgentTracingHelper { - protected CassandraHelper(Rule rule) { - super(rule); - } - - @Override - public Session patch(Session session) { - return super.patch(session); - } + protected CassandraHelper(Rule rule) { + super(rule); + } + @Override + public Session patch(Session session) { + return super.patch(session); + } - /** - * Strategy: each time we build a connection to a Cassandra cluster, the com.datastax.driver.core.Cluster$Manager.newSession() - * method is called. The opentracing contribution is a simple wrapper, so we just have to wrap the new session. - * - * @param session The fresh session to patch - * @return A new tracing session - * @throws Exception - */ - protected Session doPatch(Session session) throws Exception { + /** + * Strategy: each time we build a connection to a Cassandra cluster, the com.datastax.driver.core.Cluster$Manager.newSession() + * method is called. The opentracing contribution is a simple wrapper, so we just have to wrap the new session. + * + * @param session The fresh session to patch + * @return A new tracing session + */ + protected Session doPatch(Session session) throws Exception { - if ("io.opentracing.contrib.cassandra.TracingSession".equals(session.getClass().getCanonicalName())) { - return session; - } + if ("io.opentracing.contrib.cassandra.TracingSession".equals(session.getClass().getCanonicalName())) { + return session; + } - Class clazz = Class.forName("io.opentracing.contrib.cassandra.TracingSession"); - Constructor constructor = clazz.getDeclaredConstructor(Session.class, Tracer.class); - constructor.setAccessible(true); - Session newSession = (Session) constructor.newInstance(session, tracer); + Class clazz = Class.forName("io.opentracing.contrib.cassandra.TracingSession"); + Constructor constructor = clazz.getDeclaredConstructor(Session.class, Tracer.class); + constructor.setAccessible(true); + Session newSession = (Session) constructor.newInstance(session, tracer); - return newSession; + return newSession; - } + } } \ No newline at end of file diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/DDAgentTracingHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/DDAgentTracingHelper.java index 5e50adf2644..bbf5bf454ba 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/DDAgentTracingHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/DDAgentTracingHelper.java @@ -3,10 +3,9 @@ import io.opentracing.NoopTracerFactory; import io.opentracing.Tracer; import io.opentracing.contrib.agent.OpenTracingHelper; -import org.jboss.byteman.rule.Rule; - import java.util.logging.Level; import java.util.logging.Logger; +import org.jboss.byteman.rule.Rule; /** * This class provides helpfull stuff in order to easy patch object using Byteman rules @@ -15,101 +14,101 @@ */ public abstract class DDAgentTracingHelper extends OpenTracingHelper { - private static final Logger LOGGER = Logger.getLogger(DDAgentTracingHelper.class.getCanonicalName()); - - /** - * The current instance of the tracer. If something goes wrong during the resolution, - * we provides a NoopTracer. - */ - protected final Tracer tracer; - - DDAgentTracingHelper(Rule rule) { - super(rule); - Tracer tracerResolved; - try { - tracerResolved = getTracer(); - tracerResolved = tracerResolved == null ? NoopTracerFactory.create() : tracerResolved; - } catch (Exception e) { - tracerResolved = NoopTracerFactory.create(); - warning("Failed to retrieve the tracer, using a NoopTracer instead: " + e.getMessage()); - logStackTrace(e.getMessage(), e); - } - tracer = tracerResolved; - } - - - /** - * This method takes an object and applies some mutation in order to add tracing capabilities. - * This method should never return any Exception in order to not stop the app traced. - *

- * This method should be defined as final, but something Byteman need to define this one with the explicit - * type (i.e. without using generic), so this is why we don't use final here. - * - * @param args The object to patch, the type is defined by the subclass instantiation - * @return The object patched - */ - public T patch(T args) { - - 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(className + " patched"); - } catch (Throwable e) { - warning("Failed to patch" + className + ", reason: " + e.getMessage()); - logStackTrace(e.getMessage(), e); - patched = args; - } - return patched; - } - - /** - * The current implementation of the patch - * - * @param obj the object to patch - * @return the object patched - * @throws Exception The exceptions are managed directly to the patch method - */ - abstract protected T doPatch(T obj) throws Exception; - - - /** - * Simple wrapper to emit a warning - * - * @param message the message to log as a warning - */ - protected void warning(String message) { - log(Level.WARNING, message); - } - - /** - * Simple wrapper to emit an info - * - * @param message the message to log as an info - */ - protected void info(String message) { - log(Level.INFO, message); - } - - /** - * Simple wrapper to emit the corresponding stacktrace. To not warn the user, we log the stack as a debug info. - * By default, the stack traces are noit shown in the log. - * - * @param message the stacktrace to log as a debug - */ - protected void logStackTrace(String message, Throwable th) { - LOGGER.log(Level.FINE, message, th); - } - - private void log(Level level, String message) { - LOGGER.log(level, String.format("%s - %s", getClass().getSimpleName(), message)); - } + private static final Logger LOGGER = Logger.getLogger(DDAgentTracingHelper.class.getCanonicalName()); + + /** + * The current instance of the tracer. If something goes wrong during the resolution, + * we provides a NoopTracer. + */ + protected final Tracer tracer; + + DDAgentTracingHelper(Rule rule) { + super(rule); + Tracer tracerResolved; + try { + tracerResolved = getTracer(); + tracerResolved = tracerResolved == null ? NoopTracerFactory.create() : tracerResolved; + } catch (Exception e) { + tracerResolved = NoopTracerFactory.create(); + warning("Failed to retrieve the tracer, using a NoopTracer instead: " + e.getMessage()); + logStackTrace(e.getMessage(), e); + } + tracer = tracerResolved; + } + + + /** + * This method takes an object and applies some mutation in order to add tracing capabilities. + * This method should never return any Exception in order to not stop the app traced. + *

+ * This method should be defined as final, but something Byteman need to define this one with the explicit + * type (i.e. without using generic), so this is why we don't use final here. + * + * @param args The object to patch, the type is defined by the subclass instantiation + * @return The object patched + */ + public T patch(T args) { + + 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(className + " patched"); + } catch (Throwable e) { + warning("Failed to patch" + className + ", reason: " + e.getMessage()); + logStackTrace(e.getMessage(), e); + patched = args; + } + return patched; + } + + /** + * The current implementation of the patch + * + * @param obj the object to patch + * @return the object patched + * @throws Exception The exceptions are managed directly to the patch method + */ + abstract protected T doPatch(T obj) throws Exception; + + + /** + * Simple wrapper to emit a warning + * + * @param message the message to log as a warning + */ + protected void warning(String message) { + log(Level.WARNING, message); + } + + /** + * Simple wrapper to emit an info + * + * @param message the message to log as an info + */ + protected void info(String message) { + log(Level.INFO, message); + } + + /** + * Simple wrapper to emit the corresponding stacktrace. To not warn the user, we log the stack as a debug info. + * By default, the stack traces are noit shown in the log. + * + * @param message the stacktrace to log as a debug + */ + protected void logStackTrace(String message, Throwable th) { + LOGGER.log(Level.FINE, message, th); + } + + private void log(Level level, String message) { + LOGGER.log(level, String.format("%s - %s", getClass().getSimpleName(), message)); + } } diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/ElasticsearchHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/ElasticsearchHelper.java index 158a3f0ce30..113edaf3bf8 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/ElasticsearchHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/ElasticsearchHelper.java @@ -5,11 +5,10 @@ import io.opentracing.Tracer; import io.opentracing.contrib.elasticsearch.TracingResponseListener; import io.opentracing.tag.Tags; +import java.lang.reflect.Method; import org.elasticsearch.action.ActionListener; import org.jboss.byteman.rule.Rule; -import java.lang.reflect.Method; - /** * Instrument all Elasticsearch queries. * We have not found a way to inject the opentracing contribution, so this integration is the integration. @@ -17,56 +16,56 @@ */ public class ElasticsearchHelper extends DDAgentTracingHelper { - public ElasticsearchHelper(Rule rule) { - super(rule); - } + public ElasticsearchHelper(Rule rule) { + super(rule); + } - private Object request; + private Object request; - /** - * This method is used to register/save some object that will be used for the integration. - * Currently, we need to keep a reference of the request called - * - * @param request The request used for the query - */ - public void registerArgs(Object request) { - this.request = request; - } + /** + * This method is used to register/save some object that will be used for the integration. + * Currently, we need to keep a reference of the request called + * + * @param request The request used for the query + */ + public void registerArgs(Object request) { + this.request = request; + } - @Override - public ActionListener patch(ActionListener listener) { - return super.patch(listener); - } + @Override + public ActionListener patch(ActionListener listener) { + return super.patch(listener); + } - /** - * Strategy: When a query is executed, if start the integration and a new Span. - * We override the default FutureAction by using the one provided in the opentracing contribution. - * - * @param listener default listener - * @return The tracing listener, the default listener is wrapped in this one. - * @throws Exception - */ - protected ActionListener doPatch(ActionListener listener) throws Exception { + /** + * Strategy: When a query is executed, if start the integration and a new Span. + * We override the default FutureAction by using the one provided in the opentracing contribution. + * + * @param listener default listener + * @return The tracing listener, the default listener is wrapped in this one. + */ + protected ActionListener doPatch(ActionListener listener) throws Exception { - if (listener instanceof TracingResponseListener) { - return listener; - } + if (listener instanceof TracingResponseListener) { + return listener; + } - Tracer.SpanBuilder spanBuilder = tracer.buildSpan(request.getClass().getSimpleName()).ignoreActiveSpan().withTag(Tags.SPAN_KIND.getKey(), "client"); - ActiveSpan parentSpan = tracer.activeSpan(); - if (parentSpan != null) { - spanBuilder.asChildOf(parentSpan.context()); - } + Tracer.SpanBuilder spanBuilder = tracer.buildSpan(request.getClass().getSimpleName()).ignoreActiveSpan() + .withTag(Tags.SPAN_KIND.getKey(), "client"); + ActiveSpan parentSpan = tracer.activeSpan(); + if (parentSpan != null) { + spanBuilder.asChildOf(parentSpan.context()); + } - Span span = spanBuilder.startManual(); + Span span = spanBuilder.startManual(); - Class clazz = Class.forName("io.opentracing.contrib.elasticsearch.SpanDecorator"); - Method method = clazz.getDeclaredMethod("onRequest", Span.class); - method.setAccessible(true); - method.invoke(null, span); + Class clazz = Class.forName("io.opentracing.contrib.elasticsearch.SpanDecorator"); + Method method = clazz.getDeclaredMethod("onRequest", Span.class); + method.setAccessible(true); + method.invoke(null, span); - ActionListener newListener = new TracingResponseListener(listener, span); - return newListener; + ActionListener newListener = new TracingResponseListener(listener, span); + return newListener; - } + } } \ No newline at end of file diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JMSMessageConsumerHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JMSMessageConsumerHelper.java index 3ab120b3bdb..489b71e3029 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JMSMessageConsumerHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JMSMessageConsumerHelper.java @@ -1,34 +1,32 @@ package com.datadoghq.trace.agent.integration; import io.opentracing.contrib.jms.common.TracingMessageConsumer; -import org.jboss.byteman.rule.Rule; - import javax.jms.MessageConsumer; +import org.jboss.byteman.rule.Rule; 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); - } + 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 + */ + 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/com/datadoghq/trace/agent/integration/JMSMessageProducerHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JMSMessageProducerHelper.java index 5eba7fd22fe..902d5ccfa0f 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JMSMessageProducerHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JMSMessageProducerHelper.java @@ -1,32 +1,30 @@ package com.datadoghq.trace.agent.integration; import io.opentracing.contrib.jms.TracingMessageProducer; -import org.jboss.byteman.rule.Rule; - import javax.jms.MessageProducer; +import org.jboss.byteman.rule.Rule; public class JMSMessageProducerHelper extends DDAgentTracingHelper { - public JMSMessageProducerHelper(Rule rule) { - super(rule); - } + public JMSMessageProducerHelper(Rule rule) { + super(rule); + } - @Override - public MessageProducer patch(MessageProducer args) { - return super.patch(args); - } + @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); - } + /** + * Strategy: Wrapper the instance into a new one. + * + * @param producer The JMS instance + * @return A new instance with the old one wrapped + */ + 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/com/datadoghq/trace/agent/integration/JettyServletHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JettyServletHelper.java index 4f4b2dd2200..1bd1a35affc 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JettyServletHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/JettyServletHelper.java @@ -1,40 +1,38 @@ package com.datadoghq.trace.agent.integration; import io.opentracing.contrib.web.servlet.filter.TracingFilter; +import java.util.EnumSet; +import javax.servlet.Filter; import org.eclipse.jetty.servlet.ServletContextHandler; import org.jboss.byteman.rule.Rule; -import javax.servlet.Filter; -import java.util.EnumSet; - /** * Patch the Jetty Servlet during the init steps */ public class JettyServletHelper extends DDAgentTracingHelper { - public JettyServletHelper(Rule rule) { - super(rule); - } - - /** - * Strategy: Use the contextHandler provided to add a new Tracing filter - * - * @param contextHandler The current contextHandler - * @return The same current contextHandler but patched - * @throws Exception - */ - protected ServletContextHandler doPatch(ServletContextHandler contextHandler) throws Exception { - - String[] patterns = {"/*"}; - - Filter filter = new TracingFilter(tracer); - contextHandler - .getServletContext() - .addFilter("tracingFilter", filter) - .addMappingForUrlPatterns(EnumSet.allOf(javax.servlet.DispatcherType.class), true, patterns); - - setState(contextHandler.getServletContext(), 1); - return contextHandler; - } + public JettyServletHelper(Rule rule) { + super(rule); + } + + /** + * Strategy: Use the contextHandler provided to add a new Tracing filter + * + * @param contextHandler The current contextHandler + * @return The same current contextHandler but patched + */ + protected ServletContextHandler doPatch(ServletContextHandler contextHandler) throws Exception { + + String[] patterns = { "/*" }; + + Filter filter = new TracingFilter(tracer); + contextHandler + .getServletContext() + .addFilter("tracingFilter", filter) + .addMappingForUrlPatterns(EnumSet.allOf(javax.servlet.DispatcherType.class), true, patterns); + + setState(contextHandler.getServletContext(), 1); + return contextHandler; + } } diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/MongoHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/MongoHelper.java index 834716f353f..aa8d1c61026 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/MongoHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/MongoHelper.java @@ -10,27 +10,25 @@ public class MongoHelper extends DDAgentTracingHelper { - public MongoHelper(Rule rule) { - super(rule); - } + public MongoHelper(Rule rule) { + super(rule); + } - /** - * Strategy: Just before com.mongodb.MongoClientOptions$Builder.build() method is called, we add a new command listener - * in charge of the tracing. - * - * @param builder The builder instance - * @return The same builder instance with a new tracing command listener that will be use for the client construction - * @throws Exception - */ - protected MongoClientOptions.Builder doPatch(MongoClientOptions.Builder builder) throws Exception { + /** + * Strategy: Just before com.mongodb.MongoClientOptions$Builder.build() method is called, we add a new command listener + * in charge of the tracing. + * + * @param builder The builder instance + * @return The same builder instance with a new tracing command listener that will be use for the client construction + */ + protected MongoClientOptions.Builder doPatch(MongoClientOptions.Builder builder) throws Exception { + TracingCommandListener listener = new TracingCommandListener(tracer); + builder.addCommandListener(listener); - TracingCommandListener listener = new TracingCommandListener(tracer); - builder.addCommandListener(listener); + setState(builder, 1); - setState(builder, 1); + return builder; - return builder; - - } + } } diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/OkHttpHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/OkHttpHelper.java index a1c53313d19..09b6992e49f 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/OkHttpHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/OkHttpHelper.java @@ -1,13 +1,12 @@ package com.datadoghq.trace.agent.integration; +import static io.opentracing.contrib.okhttp3.OkHttpClientSpanDecorator.STANDARD_TAGS; + import io.opentracing.contrib.okhttp3.TracingInterceptor; +import java.util.Collections; import okhttp3.OkHttpClient; import org.jboss.byteman.rule.Rule; -import java.util.Collections; - -import static io.opentracing.contrib.okhttp3.OkHttpClientSpanDecorator.STANDARD_TAGS; - /** * Patch the OkHttp Client during the building steps. @@ -15,23 +14,22 @@ public class OkHttpHelper extends DDAgentTracingHelper { - public OkHttpHelper(Rule rule) { - super(rule); - } - - /** - * Strategy: Just before the okhttp3.OkHttpClient$Builder.build() method called, we add a new interceptor for the tracing - * part. - * - * @param builder The builder instance to patch - * @return The same builder instance with a new tracing interceptor - * @throws Exception - */ - protected OkHttpClient.Builder doPatch(OkHttpClient.Builder builder) throws Exception { - TracingInterceptor interceptor = new TracingInterceptor(tracer, Collections.singletonList(STANDARD_TAGS)); - builder.addInterceptor(interceptor); - builder.addNetworkInterceptor(interceptor); - - return builder; - } + public OkHttpHelper(Rule rule) { + super(rule); + } + + /** + * Strategy: Just before the okhttp3.OkHttpClient$Builder.build() method called, we add a new interceptor for the tracing + * part. + * + * @param builder The builder instance to patch + * @return The same builder instance with a new tracing interceptor + */ + protected OkHttpClient.Builder doPatch(OkHttpClient.Builder builder) throws Exception { + TracingInterceptor interceptor = new TracingInterceptor(tracer, Collections.singletonList(STANDARD_TAGS)); + builder.addInterceptor(interceptor); + builder.addNetworkInterceptor(interceptor); + + return builder; + } } \ No newline at end of file diff --git a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/TomcatServletHelper.java b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/TomcatServletHelper.java index 55d94f168dd..870e011b7db 100644 --- a/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/TomcatServletHelper.java +++ b/dd-java-agent/src/main/java/com/datadoghq/trace/agent/integration/TomcatServletHelper.java @@ -1,37 +1,35 @@ package com.datadoghq.trace.agent.integration; import io.opentracing.contrib.web.servlet.filter.TracingFilter; +import java.util.EnumSet; +import javax.servlet.Filter; import org.apache.catalina.core.ApplicationContext; import org.jboss.byteman.rule.Rule; -import javax.servlet.Filter; -import java.util.EnumSet; - /** * Patch the Jetty Servlet during the init steps */ public class TomcatServletHelper extends DDAgentTracingHelper { - public TomcatServletHelper(Rule rule) { - super(rule); - } + public TomcatServletHelper(Rule rule) { + super(rule); + } - /** - * Strategy: Use the contextHandler provided to add a new Tracing filter - * - * @param contextHandler The current contextHandler - * @return The same current contextHandler but patched - * @throws Exception - */ - protected ApplicationContext doPatch(ApplicationContext contextHandler) throws Exception { + /** + * Strategy: Use the contextHandler provided to add a new Tracing filter + * + * @param contextHandler The current contextHandler + * @return The same current contextHandler but patched + */ + protected ApplicationContext doPatch(ApplicationContext contextHandler) throws Exception { - String[] patterns = {"/*"}; + String[] patterns = { "/*" }; - Filter filter = new TracingFilter(tracer); - contextHandler - .addFilter("tracingFilter", filter) - .addMappingForUrlPatterns(EnumSet.allOf(javax.servlet.DispatcherType.class), true, patterns); + Filter filter = new TracingFilter(tracer); + contextHandler + .addFilter("tracingFilter", filter) + .addMappingForUrlPatterns(EnumSet.allOf(javax.servlet.DispatcherType.class), true, patterns); - return contextHandler; - } + return contextHandler; + } } diff --git a/dd-java-agent/src/test/java/com/datadoghq/trace/agent/InstrumentationCheckerTest.java b/dd-java-agent/src/test/java/com/datadoghq/trace/agent/InstrumentationCheckerTest.java index 9d0326e81e4..b54b1044662 100644 --- a/dd-java-agent/src/test/java/com/datadoghq/trace/agent/InstrumentationCheckerTest.java +++ b/dd-java-agent/src/test/java/com/datadoghq/trace/agent/InstrumentationCheckerTest.java @@ -1,41 +1,38 @@ package com.datadoghq.trace.agent; -import com.datadoghq.trace.agent.InstrumentationChecker; -import com.datadoghq.trace.resolver.FactoryUtils; -import org.junit.Before; -import org.junit.Test; +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import com.datadoghq.trace.resolver.FactoryUtils; import java.util.HashMap; import java.util.List; import java.util.Map; - -import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import org.junit.Before; +import org.junit.Test; 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); - } + @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 { + @Test + public void testRules() throws Exception { - List rules = InstrumentationChecker.getUnsupportedRules(); - assertThat(rules.size()).isEqualTo(3); - assertThat(rules).containsExactlyInAnyOrder("unsupportedRuleOne", "unsupportedRuleTwo", "unsupportedRuleThree"); + 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-trace-annotations/pom.xml b/dd-trace-annotations/pom.xml index bdd2a001794..a02a9941801 100644 --- a/dd-trace-annotations/pom.xml +++ b/dd-trace-annotations/pom.xml @@ -1,25 +1,26 @@ - - 4.0.0 - - com.datadoghq - dd-trace-java + + 4.0.0 + + com.datadoghq + dd-trace-java + 0.1.2-SNAPSHOT + + dd-trace-annotations 0.1.2-SNAPSHOT - - dd-trace-annotations - 0.1.2-SNAPSHOT - dd-trace-annotations - https://github.com/datadog/dd-trace-java - jar - - UTF-8 - - - - junit - junit - 3.8.1 - test - - + dd-trace-annotations + https://github.com/datadog/dd-trace-java + jar + + UTF-8 + + + + junit + junit + 3.8.1 + test + + diff --git a/dd-trace-annotations/src/main/java/com/datadoghq/trace/Trace.java b/dd-trace-annotations/src/main/java/com/datadoghq/trace/Trace.java index 3aef0263c63..87fb11653dc 100644 --- a/dd-trace-annotations/src/main/java/com/datadoghq/trace/Trace.java +++ b/dd-trace-annotations/src/main/java/com/datadoghq/trace/Trace.java @@ -12,9 +12,9 @@ @Retention(RUNTIME) @Target(METHOD) public @interface Trace { - - /** - * The operation name to set. By default it takes the method's name - */ - String operationName() default ""; + + /** + * The operation name to set. By default it takes the method's name + */ + String operationName() default ""; } diff --git a/dd-trace-examples/async-tracing/pom.xml b/dd-trace-examples/async-tracing/pom.xml index 885ce4c28a6..45e1c88e973 100644 --- a/dd-trace-examples/async-tracing/pom.xml +++ b/dd-trace-examples/async-tracing/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 com.datadoghq diff --git a/dd-trace-examples/dropwizard-mongo-client/pom.xml b/dd-trace-examples/dropwizard-mongo-client/pom.xml index 71b6ff52785..f52e53a7be9 100644 --- a/dd-trace-examples/dropwizard-mongo-client/pom.xml +++ b/dd-trace-examples/dropwizard-mongo-client/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 diff --git a/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/HelloWorldApplication.java b/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/HelloWorldApplication.java index 93401f82560..e595dbab16a 100644 --- a/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/HelloWorldApplication.java +++ b/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/HelloWorldApplication.java @@ -7,24 +7,25 @@ import io.dropwizard.setup.Environment; public class HelloWorldApplication extends Application { - public static void main(String[] args) throws Exception { - new HelloWorldApplication().run(args); - } - @Override - public String getName() { - return "hello-world"; - } + public static void main(String[] args) throws Exception { + new HelloWorldApplication().run(args); + } - @Override - public void initialize(Bootstrap bootstrap) { - // nothing to do yet - } + @Override + public String getName() { + return "hello-world"; + } - @Override - public void run(Configuration configuration, Environment environment) { + @Override + public void initialize(Bootstrap bootstrap) { + // nothing to do yet + } - environment.jersey().register(new SimpleCrudResource()); - } + @Override + public void run(Configuration configuration, Environment environment) { + + environment.jersey().register(new SimpleCrudResource()); + } } diff --git a/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/api/Book.java b/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/api/Book.java index 721ddefc4f8..e71808e468b 100644 --- a/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/api/Book.java +++ b/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/api/Book.java @@ -6,38 +6,38 @@ public class Book { - private final String title; - private final int numberPages; - private final String IsbnCode; + private final String title; + private final int numberPages; + private final String IsbnCode; - public Book(String isbnCode, String title, int numberPages) { - this.title = title; - this.numberPages = numberPages; - IsbnCode = isbnCode; - } + public Book(String isbnCode, String title, int numberPages) { + this.title = title; + this.numberPages = numberPages; + IsbnCode = isbnCode; + } - public Book(Document d) { - this(d.getString("isbn"), d.getString("title"), d.getInteger("page").intValue()); - } + public Book(Document d) { + this(d.getString("isbn"), d.getString("title"), d.getInteger("page").intValue()); + } - @JsonProperty("ISBN") - public String getIsbnCode() { - return IsbnCode; - } + @JsonProperty("ISBN") + public String getIsbnCode() { + return IsbnCode; + } - public String getTitle() { - return title; - } + public String getTitle() { + return title; + } - public int getNumberPages() { - return numberPages; - } + public int getNumberPages() { + return numberPages; + } - public Document toDocument() { - return new Document("isbn", IsbnCode) - .append("title", title) - .append("page", numberPages); - } + public Document toDocument() { + return new Document("isbn", IsbnCode) + .append("title", title) + .append("page", numberPages); + } } diff --git a/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/client/TracedClient.java b/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/client/TracedClient.java index 29337ddf165..ee97a4438bc 100644 --- a/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/client/TracedClient.java +++ b/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/client/TracedClient.java @@ -1,10 +1,9 @@ package com.example.helloworld.client; -import java.io.IOException; - import com.datadoghq.trace.Trace; import io.opentracing.tag.StringTag; import io.opentracing.util.GlobalTracer; +import java.io.IOException; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; @@ -17,24 +16,26 @@ */ public class TracedClient { - - public static void main(String[] args) throws Exception{ - executeCall(); - System.out.println("After execute"); - } - @Trace - private static void executeCall() throws IOException { - new StringTag("service-name").set(GlobalTracer.get().activeSpan(), "TracedClient"); - OkHttpClient client = new OkHttpClient().newBuilder().build(); + public static void main(String[] args) throws Exception { + executeCall(); + System.out.println("After execute"); + } + + @Trace + private static void executeCall() throws IOException { + new StringTag("service-name").set(GlobalTracer.get().activeSpan(), "TracedClient"); + OkHttpClient client = new OkHttpClient().newBuilder().build(); - Request request = new Request.Builder() - .url("http://localhost:8080/demo/") - .build(); + Request request = new Request.Builder() + .url("http://localhost:8080/demo/") + .build(); - Response response = client.newCall(request).execute(); - if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) { + throw new IOException("Unexpected code " + response); + } - System.out.println(response.body().string()); - } + System.out.println(response.body().string()); + } } diff --git a/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/resources/SimpleCrudResource.java b/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/resources/SimpleCrudResource.java index 1e0b564ccd3..bc2fb16b765 100644 --- a/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/resources/SimpleCrudResource.java +++ b/dd-trace-examples/dropwizard-mongo-client/src/main/java/com/example/helloworld/resources/SimpleCrudResource.java @@ -8,127 +8,118 @@ import com.mongodb.client.MongoDatabase; import io.opentracing.tag.StringTag; import io.opentracing.util.GlobalTracer; -import org.bson.Document; - +import java.util.ArrayList; +import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; -import java.util.ArrayList; -import java.util.List; +import org.bson.Document; @Path("/demo") @Produces(MediaType.APPLICATION_JSON) public class SimpleCrudResource { - private final MongoClient client; - private final MongoDatabase db; - private static final String HOSTNAME = "localhost"; - private static final String DATABASE = "demo"; - private static final java.lang.String COLLECTION = "books"; - - public SimpleCrudResource() { - - // Init the client - client = new MongoClient(HOSTNAME); - - - // For this example, start from a fresh DB - try { - client.dropDatabase(DATABASE); - } catch (Exception e) { - // do nothing here - } - - // Init the connection to the collection - db = client.getDatabase(DATABASE); - db.createCollection(COLLECTION); - } - - /** - * Add a book to the DB - * - * @return The status of the save - * @throws InterruptedException - */ - @GET - @Path("/add") - public String addBook( - @QueryParam("isbn") Optional isbn, - @QueryParam("title") Optional title, - @QueryParam("page") Optional page - ) throws InterruptedException { - - - // The methodDB is traced (see below), this will be produced a new child span - beforeDB(); - - if (!isbn.isPresent()) { - throw new IllegalArgumentException("ISBN should not be null"); - } - - Book book = new Book( - isbn.get(), - title.or("Missing title"), - page.or(0)); - - db.getCollection(COLLECTION).insertOne(book.toDocument()); - return "Book saved!"; - } - - /** - * List all books present in the DB - * - * @return list of Books - * @throws InterruptedException - */ - @GET - public List getBooks() throws InterruptedException { - - // The methodDB is traced (see below), this will be produced a new childre span - beforeDB(); - - List books = new ArrayList<>(); - try (MongoCursor cursor = db.getCollection(COLLECTION).find().iterator();) { - while (cursor.hasNext()) { - books.add(new Book(cursor.next())); - } - } - - // The methodDB is traced (see below), this will be produced a new child span - beforeDB(); - - return books; - } - - /** - * The beforeDB is traced using the annotation @trace with a custom operationName and a custom tag. - * - * @throws InterruptedException - */ - @Trace(operationName = "Before DB") - public void beforeDB() throws InterruptedException { - new StringTag("mytag").set(GlobalTracer.get().activeSpan(), "myvalue"); - Thread.sleep(333); - } - - /** - * The beforeDB is traced using the annotation @trace with a custom operationName and a custom tag. - * - * @throws InterruptedException - */ - @Trace(operationName = "After DB") - public void afterDB() throws InterruptedException { - new StringTag("mytag").set(GlobalTracer.get().activeSpan(), "myvalue"); - Thread.sleep(111); - } - - /** - * Flush resources - */ - public void close() { - client.close(); - } + private final MongoClient client; + private final MongoDatabase db; + private static final String HOSTNAME = "localhost"; + private static final String DATABASE = "demo"; + private static final java.lang.String COLLECTION = "books"; + + public SimpleCrudResource() { + + // Init the client + client = new MongoClient(HOSTNAME); + + // For this example, start from a fresh DB + try { + client.dropDatabase(DATABASE); + } catch (Exception e) { + // do nothing here + } + + // Init the connection to the collection + db = client.getDatabase(DATABASE); + db.createCollection(COLLECTION); + } + + /** + * Add a book to the DB + * + * @return The status of the save + */ + @GET + @Path("/add") + public String addBook( + @QueryParam("isbn") Optional isbn, + @QueryParam("title") Optional title, + @QueryParam("page") Optional page + ) throws InterruptedException { + + // The methodDB is traced (see below), this will be produced a new child span + beforeDB(); + + if (!isbn.isPresent()) { + throw new IllegalArgumentException("ISBN should not be null"); + } + + Book book = new Book( + isbn.get(), + title.or("Missing title"), + page.or(0)); + + db.getCollection(COLLECTION).insertOne(book.toDocument()); + return "Book saved!"; + } + + /** + * List all books present in the DB + * + * @return list of Books + */ + @GET + public List getBooks() throws InterruptedException { + + // The methodDB is traced (see below), this will be produced a new childre span + beforeDB(); + + List books = new ArrayList<>(); + try (MongoCursor cursor = db.getCollection(COLLECTION).find().iterator()) { + while (cursor.hasNext()) { + books.add(new Book(cursor.next())); + } + } + + // The methodDB is traced (see below), this will be produced a new child span + beforeDB(); + + return books; + } + + /** + * The beforeDB is traced using the annotation @trace with a custom operationName and a custom tag. + */ + @Trace(operationName = "Before DB") + public void beforeDB() throws InterruptedException { + new StringTag("mytag").set(GlobalTracer.get().activeSpan(), "myvalue"); + Thread.sleep(333); + } + + /** + * The beforeDB is traced using the annotation @trace with a custom operationName and a custom tag. + */ + @Trace(operationName = "After DB") + public void afterDB() throws InterruptedException { + new StringTag("mytag").set(GlobalTracer.get().activeSpan(), "myvalue"); + Thread.sleep(111); + } + + /** + * Flush resources + */ + public void close() { + client.close(); + } } diff --git a/dd-trace-examples/pom.xml b/dd-trace-examples/pom.xml index 9c2669f4948..a825cb05789 100644 --- a/dd-trace-examples/pom.xml +++ b/dd-trace-examples/pom.xml @@ -1,5 +1,6 @@ - + dd-trace-java com.datadoghq diff --git a/dd-trace-examples/spring-boot-jdbc/pom.xml b/dd-trace-examples/spring-boot-jdbc/pom.xml index ee00edecfbd..740b317c8f1 100644 --- a/dd-trace-examples/spring-boot-jdbc/pom.xml +++ b/dd-trace-examples/spring-boot-jdbc/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 @@ -19,7 +20,7 @@ 1.8 - + mysql @@ -60,15 +61,15 @@ - - - - - - - - - + + + + + + + + + org.springframework.boot diff --git a/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/Application.java b/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/Application.java index 08498ae46e4..99cef300ff0 100644 --- a/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/Application.java +++ b/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/Application.java @@ -6,7 +6,7 @@ @SpringBootApplication public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } } diff --git a/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/entities/UserRepository.java b/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/entities/UserRepository.java index 07fda4f345d..12d0f494c1e 100644 --- a/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/entities/UserRepository.java +++ b/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/entities/UserRepository.java @@ -2,7 +2,6 @@ import org.springframework.data.repository.CrudRepository; - // This will be AUTO IMPLEMENTED by Spring into a Bean called userRepository // CRUD refers Create, Read, Update, Delete diff --git a/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/resources/MySQLResource.java b/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/resources/MySQLResource.java index 9ce1c8c1ab7..be0501206e1 100644 --- a/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/resources/MySQLResource.java +++ b/dd-trace-examples/spring-boot-jdbc/src/main/java/com/datadoghq/examples/resources/MySQLResource.java @@ -10,16 +10,16 @@ import org.springframework.web.bind.annotation.ResponseBody; @Controller // This means that this class is a Controller -@RequestMapping(path="/demo") // This means URL's start with /demo (after Application path) +@RequestMapping(path = "/demo") // This means URL's start with /demo (after Application path) public class MySQLResource { @Autowired // This means to get the bean called userRepository // Which is auto-generated by Spring, we will use it to handle the data private UserRepository userRepository; - @GetMapping(path="/add") // Map ONLY GET Requests + @GetMapping(path = "/add") // Map ONLY GET Requests public @ResponseBody - String addNewUser (@RequestParam String name + String addNewUser(@RequestParam String name , @RequestParam String email) { // @ResponseBody means the returned String is the response, not a view name // @RequestParam means it is a parameter from the GET or POST request @@ -31,8 +31,9 @@ String addNewUser (@RequestParam String name return "Saved"; } - @GetMapping(path="/all") - public @ResponseBody Iterable getAllUsers() { + @GetMapping(path = "/all") + public @ResponseBody + Iterable getAllUsers() { // This returns a JSON or XML with the users return userRepository.findAll(); } diff --git a/dd-trace-examples/spring-boot-jdbc/src/main/resources/application.properties b/dd-trace-examples/spring-boot-jdbc/src/main/resources/application.properties index 7f06d041313..3bf7caed7d2 100644 --- a/dd-trace-examples/spring-boot-jdbc/src/main/resources/application.properties +++ b/dd-trace-examples/spring-boot-jdbc/src/main/resources/application.properties @@ -1,10 +1,7 @@ -spring.datasource.driver-class-name= io.opentracing.contrib.jdbc.TracingDriver -spring.datasource.url= jdbc:tracing:mysql://localhost:3306/springdb +spring.datasource.driver-class-name=io.opentracing.contrib.jdbc.TracingDriver +spring.datasource.url=jdbc:tracing:mysql://localhost:3306/springdb spring.datasource.username=root spring.datasource.password=root - spring.jpa.hibernate.ddl-auto=create-drop - - logging.level.root=INFO logging.level.com.datadoghq.trace=DEBUG \ No newline at end of file diff --git a/dd-trace-java.intellij_codestyle.xml b/dd-trace-java.intellij_codestyle.xml new file mode 100644 index 00000000000..0d4b4c3b45a --- /dev/null +++ b/dd-trace-java.intellij_codestyle.xml @@ -0,0 +1,74 @@ + + + + diff --git a/dd-trace/README.md b/dd-trace/README.md index fea1c8e44c3..aae8ead5ac8 100644 --- a/dd-trace/README.md +++ b/dd-trace/README.md @@ -1,17 +1,18 @@ -## Datadog Java Tracer +# Datadog Opentracing Tracer -### Motivations +## Motivations -The Datadog Java Tracer is an OpenTracing-compatible tracer. It provides all resources needed to instrument your code. +The Datadog Tracer is an Opentracing compatible tracer. It provides all resources needed to instrument your code +and report each operations, each traces directly to a Datadog APM platform. -Opentracing introduces the concept of the **span**. A span is **timed operation** representing "a bounded process" in the code. -The spans can **be linked together**. And a **trace** is a list of spans, each related to the same top action/operation. +Opentracing uses the concept of the **span**. A span is **timed operation** representing a bunch of work executed. +Spans can **be linked together**. And a **trace** is a collection of spans, related to the same top action/operation. Let's see an example. -The workflow can be a client requesting, via a HTTP endpoint, some resources store in a DB. -Look at the following scheme. +For instance, a client requesting a resource through an HTTP endpoint. +Look at the following workflow. ```` TRACE: @@ -31,25 +32,80 @@ As just described, the tracer produces a trace composed of 4 spans, each represe 2. Span2 is the Span1's first child, representing the amount of time to understand the query, and perform the query on the DB. 3. Span3, a Span1' grandchild, represents the DB time used to retrieve the data -4. Span4 is a child of Span2 and followed Span3. It represents a business process for instance. +4. Span4 is a child of Span2 and followed Span3. It represents a business/legacy operation. This is a very simple example of how works [Opentracing](http://opentracing.io/). -Do not hesitate to go deeper and read the full documentation: http://opentracing.io/ +To dig deeper, read the full documentation: http://opentracing.io/ -### How to instrument well-known framework? +## How to instrument your application? + +There are 3 ways to instrument an application: +1. [Use the autotracing agent for supported frawemorks](#framework) +2. [Use the Opentracing API](#api) +3. [Use annotations](#annotation) + +### Use the autotracing agent for well-known framework + +Datadog instruments many frameworks and libraries by default: SpringBoot, JDBC, Mongo, JMS, Tomcat, etc. +By using the autotracing agent, you just need to follow few steps in order to get traces. -Datadog instruments many frameworks and libraries by default: SpringBoot, JDBC, Mongo, JMS, Tomcat, etc. Check the dedicated project and agent: [dd-java-agent](../dd-java-agent) -### How the Datadog Tracer (DDTrace) is loaded in the project? +### Custom instrumentations using Opentracing API + +If you want to add custom instrumenting to your code, you have to use the Opentracing API. +The official documentation can be found right here: [](https://github.com/opentracing/opentracing-java). + +Let's look at a simple example. + + +```java +class InstrumentedClass { + + + void methodSDK() { + // Retrieve the tracer using the resolver provided + // Make sure you have : + // 1. added the agent to the jvm (-javaagent;/path/to/agent.jar) + // 2. a dd-trace.yaml file in your resources directory + Tracer tracer = io.opentracing.util.GlobalTracer.get(); + + Span span = tracer.buildSpan("operation-name").startActive(); + + //Do some thing here ... + Thread.sleep(1_000); + + // Close the span, the trace will automatically reported to the writer configured + span.finish(); + } + +} +``` + +The method above is now instrumented. As you can see, the tracer is retrieved from a global registry, called `GlobalTracer`. + +The last thing you have to do is providing a configured tracer. This can be easily done by using the `TracerFactory`. +in the bootstrap method (like the `main`). -This current implementation uses the trace-resolver feature provides by Opentracing. -That means you can add and load the tracer using a Java Agent directly with the JVM. +```java +public class Application { -The DDTrace is autoconfigured using the YAML file provided in the project: `dd-trace.yaml`. -By default, the DDTrace tries to reach a local Datadog Agent, but you can change the settings and use a different + public static void main(String[] args) { + + // Init the tracer from the configuration file + Tracer tracer = DDTracerFactory.createFromConfigurationFile(); + io.opentracing.util.GlobalTracer.register(tracer); + + // ... + } +} +``` + +The factory looks for a `dd-trace.yaml` file in the classpath. The DDTracer is auto-configured using this YAML file. + +By default, the DDTracer tries to reach a local Datadog Agent, but you can change the settings and use a different location. In order to do that, please, refer you to the latest configuration: [dd-trace.yaml](src/main/resources/dd-trace.yaml) ```yaml @@ -76,78 +132,73 @@ sampler: type: AllSampler ``` -To attach the agent to the JVM, you simply have to declare the provided `jar` file in your -JVM arguments as a valid `-javaagent:`. We assume that your `${M2_REPO}` env variable is properly set. -Don't forget to replace the `{version}` placeholder in the following commands. +Do not forget to add the corresponding dependencies to your project. -So first download the `jar` file from the main Maven repository: +```xml + + + io.opentracing + opentracing-api + ${opentracing.version} + + + + + com.datadoghq + dd-trace + ${dd-trace-java.version} + ``` -> mvn dependency:get -Dartifact=io.opentracing-contrib:opentracing-agent:${version} -``` -Then add the following JVM argument when launching your application (in IDE, using Maven run or simply in collaboration with the `>java -jar` command): -``` --javaagent:${M2_REPO}/io/opentracing-contrib/opentracing-agent/${version}/opentracing-agent-${version}.jar -``` +### Custom instrumentations using Annotation -At this point, the DDTrace is loaded in the project. Let's see now how to instrument it. +Datadog provides a third way to instrument your code: annotations. +The following example is the same as above. Just add `@Trace` to the methods you want to instrument. -### How to use the Datadog Tracer (DDTrace) for instrumenting legacy code? +```java +class InstrumentedClass { -Once, the DDTrace is loaded, you can start to instrument your code using the Opentracing SDK or the `@Trace` annotation. -`@Trace` is actually a Datadog specific, but we plan to submit it to Opentracing foundation. + @Trace(operationName = "operation-name") + void methodSDK() { -To use them, you have to add the dependency to the DDTrace. -Just edit you `pom.xml` and add this: + //Do some thing here ... + Thread.sleep(1_000); + } +} +``` +In order to use annotations, the only required dependency is that package. ```xml - - com.datadoghq - dd-trace - ${dd-trace-java.version} - + + + com.datadoghq + dd-trace-annotations + ${dd-trace-java.version} + ``` +The annotations are resolved at the runtime by the autotracing agent. If you want to use the annotations, +so have to provide the agent. +To attach the agent to the JVM, you simply have to declare the provided `jar` file in your +JVM arguments as a valid `-javaagent`. Don't forget to replace the `{version}` placeholder in the following commands. -You can start as shown below, here is an example how to use both of them to instrument 2 simple methods. +So first download the `jar` file from the main Maven repository: http://central.maven.org/maven2/com/datadoghq/dd-java-agent/ -```java -class InstrumentedClass { - - @Trace - void methodAnnoted() { - // The annotation will do the same thing as the manual instrumentation below - //Do some thing here ... - Thread.sleep(1_000); - } - - void methodSDK() { - // Retrieve the tracer using the resolver provided - // Make sure you have : - // 1. added the agent to the jvm (-javaagent;/path/to/agent.jar) - // 2. a dd-trace.yaml file in your resources directory - Tracer tracer = io.opentracing.util.GlobalTracer.get(); - - Span span = tracer.buildSpan("operation-name").build(); - - //Do some thing here ... - Thread.sleep(1_000); - - // Close the span, the trace will automatically reported to the writer configured - span.close(); - } - -} ``` +> curl -OL http://central.maven.org/maven2/com/datadoghq/dd-java-agent/{version}/dd-java-agent-{version}.jar +``` +Then add the following JVM argument when launching your application (in IDE, using Maven run or simply in collaboration with the `>java -jar` command): -If you have a running Datadog Agent with the [APM feature enabled](http://docs.datadoghq.com/tracing/), you should -see traces directly to your Datadog account. +``` +-javaagent:/path/to/dd-java-agent-{version}.jar +``` +At this point, the DDTrace is loaded in the project. -### Other useful resources +## Other useful resources Before instrumenting your own project you might want to run the provided examples: diff --git a/dd-trace/pom.xml b/dd-trace/pom.xml index 723553ce334..e4966c45df0 100644 --- a/dd-trace/pom.xml +++ b/dd-trace/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 @@ -122,8 +123,8 @@ dd.com.fasterxml - - + + org.yaml @@ -139,7 +140,7 @@ - + diff --git a/dd-trace/src/main/java/com/datadoghq/trace/DDActiveSpan.java b/dd-trace/src/main/java/com/datadoghq/trace/DDActiveSpan.java index a3d672b3117..0353240bd6f 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/DDActiveSpan.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/DDActiveSpan.java @@ -1,80 +1,79 @@ package com.datadoghq.trace; import com.fasterxml.jackson.annotation.JsonIgnore; - import io.opentracing.ActiveSpan; /** * Base implementation for opentracing {@link ActiveSpan} */ -public class DDActiveSpan extends DDBaseSpan implements ActiveSpan{ +public class DDActiveSpan extends DDBaseSpan implements ActiveSpan { + + protected final DDActiveSpan parent; + protected boolean deactivated = false; + + protected DDActiveSpan(DDActiveSpan parent, DDSpan span) { + super(span.startTimeMicro, span.context()); + this.startTimeNano = span.startTimeNano; + this.durationNano = span.durationNano; + this.parent = parent; + } + + protected DDActiveSpan(DDActiveSpan parent, long timestampMicro, DDSpanContext context) { + super(timestampMicro, context); + this.parent = parent; + } + + /** + * @return the generating parent if not null + */ + @JsonIgnore + public DDActiveSpan getParent() { + return parent; + } + + /** + * @return true if the span has already been deactivated + */ + @JsonIgnore + public boolean isDeactivated() { + return deactivated; + } + + @Override + public void deactivate() { + DDTracer tracer = context().getTracer(); + if (tracer != null) { + tracer.deactivate(this); + } + finish(); + deactivated = true; + } + + @Override + public Continuation capture() { + return new DDContinuation(); + } + + @Override + protected ActiveSpan thisInstance() { + return this; + } - protected final DDActiveSpan parent; - protected boolean deactivated = false; - - protected DDActiveSpan(DDActiveSpan parent,DDSpan span) { - super(span.startTimeMicro, span.context()); - this.startTimeNano = span.startTimeNano; - this.durationNano = span.durationNano; - this.parent = parent; - } - - protected DDActiveSpan(DDActiveSpan parent,long timestampMicro, DDSpanContext context) { - super(timestampMicro, context); - this.parent = parent; - } - - /** - * @return the generating parent if not null - */ - @JsonIgnore - public DDActiveSpan getParent() { - return parent; - } - - /** - * @return true if the span has already been deactivated - */ - @JsonIgnore - public boolean isDeactivated() { - return deactivated; - } + public class DDContinuation implements Continuation { - @Override - public void deactivate() { - DDTracer tracer = context().getTracer(); - if(tracer!=null){ - tracer.deactivate(this); - } - finish(); - deactivated = true; - } + @Override + public ActiveSpan activate() { + //Reactivate the current span + context().getTracer().makeActive(DDActiveSpan.this); - @Override - public Continuation capture() { - return new DDContinuation(); - } + //And return the encapsulating ActiveSpan + return DDActiveSpan.this; + } - @Override - protected ActiveSpan thisInstance() { - return this; - } - - public class DDContinuation implements Continuation{ - - @Override - public ActiveSpan activate() { - //Reactivate the current span - context().getTracer().makeActive(DDActiveSpan.this); - - //And return the encapsulating ActiveSpan - return DDActiveSpan.this; - } - - } + } - @Override - public void close() { - deactivate(); - } + @Override + public void close() { + deactivate(); + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/DDBaseSpan.java b/dd-trace/src/main/java/com/datadoghq/trace/DDBaseSpan.java index 9feaa6a3660..0034c66a6d9 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/DDBaseSpan.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/DDBaseSpan.java @@ -1,23 +1,20 @@ package com.datadoghq.trace; +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.opentracing.BaseSpan; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.annotation.JsonIgnore; - -import io.opentracing.BaseSpan; - @SuppressWarnings("rawtypes") public abstract class DDBaseSpan implements BaseSpan { - /** + /** * StartTime stores the creation time of the span in milliseconds */ protected long startTimeMicro; @@ -41,7 +38,7 @@ public abstract class DDBaseSpan implements BaseSpan { * Currently, users have * * @param timestampMicro if set, use this time instead of the auto-generated time - * @param context the context + * @param context the context */ protected DDBaseSpan( long timestampMicro, @@ -84,7 +81,7 @@ protected final void afterFinish() { List> spans = this.context().getTrace(); for (DDBaseSpan span : spans) { - if (((DDBaseSpan) span).getDurationNano() == 0L) { + if (span.getDurationNano() == 0L) { logger.warn("{} - The parent span is marked as finished but this span isn't. You have to close each children.", this); } } @@ -114,7 +111,7 @@ protected final boolean isRootSpan() { */ @Override public final S setTag(String tag, String value) { - this.context().setTag(tag, (Object) value); + this.context().setTag(tag, value); return thisInstance(); } @@ -124,7 +121,7 @@ public final S setTag(String tag, String value) { */ @Override public final S setTag(String tag, boolean value) { - this.context().setTag(tag, (Object) value); + this.context().setTag(tag, value); return thisInstance(); } @@ -134,8 +131,8 @@ public final S setTag(String tag, boolean value) { */ @Override public final S setTag(String tag, Number value) { - this.context().setTag(tag, (Object) value); - return thisInstance(); + this.context().setTag(tag, value); + return thisInstance(); } @@ -154,7 +151,7 @@ public final DDSpanContext context() { public final String getBaggageItem(String key) { return this.context.getBaggageItem(key); } - + /* (non-Javadoc) * @see io.opentracing.BaseSpan#setBaggageItem(java.lang.String, java.lang.String) */ @@ -196,7 +193,7 @@ public final S log(long l, Map map) { */ @Override public final S log(String s) { - logger.debug("`log` method is not implemented. Provided log: {}",s); + logger.debug("`log` method is not implemented. Provided log: {}", s); return thisInstance(); } @@ -205,7 +202,7 @@ public final S log(String s) { */ @Override public final S log(long l, String s) { - logger.debug("`log` method is not implemented. Provided log: {}",s); + logger.debug("`log` method is not implemented. Provided log: {}", s); return thisInstance(); } @@ -215,7 +212,7 @@ public final S log(long l, String s) { */ @Override public final S log(String s, Object o) { - logger.debug("`log` method is not implemented. Provided log: {}",s); + logger.debug("`log` method is not implemented. Provided log: {}", s); return thisInstance(); } @@ -224,7 +221,7 @@ public final S log(String s, Object o) { */ @Override public final S log(long l, String s, Object o) { - logger.debug("`log` method is not implemented. Provided log: {}",s); + logger.debug("`log` method is not implemented. Provided log: {}", s); return thisInstance(); } @@ -242,7 +239,7 @@ public final S setSpanType(String type) { this.context().setSpanType(type); return thisInstance(); } - + protected abstract S thisInstance(); //Getters and JSON serialisation instructions @@ -308,6 +305,7 @@ public String getOperationName() { public Map getTags() { return this.context().getTags(); } + @JsonGetter public String getType() { return context.getSpanType(); diff --git a/dd-trace/src/main/java/com/datadoghq/trace/DDSpan.java b/dd-trace/src/main/java/com/datadoghq/trace/DDSpan.java index 0845e105f40..e53a73ea506 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/DDSpan.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/DDSpan.java @@ -15,17 +15,17 @@ public class DDSpan extends DDBaseSpan implements Span { * Currently, users have * * @param timestampMicro if set, use this time instead of the auto-generated time - * @param context the context + * @param context the context */ protected DDSpan( long timestampMicro, DDSpanContext context) { - super(timestampMicro,context); + super(timestampMicro, context); } - @Override - protected DDSpan thisInstance() { - return this; - } + @Override + protected DDSpan thisInstance() { + return this; + } } 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 dd6bde94f2f..019e20d8914 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/DDSpanContext.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/DDSpanContext.java @@ -5,8 +5,11 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.common.collect.Maps; import io.opentracing.tag.Tags; - -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * SpanContext represents Span state that must propagate to descendant Spans and across process boundaries. @@ -17,215 +20,215 @@ */ public class DDSpanContext implements io.opentracing.SpanContext { - public static final String LANGUAGE_FIELDNAME = "lang"; - // Opentracing attributes - 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 - /** - * The service name is required, otherwise the span are dropped by the agent - */ - private String serviceName; - /** - * The resource associated to the service (server_web, database, etc.) - */ - private String resourceName; - /** - * True indicates that the span reports an error - */ - private boolean errorFlag; - - /** - * The type of the span. If null, the Datadog Agent will report as a custom - */ - private String spanType; - /** - * The collection of all span related to this one - */ - private final List> trace; - /** - * Each span have an operation name describing the current span - */ - private String operationName; - - - /** - * Tags are associated to the current span, they will not propagate to the children span - */ - private Map tags; - // Others attributes - /** - * For technical reasons, the ref to the original tracer - */ - private final DDTracer tracer; - - public DDSpanContext( - long traceId, - long spanId, - long parentId, - String serviceName, - String operationName, - String resourceName, - Map baggageItems, - boolean errorFlag, - String spanType, - Map tags, - List> trace, - DDTracer tracer) { - - this.traceId = traceId; - this.spanId = spanId; - this.parentId = parentId; - - - if (baggageItems == null) { - this.baggageItems = Collections.emptyMap(); - } else { - this.baggageItems = baggageItems; - } - - this.serviceName = serviceName; - this.operationName = operationName; - this.resourceName = resourceName; - this.errorFlag = errorFlag; - this.spanType = spanType; - - this.tags = tags; - - if (trace == null) { - this.trace = new ArrayList>(); - } else { - this.trace = trace; - } - - this.tracer = tracer; - } - - public long getTraceId() { - return this.traceId; - } - - public long getParentId() { - return this.parentId; - } - - public long getSpanId() { - return this.spanId; - } - - public String getServiceName() { - return serviceName; - } - - public String getResourceName() { - return this.resourceName == null || this.resourceName.isEmpty() ? this.operationName : this.resourceName; - } - - public boolean getErrorFlag() { - return errorFlag; - } - - public void setErrorFlag(boolean errorFlag) { - this.errorFlag = errorFlag; - } - - public String getSpanType() { - return spanType; - } - - public void setBaggageItem(String key, String value) { - if (this.baggageItems.isEmpty()) { - this.baggageItems = new HashMap(); - } - this.baggageItems.put(key, value); - } - - public String getBaggageItem(String key) { - return this.baggageItems.get(key); - } - - public Map getBaggageItems() { - return baggageItems; - } - - /* (non-Javadoc) - * @see io.opentracing.SpanContext#baggageItems() - */ - public Iterable> baggageItems() { - return this.baggageItems.entrySet(); - } - - @JsonIgnore - public List> getTrace() { - return this.trace; - } - - @JsonIgnore - public DDTracer getTracer() { - return this.tracer; - } - - /** - * Add a tag to the span. Tags are not propagated to the children - * - * @param tag the tag-name - * @param value the value of the value - */ - public synchronized void setTag(String tag, Object value) { - if (this.tags.isEmpty()) { - this.tags = new HashMap(); - } - this.tags.put(tag, value); - - //Call decorators - List decorators = tracer.getSpanContextDecorators(tag); - if (decorators != null) { - for (DDSpanContextDecorator decorator : decorators) { - decorator.afterSetTag(this, tag, value); - } - } - //Error management - if (Tags.ERROR.getKey().equals(tag) && Boolean.TRUE.equals(value)) { - this.errorFlag = true; - } - } - - 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); - } - - @Override - public String toString() { - return "Span [ " + traceId + " ] [ " + spanId + " | " + parentId + " ] [ " + getServiceName() + " | " + getOperationName() + " | " + getResourceName() + " ]"; - } - - public void setOperationName(String operationName) { - this.operationName = operationName; - } - - public String getOperationName() { - return operationName; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public void setResourceName(String resourceName) { - this.resourceName = resourceName; - } - - public void setSpanType(String spanType) { - this.spanType = spanType; - } + public static final String LANGUAGE_FIELDNAME = "lang"; + // Opentracing attributes + 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 + /** + * The service name is required, otherwise the span are dropped by the agent + */ + private String serviceName; + /** + * The resource associated to the service (server_web, database, etc.) + */ + private String resourceName; + /** + * True indicates that the span reports an error + */ + private boolean errorFlag; + + /** + * The type of the span. If null, the Datadog Agent will report as a custom + */ + private String spanType; + /** + * The collection of all span related to this one + */ + private final List> trace; + /** + * Each span have an operation name describing the current span + */ + private String operationName; + + + /** + * Tags are associated to the current span, they will not propagate to the children span + */ + private Map tags; + // Others attributes + /** + * For technical reasons, the ref to the original tracer + */ + private final DDTracer tracer; + + public DDSpanContext( + long traceId, + long spanId, + long parentId, + String serviceName, + String operationName, + String resourceName, + Map baggageItems, + boolean errorFlag, + String spanType, + Map tags, + List> trace, + DDTracer tracer) { + + this.traceId = traceId; + this.spanId = spanId; + this.parentId = parentId; + + if (baggageItems == null) { + this.baggageItems = Collections.emptyMap(); + } else { + this.baggageItems = baggageItems; + } + + this.serviceName = serviceName; + this.operationName = operationName; + this.resourceName = resourceName; + this.errorFlag = errorFlag; + this.spanType = spanType; + + this.tags = tags; + + if (trace == null) { + this.trace = new ArrayList>(); + } else { + this.trace = trace; + } + + this.tracer = tracer; + } + + public long getTraceId() { + return this.traceId; + } + + public long getParentId() { + return this.parentId; + } + + public long getSpanId() { + return this.spanId; + } + + public String getServiceName() { + return serviceName; + } + + public String getResourceName() { + return this.resourceName == null || this.resourceName.isEmpty() ? this.operationName : this.resourceName; + } + + public boolean getErrorFlag() { + return errorFlag; + } + + public void setErrorFlag(boolean errorFlag) { + this.errorFlag = errorFlag; + } + + public String getSpanType() { + return spanType; + } + + public void setBaggageItem(String key, String value) { + if (this.baggageItems.isEmpty()) { + this.baggageItems = new HashMap(); + } + this.baggageItems.put(key, value); + } + + public String getBaggageItem(String key) { + return this.baggageItems.get(key); + } + + public Map getBaggageItems() { + return baggageItems; + } + + /* (non-Javadoc) + * @see io.opentracing.SpanContext#baggageItems() + */ + public Iterable> baggageItems() { + return this.baggageItems.entrySet(); + } + + @JsonIgnore + public List> getTrace() { + return this.trace; + } + + @JsonIgnore + public DDTracer getTracer() { + return this.tracer; + } + + /** + * Add a tag to the span. Tags are not propagated to the children + * + * @param tag the tag-name + * @param value the value of the value + */ + public synchronized void setTag(String tag, Object value) { + if (this.tags.isEmpty()) { + this.tags = new HashMap(); + } + this.tags.put(tag, value); + + //Call decorators + List decorators = tracer.getSpanContextDecorators(tag); + if (decorators != null) { + for (DDSpanContextDecorator decorator : decorators) { + decorator.afterSetTag(this, tag, value); + } + } + //Error management + if (Tags.ERROR.getKey().equals(tag) && Boolean.TRUE.equals(value)) { + this.errorFlag = true; + } + } + + 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); + } + + @Override + public String toString() { + return "Span [ " + traceId + " ] [ " + spanId + " | " + parentId + " ] [ " + getServiceName() + " | " + getOperationName() + " | " + + getResourceName() + " ]"; + } + + public void setOperationName(String operationName) { + this.operationName = operationName; + } + + public String getOperationName() { + return operationName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public void setResourceName(String resourceName) { + this.resourceName = resourceName; + } + + public void setSpanType(String spanType) { + this.spanType = spanType; + } } 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 1b8920c4fb7..b3b66993fb4 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/DDTags.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/DDTags.java @@ -1,9 +1,10 @@ package com.datadoghq.trace; 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"; + + 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/DDTracer.java b/dd-trace/src/main/java/com/datadoghq/trace/DDTracer.java index 605f667e1ab..d1ebeb366cd 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/DDTracer.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/DDTracer.java @@ -11,424 +11,423 @@ import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.propagation.Format; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; - /** * DDTracer makes it easy to send traces and span to DD using the OpenTracing integration. */ public class DDTracer implements io.opentracing.Tracer { - public final static String CURRENT_VERSION = DDTracer.class.getPackage().getImplementationVersion(); - public final static String JAVA_VERSION = System.getProperty("java.version", "unknown"); - - /** - * Writer is an charge of reporting traces and spans to the desired endpoint - */ - private Writer writer; - /** - * Sampler defines the sampling policy in order to reduce the number of traces for instance - */ - private final Sampler sampler; - - /** - * Default service name if none provided on the trace or span - */ - private final String defaultServiceName; - - /** - * Span context decorators - */ - private final Map> spanContextDecorators = new HashMap>(); - - - private final static Logger logger = LoggerFactory.getLogger(DDTracer.class); - private final CodecRegistry registry; - - public static final String UNASSIGNED_DEFAULT_SERVICE_NAME = "unnamed-java-app"; - public static final Writer UNASSIGNED_WRITER = new LoggingWriter(); - public static final Sampler UNASSIGNED_SAMPLER = new AllSampler(); - - /** - * Default constructor, trace/spans are logged, no trace/span dropped - */ - public DDTracer() { - this(UNASSIGNED_WRITER); - } - - public DDTracer(Writer writer) { - this(writer, new AllSampler()); - } - - public DDTracer(Writer writer, Sampler sampler) { - this(UNASSIGNED_DEFAULT_SERVICE_NAME, writer, sampler); - } - - public DDTracer(String defaultServiceName, Writer writer, Sampler sampler) { - this.defaultServiceName = defaultServiceName; - this.writer = writer; - this.writer.start(); - this.sampler = sampler; - registry = new CodecRegistry(); - registry.register(Format.Builtin.HTTP_HEADERS, new HTTPCodec()); - } - - /** - * Returns the list of span context decorators - * - * @return the list of span context decorators - */ - public List getSpanContextDecorators(String tag) { - return spanContextDecorators.get(tag); - } - - /** - * Add a new decorator in the list ({@link DDSpanContextDecorator}) - * - * @param decorator The decorator in the list - */ - public void addDecorator(DDSpanContextDecorator decorator) { - - List list = spanContextDecorators.get(decorator.getMatchingTag()); - if (list == null) { - list = new ArrayList(); - } - list.add(decorator); - - spanContextDecorators.put(decorator.getMatchingTag(), list); - } - - - public DDSpanBuilder buildSpan(String operationName) { - return new DDSpanBuilder(operationName); - } - - - public void inject(SpanContext spanContext, Format format, T carrier) { - - Codec codec = registry.get(format); - if (codec == null) { - logger.warn("Unsupported format for propagation - {}", format.getClass().getName()); - } else { - codec.inject((DDSpanContext) spanContext, carrier); - } - } - - public SpanContext extract(Format format, T carrier) { - - Codec codec = registry.get(format); - if (codec == null) { - logger.warn("Unsupported format for propagation - {}", format.getClass().getName()); - } else { - return codec.extract(carrier); - } - return null; - } - - - /** - * We use the sampler to know if the trace has to be reported/written. - * The sampler is called on the first span (root span) of the trace. - * If the trace is marked as a sample, we report it. - * - * @param trace a list of the spans related to the same trace - */ - public void write(List> trace) { - if (trace.isEmpty()) { - return; - } - if (this.sampler.sample(trace.get(0))) { - this.writer.write(trace); - } - } - - public void close() { - writer.close(); - } - - private final ThreadLocal currentActiveSpan = new ThreadLocal(); - - @Override - public DDActiveSpan activeSpan() { - return currentActiveSpan.get(); - } - - /** - * Set the newly created active span as the active one from the Tracer's perspective - * - * @param activeSpan - */ - protected void makeActive(DDActiveSpan activeSpan) { - //We cannot make active a preably deactivated span - if (activeSpan != null && activeSpan.isDeactivated()) - currentActiveSpan.set(null); - else - currentActiveSpan.set(activeSpan); - } - - /** - * Deactivate the current span (if active) and make the parent active (again) - * - * @param activeSpan - */ - protected void deactivate(DDActiveSpan activeSpan) { - DDActiveSpan current = activeSpan(); - if (current == activeSpan) { - //The parent becomes the active span - makeActive(activeSpan.getParent()); - } - } - - @Override - public DDActiveSpan makeActive(Span span) { - if (!(span instanceof DDSpan)) - throw new IllegalArgumentException("Cannot transform a non DDSpan into a DDActiveSpan. Provided class: " + span.getClass()); - - //Wrap the provided manual span into an active one with the current parent - DDActiveSpan activeSpan = new DDActiveSpan(activeSpan(), (DDSpan) span); - - makeActive(activeSpan); - - return activeSpan; - } - - /** - * Spans are built using this builder - */ - public class DDSpanBuilder implements SpanBuilder { - - /** - * Each span must have an operationName according to the opentracing specification - */ - private String operationName; - - // Builder attributes - private Map tags = Collections.emptyMap(); - private long timestamp; - private SpanContext parent; - private String serviceName; - private String resourceName; - private boolean errorFlag; - private String spanType; - private boolean ignoreActiveSpan = false; - - @Override - public SpanBuilder ignoreActiveSpan() { - this.ignoreActiveSpan = true; - return this; - } - - @Override - public DDActiveSpan startActive() { - //Set the active span as parent if ignoreActiveSpan==true - DDActiveSpan activeParent = null; - if (!ignoreActiveSpan) { - DDActiveSpan current = activeSpan(); - if (current != null) { - activeParent = current; - - //Ensure parent inheritance - asChildOf(activeParent); - } - } - - //Create the active span - DDActiveSpan activeSpan = new DDActiveSpan(activeParent, this.timestamp, buildSpanContext()); - logger.debug("{} - Starting a new active span.", activeSpan); - - makeActive(activeSpan); - - return activeSpan; - } - - @Override - public DDSpan startManual() { - DDSpan span = new DDSpan(this.timestamp, buildSpanContext()); - logger.debug("{} - Starting a new manuel span.", span); - return span; - } - - @Override - @Deprecated - public DDSpan start() { - return startManual(); - } - - @Override - public DDTracer.DDSpanBuilder withTag(String tag, Number number) { - return withTag(tag, (Object) number); - } - - @Override - public DDTracer.DDSpanBuilder withTag(String tag, String string) { - if (tag.equals(DDTags.SERVICE_NAME)) { - return withServiceName(string); - } else if (tag.equals(DDTags.RESOURCE_NAME)) { - return withResourceName(string); - } else if (tag.equals(DDTags.SPAN_TYPE)) { - return withSpanType(string); - } else { - return withTag(tag, (Object) string); - } - } - - @Override - public DDTracer.DDSpanBuilder withTag(String tag, boolean bool) { - return withTag(tag, (Object) bool); - } - - - public DDSpanBuilder(String operationName) { - this.operationName = operationName; - } - - @Override - public DDTracer.DDSpanBuilder withStartTimestamp(long timestampMillis) { - this.timestamp = timestampMillis; - return this; - } - - public DDTracer.DDSpanBuilder withServiceName(String serviceName) { - this.serviceName = serviceName; - return this; - } - - public DDTracer.DDSpanBuilder withResourceName(String resourceName) { - this.resourceName = resourceName; - return this; - } - - public DDTracer.DDSpanBuilder withErrorFlag() { - this.errorFlag = true; - return this; - } - - public DDTracer.DDSpanBuilder withSpanType(String spanType) { - this.spanType = spanType; - return this; - } - - public Iterable> baggageItems() { - if (parent == null) { - return Collections.emptyList(); - } - return parent.baggageItems(); - } - - @Override - public DDTracer.DDSpanBuilder asChildOf(BaseSpan span) { - return asChildOf(span == null ? null : span.context()); - } - - @Override - public DDTracer.DDSpanBuilder asChildOf(SpanContext spanContext) { - this.parent = spanContext; - return this; - } - - @Override - public DDTracer.DDSpanBuilder addReference(String referenceType, SpanContext spanContext) { - logger.debug("`addReference` method is not implemented. Doing nothing"); - return this; - } - - // Private methods - private DDTracer.DDSpanBuilder withTag(String tag, Object value) { - if (this.tags.isEmpty()) { - this.tags = new HashMap(); - } - this.tags.put(tag, value); - return this; - } - - private long generateNewId() { - return System.nanoTime(); - } - - /** - * Build the SpanContext, if the actual span has a parent, the following attributes must be propagated: - * - ServiceName - * - Baggage - * - Trace (a list of all spans related) - * - SpanType - * - * @return the context - */ - private DDSpanContext buildSpanContext() { - long generatedId = generateNewId(); - DDSpanContext context; - DDSpanContext p = this.parent != null ? (DDSpanContext) this.parent : null; - - String spanType = this.spanType; - if (spanType == null && this.parent != null) { - spanType = p.getSpanType(); - } - - String serviceName = this.serviceName; - if (serviceName == null) { - if (p != null && p.getServiceName() != null) { - serviceName = p.getServiceName(); - } else { - serviceName = defaultServiceName; - } - } - - - String operationName = this.operationName != null ? this.operationName : this.resourceName; - - //this.operationName, this.tags, - - // some attributes are inherited from the parent - context = new DDSpanContext( - this.parent == null ? generatedId : p.getTraceId(), - generatedId, - this.parent == null ? 0L : p.getSpanId(), - serviceName, - operationName, - this.resourceName, - this.parent == null ? null : p.getBaggageItems(), - errorFlag, - spanType, - this.tags, - this.parent == null ? null : p.getTrace(), - DDTracer.this - ); - - - // Force the lang meta - if (context.getBaggageItem(DDSpanContext.LANGUAGE_FIELDNAME) == null) { - context.setBaggageItem(DDSpanContext.LANGUAGE_FIELDNAME, "java"); - } - - return context; - } - - } - - - private static class CodecRegistry { - - private final Map, Codec> codecs = new HashMap, Codec>(); - - @SuppressWarnings("unchecked") - Codec get(Format format) { - return (Codec) codecs.get(format); - } - - public void register(Format format, Codec codec) { - codecs.put(format, codec); - } - - } - - @Override - public String toString() { - return "DDTracer{" + - "writer=" + writer + - ", sampler=" + sampler + - '}'; - } + public final static String CURRENT_VERSION = DDTracer.class.getPackage().getImplementationVersion(); + public final static String JAVA_VERSION = System.getProperty("java.version", "unknown"); + + /** + * Writer is an charge of reporting traces and spans to the desired endpoint + */ + private Writer writer; + /** + * Sampler defines the sampling policy in order to reduce the number of traces for instance + */ + private final Sampler sampler; + + /** + * Default service name if none provided on the trace or span + */ + private final String defaultServiceName; + + /** + * Span context decorators + */ + private final Map> spanContextDecorators = new HashMap>(); + + + private final static Logger logger = LoggerFactory.getLogger(DDTracer.class); + private final CodecRegistry registry; + + public static final String UNASSIGNED_DEFAULT_SERVICE_NAME = "unnamed-java-app"; + public static final Writer UNASSIGNED_WRITER = new LoggingWriter(); + public static final Sampler UNASSIGNED_SAMPLER = new AllSampler(); + + /** + * Default constructor, trace/spans are logged, no trace/span dropped + */ + public DDTracer() { + this(UNASSIGNED_WRITER); + } + + public DDTracer(Writer writer) { + this(writer, new AllSampler()); + } + + public DDTracer(Writer writer, Sampler sampler) { + this(UNASSIGNED_DEFAULT_SERVICE_NAME, writer, sampler); + } + + public DDTracer(String defaultServiceName, Writer writer, Sampler sampler) { + this.defaultServiceName = defaultServiceName; + this.writer = writer; + this.writer.start(); + this.sampler = sampler; + registry = new CodecRegistry(); + registry.register(Format.Builtin.HTTP_HEADERS, new HTTPCodec()); + } + + /** + * Returns the list of span context decorators + * + * @return the list of span context decorators + */ + public List getSpanContextDecorators(String tag) { + return spanContextDecorators.get(tag); + } + + /** + * Add a new decorator in the list ({@link DDSpanContextDecorator}) + * + * @param decorator The decorator in the list + */ + public void addDecorator(DDSpanContextDecorator decorator) { + + List list = spanContextDecorators.get(decorator.getMatchingTag()); + if (list == null) { + list = new ArrayList(); + } + list.add(decorator); + + spanContextDecorators.put(decorator.getMatchingTag(), list); + } + + + public DDSpanBuilder buildSpan(String operationName) { + return new DDSpanBuilder(operationName); + } + + + public void inject(SpanContext spanContext, Format format, T carrier) { + + Codec codec = registry.get(format); + if (codec == null) { + logger.warn("Unsupported format for propagation - {}", format.getClass().getName()); + } else { + codec.inject((DDSpanContext) spanContext, carrier); + } + } + + public SpanContext extract(Format format, T carrier) { + + Codec codec = registry.get(format); + if (codec == null) { + logger.warn("Unsupported format for propagation - {}", format.getClass().getName()); + } else { + return codec.extract(carrier); + } + return null; + } + + + /** + * We use the sampler to know if the trace has to be reported/written. + * The sampler is called on the first span (root span) of the trace. + * If the trace is marked as a sample, we report it. + * + * @param trace a list of the spans related to the same trace + */ + public void write(List> trace) { + if (trace.isEmpty()) { + return; + } + if (this.sampler.sample(trace.get(0))) { + this.writer.write(trace); + } + } + + public void close() { + writer.close(); + } + + private final ThreadLocal currentActiveSpan = new ThreadLocal(); + + @Override + public DDActiveSpan activeSpan() { + return currentActiveSpan.get(); + } + + /** + * Set the newly created active span as the active one from the Tracer's perspective + */ + protected void makeActive(DDActiveSpan activeSpan) { + //We cannot make active a preably deactivated span + if (activeSpan != null && activeSpan.isDeactivated()) { + currentActiveSpan.set(null); + } else { + currentActiveSpan.set(activeSpan); + } + } + + /** + * Deactivate the current span (if active) and make the parent active (again) + */ + protected void deactivate(DDActiveSpan activeSpan) { + DDActiveSpan current = activeSpan(); + if (current == activeSpan) { + //The parent becomes the active span + makeActive(activeSpan.getParent()); + } + } + + @Override + public DDActiveSpan makeActive(Span span) { + if (!(span instanceof DDSpan)) { + throw new IllegalArgumentException("Cannot transform a non DDSpan into a DDActiveSpan. Provided class: " + span.getClass()); + } + + //Wrap the provided manual span into an active one with the current parent + DDActiveSpan activeSpan = new DDActiveSpan(activeSpan(), (DDSpan) span); + + makeActive(activeSpan); + + return activeSpan; + } + + /** + * Spans are built using this builder + */ + public class DDSpanBuilder implements SpanBuilder { + + /** + * Each span must have an operationName according to the opentracing specification + */ + private String operationName; + + // Builder attributes + private Map tags = Collections.emptyMap(); + private long timestamp; + private SpanContext parent; + private String serviceName; + private String resourceName; + private boolean errorFlag; + private String spanType; + private boolean ignoreActiveSpan = false; + + @Override + public SpanBuilder ignoreActiveSpan() { + this.ignoreActiveSpan = true; + return this; + } + + @Override + public DDActiveSpan startActive() { + //Set the active span as parent if ignoreActiveSpan==true + DDActiveSpan activeParent = null; + if (!ignoreActiveSpan) { + DDActiveSpan current = activeSpan(); + if (current != null) { + activeParent = current; + + //Ensure parent inheritance + asChildOf(activeParent); + } + } + + //Create the active span + DDActiveSpan activeSpan = new DDActiveSpan(activeParent, this.timestamp, buildSpanContext()); + logger.debug("{} - Starting a new active span.", activeSpan); + + makeActive(activeSpan); + + return activeSpan; + } + + @Override + public DDSpan startManual() { + DDSpan span = new DDSpan(this.timestamp, buildSpanContext()); + logger.debug("{} - Starting a new manuel span.", span); + return span; + } + + @Override + @Deprecated + public DDSpan start() { + return startManual(); + } + + @Override + public DDTracer.DDSpanBuilder withTag(String tag, Number number) { + return withTag(tag, (Object) number); + } + + @Override + public DDTracer.DDSpanBuilder withTag(String tag, String string) { + if (tag.equals(DDTags.SERVICE_NAME)) { + return withServiceName(string); + } else if (tag.equals(DDTags.RESOURCE_NAME)) { + return withResourceName(string); + } else if (tag.equals(DDTags.SPAN_TYPE)) { + return withSpanType(string); + } else { + return withTag(tag, (Object) string); + } + } + + @Override + public DDTracer.DDSpanBuilder withTag(String tag, boolean bool) { + return withTag(tag, (Object) bool); + } + + + public DDSpanBuilder(String operationName) { + this.operationName = operationName; + } + + @Override + public DDTracer.DDSpanBuilder withStartTimestamp(long timestampMillis) { + this.timestamp = timestampMillis; + return this; + } + + public DDTracer.DDSpanBuilder withServiceName(String serviceName) { + this.serviceName = serviceName; + return this; + } + + public DDTracer.DDSpanBuilder withResourceName(String resourceName) { + this.resourceName = resourceName; + return this; + } + + public DDTracer.DDSpanBuilder withErrorFlag() { + this.errorFlag = true; + return this; + } + + public DDTracer.DDSpanBuilder withSpanType(String spanType) { + this.spanType = spanType; + return this; + } + + public Iterable> baggageItems() { + if (parent == null) { + return Collections.emptyList(); + } + return parent.baggageItems(); + } + + @Override + public DDTracer.DDSpanBuilder asChildOf(BaseSpan span) { + return asChildOf(span == null ? null : span.context()); + } + + @Override + public DDTracer.DDSpanBuilder asChildOf(SpanContext spanContext) { + this.parent = spanContext; + return this; + } + + @Override + public DDTracer.DDSpanBuilder addReference(String referenceType, SpanContext spanContext) { + logger.debug("`addReference` method is not implemented. Doing nothing"); + return this; + } + + // Private methods + private DDTracer.DDSpanBuilder withTag(String tag, Object value) { + if (this.tags.isEmpty()) { + this.tags = new HashMap(); + } + this.tags.put(tag, value); + return this; + } + + private long generateNewId() { + return System.nanoTime(); + } + + /** + * Build the SpanContext, if the actual span has a parent, the following attributes must be propagated: + * - ServiceName + * - Baggage + * - Trace (a list of all spans related) + * - SpanType + * + * @return the context + */ + private DDSpanContext buildSpanContext() { + long generatedId = generateNewId(); + DDSpanContext context; + DDSpanContext p = this.parent != null ? (DDSpanContext) this.parent : null; + + String spanType = this.spanType; + if (spanType == null && this.parent != null) { + spanType = p.getSpanType(); + } + + String serviceName = this.serviceName; + if (serviceName == null) { + if (p != null && p.getServiceName() != null) { + serviceName = p.getServiceName(); + } else { + serviceName = defaultServiceName; + } + } + + String operationName = this.operationName != null ? this.operationName : this.resourceName; + + //this.operationName, this.tags, + + // some attributes are inherited from the parent + context = new DDSpanContext( + this.parent == null ? generatedId : p.getTraceId(), + generatedId, + this.parent == null ? 0L : p.getSpanId(), + serviceName, + operationName, + this.resourceName, + this.parent == null ? null : p.getBaggageItems(), + errorFlag, + spanType, + this.tags, + this.parent == null ? null : p.getTrace(), + DDTracer.this + ); + + // Force the lang meta + if (context.getBaggageItem(DDSpanContext.LANGUAGE_FIELDNAME) == null) { + context.setBaggageItem(DDSpanContext.LANGUAGE_FIELDNAME, "java"); + } + + return context; + } + + } + + + private static class CodecRegistry { + + private final Map, Codec> codecs = new HashMap, Codec>(); + + @SuppressWarnings("unchecked") + Codec get(Format format) { + return (Codec) codecs.get(format); + } + + public void register(Format format, Codec codec) { + codecs.put(format, codec); + } + + } + + @Override + public String toString() { + return "DDTracer{" + + "writer=" + writer + + ", sampler=" + sampler + + '}'; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/integration/DBComponent.java b/dd-trace/src/main/java/com/datadoghq/trace/integration/DBComponent.java index c2d19263ec9..fd1a98c93b0 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/integration/DBComponent.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/integration/DBComponent.java @@ -10,20 +10,20 @@ */ public class DBComponent extends DDSpanContextDecorator { - public DBComponent() { - super(); - this.setMatchingTag(Tags.COMPONENT.getKey()); - this.setSetTag(DDTags.SERVICE_NAME); - } + public DBComponent() { + super(); + this.setMatchingTag(Tags.COMPONENT.getKey()); + this.setSetTag(DDTags.SERVICE_NAME); + } - @Override - public boolean afterSetTag(DDSpanContext context, String tag, Object value) { - //Assign service name - if (super.afterSetTag(context, tag, value)) { - //Assign span type to DB - context.setSpanType("db"); - return true; - } - return false; - } + @Override + public boolean afterSetTag(DDSpanContext context, String tag, Object value) { + //Assign service name + if (super.afterSetTag(context, tag, value)) { + //Assign span type to DB + context.setSpanType("db"); + return true; + } + return false; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/integration/DBStatementAsResourceName.java b/dd-trace/src/main/java/com/datadoghq/trace/integration/DBStatementAsResourceName.java index 87f55983f1a..ee80d4b7cab 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/integration/DBStatementAsResourceName.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/integration/DBStatementAsResourceName.java @@ -1,14 +1,13 @@ package com.datadoghq.trace.integration; import com.datadoghq.trace.DDTags; - import io.opentracing.tag.Tags; public class DBStatementAsResourceName extends DDSpanContextDecorator { - public DBStatementAsResourceName() { - super(); - this.setMatchingTag(Tags.DB_STATEMENT.getKey()); - this.setSetTag(DDTags.RESOURCE_NAME); - } + public DBStatementAsResourceName() { + super(); + this.setMatchingTag(Tags.DB_STATEMENT.getKey()); + this.setSetTag(DDTags.RESOURCE_NAME); + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/integration/DDSpanContextDecorator.java b/dd-trace/src/main/java/com/datadoghq/trace/integration/DDSpanContextDecorator.java index 14f05873062..4566505f7a8 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/integration/DDSpanContextDecorator.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/integration/DDSpanContextDecorator.java @@ -8,63 +8,63 @@ */ public abstract class DDSpanContextDecorator { - private String matchingTag; - - private String matchingValue; - - private String setTag; - - private String setValue; - - public boolean afterSetTag(DDSpanContext context, String tag, Object value) { - if ((this.getMatchingValue() == null || value.equals(this.getMatchingValue()))) { - String targetTag = getSetTag() == null ? tag : getSetTag(); - String targetValue = getSetValue() == null ? String.valueOf(value) : getSetValue(); - - if (targetTag.equals(DDTags.SERVICE_NAME)) { - context.setServiceName(targetValue); - } else if (targetTag.equals(DDTags.RESOURCE_NAME)) { - context.setResourceName(targetValue); - } else if (targetTag.equals(DDTags.SPAN_TYPE)) { - context.setSpanType(targetValue); - } else { - context.setTag(targetTag, targetValue); - } - return true; - } else { - return false; - } - } - - public String getMatchingTag() { - return matchingTag; - } - - public void setMatchingTag(String tag) { - this.matchingTag = tag; - } - - public String getMatchingValue() { - return matchingValue; - } - - public void setMatchingValue(String value) { - this.matchingValue = value; - } - - public String getSetTag() { - return setTag; - } - - public void setSetTag(String targetTag) { - this.setTag = targetTag; - } - - public String getSetValue() { - return setValue; - } - - public void setSetValue(String targetValue) { - this.setValue = targetValue; - } + private String matchingTag; + + private String matchingValue; + + private String setTag; + + private String setValue; + + public boolean afterSetTag(DDSpanContext context, String tag, Object value) { + if ((this.getMatchingValue() == null || value.equals(this.getMatchingValue()))) { + String targetTag = getSetTag() == null ? tag : getSetTag(); + String targetValue = getSetValue() == null ? String.valueOf(value) : getSetValue(); + + if (targetTag.equals(DDTags.SERVICE_NAME)) { + context.setServiceName(targetValue); + } else if (targetTag.equals(DDTags.RESOURCE_NAME)) { + context.setResourceName(targetValue); + } else if (targetTag.equals(DDTags.SPAN_TYPE)) { + context.setSpanType(targetValue); + } else { + context.setTag(targetTag, targetValue); + } + return true; + } else { + return false; + } + } + + public String getMatchingTag() { + return matchingTag; + } + + public void setMatchingTag(String tag) { + this.matchingTag = tag; + } + + public String getMatchingValue() { + return matchingValue; + } + + public void setMatchingValue(String value) { + this.matchingValue = value; + } + + public String getSetTag() { + return setTag; + } + + public void setSetTag(String targetTag) { + this.setTag = targetTag; + } + + public String getSetValue() { + return setValue; + } + + public void setSetValue(String targetValue) { + this.setValue = targetValue; + } } \ No newline at end of file diff --git a/dd-trace/src/main/java/com/datadoghq/trace/integration/ErrorFlag.java b/dd-trace/src/main/java/com/datadoghq/trace/integration/ErrorFlag.java index b6e7a32bc83..2381d10d9eb 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/integration/ErrorFlag.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/integration/ErrorFlag.java @@ -1,24 +1,23 @@ package com.datadoghq.trace.integration; import com.datadoghq.trace.DDSpanContext; - import io.opentracing.tag.Tags; public class ErrorFlag extends DDSpanContextDecorator { - public ErrorFlag() { - super(); - this.setMatchingTag(Tags.DB_STATEMENT.getKey()); - } - - @Override - public boolean afterSetTag(DDSpanContext context, String tag, Object value) { - //Assign resource name - try{ - context.setErrorFlag(Boolean.parseBoolean(String.valueOf(value))); - }catch(Throwable t){ - //DO NOTHING - } - return true; - } + public ErrorFlag() { + super(); + this.setMatchingTag(Tags.DB_STATEMENT.getKey()); + } + + @Override + public boolean afterSetTag(DDSpanContext context, String tag, Object value) { + //Assign resource name + try { + context.setErrorFlag(Boolean.parseBoolean(String.valueOf(value))); + } catch (Throwable t) { + //DO NOTHING + } + return true; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/integration/HTTPComponent.java b/dd-trace/src/main/java/com/datadoghq/trace/integration/HTTPComponent.java index 5b7fdd9924b..4e38c33e0ab 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/integration/HTTPComponent.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/integration/HTTPComponent.java @@ -11,21 +11,21 @@ */ public class HTTPComponent extends DDSpanContextDecorator { - public HTTPComponent() { - super(); - this.setMatchingTag(Tags.COMPONENT.getKey()); - this.setSetTag(DDTags.SERVICE_NAME); - } + public HTTPComponent() { + super(); + this.setMatchingTag(Tags.COMPONENT.getKey()); + this.setSetTag(DDTags.SERVICE_NAME); + } - @Override - public boolean afterSetTag(DDSpanContext context, String tag, Object value) { - //Assign service name - if (super.afterSetTag(context, tag, value)) { - //Assign span type to WEB - context.setSpanType("web"); - return true; - } else { - return false; - } - } + @Override + public boolean afterSetTag(DDSpanContext context, String tag, Object value) { + //Assign service name + if (super.afterSetTag(context, tag, value)) { + //Assign span type to WEB + context.setSpanType("web"); + return true; + } else { + return false; + } + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/integration/URLAsResourceName.java b/dd-trace/src/main/java/com/datadoghq/trace/integration/URLAsResourceName.java index 1307f06848c..c84a374a7c9 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/integration/URLAsResourceName.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/integration/URLAsResourceName.java @@ -3,27 +3,26 @@ import com.datadoghq.trace.DDSpanContext; import com.datadoghq.trace.DDTags; import io.opentracing.tag.Tags; - import java.net.MalformedURLException; public class URLAsResourceName extends DDSpanContextDecorator { - public URLAsResourceName() { - super(); - this.setMatchingTag(Tags.HTTP_URL.getKey()); - this.setSetTag(DDTags.RESOURCE_NAME); - } + public URLAsResourceName() { + super(); + this.setMatchingTag(Tags.HTTP_URL.getKey()); + this.setSetTag(DDTags.RESOURCE_NAME); + } - @Override - public boolean afterSetTag(DDSpanContext context, String tag, Object value) { - //Assign resource name - try { - String path = new java.net.URL(String.valueOf(value)).getPath(); - context.setResourceName(path); - } catch (MalformedURLException e) { - context.setResourceName(String.valueOf(value)); - } - return true; - } + @Override + public boolean afterSetTag(DDSpanContext context, String tag, Object value) { + //Assign resource name + try { + String path = new java.net.URL(String.valueOf(value)).getPath(); + context.setResourceName(path); + } catch (MalformedURLException e) { + context.setResourceName(String.valueOf(value)); + } + return true; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/propagation/Codec.java b/dd-trace/src/main/java/com/datadoghq/trace/propagation/Codec.java index bc5cd95d777..26946b0a402 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/propagation/Codec.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/propagation/Codec.java @@ -32,16 +32,12 @@ public interface Codec { /** * Serialize the span context using the provided carrier - * - * @param context - * @param carrier */ void inject(DDSpanContext context, T carrier); /** * Given a carrier, retrieve (rebuild) a span context. This context built will be use as the parent * - * @param carrier * @return the span context */ DDSpanContext extract(T carrier); 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 c3d6e12a2d7..066c6d70fbe 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 @@ -2,101 +2,100 @@ import com.datadoghq.trace.DDSpanContext; import io.opentracing.propagation.TextMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A codec designed for HTTP transport via headers */ 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().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; - } + 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/DDDecoratorsFactory.java b/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDDecoratorsFactory.java index af8f136e628..65dfb86d23b 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDDecoratorsFactory.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDDecoratorsFactory.java @@ -1,81 +1,79 @@ package com.datadoghq.trace.resolver; +import com.datadoghq.trace.integration.DDSpanContextDecorator; import java.util.ArrayList; import java.util.List; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.datadoghq.trace.integration.DDSpanContextDecorator; - /** * Create DDSpaDecorators from a valid configuration */ public class DDDecoratorsFactory { - private final static Logger logger = LoggerFactory.getLogger(DDDecoratorsFactory.class); + private final static Logger logger = LoggerFactory.getLogger(DDDecoratorsFactory.class); - public static String DECORATORS_PACKAGE = "com.datadoghq.trace.integration."; + public static String DECORATORS_PACKAGE = "com.datadoghq.trace.integration."; - public static final String CONFIG_PATH = "dd-trace-decorators.yaml"; + public static final String CONFIG_PATH = "dd-trace-decorators.yaml"; - /** - * Create decorators from configuration - * - * @param decoratorsConfig - * @return the list of instanciated and configured decorators - */ - public static List create(List decoratorsConfig){ - List decorators = new ArrayList(); - for (DDSpanDecoratorConfig decoratorConfig : decoratorsConfig) { - if(decoratorConfig.getType()==null){ - logger.warn("Cannot create decorator without type from configuration {}",decoratorConfig); - continue; - } + /** + * Create decorators from configuration + * + * @return the list of instanciated and configured decorators + */ + public static List create(List decoratorsConfig) { + List decorators = new ArrayList(); + for (DDSpanDecoratorConfig decoratorConfig : decoratorsConfig) { + if (decoratorConfig.getType() == null) { + logger.warn("Cannot create decorator without type from configuration {}", decoratorConfig); + continue; + } - //Find class and create - Class decoratorClass; - try { - decoratorClass = Class.forName(DECORATORS_PACKAGE+decoratorConfig.getType()); - } catch (ClassNotFoundException e) { - logger.warn("Cannot create decorator as the class {} is not defined. Provided configuration {}",decoratorConfig); - continue; - } + //Find class and create + Class decoratorClass; + try { + decoratorClass = Class.forName(DECORATORS_PACKAGE + decoratorConfig.getType()); + } catch (ClassNotFoundException e) { + logger.warn("Cannot create decorator as the class {} is not defined. Provided configuration {}", decoratorConfig); + continue; + } - DDSpanContextDecorator decorator = null; - try{ - decorator = (DDSpanContextDecorator) decoratorClass.getConstructor().newInstance(); - }catch(Exception e){ - logger.warn("Cannot create decorator as we could not invoke the default constructor. Provided configuration {}",decoratorConfig); - continue; - } + DDSpanContextDecorator decorator = null; + try { + decorator = (DDSpanContextDecorator) decoratorClass.getConstructor().newInstance(); + } catch (Exception e) { + logger.warn("Cannot create decorator as we could not invoke the default constructor. Provided configuration {}", + decoratorConfig); + continue; + } - //Fill with config values - if(decoratorConfig.getMatchingTag()!=null){ - decorator.setMatchingTag(decoratorConfig.getMatchingTag()); - } - if(decoratorConfig.getMatchingValue()!=null){ - decorator.setMatchingValue(decoratorConfig.getMatchingValue()); - } - if(decoratorConfig.getSetTag()!=null){ - decorator.setSetTag(decoratorConfig.getSetTag()); - } - if(decoratorConfig.getSetValue()!=null){ - decorator.setSetValue(decoratorConfig.getSetValue()); - } + //Fill with config values + if (decoratorConfig.getMatchingTag() != null) { + decorator.setMatchingTag(decoratorConfig.getMatchingTag()); + } + if (decoratorConfig.getMatchingValue() != null) { + decorator.setMatchingValue(decoratorConfig.getMatchingValue()); + } + if (decoratorConfig.getSetTag() != null) { + decorator.setSetTag(decoratorConfig.getSetTag()); + } + if (decoratorConfig.getSetValue() != null) { + decorator.setSetValue(decoratorConfig.getSetValue()); + } - decorators.add(decorator); - } - return decorators; - } + decorators.add(decorator); + } + return decorators; + } - public static List createFromResources(){ - List result = new ArrayList(); - TracerConfig config = FactoryUtils.loadConfigFromResource(CONFIG_PATH, TracerConfig.class); - if(config!=null){ - result = DDDecoratorsFactory.create(config.getDecorators()); - } - return result; - } + public static List createFromResources() { + List result = new ArrayList(); + TracerConfig config = FactoryUtils.loadConfigFromResource(CONFIG_PATH, TracerConfig.class); + if (config != null) { + result = DDDecoratorsFactory.create(config.getDecorators()); + } + return result; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDSpanDecoratorConfig.java b/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDSpanDecoratorConfig.java index 4d84c0131e9..ae2569c3742 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDSpanDecoratorConfig.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDSpanDecoratorConfig.java @@ -5,64 +5,64 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; public class DDSpanDecoratorConfig { - - private String type; - - private String matchingTag; - - private String matchingValue; - - private String setTag; - - private String setValue; - - public String getMatchingTag() { - return matchingTag; - } - - public void setMatchingTag(String matchingTag) { - this.matchingTag = matchingTag; - } - - public String getMatchingValue() { - return matchingValue; - } - - public void setMatchingValue(String matchingValue) { - this.matchingValue = matchingValue; - } - - public String getSetTag() { - return setTag; - } - - public void setSetTag(String setTag) { - this.setTag = setTag; - } - - public String getSetValue() { - return setValue; - } - - public void setSetValue(String setValue) { - this.setValue = setValue; - } - - public void setType(String type) { - this.type = type; - } - - public String getType() { - return type; - } - - @Override - public String toString() { - try { - return new ObjectMapper(new YAMLFactory()).writeValueAsString(this); - } catch (JsonProcessingException e) { - return null; - } - } - + + private String type; + + private String matchingTag; + + private String matchingValue; + + private String setTag; + + private String setValue; + + public String getMatchingTag() { + return matchingTag; + } + + public void setMatchingTag(String matchingTag) { + this.matchingTag = matchingTag; + } + + public String getMatchingValue() { + return matchingValue; + } + + public void setMatchingValue(String matchingValue) { + this.matchingValue = matchingValue; + } + + public String getSetTag() { + return setTag; + } + + public void setSetTag(String setTag) { + this.setTag = setTag; + } + + public String getSetValue() { + return setValue; + } + + public void setSetValue(String setValue) { + this.setValue = setValue; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + @Override + public String toString() { + try { + return new ObjectMapper(new YAMLFactory()).writeValueAsString(this); + } catch (JsonProcessingException e) { + return null; + } + } + } 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 1680167661f..9935c2f6a9c 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 @@ -9,97 +9,96 @@ import com.datadoghq.trace.writer.DDApi; import com.datadoghq.trace.writer.LoggingWriter; import com.datadoghq.trace.writer.Writer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Map; import java.util.regex.Pattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Create a tracer from a configuration file */ public class DDTracerFactory { - private final static Logger logger = LoggerFactory.getLogger(DDTracerFactory.class); - - public static final String SYSTEM_PROPERTY_CONFIG_PATH = "dd.trace.configurationFile"; - public static final String CONFIG_PATH = "dd-trace.yaml"; - - private static final String DD_AGENT_WRITER_TYPE = DDAgentWriter.class.getSimpleName(); - private static final String LOGGING_WRITER_TYPE = LoggingWriter.class.getSimpleName(); - private static final String ALL_SAMPLER_TYPE = AllSampler.class.getSimpleName(); - private static final String RATE_SAMPLER_TYPE = RateSampler.class.getSimpleName(); - - /** - * Create a tracer from a TracerConfig object - * - * @param config - * @return the corresponding tracer - */ - public static DDTracer create(TracerConfig config) { - String defaultServiceName = config.getDefaultServiceName() != null ? config.getDefaultServiceName() : DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME; - - //Create writer - Writer writer; - - if (config.getWriter() != null) { - WriterConfig c = config.getWriter(); - if (DD_AGENT_WRITER_TYPE.equals(c.getType())) { - writer = new DDAgentWriter(new DDApi(c.getHost(DDAgentWriter.DEFAULT_HOSTNAME), c.getPort(DDAgentWriter.DEFAULT_PORT))); - } else if (LOGGING_WRITER_TYPE.equals(c.getType())) { - writer = new LoggingWriter(); - } else { - writer = DDTracer.UNASSIGNED_WRITER; - } - } else { - writer = DDTracer.UNASSIGNED_WRITER; - - } - - //Create sampler - Sampler sampler; - - if (config.getSampler() != null) { - if (RATE_SAMPLER_TYPE.equals(config.getSampler().getType())) { - sampler = new RateSampler(config.getSampler().getRate()); - } else if (ALL_SAMPLER_TYPE.equals(config.getSampler().getType())) { - sampler = new AllSampler(); - } else { - sampler = DDTracer.UNASSIGNED_SAMPLER; - } - - } else { - sampler = DDTracer.UNASSIGNED_SAMPLER; - } - - //Add sampled tags - Map skipTagsPatterns = config.getSampler().getSkipTagsPatterns(); - if (skipTagsPatterns != null && sampler instanceof AbstractSampler) { - AbstractSampler aSampler = (AbstractSampler) sampler; - for (Map.Entry entry : skipTagsPatterns.entrySet()) { - aSampler.addSkipTagPattern(entry.getKey(), Pattern.compile(entry.getValue())); - } - } - - - //Create tracer - return new DDTracer(defaultServiceName, writer, sampler); - - } - - - public static DDTracer createFromConfigurationFile() { - TracerConfig tracerConfig = FactoryUtils.loadConfigFromFilePropertyOrResource(SYSTEM_PROPERTY_CONFIG_PATH,CONFIG_PATH, TracerConfig.class); - - DDTracer tracer = null; - if (tracerConfig == null) { - logger.info("No valid configuration file {} found. Loading default tracer.", CONFIG_PATH); - tracer = new DDTracer(); - } else { - tracer = DDTracerFactory.create(tracerConfig); - } - - return tracer; - } + private final static Logger logger = LoggerFactory.getLogger(DDTracerFactory.class); + + public static final String SYSTEM_PROPERTY_CONFIG_PATH = "dd.trace.configurationFile"; + public static final String CONFIG_PATH = "dd-trace.yaml"; + + private static final String DD_AGENT_WRITER_TYPE = DDAgentWriter.class.getSimpleName(); + private static final String LOGGING_WRITER_TYPE = LoggingWriter.class.getSimpleName(); + private static final String ALL_SAMPLER_TYPE = AllSampler.class.getSimpleName(); + private static final String RATE_SAMPLER_TYPE = RateSampler.class.getSimpleName(); + + /** + * Create a tracer from a TracerConfig object + * + * @return the corresponding tracer + */ + public static DDTracer create(TracerConfig config) { + String defaultServiceName = + config.getDefaultServiceName() != null ? config.getDefaultServiceName() : DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME; + + //Create writer + Writer writer; + + if (config.getWriter() != null) { + WriterConfig c = config.getWriter(); + if (DD_AGENT_WRITER_TYPE.equals(c.getType())) { + writer = new DDAgentWriter(new DDApi(c.getHost(DDAgentWriter.DEFAULT_HOSTNAME), c.getPort(DDAgentWriter.DEFAULT_PORT))); + } else if (LOGGING_WRITER_TYPE.equals(c.getType())) { + writer = new LoggingWriter(); + } else { + writer = DDTracer.UNASSIGNED_WRITER; + } + } else { + writer = DDTracer.UNASSIGNED_WRITER; + + } + + //Create sampler + Sampler sampler; + + if (config.getSampler() != null) { + if (RATE_SAMPLER_TYPE.equals(config.getSampler().getType())) { + sampler = new RateSampler(config.getSampler().getRate()); + } else if (ALL_SAMPLER_TYPE.equals(config.getSampler().getType())) { + sampler = new AllSampler(); + } else { + sampler = DDTracer.UNASSIGNED_SAMPLER; + } + + } else { + sampler = DDTracer.UNASSIGNED_SAMPLER; + } + + //Add sampled tags + Map skipTagsPatterns = config.getSampler().getSkipTagsPatterns(); + if (skipTagsPatterns != null && sampler instanceof AbstractSampler) { + AbstractSampler aSampler = (AbstractSampler) sampler; + for (Map.Entry entry : skipTagsPatterns.entrySet()) { + aSampler.addSkipTagPattern(entry.getKey(), Pattern.compile(entry.getValue())); + } + } + + //Create tracer + return new DDTracer(defaultServiceName, writer, sampler); + + } + + + public static DDTracer createFromConfigurationFile() { + TracerConfig tracerConfig = FactoryUtils + .loadConfigFromFilePropertyOrResource(SYSTEM_PROPERTY_CONFIG_PATH, CONFIG_PATH, TracerConfig.class); + + DDTracer tracer = null; + if (tracerConfig == null) { + logger.info("No valid configuration file {} found. Loading default tracer.", CONFIG_PATH); + tracer = new DDTracer(); + } else { + tracer = DDTracerFactory.create(tracerConfig); + } + + return tracer; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDTracerResolver.java b/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDTracerResolver.java index 5900c076cd5..ad1e790fcb2 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDTracerResolver.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/resolver/DDTracerResolver.java @@ -1,62 +1,59 @@ package com.datadoghq.trace.resolver; -import java.util.List; -import java.util.ServiceLoader; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.datadoghq.trace.DDTracer; import com.datadoghq.trace.integration.DDSpanContextDecorator; import com.google.auto.service.AutoService; - import io.opentracing.NoopTracerFactory; import io.opentracing.Tracer; import io.opentracing.contrib.tracerresolver.TracerResolver; import io.opentracing.util.GlobalTracer; +import java.util.List; +import java.util.ServiceLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @AutoService(TracerResolver.class) public class DDTracerResolver extends TracerResolver { - private final static Logger logger = LoggerFactory.getLogger(DDTracerResolver.class); + private final static Logger logger = LoggerFactory.getLogger(DDTracerResolver.class); - @Override - protected Tracer resolve() { - logger.info("Creating the Datadog tracer"); + @Override + protected Tracer resolve() { + logger.info("Creating the Datadog tracer"); - //Find a resource file named dd-trace.yml - DDTracer tracer = null; - //Create tracer from resource files - tracer = DDTracerFactory.createFromConfigurationFile(); + //Find a resource file named dd-trace.yml + DDTracer tracer = null; + //Create tracer from resource files + tracer = DDTracerFactory.createFromConfigurationFile(); - //Create decorators from resource files - List decorators = DDDecoratorsFactory.createFromResources(); - for(DDSpanContextDecorator decorator : decorators){ - tracer.addDecorator(decorator); - } + //Create decorators from resource files + List decorators = DDDecoratorsFactory.createFromResources(); + for (DDSpanContextDecorator decorator : decorators) { + tracer.addDecorator(decorator); + } - return tracer; - } + return tracer; + } - @SuppressWarnings("static-access") - public static Tracer registerTracer() { + @SuppressWarnings("static-access") + public static Tracer registerTracer() { - ServiceLoader RESOLVERS = ServiceLoader.load(TracerResolver.class); + ServiceLoader RESOLVERS = ServiceLoader.load(TracerResolver.class); - Tracer tracer = null; - for (TracerResolver value : RESOLVERS) { - tracer = value.resolveTracer(); - if (tracer != null) { - break; - } - } + Tracer tracer = null; + for (TracerResolver value : RESOLVERS) { + tracer = value.resolveTracer(); + if (tracer != null) { + break; + } + } - if (tracer == null) { - tracer = NoopTracerFactory.create(); - } + if (tracer == null) { + tracer = NoopTracerFactory.create(); + } - GlobalTracer.register(tracer); - return tracer; - } + GlobalTracer.register(tracer); + return tracer; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/resolver/FactoryUtils.java b/dd-trace/src/main/java/com/datadoghq/trace/resolver/FactoryUtils.java index ebe3c520eed..4a0b411377a 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/resolver/FactoryUtils.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/resolver/FactoryUtils.java @@ -1,49 +1,48 @@ package com.datadoghq.trace.resolver; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Enumeration; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; - public class FactoryUtils { - private final static Logger logger = LoggerFactory.getLogger(FactoryUtils.class); - - private static final ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()); - - public static A loadConfigFromFilePropertyOrResource(String systemProperty, String resourceName, Class targetClass){ - String filePath = System.getProperty(systemProperty); - if(filePath!=null){ - try { - return objectMapper.readValue(new File(filePath), targetClass); - } catch (Exception e) { - logger.error("Cannot read provided configuration file "+ filePath +". Using the default one.", e); - } - } - - return loadConfigFromResource(resourceName,targetClass); - - } - - public static A loadConfigFromResource(String resourceName, Class targetClass){ - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - A config = null; - try { - Enumeration iter = classLoader.getResources(resourceName); - while (iter.hasMoreElements()) { - config = objectMapper.readValue(iter.nextElement().openStream(), targetClass); - - break; // ONLY the closest resource file is taken into account - } - } catch (IOException e) { - logger.warn("Could not load configuration file {}.", resourceName); - logger.error("Error when loading config file", e); - } - return config; - } + + private final static Logger logger = LoggerFactory.getLogger(FactoryUtils.class); + + private static final ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()); + + public static A loadConfigFromFilePropertyOrResource(String systemProperty, String resourceName, Class targetClass) { + String filePath = System.getProperty(systemProperty); + if (filePath != null) { + try { + return objectMapper.readValue(new File(filePath), targetClass); + } catch (Exception e) { + logger.error("Cannot read provided configuration file " + filePath + ". Using the default one.", e); + } + } + + return loadConfigFromResource(resourceName, targetClass); + + } + + public static A loadConfigFromResource(String resourceName, Class targetClass) { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + A config = null; + try { + Enumeration iter = classLoader.getResources(resourceName); + while (iter.hasMoreElements()) { + config = objectMapper.readValue(iter.nextElement().openStream(), targetClass); + + break; // ONLY the closest resource file is taken into account + } + } catch (IOException e) { + logger.warn("Could not load configuration file {}.", resourceName); + logger.error("Error when loading config file", e); + } + return config; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/resolver/TracerConfig.java b/dd-trace/src/main/java/com/datadoghq/trace/resolver/TracerConfig.java index caac76351b9..3ca38269a8d 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/resolver/TracerConfig.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/resolver/TracerConfig.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; - import java.util.List; import java.util.Map; @@ -14,123 +13,123 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class TracerConfig { - private String defaultServiceName; - private WriterConfig writer; - private SamplerConfig sampler; - private List decorators; + private String defaultServiceName; + private WriterConfig writer; + private SamplerConfig sampler; + private List decorators; - public String getDefaultServiceName() { - return defaultServiceName; - } + public String getDefaultServiceName() { + return defaultServiceName; + } - public void setDefaultServiceName(String defaultServiceName) { - this.defaultServiceName = defaultServiceName; - } + public void setDefaultServiceName(String defaultServiceName) { + this.defaultServiceName = defaultServiceName; + } - public WriterConfig getWriter() { - return writer; - } + public WriterConfig getWriter() { + return writer; + } - public void setWriter(WriterConfig writer) { - this.writer = writer; - } + public void setWriter(WriterConfig writer) { + this.writer = writer; + } - public SamplerConfig getSampler() { - return sampler; - } + public SamplerConfig getSampler() { + return sampler; + } - public void setSampler(SamplerConfig sampler) { - this.sampler = sampler; - } + public void setSampler(SamplerConfig sampler) { + this.sampler = sampler; + } - public List getDecorators() { - return decorators; - } + public List getDecorators() { + return decorators; + } - public void setDecorators(List decorators) { - this.decorators = decorators; - } + public void setDecorators(List decorators) { + this.decorators = decorators; + } - @Override - public String toString() { - try { - return new ObjectMapper(new YAMLFactory()).writeValueAsString(this); - } catch (JsonProcessingException e) { - //FIXME better toString() while config object stabilized - return null; - } - } + @Override + public String toString() { + try { + return new ObjectMapper(new YAMLFactory()).writeValueAsString(this); + } catch (JsonProcessingException e) { + //FIXME better toString() while config object stabilized + return null; + } + } } class SamplerConfig { - private Double rate; - private String type; - private Map skipTagsPatterns; + private Double rate; + private String type; + private Map skipTagsPatterns; - public String getType() { - return type; - } + public String getType() { + return type; + } - public Double getRate() { - return rate; - } + public Double getRate() { + return rate; + } - public void setRate(Double rate) { - this.rate = rate; - } + public void setRate(Double rate) { + this.rate = rate; + } - public void setType(String type) { - this.type = type; - } + public void setType(String type) { + this.type = type; + } - public Map getSkipTagsPatterns() { - return skipTagsPatterns; - } + public Map getSkipTagsPatterns() { + return skipTagsPatterns; + } } class WriterConfig { - private String host; - private Integer port; - private String type; + private String host; + private Integer port; + private String type; - public void setHost(String host) { - this.host = host; - } + public void setHost(String host) { + this.host = host; + } - public void setPort(Integer port) { - this.port = port; - } + public void setPort(Integer port) { + this.port = port; + } - public void setType(String type) { - this.type = type; - } + public void setType(String type) { + this.type = type; + } - public String getHost() { - return host; - } + public String getHost() { + return host; + } - public Integer getPort() { - return port; - } + public Integer getPort() { + return port; + } - public String getType() { - return type; - } + public String getType() { + return type; + } - public String getHost(String defaultHostname) { - return host == null ? defaultHostname : host; - } + public String getHost(String defaultHostname) { + return host == null ? defaultHostname : host; + } - public Integer getPort(int defaultPort) { - return port == null ? defaultPort : port; - } + public Integer getPort(int defaultPort) { + return port == null ? defaultPort : port; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/sampling/AbstractSampler.java b/dd-trace/src/main/java/com/datadoghq/trace/sampling/AbstractSampler.java index 442d156521e..8ad5f7ac1ad 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/sampling/AbstractSampler.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/sampling/AbstractSampler.java @@ -1,7 +1,6 @@ package com.datadoghq.trace.sampling; import com.datadoghq.trace.DDBaseSpan; - import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -9,39 +8,36 @@ public abstract class AbstractSampler implements Sampler { - /** - * Sample tags - */ - protected Map skipTagsPatterns = new HashMap(); - - @Override - public boolean sample(DDBaseSpan span) { - - //Filter by tag values - for(Entry entry: skipTagsPatterns.entrySet()){ - Object value = span.getTags().get(entry.getKey()); - if(value != null){ - String strValue = String.valueOf(value); - Pattern skipPattern = entry.getValue(); - if(skipPattern.matcher(strValue).matches()){ - return false; - } - } - } - - return doSample(span); - } - - /** - * Pattern based skipping of tag values - * - * @param tag - * @param skipPattern - */ - public void addSkipTagPattern(String tag,Pattern skipPattern){ - skipTagsPatterns.put(tag, skipPattern); - } - - protected abstract boolean doSample(DDBaseSpan span); + /** + * Sample tags + */ + protected Map skipTagsPatterns = new HashMap(); + + @Override + public boolean sample(DDBaseSpan span) { + + //Filter by tag values + for (Entry entry : skipTagsPatterns.entrySet()) { + Object value = span.getTags().get(entry.getKey()); + if (value != null) { + String strValue = String.valueOf(value); + Pattern skipPattern = entry.getValue(); + if (skipPattern.matcher(strValue).matches()) { + return false; + } + } + } + + return doSample(span); + } + + /** + * Pattern based skipping of tag values + */ + public void addSkipTagPattern(String tag, Pattern skipPattern) { + skipTagsPatterns.put(tag, skipPattern); + } + + protected abstract boolean doSample(DDBaseSpan span); } 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 ec195d9d784..c41528966e7 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 @@ -7,9 +7,9 @@ */ public class AllSampler extends AbstractSampler { - @Override - public boolean doSample(DDBaseSpan span) { - return true; - } + @Override + public boolean doSample(DDBaseSpan span) { + return true; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/writer/DDAgentWriter.java b/dd-trace/src/main/java/com/datadoghq/trace/writer/DDAgentWriter.java index 92687b9e1ad..ee9af0390df 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/writer/DDAgentWriter.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/writer/DDAgentWriter.java @@ -1,5 +1,7 @@ package com.datadoghq.trace.writer; +import com.datadoghq.trace.DDBaseSpan; +import com.google.auto.service.AutoService; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ArrayBlockingQueue; @@ -8,13 +10,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.datadoghq.trace.DDBaseSpan; -import com.google.auto.service.AutoService; - /** * This writer write provided traces to the a DD agent which is most of time located on the same host. *

@@ -87,14 +85,14 @@ public void write(List> trace) { logger.warn("Cannot add a trace of {} as the async queue is full. Queue max size: {}", trace.size(), DEFAULT_MAX_SPANS); } } - + /* (non-Javadoc) * @see com.datadoghq.trace.writer.Writer#start() */ @Override - public void start() { - executor.submit(new SpansSendingTask()); - } + public void start() { + executor.submit(new SpansSendingTask()); + } /* (non-Javadoc) * @see com.datadoghq.trace.Writer#close() @@ -143,8 +141,8 @@ public void run() { //The thread was interrupted, we break the LOOP break; - } catch(Throwable e){ - logger.error("Unexpected error! Some traces may have been dropped.",e); + } catch (Throwable e) { + logger.error("Unexpected error! Some traces may have been dropped.", e); } } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/writer/DDApi.java b/dd-trace/src/main/java/com/datadoghq/trace/writer/DDApi.java index 164eeba3a6f..d97b5237307 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/writer/DDApi.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/writer/DDApi.java @@ -5,97 +5,95 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.IOException; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The API pointing to a DD agent */ public class DDApi { - private static final Logger logger = LoggerFactory.getLogger(DDApi.class.getName()); + private static final Logger logger = LoggerFactory.getLogger(DDApi.class.getName()); - private static final String TRACES_ENDPOINT = "/v0.3/traces"; + private static final String TRACES_ENDPOINT = "/v0.3/traces"; - private final String tracesEndpoint; + private final String tracesEndpoint; - private final ObjectMapper objectMapper = new ObjectMapper(); - private final JsonFactory jsonFactory = objectMapper.getFactory(); + private final ObjectMapper objectMapper = new ObjectMapper(); + private final JsonFactory jsonFactory = objectMapper.getFactory(); - public DDApi(String host, int port) { - this.tracesEndpoint = "http://" + host + ":" + port + TRACES_ENDPOINT; - } + public DDApi(String host, int port) { + this.tracesEndpoint = "http://" + host + ":" + port + TRACES_ENDPOINT; + } - /** - * Send traces to the DD agent - * - * @param traces the traces to be sent - * @return the staus code returned - */ - public boolean sendTraces(List>> traces) { - int status = callPUT(traces); - if (status == 200) { - logger.debug("Succesfully sent {} traces to the DD agent.", traces.size()); - return true; - } else { - logger.warn("Error while sending {} traces to the DD agent. Status: {}", traces.size(), status); - return false; - } - } + /** + * Send traces to the DD agent + * + * @param traces the traces to be sent + * @return the staus code returned + */ + public boolean sendTraces(List>> traces) { + int status = callPUT(traces); + if (status == 200) { + logger.debug("Succesfully sent {} traces to the DD agent.", traces.size()); + return true; + } else { + logger.warn("Error while sending {} traces to the DD agent. Status: {}", traces.size(), status); + return false; + } + } - /** - * PUT to an endpoint the provided JSON content - * - * @param endpoint - * @param content - * @return the status code - */ - private int callPUT(Object content) { - HttpURLConnection httpCon = null; - try { - httpCon = getHttpURLConnection(); - } catch (Exception e) { - logger.warn("Error thrown before PUT call to the DD agent.", e); - return -1; - } + /** + * PUT to an endpoint the provided JSON content + * + * @return the status code + */ + private int callPUT(Object content) { + HttpURLConnection httpCon = null; + try { + httpCon = getHttpURLConnection(); + } catch (Exception e) { + logger.warn("Error thrown before PUT call to the DD agent.", e); + return -1; + } - try { - OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream()); - JsonGenerator jsonGen = jsonFactory.createGenerator(out); - objectMapper.writeValue(jsonGen, content); - jsonGen.flush(); - jsonGen.close(); - int responseCode = httpCon.getResponseCode(); - if (responseCode == 200) { - logger.debug("Sent the payload to the DD agent."); - } else { - logger.warn("Could not send the payload to the DD agent. Status: {} ResponseMessage: {}", httpCon.getResponseCode(), httpCon.getResponseMessage()); - } - return responseCode; - } catch (Exception e) { - logger.warn("Could not send the payload to the DD agent.", e); - return -1; - } - } + try { + OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream()); + JsonGenerator jsonGen = jsonFactory.createGenerator(out); + objectMapper.writeValue(jsonGen, content); + jsonGen.flush(); + jsonGen.close(); + int responseCode = httpCon.getResponseCode(); + if (responseCode == 200) { + logger.debug("Sent the payload to the DD agent."); + } else { + logger.warn("Could not send the payload to the DD agent. Status: {} ResponseMessage: {}", httpCon.getResponseCode(), + httpCon.getResponseMessage()); + } + return responseCode; + } catch (Exception e) { + logger.warn("Could not send the payload to the DD agent.", e); + return -1; + } + } - private HttpURLConnection getHttpURLConnection() throws IOException { - HttpURLConnection httpCon; - URL url = new URL(tracesEndpoint); - httpCon = (HttpURLConnection) url.openConnection(); - httpCon.setDoOutput(true); - httpCon.setRequestMethod("PUT"); - httpCon.setRequestProperty("Content-Type", "application/json"); - httpCon.setRequestProperty("Datadog-Meta-Lang", "java"); - httpCon.setRequestProperty("Datadog-Meta-Lang-Version", DDTracer.JAVA_VERSION); - httpCon.setRequestProperty("Datadog-Meta-Tracer-Version", DDTracer.CURRENT_VERSION); - return httpCon; - } + private HttpURLConnection getHttpURLConnection() throws IOException { + HttpURLConnection httpCon; + URL url = new URL(tracesEndpoint); + httpCon = (HttpURLConnection) url.openConnection(); + httpCon.setDoOutput(true); + httpCon.setRequestMethod("PUT"); + httpCon.setRequestProperty("Content-Type", "application/json"); + httpCon.setRequestProperty("Datadog-Meta-Lang", "java"); + httpCon.setRequestProperty("Datadog-Meta-Lang-Version", DDTracer.JAVA_VERSION); + httpCon.setRequestProperty("Datadog-Meta-Tracer-Version", DDTracer.CURRENT_VERSION); + return httpCon; + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/writer/ListWriter.java b/dd-trace/src/main/java/com/datadoghq/trace/writer/ListWriter.java index e04c529bc3a..dd5faa90994 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/writer/ListWriter.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/writer/ListWriter.java @@ -1,38 +1,37 @@ package com.datadoghq.trace.writer; +import com.datadoghq.trace.DDBaseSpan; import java.util.ArrayList; import java.util.List; -import com.datadoghq.trace.DDBaseSpan; - /** - * List writer used by tests mostly + * List writer used by tests mostly */ public class ListWriter implements Writer { - protected List>> list = new ArrayList>>(); - - public List>> getList() { - return list; - } - - public List> firstTrace() { - return list.get(0); - } - - @Override - public void write(List> trace) { - list.add(trace); - } - - @Override - public void start() { - list.clear(); - } - - @Override - public void close() { - list.clear(); - } + protected List>> list = new ArrayList>>(); + + public List>> getList() { + return list; + } + + public List> firstTrace() { + return list.get(0); + } + + @Override + public void write(List> trace) { + list.add(trace); + } + + @Override + public void start() { + list.clear(); + } + + @Override + public void close() { + list.clear(); + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/writer/LoggingWriter.java b/dd-trace/src/main/java/com/datadoghq/trace/writer/LoggingWriter.java index 929008f7755..cac40c7e17e 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/writer/LoggingWriter.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/writer/LoggingWriter.java @@ -1,30 +1,28 @@ package com.datadoghq.trace.writer; +import com.datadoghq.trace.DDBaseSpan; +import com.google.auto.service.AutoService; import java.util.List; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.datadoghq.trace.DDBaseSpan; -import com.google.auto.service.AutoService; - @AutoService(Writer.class) -public class LoggingWriter implements Writer{ +public class LoggingWriter implements Writer { + + private static final Logger logger = LoggerFactory.getLogger(LoggingWriter.class.getName()); - private static final Logger logger = LoggerFactory.getLogger(LoggingWriter.class.getName()); - - @Override - public void write(List> trace) { - logger.info("write(trace): {}", trace); - } + @Override + public void write(List> trace) { + logger.info("write(trace): {}", trace); + } - @Override - public void close() { - logger.info("close()"); - } + @Override + public void close() { + logger.info("close()"); + } - @Override - public void start() { - logger.info("start()"); - } + @Override + public void start() { + logger.info("start()"); + } } diff --git a/dd-trace/src/main/java/com/datadoghq/trace/writer/Writer.java b/dd-trace/src/main/java/com/datadoghq/trace/writer/Writer.java index 2fd8ae7af8c..8a3bda8d3a7 100644 --- a/dd-trace/src/main/java/com/datadoghq/trace/writer/Writer.java +++ b/dd-trace/src/main/java/com/datadoghq/trace/writer/Writer.java @@ -1,21 +1,20 @@ package com.datadoghq.trace.writer; -import java.util.List; - import com.datadoghq.trace.DDBaseSpan; +import java.util.List; /** - * A writer is responsible to send collected spans to some place + * A writer is responsible to send collected spans to some place */ public interface Writer { /** * Write a trace represented by the entire list of all the finished spans - * + * * @param trace the list of spans to write */ void write(List> trace); - + /** * Start the writer */ diff --git a/dd-trace/src/test/java/ExampleWithLoggingWriter.java b/dd-trace/src/test/java/ExampleWithLoggingWriter.java index 50116c84124..a7d3dee475f 100644 --- a/dd-trace/src/test/java/ExampleWithLoggingWriter.java +++ b/dd-trace/src/test/java/ExampleWithLoggingWriter.java @@ -1,7 +1,6 @@ import com.datadoghq.trace.DDTracer; import com.datadoghq.trace.sampling.AllSampler; import com.datadoghq.trace.writer.LoggingWriter; - import io.opentracing.Span; public class ExampleWithLoggingWriter { diff --git a/dd-trace/src/test/java/com/datadoghq/trace/DDActiveSpanTest.java b/dd-trace/src/test/java/com/datadoghq/trace/DDActiveSpanTest.java index 4ca4aac46b0..0b69c7585cb 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/DDActiveSpanTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/DDActiveSpanTest.java @@ -2,128 +2,126 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.datadoghq.trace.writer.ListWriter; +import io.opentracing.ActiveSpan.Continuation; import org.junit.Before; import org.junit.Test; -import com.datadoghq.trace.writer.ListWriter; +public class DDActiveSpanTest { -import io.opentracing.ActiveSpan.Continuation; + private ListWriter listWriter = new ListWriter(); + private DDTracer ddTracer = new DDTracer(listWriter); -public class DDActiveSpanTest { + @Before + public void setUp() { + listWriter.start(); + } + + @Test + public void testThreadContextPropagation() { + + DDActiveSpan span1 = ddTracer.buildSpan("op1").startActive(); + + assertThat(span1.getOperationName()).isEqualTo("op1"); + assertThat(ddTracer.activeSpan()).isEqualTo(span1); + + DDActiveSpan span2 = ddTracer.buildSpan("op2").startActive(); + assertThat(span2.getOperationName()).isEqualTo("op2"); + assertThat(span2.getParent()).isEqualTo(span1); + assertThat(span2.context().getParentId()).isEqualTo(span1.getSpanId()); + assertThat(span2.context().getTraceId()).isEqualTo(span1.getTraceId()); + assertThat(ddTracer.activeSpan()).isEqualTo(span2); + + span2.deactivate(); + assertThat(ddTracer.activeSpan()).isEqualTo(span1); + + assertThat(listWriter.getList().size()).isEqualTo(0); + span1.deactivate(); + assertThat(ddTracer.activeSpan()).isNull(); + + assertThat(listWriter.getList().size()).isEqualTo(1); + assertThat(listWriter.getList().get(0).size()).isEqualTo(2); + assertThat(listWriter.getList().get(0).get(0)).isEqualTo(span1); + assertThat(listWriter.getList().get(0).get(1)).isEqualTo(span2); + } + + @Test + public void testParentDeactivationFirst() { + + DDActiveSpan span1 = ddTracer.buildSpan("op1").startActive(); + + assertThat(span1.getOperationName()).isEqualTo("op1"); + + DDActiveSpan span2 = ddTracer.buildSpan("op2").startActive(); + + assertThat(ddTracer.activeSpan()).isEqualTo(span2); + + span1.deactivate(); + + //If parent span deactivated first => Span 2 remains the active span + assertThat(ddTracer.activeSpan()).isEqualTo(span2); + + span2.deactivate(); + + //If span2 comes to be deactivated + assertThat(ddTracer.activeSpan()).isNull(); + + assertThat(listWriter.getList().size()).isEqualTo(1); + assertThat(listWriter.getList().get(0).size()).isEqualTo(2); + assertThat(listWriter.getList().get(0).get(0)).isEqualTo(span1); + assertThat(listWriter.getList().get(0).get(1)).isEqualTo(span2); + } + + @Test + public void testContinuation() throws Exception { + final DDActiveSpan span1 = ddTracer.buildSpan("op1").startActive(); + + final Continuation continuation = span1.capture(); + + Thread t = new Thread(new Runnable() { + @Override + public void run() { + assertThat(ddTracer.activeSpan()).isNull(); + continuation.activate(); + assertThat(ddTracer.activeSpan()).isEqualTo(span1); + DDActiveSpan span2 = ddTracer.buildSpan("op2").startActive(); + assertThat(ddTracer.activeSpan()).isEqualTo(span2); + span2.deactivate(); + assertThat(ddTracer.activeSpan()).isEqualTo(span1); + } + }); + + t.start(); + t.join(); + + span1.deactivate(); + assertThat(ddTracer.activeSpan()).isNull(); + + assertThat(listWriter.getList().size()).isEqualTo(1); + assertThat(listWriter.getList().get(0).size()).isEqualTo(2); + assertThat(listWriter.getList().get(0).get(0)).isEqualTo(span1); + } + + @Test + public void testMakeSpanActive() { + final DDSpan manualSpan = ddTracer.buildSpan("op1").startManual(); + + DDActiveSpan span1 = ddTracer.makeActive(manualSpan); + + assertThat(span1.getOperationName()).isEqualTo("op1"); + assertThat(ddTracer.activeSpan()).isEqualTo(span1); + assertThat(manualSpan.context()).isEqualTo(span1.context()); + assertThat(manualSpan.startTimeNano).isEqualTo(span1.startTimeNano); + assertThat(manualSpan.startTimeMicro).isEqualTo(span1.startTimeMicro); + } + + @Test + public void testCrossContextPropagation() { + final DDSpan manualSpan = ddTracer.buildSpan("op1").startManual(); - private ListWriter listWriter = new ListWriter(); - private DDTracer ddTracer = new DDTracer(listWriter); + DDActiveSpan activeSpan = ddTracer.buildSpan("op2").asChildOf(manualSpan.context()).startActive(); - @Before - public void setUp(){ - listWriter.start(); - } - - @Test - public void testThreadContextPropagation() { - - DDActiveSpan span1 = ddTracer.buildSpan("op1").startActive(); - - assertThat(span1.getOperationName()).isEqualTo("op1"); - assertThat(ddTracer.activeSpan()).isEqualTo(span1); - - DDActiveSpan span2 = ddTracer.buildSpan("op2").startActive(); - assertThat(span2.getOperationName()).isEqualTo("op2"); - assertThat(span2.getParent()).isEqualTo(span1); - assertThat(span2.context().getParentId()).isEqualTo(span1.getSpanId()); - assertThat(span2.context().getTraceId()).isEqualTo(span1.getTraceId()); - assertThat(ddTracer.activeSpan()).isEqualTo(span2); - - span2.deactivate(); - assertThat(ddTracer.activeSpan()).isEqualTo(span1); - - assertThat(listWriter.getList().size()).isEqualTo(0); - span1.deactivate(); - assertThat(ddTracer.activeSpan()).isNull(); - - assertThat(listWriter.getList().size()).isEqualTo(1); - assertThat(listWriter.getList().get(0).size()).isEqualTo(2); - assertThat(listWriter.getList().get(0).get(0)).isEqualTo(span1); - assertThat(listWriter.getList().get(0).get(1)).isEqualTo(span2); - } - - @Test - public void testParentDeactivationFirst() { - - DDActiveSpan span1 = ddTracer.buildSpan("op1").startActive(); - - assertThat(span1.getOperationName()).isEqualTo("op1"); - - DDActiveSpan span2 = ddTracer.buildSpan("op2").startActive(); - - assertThat(ddTracer.activeSpan()).isEqualTo(span2); - - span1.deactivate(); - - //If parent span deactivated first => Span 2 remains the active span - assertThat(ddTracer.activeSpan()).isEqualTo(span2); - - span2.deactivate(); - - //If span2 comes to be deactivated - assertThat(ddTracer.activeSpan()).isNull(); - - assertThat(listWriter.getList().size()).isEqualTo(1); - assertThat(listWriter.getList().get(0).size()).isEqualTo(2); - assertThat(listWriter.getList().get(0).get(0)).isEqualTo(span1); - assertThat(listWriter.getList().get(0).get(1)).isEqualTo(span2); - } - - @Test - public void testContinuation() throws Exception{ - final DDActiveSpan span1 = ddTracer.buildSpan("op1").startActive(); - - final Continuation continuation = span1.capture(); - - Thread t = new Thread(new Runnable() { - @Override - public void run() { - assertThat(ddTracer.activeSpan()).isNull(); - continuation.activate(); - assertThat(ddTracer.activeSpan()).isEqualTo(span1); - DDActiveSpan span2 = ddTracer.buildSpan("op2").startActive(); - assertThat(ddTracer.activeSpan()).isEqualTo(span2); - span2.deactivate(); - assertThat(ddTracer.activeSpan()).isEqualTo(span1); - } - }); - - t.start(); - t.join(); - - span1.deactivate(); - assertThat(ddTracer.activeSpan()).isNull(); - - assertThat(listWriter.getList().size()).isEqualTo(1); - assertThat(listWriter.getList().get(0).size()).isEqualTo(2); - assertThat(listWriter.getList().get(0).get(0)).isEqualTo(span1); - } - - @Test - public void testMakeSpanActive() { - final DDSpan manualSpan = ddTracer.buildSpan("op1").startManual(); - - DDActiveSpan span1 = ddTracer.makeActive(manualSpan); - - assertThat(span1.getOperationName()).isEqualTo("op1"); - assertThat(ddTracer.activeSpan()).isEqualTo(span1); - assertThat(manualSpan.context()).isEqualTo(span1.context()); - assertThat(manualSpan.startTimeNano).isEqualTo(span1.startTimeNano); - assertThat(manualSpan.startTimeMicro).isEqualTo(span1.startTimeMicro); - } - - @Test - public void testCrossContextPropagation() { - final DDSpan manualSpan = ddTracer.buildSpan("op1").startManual(); - - DDActiveSpan activeSpan = ddTracer.buildSpan("op2").asChildOf(manualSpan.context()).startActive(); - - assertThat(activeSpan.getParentId()).isEqualTo(manualSpan.getSpanId()); - assertThat(activeSpan.getTraceId()).isEqualTo(manualSpan.getTraceId()); - } + assertThat(activeSpan.getParentId()).isEqualTo(manualSpan.getSpanId()); + assertThat(activeSpan.getTraceId()).isEqualTo(manualSpan.getTraceId()); + } } 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 6e6d6dabd84..d4c2457ec37 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/DDSpanBuilderTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/DDSpanBuilderTest.java @@ -1,16 +1,15 @@ package com.datadoghq.trace; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; public class DDSpanBuilderTest { @@ -36,76 +35,76 @@ public void shouldBuildSimpleSpan() { } @Test - public void shouldBuildMoreComplexSpan() { + public void shouldBuildMoreComplexSpan() { - final String expectedName = "fakeName"; - final Map tags = new HashMap() { - { - put("1", true); - put("2", "fakeString"); - put("3", 42.0); - } - }; + final String expectedName = "fakeName"; + final Map tags = new HashMap() { + { + put("1", true); + put("2", "fakeString"); + put("3", 42.0); + } + }; - DDSpan span = tracer - .buildSpan(expectedName) - .withServiceName("foo") - .withTag("1", (Boolean) tags.get("1")) - .withTag("2", (String) tags.get("2")) - .withTag("3", (Number) tags.get("3")) - .start(); + DDSpan span = tracer + .buildSpan(expectedName) + .withServiceName("foo") + .withTag("1", (Boolean) tags.get("1")) + .withTag("2", (String) tags.get("2")) + .withTag("3", (Number) tags.get("3")) + .start(); - assertThat(span.getOperationName()).isEqualTo(expectedName); - assertThat(span.getTags()).containsAllEntriesOf(tags); + assertThat(span.getOperationName()).isEqualTo(expectedName); + assertThat(span.getTags()).containsAllEntriesOf(tags); - // with no tag provided + // with no tag provided - span = tracer - .buildSpan(expectedName) - .withServiceName("foo") - .start(); + span = tracer + .buildSpan(expectedName) + .withServiceName("foo") + .start(); - assertThat(span.getTags()).isNotNull(); - assertThat(span.getTags().size()).isEqualTo(2); + assertThat(span.getTags()).isNotNull(); + assertThat(span.getTags().size()).isEqualTo(2); - // with all custom fields provided - final String expectedResource = "fakeResource"; - final String expectedService = "fakeService"; - final String expectedType = "fakeType"; + // with all custom fields provided + final String expectedResource = "fakeResource"; + final String expectedService = "fakeService"; + final String expectedType = "fakeType"; - span = tracer - .buildSpan(expectedName) - .withServiceName("foo") - .withResourceName(expectedResource) - .withServiceName(expectedService) - .withErrorFlag() - .withSpanType(expectedType) - .start(); + span = tracer + .buildSpan(expectedName) + .withServiceName("foo") + .withResourceName(expectedResource) + .withServiceName(expectedService) + .withErrorFlag() + .withSpanType(expectedType) + .start(); - DDSpanContext actualContext = span.context(); + DDSpanContext actualContext = span.context(); - assertThat(actualContext.getResourceName()).isEqualTo(expectedResource); - 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()); + assertThat(actualContext.getResourceName()).isEqualTo(expectedResource); + 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()); - } + } - @Test - public void shouldAddLangMeta() { + @Test + public void shouldAddLangMeta() { - final String expectedName = "fakeName"; + final String expectedName = "fakeName"; - DDSpan span = tracer - .buildSpan(expectedName) - .withServiceName("foo") - .start(); + DDSpan span = tracer + .buildSpan(expectedName) + .withServiceName("foo") + .start(); - assertThat(span.getBaggageItem(DDSpanContext.LANGUAGE_FIELDNAME)).isEqualTo("java"); + assertThat(span.getBaggageItem(DDSpanContext.LANGUAGE_FIELDNAME)).isEqualTo("java"); - } + } @Test public void shouldBuildSpanTimestampInNano() { @@ -143,7 +142,7 @@ public void shouldLinkToParentSpan() { final long expectedParentId = spanId; DDSpanContext mockedContext = mock(DDSpanContext.class); - + when(mockedContext.getSpanId()).thenReturn(spanId); when(mockedContext.getServiceName()).thenReturn("foo"); @@ -226,11 +225,9 @@ public void shouldTrackAllSpanInTrace() throws InterruptedException { DDSpan root = tracer.buildSpan("fake_O").withServiceName("foo").start(); spans.add(root); - Thread.sleep(200); long tickEnd = System.currentTimeMillis(); - for (int i = 1; i <= 10; i++) { spans.add(tracer.buildSpan("fake_" + i).withServiceName("foo").asChildOf(spans.get(i - 1)).start()); } 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 cb55e784032..a199a979cdd 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/DDSpanSerializationTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/DDSpanSerializationTest.java @@ -2,22 +2,20 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Maps; import java.util.HashMap; import java.util.Map; - -import com.google.common.collect.Maps; import org.junit.Before; import org.junit.Test; -import com.fasterxml.jackson.databind.ObjectMapper; - public class DDSpanSerializationTest { ObjectMapper serializer; DDSpan span; DDActiveSpan activeSpan; - Map expected = Maps.newHashMap(); + Map expected = Maps.newHashMap(); @Before public void setUp() throws Exception { @@ -39,7 +37,6 @@ public void setUp() throws Exception { expected.put("parent_id", 0l); expected.put("trace_id", 1l); - DDSpanContext context = new DDSpanContext( 1L, 2L, @@ -61,8 +58,8 @@ public void setUp() throws Exception { 100L, context); span.finish(133L); - - activeSpan = new DDActiveSpan(null,100L,context); + + activeSpan = new DDActiveSpan(null, 100L, context); activeSpan.deactivate(); serializer = new ObjectMapper(); } diff --git a/dd-trace/src/test/java/com/datadoghq/trace/DDSpanTest.java b/dd-trace/src/test/java/com/datadoghq/trace/DDSpanTest.java index 78eb9a8f1af..b7dbff3bfc0 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/DDSpanTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/DDSpanTest.java @@ -3,13 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.Collections; - import org.junit.Test; -import com.datadoghq.trace.DDSpan; -import com.datadoghq.trace.DDSpanContext; -import com.datadoghq.trace.DDTracer; - public class DDSpanTest { @@ -31,7 +26,6 @@ public void testGetterSetter() { null, null); - String expected; DDSpan span = new DDSpan(1L, context); diff --git a/dd-trace/src/test/java/com/datadoghq/trace/DDTracerTest.java b/dd-trace/src/test/java/com/datadoghq/trace/DDTracerTest.java index 866eddcd733..709198dcc91 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/DDTracerTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/DDTracerTest.java @@ -6,19 +6,12 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.datadoghq.trace.sampling.RateSampler; +import com.datadoghq.trace.writer.Writer; import java.util.ArrayList; import java.util.List; - import org.junit.Test; -import com.datadoghq.trace.DDSpan; -import com.datadoghq.trace.DDTracer; -import com.datadoghq.trace.sampling.RateSampler; -import com.datadoghq.trace.writer.Writer; - -import io.opentracing.BaseSpan; -import io.opentracing.Span; - public class DDTracerTest { diff --git a/dd-trace/src/test/java/com/datadoghq/trace/RateSamplerTest.java b/dd-trace/src/test/java/com/datadoghq/trace/RateSamplerTest.java index fbd5bdc7036..cb28ad7873e 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/RateSamplerTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/RateSamplerTest.java @@ -1,14 +1,12 @@ package com.datadoghq.trace; -import com.datadoghq.trace.DDSpan; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + import com.datadoghq.trace.sampling.RateSampler; import com.datadoghq.trace.sampling.Sampler; - import org.junit.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - public class RateSamplerTest { 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 index 1dd61d3d3e9..9a41f764eb7 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/propagation/HTTPCodecTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/propagation/HTTPCodecTest.java @@ -1,14 +1,13 @@ package com.datadoghq.trace.propagation; +import static org.assertj.core.api.Java6Assertions.assertThat; + 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; +import org.junit.Test; /** * Created by gpolaert on 6/23/17. @@ -16,69 +15,66 @@ 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); + 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"; - Map carrier = new HashMap<>(); - HTTPCodec codec = new HTTPCodec(); - codec.inject(mockedContext, new TextMapInjectAdapter(carrier)); + @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); - 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"); + 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"); - }}; + @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)); + 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"); + 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/resolver/DDTracerFactoryTest.java b/dd-trace/src/test/java/com/datadoghq/trace/resolver/DDTracerFactoryTest.java index 1fc50d0995d..b9e6964dc48 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/resolver/DDTracerFactoryTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/resolver/DDTracerFactoryTest.java @@ -1,44 +1,38 @@ package com.datadoghq.trace.resolver; +import static org.assertj.core.api.Java6Assertions.assertThat; + import com.datadoghq.trace.sampling.AllSampler; import com.datadoghq.trace.sampling.RateSampler; import com.datadoghq.trace.writer.DDAgentWriter; -import org.assertj.core.api.Assertions; -import org.junit.Before; import org.junit.Test; -import static org.assertj.core.api.Java6Assertions.assertThat; - public class DDTracerFactoryTest { + @Test + public void test() throws Exception { + TracerConfig tracerConfig = FactoryUtils.loadConfigFromResource("dd-trace-1.yaml", TracerConfig.class); + assertThat(tracerConfig.getWriter()).isNotNull(); + assertThat(tracerConfig.getSampler()).isNotNull(); + assertThat(tracerConfig.getDefaultServiceName()).isEqualTo("java-app"); + assertThat(tracerConfig.getWriter().getHost()).isEqualTo("foo"); + assertThat(tracerConfig.getWriter().getPort()).isEqualTo(123); + assertThat(tracerConfig.getWriter().getType()).isEqualTo(DDAgentWriter.class.getSimpleName()); + assertThat(tracerConfig.getSampler().getType()).isEqualTo(AllSampler.class.getSimpleName()); + assertThat(tracerConfig.getSampler().getRate()).isNull(); - @Test - public void test() throws Exception { - TracerConfig tracerConfig = FactoryUtils.loadConfigFromResource("dd-trace-1.yaml", TracerConfig.class); - - assertThat(tracerConfig.getWriter()).isNotNull(); - assertThat(tracerConfig.getSampler()).isNotNull(); - assertThat(tracerConfig.getDefaultServiceName()).isEqualTo("java-app"); - assertThat(tracerConfig.getWriter().getHost()).isEqualTo("foo"); - assertThat(tracerConfig.getWriter().getPort()).isEqualTo(123); - assertThat(tracerConfig.getWriter().getType()).isEqualTo(DDAgentWriter.class.getSimpleName()); - assertThat(tracerConfig.getSampler().getType()).isEqualTo(AllSampler.class.getSimpleName()); - assertThat(tracerConfig.getSampler().getRate()).isNull(); - - - tracerConfig = FactoryUtils.loadConfigFromResource("dd-trace-2.yaml", TracerConfig.class); - assertThat(tracerConfig.getWriter()).isNotNull(); - assertThat(tracerConfig.getDefaultServiceName()).isEqualTo("java-app"); - assertThat(tracerConfig.getWriter().getHost("localhost")).isEqualTo("localhost"); - assertThat(tracerConfig.getWriter().getPort(8126)).isEqualTo(8126); - assertThat(tracerConfig.getWriter().getType()).isEqualTo(DDAgentWriter.class.getSimpleName()); - assertThat(tracerConfig.getSampler().getType()).isEqualTo(RateSampler.class.getSimpleName()); - assertThat(tracerConfig.getSampler().getRate()).isEqualTo(0.4); - + tracerConfig = FactoryUtils.loadConfigFromResource("dd-trace-2.yaml", TracerConfig.class); + assertThat(tracerConfig.getWriter()).isNotNull(); + assertThat(tracerConfig.getDefaultServiceName()).isEqualTo("java-app"); + assertThat(tracerConfig.getWriter().getHost("localhost")).isEqualTo("localhost"); + assertThat(tracerConfig.getWriter().getPort(8126)).isEqualTo(8126); + assertThat(tracerConfig.getWriter().getType()).isEqualTo(DDAgentWriter.class.getSimpleName()); + assertThat(tracerConfig.getSampler().getType()).isEqualTo(RateSampler.class.getSimpleName()); + assertThat(tracerConfig.getSampler().getRate()).isEqualTo(0.4); - } + } } \ No newline at end of file diff --git a/dd-trace/src/test/java/com/datadoghq/trace/resolver/TracerResolverTest.java b/dd-trace/src/test/java/com/datadoghq/trace/resolver/TracerResolverTest.java index 84023cfdf06..59be8119c1f 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/resolver/TracerResolverTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/resolver/TracerResolverTest.java @@ -2,41 +2,39 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.util.List; - -import io.opentracing.tag.Tags; -import org.junit.Test; - import com.datadoghq.trace.DDTracer; import com.datadoghq.trace.integration.DDSpanContextDecorator; import com.datadoghq.trace.integration.HTTPComponent; import com.datadoghq.trace.integration.URLAsResourceName; +import io.opentracing.tag.Tags; +import java.util.List; +import org.junit.Test; public class TracerResolverTest { - @Test - public void test() { - DDTracerResolver tracerResolver = new DDTracerResolver(); - DDTracer tracer = (DDTracer) tracerResolver.resolve(); - - // for HTTP decorators - List decorators = tracer.getSpanContextDecorators(Tags.COMPONENT.getKey()); - - assertThat(decorators.size()).isEqualTo(2); - DDSpanContextDecorator decorator = decorators.get(0); - assertThat(decorator.getClass()).isEqualTo(HTTPComponent.class); - HTTPComponent httpServiceDecorator = (HTTPComponent) decorator; - assertThat(httpServiceDecorator.getMatchingTag()).isEqualTo("component"); - assertThat(httpServiceDecorator.getMatchingValue()).isEqualTo("hello"); - assertThat(httpServiceDecorator.getSetValue()).isEqualTo("world"); - - // for URL decorators - decorators = tracer.getSpanContextDecorators(Tags.HTTP_URL.getKey()); - assertThat(decorators.size()).isEqualTo(1); - - decorator = decorators.get(0); - assertThat(decorator.getClass()).isEqualTo(URLAsResourceName.class); - - } + @Test + public void test() { + DDTracerResolver tracerResolver = new DDTracerResolver(); + DDTracer tracer = (DDTracer) tracerResolver.resolve(); + + // for HTTP decorators + List decorators = tracer.getSpanContextDecorators(Tags.COMPONENT.getKey()); + + assertThat(decorators.size()).isEqualTo(2); + DDSpanContextDecorator decorator = decorators.get(0); + assertThat(decorator.getClass()).isEqualTo(HTTPComponent.class); + HTTPComponent httpServiceDecorator = (HTTPComponent) decorator; + assertThat(httpServiceDecorator.getMatchingTag()).isEqualTo("component"); + assertThat(httpServiceDecorator.getMatchingValue()).isEqualTo("hello"); + assertThat(httpServiceDecorator.getSetValue()).isEqualTo("world"); + + // for URL decorators + decorators = tracer.getSpanContextDecorators(Tags.HTTP_URL.getKey()); + assertThat(decorators.size()).isEqualTo(1); + + decorator = decorators.get(0); + assertThat(decorator.getClass()).isEqualTo(URLAsResourceName.class); + + } } 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 index e0a6d7bed50..ea2d7d98a8f 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/sampling/AllSamplerTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/sampling/AllSamplerTest.java @@ -1,47 +1,46 @@ package com.datadoghq.trace.sampling; -import com.datadoghq.trace.DDSpan; -import org.junit.Test; -import org.mockito.Mock; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import com.datadoghq.trace.DDSpan; 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; +import org.junit.Test; +import org.mockito.Mock; public class AllSamplerTest { - @Mock - DDSpan mockSpan; + @Mock + DDSpan mockSpan; - private final AllSampler sampler = new AllSampler(); + private final AllSampler sampler = new AllSampler(); - @Test - public void testAllSampler() { + @Test + public void testAllSampler() { - for (int i = 0; i < 500; i++) { - assertThat(sampler.doSample(mockSpan)).isTrue(); - } - } + for (int i = 0; i < 500; i++) { + assertThat(sampler.doSample(mockSpan)).isTrue(); + } + } - @Test - public void testSkipTagPatternSampler() { + @Test + public void testSkipTagPatternSampler() { - Map tags = new HashMap<>(); - mockSpan = mock(DDSpan.class); - when(mockSpan.getTags()).thenReturn(tags).thenReturn(tags); + Map tags = new HashMap<>(); + mockSpan = mock(DDSpan.class); + when(mockSpan.getTags()).thenReturn(tags).thenReturn(tags); - sampler.addSkipTagPattern("http.url", Pattern.compile(".*/hello")); + 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/hello"); + assertThat(sampler.sample(mockSpan)).isFalse(); - tags.put("http.url", "http://a/hello2"); - assertThat(sampler.sample(mockSpan)).isTrue(); + 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 index b98ceb7c65d..9f926dee923 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/sampling/ExampleWithDDAgentWriter.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/sampling/ExampleWithDDAgentWriter.java @@ -7,47 +7,45 @@ public class ExampleWithDDAgentWriter { - public static void main(String[] args) throws Exception { + 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 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(); + // 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); - // Create the tracer - DDTracer tracer = new DDTracer(writer, sampler); + Span parent = tracer + .buildSpan("hello-world") + .withServiceName("service-name") + .withSpanType("web") + .start(); + Thread.sleep(100); - Span parent = tracer - .buildSpan("hello-world") - .withServiceName("service-name") - .withSpanType("web") - .start(); + parent.setBaggageItem("a-baggage", "value"); - Thread.sleep(100); + Span child = tracer + .buildSpan("hello-world") + .asChildOf(parent) + .withResourceName("resource-name") + .start(); - parent.setBaggageItem("a-baggage", "value"); + Thread.sleep(100); - Span child = tracer - .buildSpan("hello-world") - .asChildOf(parent) - .withResourceName("resource-name") - .start(); + child.finish(); - Thread.sleep(100); + Thread.sleep(100); - child.finish(); + parent.finish(); - Thread.sleep(100); + writer.close(); - parent.finish(); - - writer.close(); - - } + } } \ No newline at end of file diff --git a/dd-trace/src/test/java/com/datadoghq/trace/writer/impl/DDAgentWriterTest.java b/dd-trace/src/test/java/com/datadoghq/trace/writer/impl/DDAgentWriterTest.java index 80edb066381..d03889a28b3 100644 --- a/dd-trace/src/test/java/com/datadoghq/trace/writer/impl/DDAgentWriterTest.java +++ b/dd-trace/src/test/java/com/datadoghq/trace/writer/impl/DDAgentWriterTest.java @@ -5,66 +5,62 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - import com.datadoghq.trace.DDBaseSpan; import com.datadoghq.trace.DDSpan; import com.datadoghq.trace.DDTracer; import com.datadoghq.trace.writer.DDAgentWriter; import com.datadoghq.trace.writer.DDApi; - -import io.opentracing.Span; +import java.util.ArrayList; +import java.util.List; +import org.junit.Before; +import org.junit.Test; public class DDAgentWriterTest { - DDSpan parent = null; - DDApi mockedAPI = null; - List>> traces = new ArrayList>>(); - DDAgentWriter ddAgentWriter = null; + DDSpan parent = null; + DDApi mockedAPI = null; + List>> traces = new ArrayList>>(); + DDAgentWriter ddAgentWriter = null; + + @Before + public void setUp() throws Exception { + //Setup + DDTracer tracer = new DDTracer(); + + parent = tracer.buildSpan("hello-world").withServiceName("service-name").start(); + parent.setBaggageItem("a-baggage", "value"); - @Before - public void setUp() throws Exception { - //Setup - DDTracer tracer = new DDTracer(); + Thread.sleep(100); - parent = tracer.buildSpan("hello-world").withServiceName("service-name").start(); - parent.setBaggageItem("a-baggage", "value"); + DDSpan child = tracer.buildSpan("hello-world").asChildOf(parent).start(); + Thread.sleep(100); - Thread.sleep(100); + child.finish(); + Thread.sleep(100); + parent.finish(); - DDSpan child = tracer.buildSpan("hello-world").asChildOf(parent).start(); - Thread.sleep(100); + //Create DDWriter + traces.add(parent.context().getTrace()); + mockedAPI = mock(DDApi.class); + when(mockedAPI.sendTraces(traces)).thenReturn(true); + ddAgentWriter = new DDAgentWriter(mockedAPI); + ddAgentWriter.start(); + } - child.finish(); - Thread.sleep(100); - parent.finish(); + @Test + public void testWrite() throws Exception { + ddAgentWriter.write(parent.context().getTrace()); + Thread.sleep(500); + verify(mockedAPI).sendTraces(traces); + } - //Create DDWriter - traces.add(parent.context().getTrace()); - mockedAPI = mock(DDApi.class); - when(mockedAPI.sendTraces(traces)).thenReturn(true); - ddAgentWriter = new DDAgentWriter(mockedAPI); - ddAgentWriter.start(); - } + @Test + public void testClose() throws Exception { + ddAgentWriter.close(); - @Test - public void testWrite() throws Exception{ - ddAgentWriter.write(parent.context().getTrace()); - Thread.sleep(500); - verify(mockedAPI).sendTraces(traces); - } - - @Test - public void testClose() throws Exception{ - ddAgentWriter.close(); - - ddAgentWriter.write(parent.context().getTrace()); - Thread.sleep(500); - verifyNoMoreInteractions(mockedAPI); - } + ddAgentWriter.write(parent.context().getTrace()); + Thread.sleep(500); + verifyNoMoreInteractions(mockedAPI); + } } diff --git a/pom.xml b/pom.xml index 9da053e7461..6e837f98417 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 com.datadoghq @@ -32,8 +33,8 @@ https://github.com/datadog/dd-trace-java scm:git:git://github.com/datadog/dd-trace-java.git scm:git:git@github.com:datadog/dd-trace-java.git - HEAD - + HEAD + dd-trace @@ -59,12 +60,12 @@ http://localhost:8081/nexus/content/repositories/snapshots - - + + - - + +