Introduce base decorators
MODIFY
dd-java-agent/agent-tooling/agent-tooling.gradle
dd-java-agent/agent-tooling/agent-tooling.gradle
apply from: "${rootDir}/gradle/java.gradle"
+minimumBranchCoverage = 0.6
excludedClassesConverage += ['datadog.trace.agent.tooling.*']
configurations {

ADD
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/decorator/BaseDecorator.java
+package datadog.trace.agent.decorator;
+
+import static io.opentracing.log.Fields.ERROR_OBJECT;
+
+import datadog.trace.api.Config;
+import datadog.trace.api.DDTags;
+import io.opentracing.Span;
+import io.opentracing.tag.Tags;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.TreeSet;
+
+public abstract class BaseDecorator {
+
+ protected final boolean traceAnalyticsEnabled;
+ protected final float traceAnalyticsSampleRate;
+
+ protected BaseDecorator() {
+ traceAnalyticsEnabled =
+ Config.traceAnalyticsIntegrationEnabled(
+ new TreeSet<>(Arrays.asList(instrumentationNames())), traceAnalyticsDefault());
+ float rate = 1.0f;
+ for (final String name : instrumentationNames()) {
+ rate =
+ Config.getFloatSettingFromEnvironment(
+ "integration." + name + ".analytics.sample-rate", rate);
+ }
+ traceAnalyticsSampleRate = rate;
+ }
+
+ protected abstract String[] instrumentationNames();
+
+ protected abstract String spanType();
+
+ protected abstract String component();
+
+ protected boolean traceAnalyticsDefault() {
+ return false;
+ }
+
+ public Span afterStart(final Span span) {
+ assert span != null;
+ span.setTag(DDTags.SPAN_TYPE, spanType());
+ Tags.COMPONENT.set(span, component());
+ if (traceAnalyticsEnabled) {
+ span.setTag(DDTags.ANALYTICS_SAMPLE_RATE, traceAnalyticsSampleRate);
+ }
+ return span;
+ }
+
+ public Span beforeFinish(final Span span) {
+ assert span != null;
+ return span;
+ }
+
+ public Span onError(final Span span, final Throwable throwable) {
+ assert span != null;
+ if (throwable != null) {
+ Tags.ERROR.set(span, true);
+ span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
+ }
+ return span;
+ }
+}

ADD
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/decorator/ClientDecorator.java
+package datadog.trace.agent.decorator;
+
+import datadog.trace.api.DDTags;
+import io.opentracing.Span;
+import io.opentracing.tag.Tags;
+
+public abstract class ClientDecorator extends BaseDecorator {
+
+ protected abstract String service();
+
+ @Override
+ public Span afterStart(final Span span) {
+ assert span != null;
+ if (service() != null) {
+ span.setTag(DDTags.SERVICE_NAME, service());
+ }
+ Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT);
+ return super.afterStart(span);
+ }
+}

ADD
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/decorator/HttpClientDecorator.java
+package datadog.trace.agent.decorator;
+
+import datadog.trace.api.Config;
+import datadog.trace.api.DDSpanTypes;
+import datadog.trace.api.DDTags;
+import io.opentracing.Span;
+import io.opentracing.tag.Tags;
+
+public abstract class HttpClientDecorator<REQUEST, RESPONSE> extends ClientDecorator {
+
+ protected abstract String method(REQUEST request);
+
+ protected abstract String url(REQUEST request);
+
+ protected abstract String hostname(REQUEST request);
+
+ protected abstract Integer port(REQUEST request);
+
+ protected abstract Integer status(RESPONSE response);
+
+ @Override
+ protected String spanType() {
+ return DDSpanTypes.HTTP_CLIENT;
+ }
+
+ public Span onRequest(final Span span, final REQUEST request) {
+ assert span != null;
+ if (request != null) {
+ Tags.HTTP_METHOD.set(span, method(request));
+ Tags.HTTP_URL.set(span, url(request));
+ Tags.PEER_HOSTNAME.set(span, hostname(request));
+ Tags.PEER_PORT.set(span, port(request));
+
+ if (Config.get().isHttpClientSplitByDomain()) {
+ span.setTag(DDTags.SERVICE_NAME, hostname(request));
+ }
+ }
+ return span;
+ }
+
+ public Span onResponse(final Span span, final RESPONSE response) {
+ assert span != null;
+ if (response != null) {
+ final Integer status = status(response);
+ if (status != null) {
+ Tags.HTTP_STATUS.set(span, status);
+ if (400 <= status && status < 500) {
+ Tags.ERROR.set(span, true);
+ }
+ }
+ }
+ return span;
+ }
+}

