Use lombok builder for Tracer construction.
This will work better for long-term support without breaking compatibility for adding new fields.
MODIFY
dd-trace-ext/src/main/java/datadog/trace/tracer/ext/Examples.java
dd-trace-ext/src/main/java/datadog/trace/tracer/ext/Examples.java
@@ -12,7 +12,7 @@ class Examples {
public static void test() {
final Throwable someThrowable = null;
// registration
- TracerContext.registerGlobalContext(new TracerContext(new Tracer()), false);
+ TracerContext.registerGlobalContext(new TracerContext(Tracer.builder().build()), false);
// scope
final TracerContext ctx = TracerContext.getGlobalContext();

MODIFY
dd-trace/src/main/java/datadog/trace/tracer/Tracer.java
dd-trace/src/main/java/datadog/trace/tracer/Tracer.java
@@ -4,56 +4,52 @@ import datadog.trace.api.Config;
import datadog.trace.tracer.sampling.AllSampler;
import datadog.trace.tracer.sampling.Sampler;
import datadog.trace.tracer.writer.Writer;
+import java.io.Closeable;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Properties;
+import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
/** A Tracer creates {@link Trace}s and holds common settings across traces. */
@Slf4j
-public class Tracer {
+public class Tracer implements Closeable {
/** Writer is an charge of reporting traces and spans to the desired endpoint */
private final Writer writer;
+
/** Sampler defines the sampling policy in order to reduce the number of traces for instance */
private final Sampler sampler;
+
/** Settings for this tracer. */
private final Config config;
/** Interceptors to be called on certain trace and span events */
private final List<Interceptor> interceptors;
- public Tracer() {
- this(Config.get());
- }
-
- public Tracer(final List<Interceptor> interceptors) {
- this(Config.get(), interceptors);
- }
-
- public Tracer(final Config config) {
- this(config, Collections.<Interceptor>emptyList());
- }
-
- public Tracer(final Config config, final List<Interceptor> interceptors) {
- // TODO: implement and include "standard" interceptors
- this(
- config,
- Writer.Builder.forConfig(config),
- new AllSampler(),
- Collections.unmodifiableList(new ArrayList<>(interceptors)));
- }
-
- Tracer(
+ @Builder
+ private Tracer(
+ final String defaultServiceName,
final Config config,
final Writer writer,
final Sampler sampler,
final List<Interceptor> interceptors) {
- this.config = config;
- // TODO: we probably need to implement some sort of 'close' method for Tracer
- this.writer = writer;
- this.sampler = sampler;
- this.interceptors = Collections.unmodifiableList(new ArrayList<>(interceptors));
+ // Apply defaults:
+ final Properties serviceNameConfig = new Properties();
+ if (defaultServiceName != null && !defaultServiceName.trim().isEmpty()) {
+ serviceNameConfig.setProperty(Config.SERVICE_NAME, defaultServiceName);
+ }
+ this.config = config != null ? config : Config.get(serviceNameConfig);
+ this.writer = writer != null ? writer : Writer.Builder.forConfig(this.config);
+ this.sampler = sampler != null ? sampler : new AllSampler();
+
+ // TODO: implement and include "standard" interceptors
+ this.interceptors =
+ interceptors != null
+ ? Collections.unmodifiableList(new ArrayList<>(interceptors))
+ : Collections.<Interceptor>emptyList();
}
/** @return {@link Writer} used by this tracer */
@@ -123,4 +119,9 @@ public class Tracer {
log.debug(completeMessage);
throw new TraceException(completeMessage);
}
+
+ @Override
+ public void close() throws IOException {
+ writer.close();
+ }
}

MODIFY
dd-trace/src/test/groovy/datadog/trace/tracer/TracerTest.groovy
dd-trace/src/test/groovy/datadog/trace/tracer/TracerTest.groovy
@@ -23,7 +23,7 @@ class TracerTest extends Specification {
// TODO: add more tests for different config options and interceptors
def "test getters"() {
when:
- def tracer = new Tracer(config)
+ def tracer = Tracer.builder().config(config).build()
then:
tracer.getWriter() instanceof AgentWriter
@@ -32,9 +32,23 @@ class TracerTest extends Specification {
tracer.getDefaultServiceName() == config.getServiceName()
}
+ def "test defaultServiceName=#serviceName"() {
+ when:
+ def tracer = Tracer.builder().defaultServiceName(serviceName).build()
+
+ then:
+ tracer.config.serviceName == expected
+
+ where:
+ serviceName | expected
+ null | Config.DEFAULT_SERVICE_NAME
+ "" | Config.DEFAULT_SERVICE_NAME
+ "some-service" | "some-service"
+ }
+
def "test create current timestamp"() {
setup:
- def tracer = new Tracer(config)
+ def tracer = Tracer.builder().config(config).build()
when:
def timestamp = tracer.createCurrentTimestamp()
@@ -45,7 +59,7 @@ class TracerTest extends Specification {
def "test trace happy path"() {
setup:
- def tracer = new Tracer(config, testWriter, new AllSampler(), [])
+ def tracer = Tracer.builder().config(config).writer(testWriter).build()
when:
def rootSpan = tracer.buildTrace(null)
@@ -76,7 +90,7 @@ class TracerTest extends Specification {
//TODO implement this test properly
setup:
def context = Mock(SpanContext)
- def tracer = new Tracer(config, testWriter, new AllSampler(), [])
+ def tracer = Tracer.builder().config(config).writer(testWriter).build()
when:
tracer.inject(context, null, null)
@@ -88,7 +102,7 @@ class TracerTest extends Specification {
def "test extract"() {
//TODO implement this test properly
setup:
- def tracer = new Tracer(config, testWriter, new AllSampler(), [])
+ def tracer = Tracer.builder().config(config).writer(testWriter).build()
when:
def context = tracer.extract(null, null)
@@ -100,7 +114,7 @@ class TracerTest extends Specification {
def testReportError() {
//TODO implement this test properly
setup:
- def tracer = new Tracer(config, testWriter, new AllSampler(), [])
+ def tracer = Tracer.builder().config(config).writer(testWriter).build()
when:
tracer.reportError("message %s", 123)
@@ -111,7 +125,7 @@ class TracerTest extends Specification {
def "test trace that had a GCed span"() {
setup:
- def tracer = new Tracer(config, testWriter, new AllSampler(), [])
+ def tracer = Tracer.builder().config(config).writer(testWriter).build()
when: "trace and spans get created"
def rootSpan = tracer.buildTrace(null)
@@ -137,7 +151,7 @@ class TracerTest extends Specification {
def "test trace that had a GCed continuation"() {
setup:
- def tracer = new Tracer(config, testWriter, new AllSampler(), [])
+ def tracer = Tracer.builder().config(config).writer(testWriter).build()
when: "trace and spans get created"
def rootSpan = tracer.buildTrace(null)

Use lombok builder for Tracer construction.

This will work better for long-term support without breaking compatibility for adding new fields.