opentelemetry-java-instrume.../dd-trace/README.md

8.8 KiB

Datadog Opentracing Tracer

Motivations

The Datadog Tracer is an Opentracing compatible tracer. It provides all resources needed to instrument your code and report each operation and each trace directly to a Datadog APM platform.

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.

For instance, a client requesting a resource through an HTTP endpoint. Look at the following workflow.

TRACE:

   client ---> HTTP Endpoint ---> DB Query/Result ---> Custom processing ---> client
  
   SPAN 1 (Root Span) ................................................... (end)   - 200ms
   |--------SPAN 2 (Child of 1).................................(end)             - 100ms
            |-----------SPAN 3 (Child of 2).(end)                                 - 50 ms
            |----------------------------------------SPAN 4 (Child of 2)..(end)   - 50 ms

Opentracing provides a way for measuring the time consumed for each operation. As just described, the tracer produces a trace composed of 4 spans, each representing a specific action:

  1. Span1 is the time from doing the request to getting the response.
  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/legacy operation.

This is a very simple example of how works Opentracing. To dig deeper, read the full documentation: http://opentracing.io/

How to instrument your application?

There are 3 ways to instrument an application:

  1. Use the autotracing agent for supported frawemorks
  2. Use the Opentracing API
  3. Use annotations

Use the Datadog Java agent for well-known framework

Datadog uses instrumentation contributed by the community to instrument many frameworks: SpringBoot, JDBC, Mongo, JMS, Tomcat, etc. By using the Datadog Java agent, you just need to follow few steps in order to get traces.

Get the latest version of the Datadog Java agent (Do not forget to replace the version ${version} by the appropriate one).

version=0.1.1
curl -OL http://central.maven.org/maven2/com/datadoghq/dd-java-agent/${version}/dd-java-agent-${version}.jar 

Then, attach the Java agent to your JVM using th javaagent option.

java -javaagent:/path/to/dd-java-agent-${version}.jar ...

If you have a local Datadog agent running on your host, traces are visible in your Datadog account.

You can choose which framework you want to instrument, or sending traces to a remote Datadog agent by configuring the Datadog Java Agent YAML file. Check the dedicated project for the full documentation: dd-java-agent

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: .

Let's look at a simple example.

class InstrumentedClass {

    
    void method0() {
        // 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();
        new io.opentracing.tag.StringTag("service-name").set(span, "new-service-name"); 
        
        
        //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 or manually in the bootstrap method (like the main).

public class Application {

    public static void main(String[] args) {
	
        // Init the tracer from the configuration file      
        Tracer tracer = DDTracerFactory.createFromConfigurationFile();
        io.opentracing.util.GlobalTracer.register(tracer);
        
        // Init the tracer from the API
        Writer writer = new com.datadoghq.trace.writer.DDAgentWriter();
        Sampler sampler = new com.datadoghq.trace.sampling.AllSampler();
        Tracer tracer = new com.datadoghq.trace.DDTracer(writer, sampler);
        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

# Service name used if none is provided in the app
defaultServiceName: unnamed-java-app

# The writer to use.
# Could be: LoggingWritter or DDAgentWriter (default)
writer:
  # LoggingWriter: Spans are logged using the application configuration
  # DDAgentWriter: Spans are forwarding to a Datadog Agent
  #  - Param 'host': the hostname where the DD Agent running (default: localhost)
  #  - Param 'port': the port to reach the DD Agent (default: 8126)
  type: DDAgentWriter
  host: localhost
  port: 8126

# The sampler to use.
# Could be: AllSampler (default) or RateSampler
sampler:
  # AllSampler: all spans are reported to the writer
  # RateSample: only a portion of spans are reported to the writer
  #  - Param 'rate': the portion of spans to keep
  type: AllSampler

Do not forget to add the corresponding dependencies to your project.

        <!-- Opentracing API -->
        <dependency>
            <groupId>io.opentracing</groupId>
            <artifactId>opentracing-api</artifactId>
            <version>${opentracing.version}</version>
        </dependency>
        
        <!-- Datadog Tracer (only needed if you do not use the Datadog autotracing agent) -->
        <dependency>
            <groupId>com.datadoghq</groupId>
            <artifactId>dd-trace</artifactId>
            <version>${dd-trace-java.version}</version>
        </dependency>

Custom instrumentations using Annotation

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.

class InstrumentedClass {

    @Trace(operationName = "operation-name-1")
    void method1() {

        //Do some thing here ...
        Thread.sleep(1_000);
    }	
    
    @Trace(operationName = "operation-name-2")
    void method2() {
        
        // You can get the current span and add tag as follow
        Span current = io.opentracing.util.GlobalTracer.get().activeSpan();
        new io.opentracing.tag.StringTag("service-name").set(current, "new-service-name");

        //Do some thing here ...
        Thread.sleep(1_000);
    }	
}

In order to use annotations, the only required dependency is that package.

        <!-- Datadog annotations -->
        <dependency>
            <groupId>com.datadoghq</groupId>
            <artifactId>dd-trace-annotations</artifactId>
            <version>${dd-trace-java.version}</version>
        </dependency>

The annotations are resolved at the runtime by the Datadog Java agent. If you want to use the annotations, so you must run the Datadog Java Agent.

To run the agent, please refer to the Datadog Java agent documentation: dd-java-agent

Other useful resources

Before instrumenting your own project you might want to run the provided examples:

Other links that you might want to read:

And for any questions, feedback, feel free to send us an email: support@datadoghq.com