ADD
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/decorator/HttpServerDecorator.java
+package datadog.trace.agent.decorator;
+
+import datadog.trace.api.Config;
+import datadog.trace.api.DDSpanTypes;
+import io.opentracing.Span;
+import io.opentracing.tag.Tags;
+
+public abstract class HttpServerDecorator<REQUEST, RESPONSE> extends ServerDecorator {
+
+ protected abstract String method(REQUEST request);
+
+ protected abstract String url(REQUEST request);
+
+ protected abstract String hostname(REQUEST request);
+
+ protected abstract Integer port(REQUEST request);
+
+ protected abstract Integer status(RESPONSE response);
+
+ @Override
+ protected String spanType() {
+ return DDSpanTypes.HTTP_SERVER;
+ }
+
+ @Override
+ protected boolean traceAnalyticsDefault() {
+ return Config.getBooleanSettingFromEnvironment(Config.TRACE_ANALYTICS_ENABLED, false);
+ }
+
+ public Span onRequest(final Span span, final REQUEST request) {
+ assert span != null;
+ if (request != null) {
+ Tags.HTTP_METHOD.set(span, method(request));
+ Tags.HTTP_URL.set(span, url(request));
+ Tags.PEER_HOSTNAME.set(span, hostname(request));
+ Tags.PEER_PORT.set(span, port(request));
+ // TODO set resource name from URL.
+ }
+ return span;
+ }
+
+ public Span onResponse(final Span span, final RESPONSE response) {
+ assert span != null;
+ if (response != null) {
+ final Integer status = status(response);
+ if (status != null) {
+ Tags.HTTP_STATUS.set(span, status);
+ if (status >= 500) {
+ Tags.ERROR.set(span, true);
+ }
+ }
+ }
+ return span;
+ }
+
+ // @Override
+ // public Span onError(final Span span, final Throwable throwable) {
+ // assert span != null;
+ // // FIXME
+ // final Object status = span.getTag("http.status");
+ // if (status == null || status.equals(200)) {
+ // // Ensure status set correctly
+ // span.setTag("http.status", 500);
+ // }
+ // return super.onError(span, throwable);
+ // }
+}

ADD
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/decorator/ServerDecorator.java
+package datadog.trace.agent.decorator;
+
+import io.opentracing.Span;
+import io.opentracing.tag.Tags;
+
+public abstract class ServerDecorator extends BaseDecorator {
+
+ @Override
+ public Span afterStart(final Span span) {
+ assert span != null;
+ Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_SERVER);
+ return super.afterStart(span);
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/decorator/BaseDecoratorTest.groovy
+package datadog.trace.agent.decorator
+
+import datadog.trace.api.DDTags
+import io.opentracing.Span
+import io.opentracing.tag.Tags
+import spock.lang.Shared
+import spock.lang.Specification
+
+import static datadog.trace.agent.test.utils.TraceUtils.withSystemProperty
+import static io.opentracing.log.Fields.ERROR_OBJECT
+
+class BaseDecoratorTest extends Specification {
+
+ @Shared
+ def decorator = newDecorator()
+
+ def span = Mock(Span)
+
+ def "test afterStart"() {
+ when:
+ decorator.afterStart(span)
+
+ then:
+ 1 * span.setTag(DDTags.SPAN_TYPE, decorator.spanType())
+ 1 * span.setTag(Tags.COMPONENT.key, "test-component")
+ _ * span.setTag(_, _) // Want to allow other calls from child implementations.
+ 0 * _
+ }
+
+ def "test onError"() {
+ when:
+ decorator.onError(span, error)
+
+ then:
+ if (error) {
+ 1 * span.setTag(Tags.ERROR.key, true)
+ 1 * span.log([(ERROR_OBJECT): error])
+ }
+ 0 * _
+
+ where:
+ error << [new Exception(), null]
+ }
+
+ def "test beforeFinish"() {
+ when:
+ decorator.beforeFinish(span)
+
+ then:
+ 0 * _
+ }
+
+ def "test assert null span"() {
+ when:
+ decorator.afterStart(null)
+
+ then:
+ thrown(AssertionError)
+
+ when:
+ decorator.onError(null, null)
+
+ then:
+ thrown(AssertionError)
+
+ when:
+ decorator.beforeFinish(null)
+
+ then:
+ thrown(AssertionError)
+ }
+
+ def "test analytics rate default disabled"() {
+ when:
+ BaseDecorator dec = newDecorator(defaultEnabled)
+
+ then:
+ dec.traceAnalyticsEnabled == defaultEnabled
+ dec.traceAnalyticsSampleRate == sampleRate
+
+ where:
+ defaultEnabled | sampleRate
+ true | 1.0
+ false | 1.0
+ }
+
+ def "test analytics rate enabled"() {
+ when:
+ BaseDecorator dec = withSystemProperty("dd.integration.${integName}.analytics.enabled", "true") {
+ withSystemProperty("dd.integration.${integName}.analytics.sample-rate", "$sampleRate") {
+ newDecorator(enabled)
+ }
+ }
+
+ then:
+ dec.traceAnalyticsEnabled == expectedEnabled
+ dec.traceAnalyticsSampleRate == (Float) expectedRate
+
+ where:
+ enabled | integName | sampleRate | expectedEnabled | expectedRate
+ false | "" | "" | false | 1.0
+ true | "" | "" | true | 1.0
+ false | "test1" | 0.5 | true | 0.5
+ false | "test2" | 0.75 | true | 0.75
+ true | "test1" | 0.2 | true | 0.2
+ true | "test2" | 0.4 | true | 0.4
+ true | "test1" | "" | true | 1.0
+ true | "test2" | "" | true | 1.0
+ }
+
+ def newDecorator() {
+ return newDecorator(false)
+ }
+
+ def newDecorator(final Boolean analyticsEnabledDefault) {
+ return analyticsEnabledDefault ?
+ new BaseDecorator() {
+ @Override
+ protected String[] instrumentationNames() {
+ return ["test1", "test2"]
+ }
+
+ @Override
+ protected String spanType() {
+ return "test-type"
+ }
+
+ @Override
+ protected String component() {
+ return "test-component"
+ }
+
+ protected boolean traceAnalyticsDefault() {
+ return true
+ }
+ } :
+ new BaseDecorator() {
+ @Override
+ protected String[] instrumentationNames() {
+ return ["test1", "test2"]
+ }
+
+ @Override
+ protected String spanType() {
+ return "test-type"
+ }
+
+ @Override
+ protected String component() {
+ return "test-component"
+ }
+ }
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/decorator/ClientDecoratorTest.groovy
+package datadog.trace.agent.decorator
+
+import datadog.trace.api.DDTags
+import io.opentracing.Span
+import io.opentracing.tag.Tags
+
+class ClientDecoratorTest extends BaseDecoratorTest {
+
+ def span = Mock(Span)
+
+ def "test afterStart"() {
+ setup:
+ def decorator = newDecorator((String) serviceName)
+
+ when:
+ decorator.afterStart(span)
+
+ then:
+ if (serviceName != null) {
+ 1 * span.setTag(DDTags.SERVICE_NAME, serviceName)
+ }
+ 1 * span.setTag(Tags.COMPONENT.key, "test-component")
+ 1 * span.setTag(Tags.SPAN_KIND.key, "client")
+ 1 * span.setTag(DDTags.SPAN_TYPE, decorator.spanType())
+ 1 * span.setTag(DDTags.ANALYTICS_SAMPLE_RATE, 1.0)
+ 0 * _
+
+ where:
+ serviceName << ["test-service", "other-service", null]
+ }
+
+ def "test beforeFinish"() {
+ when:
+ newDecorator("test-service").beforeFinish(span)
+
+ then:
+ 0 * _
+ }
+
+ @Override
+ def newDecorator() {
+ return newDecorator("test-service")
+ }
+
+ def newDecorator(String serviceName) {
+ return new ClientDecorator() {
+ @Override
+ protected String[] instrumentationNames() {
+ return ["test1", "test2"]
+ }
+
+ @Override
+ protected String service() {
+ return serviceName
+ }
+
+ @Override
+ protected String spanType() {
+ return "test-type"
+ }
+
+ @Override
+ protected String component() {
+ return "test-component"
+ }
+
+ protected boolean traceAnalyticsDefault() {
+ return true
+ }
+ }
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/decorator/HttpClientDecoratorTest.groovy
+package datadog.trace.agent.decorator
+
+import datadog.trace.api.Config
+import datadog.trace.api.DDTags
+import io.opentracing.Span
+import io.opentracing.tag.Tags
+
+import static datadog.trace.agent.test.utils.TraceUtils.withConfigOverride
+
+class HttpClientDecoratorTest extends ClientDecoratorTest {
+
+ def span = Mock(Span)
+
+ def "test onRequest"() {
+ setup:
+ def decorator = newDecorator()
+
+ when:
+ withConfigOverride(Config.HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "$renameService") {
+ decorator.onRequest(span, req)
+ }
+
+ then:
+ if (req) {
+ 1 * span.setTag(Tags.HTTP_METHOD.key, "test-method")
+ 1 * span.setTag(Tags.HTTP_URL.key, "test-url")
+ 1 * span.setTag(Tags.PEER_HOSTNAME.key, "test-host")
+ 1 * span.setTag(Tags.PEER_PORT.key, 555)
+ if (renameService) {
+ 1 * span.setTag(DDTags.SERVICE_NAME, "test-host")
+ }
+ }
+ 0 * _
+
+ where:
+ renameService | req
+ false | null
+ true | null
+ false | [method: "test-method", url: "test-url", host: "test-host", port: 555]
+ true | [method: "test-method", url: "test-url", host: "test-host", port: 555]
+ }
+
+ def "test onResponse"() {
+ setup:
+ def decorator = newDecorator()
+
+ when:
+ decorator.onResponse(span, resp)
+
+ then:
+ if (status) {
+ 1 * span.setTag(Tags.HTTP_STATUS.key, status)
+ }
+ if (error) {
+ 1 * span.setTag(Tags.ERROR.key, true)
+ }
+ 0 * _
+
+ where:
+ status | error | resp
+ 200 | false | [status: 200]
+ 399 | false | [status: 399]
+ 400 | true | [status: 400]
+ 499 | true | [status: 499]
+ 500 | false | [status: 500]
+ 600 | false | [status: 600]
+ null | false | [status: null]
+ null | false | null
+ }
+
+ def "test assert null span"() {
+ setup:
+ def decorator = newDecorator()
+
+ when:
+ decorator.onRequest(null, null)
+
+ then:
+ thrown(AssertionError)
+
+ when:
+ decorator.onResponse(null, null)
+
+ then:
+ thrown(AssertionError)
+ }
+
+ @Override
+ def newDecorator(String serviceName = "test-service") {
+ return new HttpClientDecorator<Map, Map>() {
+ @Override
+ protected String[] instrumentationNames() {
+ return ["test1", "test2"]
+ }
+
+ @Override
+ protected String service() {
+ return serviceName
+ }
+
+ @Override
+ protected String component() {
+ return "test-component"
+ }
+
+ @Override
+ protected String method(Map m) {
+ return m.method
+ }
+
+ @Override
+ protected String url(Map m) {
+ return m.url
+ }
+
+ @Override
+ protected String hostname(Map m) {
+ return m.host
+ }
+
+ @Override
+ protected Integer port(Map m) {
+ return m.port
+ }
+
+ @Override
+ protected Integer status(Map m) {
+ return m.status
+ }
+
+ protected boolean traceAnalyticsDefault() {
+ return true
+ }
+ }
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/decorator/HttpServerDecoratorTest.groovy
+package datadog.trace.agent.decorator
+
+import io.opentracing.Span
+import io.opentracing.tag.Tags
+
+class HttpServerDecoratorTest extends ServerDecoratorTest {
+
+ def span = Mock(Span)
+
+ def "test onRequest"() {
+ setup:
+ def decorator = newDecorator()
+
+ when:
+ decorator.onRequest(span, req)
+
+ then:
+ if (req) {
+ 1 * span.setTag(Tags.HTTP_METHOD.key, "test-method")
+ 1 * span.setTag(Tags.HTTP_URL.key, "test-url")
+ 1 * span.setTag(Tags.PEER_HOSTNAME.key, "test-host")
+ 1 * span.setTag(Tags.PEER_PORT.key, 555)
+ }
+ 0 * _
+
+ where:
+ req << [null, [method: "test-method", url: "test-url", host: "test-host", port: 555]]
+ }
+
+ def "test onResponse"() {
+ setup:
+ def decorator = newDecorator()
+
+ when:
+ decorator.onResponse(span, resp)
+
+ then:
+ if (status) {
+ 1 * span.setTag(Tags.HTTP_STATUS.key, status)
+ }
+ if (error) {
+ 1 * span.setTag(Tags.ERROR.key, true)
+ }
+ 0 * _
+
+ where:
+ status | error | resp
+ 200 | false | [status: 200]
+ 399 | false | [status: 399]
+ 400 | false | [status: 400]
+ 499 | false | [status: 499]
+ 500 | true | [status: 500]
+ 600 | true | [status: 600]
+ null | false | [status: null]
+ null | false | null
+ }
+
+ def "test assert null span"() {
+ setup:
+ def decorator = newDecorator()
+
+ when:
+ decorator.onRequest(null, null)
+
+ then:
+ thrown(AssertionError)
+
+ when:
+ decorator.onResponse(null, null)
+
+ then:
+ thrown(AssertionError)
+ }
+
+ @Override
+ def newDecorator() {
+ return new HttpServerDecorator<Map, Map>() {
+ @Override
+ protected String[] instrumentationNames() {
+ return ["test1", "test2"]
+ }
+
+ @Override
+ protected String component() {
+ return "test-component"
+ }
+
+ @Override
+ protected String method(Map m) {
+ return m.method
+ }
+
+ @Override
+ protected String url(Map m) {
+ return m.url
+ }
+
+ @Override
+ protected String hostname(Map m) {
+ return m.host
+ }
+
+ @Override
+ protected Integer port(Map m) {
+ return m.port
+ }
+
+ @Override
+ protected Integer status(Map m) {
+ return m.status
+ }
+ }
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/decorator/ServerDecoratorTest.groovy
+package datadog.trace.agent.decorator
+
+import datadog.trace.api.DDTags
+import io.opentracing.Span
+import io.opentracing.tag.Tags
+
+class ServerDecoratorTest extends BaseDecoratorTest {
+
+ def span = Mock(Span)
+
+ def "test afterStart"() {
+ def decorator = newDecorator()
+ when:
+ decorator.afterStart(span)
+
+ then:
+ 1 * span.setTag(Tags.COMPONENT.key, "test-component")
+ 1 * span.setTag(Tags.SPAN_KIND.key, "server")
+ 1 * span.setTag(DDTags.SPAN_TYPE, decorator.spanType())
+ if (decorator.traceAnalyticsEnabled) {
+ 1 * span.setTag(DDTags.ANALYTICS_SAMPLE_RATE, 1.0)
+ }
+ 0 * _
+ }
+
+ def "test beforeFinish"() {
+ when:
+ newDecorator().beforeFinish(span)
+
+ then:
+ 0 * _
+ }
+
+ @Override
+ def newDecorator() {
+ return new ServerDecorator() {
+ @Override
+ protected String[] instrumentationNames() {
+ return ["test1", "test2"]
+ }
+
+ @Override
+ protected String spanType() {
+ return "test-type"
+ }
+
+ @Override
+ protected String component() {
+ return "test-component"
+ }
+
+ protected boolean traceAnalyticsDefault() {
+ return true
+ }
+ }
+ }
+}

MODIFY
dd-java-agent/instrumentation/trace-annotation/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy
dd-java-agent/instrumentation/trace-annotation/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy
@@ -4,8 +4,8 @@ import dd.test.trace.annotation.SayTracedHello
import java.util.concurrent.Callable
-import static TraceAnnotationsInstrumentation.DEFAULT_ANNOTATIONS
import static datadog.trace.agent.test.utils.TraceUtils.withSystemProperty
+import static datadog.trace.instrumentation.trace_annotation.TraceAnnotationsInstrumentation.DEFAULT_ANNOTATIONS
class ConfiguredTraceAnnotationsTest extends AgentTestRunner {
@@ -46,11 +46,10 @@ class ConfiguredTraceAnnotationsTest extends AgentTestRunner {
def "test configuration #value"() {
setup:
- def config = null
- withSystemProperty("dd.trace.annotations", value) {
- def instrumentation = new TraceAnnotationsInstrumentation()
- config = instrumentation.additionalTraceAnnotations
+ def config = withSystemProperty("dd.trace.annotations", value) {
+ new TraceAnnotationsInstrumentation().additionalTraceAnnotations
}
+
expect:
config == expected.toSet()

MODIFY
dd-trace-api/src/main/java/datadog/trace/api/Config.java
dd-trace-api/src/main/java/datadog/trace/api/Config.java
@@ -332,7 +332,7 @@ public class Config {
public static Boolean getBooleanSettingFromEnvironment(
final String name, final Boolean defaultValue) {
final String value = getSettingFromEnvironment(name, null);
- return value == null ? defaultValue : Boolean.valueOf(value);
+ return value == null || value.trim().isEmpty() ? defaultValue : Boolean.valueOf(value);
}
/**
@@ -344,13 +344,23 @@ public class Config {
*/
public static Float getFloatSettingFromEnvironment(final String name, final Float defaultValue) {
final String value = getSettingFromEnvironment(name, null);
+ try {
return value == null ? defaultValue : Float.valueOf(value);
+ } catch (final NumberFormatException e) {
+ log.warn("Invalid configuration for " + name, e);
+ return defaultValue;
+ }
}
private static Integer getIntegerSettingFromEnvironment(
final String name, final Integer defaultValue) {
final String value = getSettingFromEnvironment(name, null);
+ try {
return value == null ? defaultValue : Integer.valueOf(value);
+ } catch (final NumberFormatException e) {
+ log.warn("Invalid configuration for " + name, e);
+ return defaultValue;
+ }
}
private static String propertyToEnvironmentName(final String name) {
@@ -360,25 +370,25 @@ public class Config {
private static Map<String, String> getPropertyMapValue(
final Properties properties, final String name, final Map<String, String> defaultValue) {
final String value = properties.getProperty(name);
- return value == null ? defaultValue : parseMap(value, name);
+ return value == null || value.trim().isEmpty() ? defaultValue : parseMap(value, name);
}
private static List<String> getPropertyListValue(
final Properties properties, final String name, final List<String> defaultValue) {
final String value = properties.getProperty(name);
- return value == null ? defaultValue : parseList(value);
+ return value == null || value.trim().isEmpty() ? defaultValue : parseList(value);
}
private static Boolean getPropertyBooleanValue(
final Properties properties, final String name, final Boolean defaultValue) {
final String value = properties.getProperty(name);
- return value == null ? defaultValue : Boolean.valueOf(value);
+ return value == null || value.trim().isEmpty() ? defaultValue : Boolean.valueOf(value);
}
private static Integer getPropertyIntegerValue(
final Properties properties, final String name, final Integer defaultValue) {
final String value = properties.getProperty(name);
- return value == null ? defaultValue : Integer.valueOf(value);
+ return value == null || value.trim().isEmpty() ? defaultValue : Integer.valueOf(value);
}
private static Map<String, String> parseMap(final String str, final String settingName) {

MODIFY
dd-trace-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy
dd-trace-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy
@@ -160,6 +160,36 @@ class ConfigTest extends Specification {
config.agentPort == 123
}
+ def "default when configured incorrectly"() {
+ setup:
+ System.setProperty(PREFIX + SERVICE_NAME, " ")
+ System.setProperty(PREFIX + WRITER_TYPE, " ")
+ System.setProperty(PREFIX + AGENT_HOST, " ")
+ System.setProperty(PREFIX + TRACE_AGENT_PORT, " ")
+ System.setProperty(PREFIX + AGENT_PORT_LEGACY, "invalid")
+ System.setProperty(PREFIX + PRIORITY_SAMPLING, "3")
+ System.setProperty(PREFIX + TRACE_RESOLVER_ENABLED, " ")
+ System.setProperty(PREFIX + SERVICE_MAPPING, " ")
+ System.setProperty(PREFIX + HEADER_TAGS, "1")
+ System.setProperty(PREFIX + SPAN_TAGS, "invalid")
+ System.setProperty(PREFIX + HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "invalid")
+
+ when:
+ def config = new Config()
+
+ then:
+ config.serviceName == " "
+ config.writerType == " "
+ config.agentHost == " "
+ config.agentPort == 8126
+ config.prioritySamplingEnabled == false
+ config.traceResolverEnabled == true
+ config.serviceMapping == [:]
+ config.mergedSpanTags == [:]
+ config.headerTags == [:]
+ config.httpClientSplitByDomain == false
+ }
+
def "sys props and env vars overrides for trace_agent_port and agent_port_legacy as expected"() {
setup:
if (overridePortEnvVar) {
@@ -349,6 +379,33 @@ class ConfigTest extends Specification {
integrationNames = new TreeSet<>(names)
}
+ def "test getFloatSettingFromEnvironment(#name)"() {
+ setup:
+ environmentVariables.set("DD_ENV_ZERO_TEST", "0.0")
+ environmentVariables.set("DD_ENV_FLOAT_TEST", "1.0")
+ environmentVariables.set("DD_FLOAT_TEST", "0.2")
+
+ System.setProperty("dd.prop.zero.test", "0")
+ System.setProperty("dd.prop.float.test", "0.3")
+ System.setProperty("dd.float.test", "0.4")
+ System.setProperty("dd.negative.test", "-1")
+
+ expect:
+ Config.getFloatSettingFromEnvironment(name, defaultValue) == (float) expected
+
+ where:
+ name | expected
+ "env.zero.test" | 0.0
+ "prop.zero.test" | 0
+ "env.float.test" | 1.0
+ "prop.float.test" | 0.3
+ "float.test" | 0.4
+ "negative.test" | -1.0
+ "default.test" | 10.0
+
+ defaultValue = 10.0
+ }
+
def "verify mapping configs on tracer"() {
setup:
System.setProperty(PREFIX + SERVICE_MAPPING, mapString)
@@ -402,6 +459,7 @@ class ConfigTest extends Specification {
where:
mapString | map
null | [:]
+ "" | [:]
}
def "verify empty value list configs on tracer"() {

Introduce base decorators