Merge pull request #496 from DataDog/mar-kolya/move-tracer-config-to-api
Refactor DDTraceConfig to a Config we can use globally
This commit is contained in:
commit
c3f7630387
|
@ -1,6 +1,15 @@
|
|||
apply from: "${rootDir}/gradle/java.gradle"
|
||||
apply from: "${rootDir}/gradle/publish.gradle"
|
||||
|
||||
// These are tested outside of this module since this module mainly just defines 'API'
|
||||
excludedClassesConverage += [
|
||||
'datadog.trace.api.DDSpanTypes',
|
||||
'datadog.trace.api.DDTraceApiInfo',
|
||||
'datadog.trace.api.GlobalTracer*',
|
||||
'datadog.trace.api.CorrelationIdentifier',
|
||||
'datadog.trace.api.DDTags'
|
||||
]
|
||||
|
||||
description = 'dd-trace-api'
|
||||
dependencies {
|
||||
compile deps.slf4j
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
package datadog.trace.api;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Config gives priority to system properties and falls back to environment variables. It also
|
||||
* includes default values to ensure a valid config.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* <p>System properties are {@link Config#PREFIX}'ed. Environment variables are the same as the
|
||||
* system property, but uppercased with '.' -> '_'.
|
||||
*/
|
||||
@Slf4j
|
||||
@ToString(includeFieldNames = true)
|
||||
public class Config {
|
||||
/** Config keys below */
|
||||
private static final String PREFIX = "dd.";
|
||||
|
||||
private static final Config INSTANCE = new Config();
|
||||
|
||||
public static final String SERVICE_NAME = "service.name";
|
||||
public static final String SERVICE_MAPPING = "service.mapping";
|
||||
public static final String WRITER_TYPE = "writer.type";
|
||||
public static final String AGENT_HOST = "agent.host";
|
||||
public static final String AGENT_PORT = "agent.port";
|
||||
public static final String PRIORITY_SAMPLING = "priority.sampling";
|
||||
public static final String TRACE_RESOLVER_ENABLED = "trace.resolver.enabled";
|
||||
public static final String SPAN_TAGS = "trace.span.tags";
|
||||
public static final String HEADER_TAGS = "trace.header.tags";
|
||||
|
||||
public static final String DEFAULT_SERVICE_NAME = "unnamed-java-app";
|
||||
|
||||
public static final String DD_AGENT_WRITER_TYPE = "DDAgentWriter";
|
||||
public static final String LOGGING_WRITER_TYPE = "LoggingWriter";
|
||||
public static final String DEFAULT_AGENT_WRITER_TYPE = DD_AGENT_WRITER_TYPE;
|
||||
|
||||
public static final String DEFAULT_AGENT_HOST = "localhost";
|
||||
public static final int DEFAULT_AGENT_PORT = 8126;
|
||||
|
||||
private static final String DEFAULT_PRIORITY_SAMPLING_ENABLED = "false";
|
||||
private static final String DEFAULT_TRACE_RESOLVER_ENABLED = "true";
|
||||
|
||||
@Getter private final String serviceName;
|
||||
@Getter private final String writerType;
|
||||
@Getter private final String agentHost;
|
||||
@Getter private final int agentPort;
|
||||
@Getter private final boolean prioritySamplingEnabled;
|
||||
@Getter private final boolean traceResolverEnabled;
|
||||
@Getter private final Map<String, String> serviceMapping;
|
||||
@Getter private final Map<String, String> spanTags;
|
||||
@Getter private final Map<String, String> headerTags;
|
||||
|
||||
// Read order: System Properties -> Env Variables, [-> default value]
|
||||
// Visible for testing
|
||||
Config() {
|
||||
serviceName = getSettingFromEnvironment(SERVICE_NAME, DEFAULT_SERVICE_NAME);
|
||||
writerType = getSettingFromEnvironment(WRITER_TYPE, DEFAULT_AGENT_WRITER_TYPE);
|
||||
agentHost = getSettingFromEnvironment(AGENT_HOST, DEFAULT_AGENT_HOST);
|
||||
agentPort =
|
||||
Integer.valueOf(
|
||||
getSettingFromEnvironment(AGENT_PORT, Integer.toString(DEFAULT_AGENT_PORT)));
|
||||
prioritySamplingEnabled =
|
||||
Boolean.valueOf(
|
||||
getSettingFromEnvironment(PRIORITY_SAMPLING, DEFAULT_PRIORITY_SAMPLING_ENABLED));
|
||||
traceResolverEnabled =
|
||||
Boolean.valueOf(
|
||||
getSettingFromEnvironment(TRACE_RESOLVER_ENABLED, DEFAULT_TRACE_RESOLVER_ENABLED));
|
||||
serviceMapping = getMapSettingFromEnvironment(SERVICE_MAPPING, null);
|
||||
spanTags = getMapSettingFromEnvironment(SPAN_TAGS, null);
|
||||
headerTags = getMapSettingFromEnvironment(HEADER_TAGS, null);
|
||||
}
|
||||
|
||||
// Read order: Properties -> Parent
|
||||
private Config(final Properties properties, final Config parent) {
|
||||
serviceName = properties.getProperty(SERVICE_NAME, parent.serviceName);
|
||||
writerType = properties.getProperty(WRITER_TYPE, parent.writerType);
|
||||
agentHost = properties.getProperty(AGENT_HOST, parent.agentHost);
|
||||
agentPort =
|
||||
Integer.valueOf(properties.getProperty(AGENT_PORT, Integer.toString(parent.agentPort)));
|
||||
prioritySamplingEnabled =
|
||||
Boolean.valueOf(
|
||||
properties.getProperty(
|
||||
PRIORITY_SAMPLING, Boolean.toString(parent.prioritySamplingEnabled)));
|
||||
traceResolverEnabled =
|
||||
Boolean.valueOf(
|
||||
properties.getProperty(
|
||||
TRACE_RESOLVER_ENABLED, Boolean.toString(parent.traceResolverEnabled)));
|
||||
serviceMapping = getPropertyMapValue(properties, SERVICE_MAPPING, parent.serviceMapping);
|
||||
spanTags = getPropertyMapValue(properties, SPAN_TAGS, parent.spanTags);
|
||||
headerTags = getPropertyMapValue(properties, HEADER_TAGS, parent.headerTags);
|
||||
}
|
||||
|
||||
private static String getSettingFromEnvironment(final String name, final String defaultValue) {
|
||||
final String completeName = PREFIX + name;
|
||||
final String value =
|
||||
System.getProperties()
|
||||
.getProperty(completeName, System.getenv(propertyToEnvironmentName(completeName)));
|
||||
return value == null ? defaultValue : value;
|
||||
}
|
||||
|
||||
private static Map<String, String> getMapSettingFromEnvironment(
|
||||
final String name, final String defaultValue) {
|
||||
return parseMap(getSettingFromEnvironment(name, defaultValue), PREFIX + name);
|
||||
}
|
||||
|
||||
private static String propertyToEnvironmentName(final String name) {
|
||||
return name.toUpperCase().replace(".", "_");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private static Map<String, String> parseMap(final String str, final String settingName) {
|
||||
if (str == null || str.trim().isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
if (!str.matches("(([^,:]+:[^,:]*,)*([^,:]+:[^,:]*),?)?")) {
|
||||
log.warn(
|
||||
"Invalid config for {}: '{}'. Must match 'key1:value1,key2:value2'.", settingName, str);
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
final String[] tokens = str.split(",", -1);
|
||||
final Map<String, String> map = new HashMap<>(tokens.length + 1, 1f);
|
||||
|
||||
for (final String token : tokens) {
|
||||
final String[] keyValue = token.split(":", -1);
|
||||
if (keyValue.length == 2) {
|
||||
final String key = keyValue[0].trim();
|
||||
final String value = keyValue[1].trim();
|
||||
if (value.length() <= 0) {
|
||||
log.warn("Ignoring empty value for key '{}' in config for {}", key, settingName);
|
||||
continue;
|
||||
}
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
public static Config get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static Config get(final Properties properties) {
|
||||
if (properties == null || properties.isEmpty()) {
|
||||
return INSTANCE;
|
||||
} else {
|
||||
return new Config(properties, INSTANCE);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
package datadog.trace.api
|
||||
|
||||
import org.junit.Rule
|
||||
import org.junit.contrib.java.lang.system.EnvironmentVariables
|
||||
import org.junit.contrib.java.lang.system.RestoreSystemProperties
|
||||
import spock.lang.Specification
|
||||
|
||||
import static Config.AGENT_HOST
|
||||
import static Config.AGENT_PORT
|
||||
import static Config.HEADER_TAGS
|
||||
import static Config.PREFIX
|
||||
import static Config.SERVICE_MAPPING
|
||||
import static Config.SERVICE_NAME
|
||||
import static Config.SPAN_TAGS
|
||||
import static Config.WRITER_TYPE
|
||||
|
||||
class ConfigTest extends Specification {
|
||||
@Rule
|
||||
public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties()
|
||||
@Rule
|
||||
public final EnvironmentVariables environmentVariables = new EnvironmentVariables()
|
||||
|
||||
private static final DD_SERVICE_NAME_ENV = "DD_SERVICE_NAME"
|
||||
private static final DD_WRITER_TYPE_ENV = "DD_WRITER_TYPE"
|
||||
private static final DD_SERVICE_MAPPING_ENV = "DD_SERVICE_MAPPING"
|
||||
private static final DD_SPAN_TAGS_ENV = "DD_SPAN_TAGS"
|
||||
private static final DD_HEADER_TAGS_ENV = "DD_HEADER_TAGS"
|
||||
|
||||
def "verify defaults"() {
|
||||
when:
|
||||
def config = Config.get()
|
||||
|
||||
then:
|
||||
config.serviceName == "unnamed-java-app"
|
||||
config.serviceMapping == [:]
|
||||
config.writerType == "DDAgentWriter"
|
||||
config.prioritySamplingEnabled == false
|
||||
config.agentHost == "localhost"
|
||||
config.agentPort == 8126
|
||||
config.spanTags == [:]
|
||||
config.toString().contains("unnamed-java-app")
|
||||
}
|
||||
|
||||
def "specify overrides via system properties"() {
|
||||
setup:
|
||||
System.setProperty(PREFIX + SERVICE_NAME, "something else")
|
||||
System.setProperty(PREFIX + WRITER_TYPE, "LoggingWriter")
|
||||
|
||||
when:
|
||||
def config = new Config()
|
||||
|
||||
then:
|
||||
config.serviceName == "something else"
|
||||
config.writerType == "LoggingWriter"
|
||||
}
|
||||
|
||||
def "specify overrides via env vars"() {
|
||||
setup:
|
||||
environmentVariables.set(DD_SERVICE_NAME_ENV, "still something else")
|
||||
environmentVariables.set(DD_WRITER_TYPE_ENV, "LoggingWriter")
|
||||
|
||||
when:
|
||||
def config = new Config()
|
||||
|
||||
then:
|
||||
config.serviceName == "still something else"
|
||||
config.writerType == "LoggingWriter"
|
||||
}
|
||||
|
||||
def "sys props override env vars"() {
|
||||
setup:
|
||||
environmentVariables.set(DD_SERVICE_NAME_ENV, "still something else")
|
||||
environmentVariables.set(DD_WRITER_TYPE_ENV, "LoggingWriter")
|
||||
|
||||
System.setProperty(PREFIX + SERVICE_NAME, "what we actually want")
|
||||
System.setProperty(PREFIX + WRITER_TYPE, "DDAgentWriter")
|
||||
System.setProperty(PREFIX + AGENT_HOST, "somewhere")
|
||||
System.setProperty(PREFIX + AGENT_PORT, "9999")
|
||||
|
||||
when:
|
||||
def config = new Config()
|
||||
|
||||
then:
|
||||
config.serviceName == "what we actually want"
|
||||
config.writerType == "DDAgentWriter"
|
||||
config.agentHost == "somewhere"
|
||||
config.agentPort == 9999
|
||||
}
|
||||
|
||||
def "sys props override properties"() {
|
||||
setup:
|
||||
Properties properties = new Properties()
|
||||
properties.setProperty(SERVICE_NAME, "what we actually want")
|
||||
properties.setProperty(WRITER_TYPE, "DDAgentWriter")
|
||||
properties.setProperty(AGENT_HOST, "somewhere")
|
||||
properties.setProperty(AGENT_PORT, "9999")
|
||||
|
||||
when:
|
||||
def config = Config.get(properties)
|
||||
|
||||
then:
|
||||
config.serviceName == "what we actually want"
|
||||
config.writerType == "DDAgentWriter"
|
||||
config.agentHost == "somewhere"
|
||||
config.agentPort == 9999
|
||||
}
|
||||
|
||||
def "sys props override null properties"() {
|
||||
when:
|
||||
def config = Config.get(null)
|
||||
|
||||
then:
|
||||
config.serviceName == "unnamed-java-app"
|
||||
config.writerType == "DDAgentWriter"
|
||||
}
|
||||
|
||||
def "sys props override empty properties"() {
|
||||
setup:
|
||||
Properties properties = new Properties()
|
||||
|
||||
when:
|
||||
def config = Config.get(properties)
|
||||
|
||||
then:
|
||||
config.serviceName == "unnamed-java-app"
|
||||
config.writerType == "DDAgentWriter"
|
||||
}
|
||||
|
||||
def "verify mapping configs on tracer"() {
|
||||
setup:
|
||||
System.setProperty(PREFIX + SERVICE_MAPPING, mapString)
|
||||
System.setProperty(PREFIX + SPAN_TAGS, mapString)
|
||||
System.setProperty(PREFIX + HEADER_TAGS, mapString)
|
||||
|
||||
when:
|
||||
def config = new Config()
|
||||
|
||||
then:
|
||||
config.serviceMapping == map
|
||||
config.spanTags == map
|
||||
config.headerTags == map
|
||||
|
||||
where:
|
||||
mapString | map
|
||||
"a:1, a:2, a:3" | [a: "3"]
|
||||
"a:b,c:d,e:" | [a: "b", c: "d"]
|
||||
// More different string variants:
|
||||
"a:" | [:]
|
||||
"a:a;" | [a: "a;"]
|
||||
"a:1, a:2, a:3" | [a: "3"]
|
||||
"a:b,c:d,e:" | [a: "b", c: "d"]
|
||||
"key 1!:va|ue_1," | ["key 1!": "va|ue_1"]
|
||||
" key1 :value1 ,\t key2: value2" | [key1: "value1", key2: "value2"]
|
||||
// Invalid strings:
|
||||
"" | [:]
|
||||
"1" | [:]
|
||||
"a" | [:]
|
||||
"a,1" | [:]
|
||||
"in:val:id" | [:]
|
||||
"a:b:c:d" | [:]
|
||||
"a:b,c,d" | [:]
|
||||
"!a" | [:]
|
||||
}
|
||||
|
||||
def "verify null value mapping configs on tracer"() {
|
||||
setup:
|
||||
environmentVariables.set(DD_SERVICE_MAPPING_ENV, mapString)
|
||||
environmentVariables.set(DD_SPAN_TAGS_ENV, mapString)
|
||||
environmentVariables.set(DD_HEADER_TAGS_ENV, mapString)
|
||||
|
||||
when:
|
||||
def config = new Config()
|
||||
|
||||
then:
|
||||
config.serviceMapping == map
|
||||
config.spanTags == map
|
||||
config.headerTags == map
|
||||
|
||||
where:
|
||||
mapString | map
|
||||
null | [:]
|
||||
}
|
||||
}
|
|
@ -1,11 +1,5 @@
|
|||
package datadog.opentracing;
|
||||
|
||||
import static datadog.trace.common.DDTraceConfig.HEADER_TAGS;
|
||||
import static datadog.trace.common.DDTraceConfig.SERVICE_MAPPING;
|
||||
import static datadog.trace.common.DDTraceConfig.SERVICE_NAME;
|
||||
import static datadog.trace.common.DDTraceConfig.SPAN_TAGS;
|
||||
import static datadog.trace.common.util.Config.parseMap;
|
||||
|
||||
import datadog.opentracing.decorators.AbstractDecorator;
|
||||
import datadog.opentracing.decorators.DDDecoratorsFactory;
|
||||
import datadog.opentracing.propagation.Codec;
|
||||
|
@ -13,11 +7,10 @@ import datadog.opentracing.propagation.ExtractedContext;
|
|||
import datadog.opentracing.propagation.HTTPCodec;
|
||||
import datadog.opentracing.scopemanager.ContextualScopeManager;
|
||||
import datadog.opentracing.scopemanager.ScopeContext;
|
||||
import datadog.trace.api.Config;
|
||||
import datadog.trace.api.interceptor.MutableSpan;
|
||||
import datadog.trace.api.interceptor.TraceInterceptor;
|
||||
import datadog.trace.api.sampling.PrioritySampling;
|
||||
import datadog.trace.common.DDTraceConfig;
|
||||
import datadog.trace.common.sampling.AllSampler;
|
||||
import datadog.trace.common.sampling.RateByServiceSampler;
|
||||
import datadog.trace.common.sampling.Sampler;
|
||||
import datadog.trace.common.writer.DDAgentWriter;
|
||||
|
@ -50,8 +43,6 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace.api.Tracer {
|
||||
|
||||
public static final String UNASSIGNED_DEFAULT_SERVICE_NAME = "unnamed-java-app";
|
||||
|
||||
/** Default service name if none provided on the trace or span */
|
||||
final String serviceName;
|
||||
/** Writer is an charge of reporting traces and spans to the desired endpoint */
|
||||
|
@ -84,21 +75,29 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
|||
|
||||
/** By default, report to local agent and collect all traces. */
|
||||
public DDTracer() {
|
||||
this(new DDTraceConfig());
|
||||
this(Config.get());
|
||||
}
|
||||
|
||||
public DDTracer(final String serviceName) {
|
||||
this(new DDTraceConfig(serviceName));
|
||||
this(serviceName, Config.get());
|
||||
}
|
||||
|
||||
public DDTracer(final Properties config) {
|
||||
this(Config.get(config));
|
||||
}
|
||||
|
||||
public DDTracer(final Config config) {
|
||||
this(config.getServiceName(), config);
|
||||
}
|
||||
|
||||
private DDTracer(final String serviceName, final Config config) {
|
||||
this(
|
||||
config.getProperty(SERVICE_NAME),
|
||||
serviceName,
|
||||
Writer.Builder.forConfig(config),
|
||||
Sampler.Builder.forConfig(config),
|
||||
parseMap(config.getProperty(SPAN_TAGS), SPAN_TAGS),
|
||||
parseMap(config.getProperty(SERVICE_MAPPING), SERVICE_MAPPING),
|
||||
parseMap(config.getProperty(HEADER_TAGS), HEADER_TAGS));
|
||||
config.getSpanTags(),
|
||||
config.getServiceMapping(),
|
||||
config.getHeaderTags());
|
||||
log.debug("Using config: {}", config);
|
||||
}
|
||||
|
||||
|
@ -112,6 +111,20 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
|||
Collections.<String, String>emptyMap());
|
||||
}
|
||||
|
||||
public DDTracer(final Writer writer) {
|
||||
this(Config.get(), writer);
|
||||
}
|
||||
|
||||
public DDTracer(final Config config, final Writer writer) {
|
||||
this(
|
||||
config.getServiceName(),
|
||||
writer,
|
||||
Sampler.Builder.forConfig(config),
|
||||
config.getSpanTags(),
|
||||
config.getServiceMapping(),
|
||||
config.getHeaderTags());
|
||||
}
|
||||
|
||||
public DDTracer(
|
||||
final String serviceName,
|
||||
final Writer writer,
|
||||
|
@ -154,8 +167,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
|||
|
||||
registerClassLoader(ClassLoader.getSystemClassLoader());
|
||||
|
||||
final List<AbstractDecorator> decorators =
|
||||
DDDecoratorsFactory.createBuiltinDecorators(serviceNameMappings);
|
||||
final List<AbstractDecorator> decorators = DDDecoratorsFactory.createBuiltinDecorators();
|
||||
for (final AbstractDecorator decorator : decorators) {
|
||||
log.debug("Loading decorator: {}", decorator.getClass().getSimpleName());
|
||||
addDecorator(decorator);
|
||||
|
@ -164,16 +176,6 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
|||
log.info("New instance: {}", this);
|
||||
}
|
||||
|
||||
public DDTracer(final Writer writer) {
|
||||
this(
|
||||
UNASSIGNED_DEFAULT_SERVICE_NAME,
|
||||
writer,
|
||||
new AllSampler(),
|
||||
parseMap(new DDTraceConfig().getProperty(SPAN_TAGS), SPAN_TAGS),
|
||||
parseMap(new DDTraceConfig().getProperty(SERVICE_MAPPING), SPAN_TAGS),
|
||||
parseMap(new DDTraceConfig().getProperty(HEADER_TAGS), SPAN_TAGS));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of span context decorators
|
||||
*
|
||||
|
@ -296,7 +298,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
|||
|
||||
@Override
|
||||
public String getTraceId() {
|
||||
final Span activeSpan = this.activeSpan();
|
||||
final Span activeSpan = activeSpan();
|
||||
if (activeSpan instanceof DDSpan) {
|
||||
return ((DDSpan) activeSpan).getTraceId();
|
||||
}
|
||||
|
@ -305,7 +307,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
|||
|
||||
@Override
|
||||
public String getSpanId() {
|
||||
final Span activeSpan = this.activeSpan();
|
||||
final Span activeSpan = activeSpan();
|
||||
if (activeSpan instanceof DDSpan) {
|
||||
return ((DDSpan) activeSpan).getSpanId();
|
||||
}
|
||||
|
|
|
@ -2,12 +2,10 @@ package datadog.opentracing.decorators;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** Create DDSpanDecorators */
|
||||
public class DDDecoratorsFactory {
|
||||
public static List<AbstractDecorator> createBuiltinDecorators(
|
||||
final Map<String, String> mappings) {
|
||||
public static List<AbstractDecorator> createBuiltinDecorators() {
|
||||
final HTTPComponent httpDecorator = new HTTPComponent();
|
||||
httpDecorator.setMatchingTag("component");
|
||||
httpDecorator.setMatchingValue("java-aws-sdk");
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
package datadog.opentracing.decorators;
|
||||
|
||||
import datadog.opentracing.DDSpanContext;
|
||||
import datadog.opentracing.DDTracer;
|
||||
import datadog.trace.api.Config;
|
||||
|
||||
public class ServletContextDecorator extends AbstractDecorator {
|
||||
|
||||
public ServletContextDecorator() {
|
||||
super();
|
||||
this.setMatchingTag("servlet.context");
|
||||
setMatchingTag("servlet.context");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSetTag(final DDSpanContext context, final String tag, final Object value) {
|
||||
String contextName = String.valueOf(value).trim();
|
||||
if (contextName.equals("/")
|
||||
|| (!context.getServiceName().equals(DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME)
|
||||
|| (!context.getServiceName().equals(Config.DEFAULT_SERVICE_NAME)
|
||||
&& !context.getServiceName().isEmpty())) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,36 +1,20 @@
|
|||
package datadog.opentracing.resolver;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import datadog.opentracing.DDTracer;
|
||||
import datadog.trace.common.util.Config;
|
||||
import datadog.trace.api.Config;
|
||||
import io.opentracing.Tracer;
|
||||
import io.opentracing.contrib.tracerresolver.TracerResolver;
|
||||
import io.opentracing.noop.NoopTracerFactory;
|
||||
import io.opentracing.util.GlobalTracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@AutoService(TracerResolver.class)
|
||||
public class DDTracerResolver extends TracerResolver {
|
||||
static final String CONFIG_KEY = "dd.trace.resolver.enabled";
|
||||
|
||||
public static Tracer registerTracer() {
|
||||
final Tracer tracer = TracerResolver.resolveTracer();
|
||||
|
||||
if (tracer == null) {
|
||||
log.warn("Cannot resolved the tracer, use NoopTracer");
|
||||
return NoopTracerFactory.create();
|
||||
}
|
||||
|
||||
log.info("Register the tracer via GlobalTracer");
|
||||
GlobalTracer.register(tracer);
|
||||
return tracer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tracer resolve() {
|
||||
final boolean enabled = !"false".equalsIgnoreCase(Config.getPropOrEnv(CONFIG_KEY));
|
||||
if (enabled) {
|
||||
@VisibleForTesting
|
||||
Tracer resolve(final Config config) {
|
||||
if (config.isTraceResolverEnabled()) {
|
||||
log.info("Creating DDTracer with DDTracerResolver");
|
||||
return new DDTracer();
|
||||
} else {
|
||||
|
@ -38,4 +22,9 @@ public class DDTracerResolver extends TracerResolver {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tracer resolve() {
|
||||
return resolve(Config.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
package datadog.trace.common;
|
||||
|
||||
import static datadog.trace.common.util.Config.getPropOrEnv;
|
||||
|
||||
import datadog.opentracing.DDTracer;
|
||||
import datadog.trace.common.writer.DDAgentWriter;
|
||||
import datadog.trace.common.writer.Writer;
|
||||
import java.util.Properties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Config gives priority to system properties and falls back to environment variables. It also
|
||||
* includes default values to ensure a valid config.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* <p>System properties are {@link DDTraceConfig#PREFIX}'ed. Environment variables are the same as
|
||||
* the system property, but uppercased with '.' -> '_'.
|
||||
*/
|
||||
@Slf4j
|
||||
public class DDTraceConfig extends Properties {
|
||||
/** Config keys below */
|
||||
private static final String PREFIX = "dd.";
|
||||
|
||||
public static final String SERVICE_NAME = "service.name";
|
||||
public static final String SERVICE_MAPPING = "service.mapping";
|
||||
public static final String WRITER_TYPE = "writer.type";
|
||||
public static final String AGENT_HOST = "agent.host";
|
||||
public static final String AGENT_PORT = "agent.port";
|
||||
public static final String PRIORITY_SAMPLING = "priority.sampling";
|
||||
public static final String SPAN_TAGS = "trace.span.tags";
|
||||
public static final String HEADER_TAGS = "trace.header.tags";
|
||||
|
||||
private final String serviceName = getPropOrEnv(PREFIX + SERVICE_NAME);
|
||||
private final String serviceMapping = getPropOrEnv(PREFIX + SERVICE_MAPPING);
|
||||
private final String writerType = getPropOrEnv(PREFIX + WRITER_TYPE);
|
||||
private final String agentHost = getPropOrEnv(PREFIX + AGENT_HOST);
|
||||
private final String agentPort = getPropOrEnv(PREFIX + AGENT_PORT);
|
||||
private final String prioritySampling = getPropOrEnv(PREFIX + PRIORITY_SAMPLING);
|
||||
private final String spanTags = getPropOrEnv(PREFIX + SPAN_TAGS);
|
||||
private final String headerTags = getPropOrEnv(PREFIX + HEADER_TAGS);
|
||||
|
||||
public DDTraceConfig() {
|
||||
super();
|
||||
|
||||
final Properties defaults = new Properties();
|
||||
defaults.setProperty(SERVICE_NAME, DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME);
|
||||
defaults.setProperty(WRITER_TYPE, Writer.DD_AGENT_WRITER_TYPE);
|
||||
defaults.setProperty(AGENT_HOST, DDAgentWriter.DEFAULT_HOSTNAME);
|
||||
defaults.setProperty(AGENT_PORT, String.valueOf(DDAgentWriter.DEFAULT_PORT));
|
||||
super.defaults = defaults;
|
||||
|
||||
setIfNotNull(SERVICE_NAME, serviceName);
|
||||
setIfNotNull(SERVICE_MAPPING, serviceMapping);
|
||||
setIfNotNull(WRITER_TYPE, writerType);
|
||||
setIfNotNull(AGENT_HOST, agentHost);
|
||||
setIfNotNull(AGENT_PORT, agentPort);
|
||||
setIfNotNull(PRIORITY_SAMPLING, prioritySampling);
|
||||
setIfNotNull(SPAN_TAGS, spanTags);
|
||||
setIfNotNull(HEADER_TAGS, headerTags);
|
||||
}
|
||||
|
||||
public DDTraceConfig(final String serviceName) {
|
||||
this();
|
||||
put(SERVICE_NAME, serviceName);
|
||||
}
|
||||
|
||||
private void setIfNotNull(final String key, final String value) {
|
||||
if (value != null) {
|
||||
setProperty(key, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
package datadog.trace.common.sampling;
|
||||
|
||||
import datadog.opentracing.DDSpan;
|
||||
import datadog.trace.common.DDTraceConfig;
|
||||
import datadog.trace.api.Config;
|
||||
import java.util.Properties;
|
||||
|
||||
/** Main interface to sample a collection of traces. */
|
||||
public interface Sampler {
|
||||
static final String ALL_SAMPLER_TYPE = AllSampler.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Sample a collection of traces based on the parent span
|
||||
|
@ -17,12 +16,10 @@ public interface Sampler {
|
|||
boolean sample(DDSpan span);
|
||||
|
||||
final class Builder {
|
||||
public static Sampler forConfig(final Properties config) {
|
||||
public static Sampler forConfig(final Config config) {
|
||||
final Sampler sampler;
|
||||
if (config != null) {
|
||||
final boolean prioritySamplingEnabled =
|
||||
Boolean.parseBoolean(config.getProperty(DDTraceConfig.PRIORITY_SAMPLING));
|
||||
if (prioritySamplingEnabled) {
|
||||
if (config.isPrioritySamplingEnabled()) {
|
||||
sampler = new RateByServiceSampler();
|
||||
} else {
|
||||
sampler = new AllSampler();
|
||||
|
@ -33,6 +30,10 @@ public interface Sampler {
|
|||
return sampler;
|
||||
}
|
||||
|
||||
public static Sampler forConfig(final Properties config) {
|
||||
return forConfig(Config.get(config));
|
||||
}
|
||||
|
||||
private Builder() {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package datadog.trace.common.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public abstract class Config {
|
||||
|
||||
public static String getPropOrEnv(final String name) {
|
||||
return System.getProperty(name, System.getenv(propToEnvName(name)));
|
||||
}
|
||||
|
||||
public static String propToEnvName(final String name) {
|
||||
return name.toUpperCase().replace(".", "_");
|
||||
}
|
||||
|
||||
public static Map<String, String> parseMap(final String str, final String settingName) {
|
||||
if (str == null || str.trim().isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
if (!str.matches("(([^,:]+:[^,:]*,)*([^,:]+:[^,:]*),?)?")) {
|
||||
log.warn(
|
||||
"Invalid config for {}: '{}'. Must match 'key1:value1,key2:value2'.", settingName, str);
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
final String[] tokens = str.split(",", -1);
|
||||
final Map<String, String> map = new HashMap<>(tokens.length + 1, 1f);
|
||||
|
||||
for (final String token : tokens) {
|
||||
final String[] keyValue = token.split(":", -1);
|
||||
if (keyValue.length == 2) {
|
||||
final String key = keyValue[0].trim();
|
||||
final String value = keyValue[1].trim();
|
||||
if (value.length() <= 0) {
|
||||
log.warn("Ignoring empty value for key '{}' in config for {}", key, settingName);
|
||||
continue;
|
||||
}
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package datadog.trace.common.writer;
|
||||
|
||||
import static datadog.trace.api.Config.DEFAULT_AGENT_HOST;
|
||||
import static datadog.trace.api.Config.DEFAULT_AGENT_PORT;
|
||||
|
||||
import datadog.opentracing.DDSpan;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
@ -25,11 +28,6 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
public class DDAgentWriter implements Writer {
|
||||
|
||||
/** Default location of the DD agent */
|
||||
public static final String DEFAULT_HOSTNAME = "localhost";
|
||||
|
||||
public static final int DEFAULT_PORT = 8126;
|
||||
|
||||
/** Maximum number of traces kept in memory */
|
||||
static final int DEFAULT_MAX_TRACES = 7000;
|
||||
|
||||
|
@ -66,7 +64,7 @@ public class DDAgentWriter implements Writer {
|
|||
private boolean queueFullReported = false;
|
||||
|
||||
public DDAgentWriter() {
|
||||
this(new DDApi(DEFAULT_HOSTNAME, DEFAULT_PORT));
|
||||
this(new DDApi(DEFAULT_AGENT_HOST, DEFAULT_AGENT_PORT));
|
||||
}
|
||||
|
||||
public DDAgentWriter(final DDApi api) {
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
package datadog.trace.common.writer;
|
||||
|
||||
import datadog.opentracing.DDSpan;
|
||||
import datadog.trace.common.DDTraceConfig;
|
||||
import datadog.trace.api.Config;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/** A writer is responsible to send collected spans to some place */
|
||||
public interface Writer {
|
||||
static final String DD_AGENT_WRITER_TYPE = DDAgentWriter.class.getSimpleName();
|
||||
static final String LOGGING_WRITER_TYPE = LoggingWriter.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Write a trace represented by the entire list of all the finished spans
|
||||
|
@ -29,28 +27,21 @@ public interface Writer {
|
|||
|
||||
@Slf4j
|
||||
final class Builder {
|
||||
public static Writer forConfig(final Properties config) {
|
||||
|
||||
public static Writer forConfig(final Config config) {
|
||||
final Writer writer;
|
||||
|
||||
if (config != null) {
|
||||
final String configuredType = config.getProperty(DDTraceConfig.WRITER_TYPE);
|
||||
if (DD_AGENT_WRITER_TYPE.equals(configuredType)) {
|
||||
writer =
|
||||
new DDAgentWriter(
|
||||
new DDApi(
|
||||
config.getProperty(DDTraceConfig.AGENT_HOST),
|
||||
Integer.parseInt(config.getProperty(DDTraceConfig.AGENT_PORT))));
|
||||
} else if (LOGGING_WRITER_TYPE.equals(configuredType)) {
|
||||
final String configuredType = config.getWriterType();
|
||||
if (Config.DD_AGENT_WRITER_TYPE.equals(configuredType)) {
|
||||
writer = createAgentWriter(config);
|
||||
} else if (Config.LOGGING_WRITER_TYPE.equals(configuredType)) {
|
||||
writer = new LoggingWriter();
|
||||
} else {
|
||||
log.warn(
|
||||
"Writer type not configured correctly: Type {} not recognized. Defaulting to DDAgentWriter.",
|
||||
configuredType);
|
||||
writer =
|
||||
new DDAgentWriter(
|
||||
new DDApi(
|
||||
config.getProperty(DDTraceConfig.AGENT_HOST),
|
||||
Integer.parseInt(config.getProperty(DDTraceConfig.AGENT_PORT))));
|
||||
writer = createAgentWriter(config);
|
||||
}
|
||||
} else {
|
||||
log.warn(
|
||||
|
@ -61,6 +52,14 @@ public interface Writer {
|
|||
return writer;
|
||||
}
|
||||
|
||||
public static Writer forConfig(final Properties config) {
|
||||
return forConfig(Config.get(config));
|
||||
}
|
||||
|
||||
private static Writer createAgentWriter(final Config config) {
|
||||
return new DDAgentWriter(new DDApi(config.getAgentHost(), config.getAgentPort()));
|
||||
}
|
||||
|
||||
private Builder() {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package datadog.opentracing
|
||||
|
||||
import datadog.opentracing.propagation.ExtractedContext
|
||||
import datadog.trace.api.Config
|
||||
import datadog.trace.api.DDTags
|
||||
import datadog.trace.common.writer.ListWriter
|
||||
import spock.lang.Specification
|
||||
|
@ -273,7 +274,7 @@ class DDSpanBuilderTest extends Specification {
|
|||
def "global span tags populated on each span"() {
|
||||
setup:
|
||||
System.setProperty("dd.trace.span.tags", tagString)
|
||||
tracer = new DDTracer(writer)
|
||||
tracer = new DDTracer(new Config(), writer)
|
||||
def span = tracer.buildSpan("op name").withServiceName("foo").start()
|
||||
tags.putAll([
|
||||
(DDTags.THREAD_NAME): Thread.currentThread().getName(),
|
||||
|
|
|
@ -7,9 +7,11 @@ import spock.lang.Specification
|
|||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import static datadog.trace.api.Config.DEFAULT_SERVICE_NAME
|
||||
|
||||
class DDSpanTest extends Specification {
|
||||
def writer = new ListWriter()
|
||||
def tracer = new DDTracer(DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME, writer, new RateByServiceSampler())
|
||||
def tracer = new DDTracer(DEFAULT_SERVICE_NAME, writer, new RateByServiceSampler())
|
||||
|
||||
def "getters and setters"() {
|
||||
setup:
|
||||
|
@ -77,7 +79,7 @@ class DDSpanTest extends Specification {
|
|||
span = tracer.buildSpan(opName).start()
|
||||
then:
|
||||
span.getResourceName() == opName
|
||||
span.getServiceName() == DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME
|
||||
span.getServiceName() == DEFAULT_SERVICE_NAME
|
||||
|
||||
when:
|
||||
final String resourceName = "fake"
|
||||
|
|
|
@ -11,7 +11,7 @@ import io.opentracing.tag.StringTag
|
|||
import io.opentracing.tag.Tags
|
||||
import spock.lang.Specification
|
||||
|
||||
import static datadog.opentracing.DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME
|
||||
import static datadog.trace.api.Config.DEFAULT_SERVICE_NAME
|
||||
import static java.util.Collections.emptyMap
|
||||
|
||||
class SpanDecoratorTest extends Specification {
|
||||
|
@ -75,10 +75,10 @@ class SpanDecoratorTest extends Specification {
|
|||
span.serviceName == expected
|
||||
|
||||
where:
|
||||
serviceName | expected | mapping
|
||||
UNASSIGNED_DEFAULT_SERVICE_NAME | UNASSIGNED_DEFAULT_SERVICE_NAME | ["other-service-name": "other-service"]
|
||||
UNASSIGNED_DEFAULT_SERVICE_NAME | "new-service" | [(UNASSIGNED_DEFAULT_SERVICE_NAME): "new-service"]
|
||||
"other-service-name" | "other-service" | ["other-service-name": "other-service"]
|
||||
serviceName | expected | mapping
|
||||
DEFAULT_SERVICE_NAME | DEFAULT_SERVICE_NAME | ["other-service-name": "other-service"]
|
||||
DEFAULT_SERVICE_NAME | "new-service" | [(DEFAULT_SERVICE_NAME): "new-service"]
|
||||
"other-service-name" | "other-service" | ["other-service-name": "other-service"]
|
||||
}
|
||||
|
||||
def "set service name from servlet.context with context '#context'"() {
|
||||
|
@ -90,15 +90,15 @@ class SpanDecoratorTest extends Specification {
|
|||
span.serviceName == expected
|
||||
|
||||
where:
|
||||
context | serviceName | expected
|
||||
"/" | UNASSIGNED_DEFAULT_SERVICE_NAME | UNASSIGNED_DEFAULT_SERVICE_NAME
|
||||
"" | UNASSIGNED_DEFAULT_SERVICE_NAME | UNASSIGNED_DEFAULT_SERVICE_NAME
|
||||
"/some-context" | UNASSIGNED_DEFAULT_SERVICE_NAME | "some-context"
|
||||
"other-context" | UNASSIGNED_DEFAULT_SERVICE_NAME | "other-context"
|
||||
"/" | "my-service" | "my-service"
|
||||
"" | "my-service" | "my-service"
|
||||
"/some-context" | "my-service" | "my-service"
|
||||
"other-context" | "my-service" | "my-service"
|
||||
context | serviceName | expected
|
||||
"/" | DEFAULT_SERVICE_NAME | DEFAULT_SERVICE_NAME
|
||||
"" | DEFAULT_SERVICE_NAME | DEFAULT_SERVICE_NAME
|
||||
"/some-context" | DEFAULT_SERVICE_NAME | "some-context"
|
||||
"other-context" | DEFAULT_SERVICE_NAME | "other-context"
|
||||
"/" | "my-service" | "my-service"
|
||||
"" | "my-service" | "my-service"
|
||||
"/some-context" | "my-service" | "my-service"
|
||||
"other-context" | "my-service" | "my-service"
|
||||
}
|
||||
|
||||
def "set service name from servlet.context with context '#context' for service #serviceName"() {
|
||||
|
@ -114,15 +114,15 @@ class SpanDecoratorTest extends Specification {
|
|||
span.serviceName == expected
|
||||
|
||||
where:
|
||||
context | serviceName | expected
|
||||
"/" | UNASSIGNED_DEFAULT_SERVICE_NAME | "new-service"
|
||||
"" | UNASSIGNED_DEFAULT_SERVICE_NAME | "new-service"
|
||||
"/some-context" | UNASSIGNED_DEFAULT_SERVICE_NAME | "some-context"
|
||||
"other-context" | UNASSIGNED_DEFAULT_SERVICE_NAME | "other-context"
|
||||
"/" | "my-service" | "new-service"
|
||||
"" | "my-service" | "new-service"
|
||||
"/some-context" | "my-service" | "new-service"
|
||||
"other-context" | "my-service" | "new-service"
|
||||
context | serviceName | expected
|
||||
"/" | DEFAULT_SERVICE_NAME | "new-service"
|
||||
"" | DEFAULT_SERVICE_NAME | "new-service"
|
||||
"/some-context" | DEFAULT_SERVICE_NAME | "some-context"
|
||||
"other-context" | DEFAULT_SERVICE_NAME | "other-context"
|
||||
"/" | "my-service" | "new-service"
|
||||
"" | "my-service" | "new-service"
|
||||
"/some-context" | "my-service" | "new-service"
|
||||
"other-context" | "my-service" | "new-service"
|
||||
|
||||
mapping = [(serviceName): "new-service"]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package datadog.opentracing.resolver
|
||||
|
||||
import datadog.opentracing.DDTracer
|
||||
import datadog.trace.api.Config
|
||||
import io.opentracing.contrib.tracerresolver.TracerResolver
|
||||
import spock.lang.Specification
|
||||
|
||||
class DDTracerResolverTest extends Specification {
|
||||
|
||||
def resolver = new DDTracerResolver()
|
||||
|
||||
def "test resolveTracer"() {
|
||||
when:
|
||||
def tracer = TracerResolver.resolveTracer()
|
||||
|
||||
then:
|
||||
tracer instanceof DDTracer
|
||||
}
|
||||
|
||||
def "test disable DDTracerResolver"() {
|
||||
setup:
|
||||
System.setProperty("dd.trace.resolver.enabled", "false")
|
||||
|
||||
when:
|
||||
def tracer = resolver.resolve(new Config())
|
||||
|
||||
then:
|
||||
tracer == null
|
||||
|
||||
cleanup:
|
||||
System.clearProperty("dd.trace.resolver.enabled")
|
||||
}
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package datadog.opentracing.resolver
|
||||
|
||||
import datadog.opentracing.DDTracer
|
||||
import io.opentracing.Tracer
|
||||
import io.opentracing.contrib.tracerresolver.TracerResolver
|
||||
import io.opentracing.noop.NoopTracer
|
||||
import io.opentracing.noop.NoopTracerFactory
|
||||
import io.opentracing.util.GlobalTracer
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.lang.reflect.Field
|
||||
|
||||
class TracerResolverTest extends Specification {
|
||||
|
||||
def setup() {
|
||||
setTracer(null)
|
||||
assert !GlobalTracer.isRegistered()
|
||||
}
|
||||
|
||||
def "test resolveTracer"() {
|
||||
when:
|
||||
def tracer = TracerResolver.resolveTracer()
|
||||
|
||||
then:
|
||||
!GlobalTracer.isRegistered()
|
||||
tracer instanceof DDTracer
|
||||
}
|
||||
|
||||
def "test registerTracer"() {
|
||||
when:
|
||||
def tracer = DDTracerResolver.registerTracer()
|
||||
|
||||
then:
|
||||
GlobalTracer.isRegistered()
|
||||
tracer instanceof DDTracer
|
||||
}
|
||||
|
||||
def "test disable DDTracerResolver"() {
|
||||
setup:
|
||||
System.setProperty("dd.trace.resolver.enabled", "false")
|
||||
|
||||
when:
|
||||
def tracer = TracerResolver.resolveTracer()
|
||||
|
||||
then:
|
||||
!GlobalTracer.isRegistered()
|
||||
tracer == null
|
||||
|
||||
when:
|
||||
tracer = DDTracerResolver.registerTracer()
|
||||
|
||||
then:
|
||||
!GlobalTracer.isRegistered()
|
||||
tracer instanceof NoopTracer
|
||||
|
||||
cleanup:
|
||||
System.clearProperty("dd.trace.resolver.enabled")
|
||||
}
|
||||
|
||||
def setTracer(Tracer tracer) {
|
||||
final Field tracerField = GlobalTracer.getDeclaredField("tracer")
|
||||
tracerField.setAccessible(true)
|
||||
tracerField.set(tracer, NoopTracerFactory.create())
|
||||
}
|
||||
}
|
|
@ -1,182 +0,0 @@
|
|||
package datadog.trace
|
||||
|
||||
import datadog.opentracing.DDTracer
|
||||
import datadog.trace.common.DDTraceConfig
|
||||
import datadog.trace.common.sampling.AllSampler
|
||||
import datadog.trace.common.writer.DDAgentWriter
|
||||
import datadog.trace.common.writer.ListWriter
|
||||
import datadog.trace.common.writer.LoggingWriter
|
||||
import org.junit.Rule
|
||||
import org.junit.contrib.java.lang.system.EnvironmentVariables
|
||||
import org.junit.contrib.java.lang.system.RestoreSystemProperties
|
||||
import spock.lang.Specification
|
||||
|
||||
import static datadog.trace.common.DDTraceConfig.AGENT_HOST
|
||||
import static datadog.trace.common.DDTraceConfig.AGENT_PORT
|
||||
import static datadog.trace.common.DDTraceConfig.HEADER_TAGS
|
||||
import static datadog.trace.common.DDTraceConfig.PREFIX
|
||||
import static datadog.trace.common.DDTraceConfig.SERVICE_MAPPING
|
||||
import static datadog.trace.common.DDTraceConfig.SERVICE_NAME
|
||||
import static datadog.trace.common.DDTraceConfig.SPAN_TAGS
|
||||
import static datadog.trace.common.DDTraceConfig.WRITER_TYPE
|
||||
import static datadog.trace.common.util.Config.parseMap
|
||||
import static datadog.trace.common.util.Config.propToEnvName
|
||||
|
||||
class DDTraceConfigTest extends Specification {
|
||||
@Rule
|
||||
public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties()
|
||||
@Rule
|
||||
public final EnvironmentVariables environmentVariables = new EnvironmentVariables()
|
||||
|
||||
def "verify env override"() {
|
||||
setup:
|
||||
environmentVariables.set("SOME_RANDOM_ENTRY", "asdf")
|
||||
|
||||
expect:
|
||||
System.getenv("SOME_RANDOM_ENTRY") == "asdf"
|
||||
}
|
||||
|
||||
def "verify defaults"() {
|
||||
when:
|
||||
def config = new DDTraceConfig()
|
||||
|
||||
then:
|
||||
config.getProperty(SERVICE_NAME) == "unnamed-java-app"
|
||||
config.getProperty(SERVICE_MAPPING) == null
|
||||
config.getProperty(WRITER_TYPE) == "DDAgentWriter"
|
||||
config.getProperty(AGENT_HOST) == "localhost"
|
||||
config.getProperty(AGENT_PORT) == "8126"
|
||||
config.getProperty(SPAN_TAGS) == null
|
||||
|
||||
when:
|
||||
config = new DDTraceConfig("A different service name")
|
||||
|
||||
then:
|
||||
config.getProperty(SERVICE_NAME) == "A different service name"
|
||||
config.getProperty(SERVICE_MAPPING) == null
|
||||
config.getProperty(WRITER_TYPE) == "DDAgentWriter"
|
||||
config.getProperty(AGENT_HOST) == "localhost"
|
||||
config.getProperty(AGENT_PORT) == "8126"
|
||||
config.getProperty(SPAN_TAGS) == null
|
||||
}
|
||||
|
||||
def "specify overrides via system properties"() {
|
||||
when:
|
||||
System.setProperty(PREFIX + SERVICE_NAME, "something else")
|
||||
System.setProperty(PREFIX + WRITER_TYPE, LoggingWriter.simpleName)
|
||||
def tracer = new DDTracer()
|
||||
|
||||
then:
|
||||
tracer.serviceName == "something else"
|
||||
tracer.writer instanceof LoggingWriter
|
||||
}
|
||||
|
||||
def "specify overrides via env vars"() {
|
||||
when:
|
||||
environmentVariables.set(propToEnvName(PREFIX + SERVICE_NAME), "still something else")
|
||||
environmentVariables.set(propToEnvName(PREFIX + WRITER_TYPE), LoggingWriter.simpleName)
|
||||
def tracer = new DDTracer()
|
||||
|
||||
then:
|
||||
tracer.serviceName == "still something else"
|
||||
tracer.writer instanceof LoggingWriter
|
||||
}
|
||||
|
||||
def "sys props override env vars"() {
|
||||
when:
|
||||
environmentVariables.set(propToEnvName(PREFIX + SERVICE_NAME), "still something else")
|
||||
environmentVariables.set(propToEnvName(PREFIX + WRITER_TYPE), ListWriter.simpleName)
|
||||
|
||||
System.setProperty(PREFIX + SERVICE_NAME, "what we actually want")
|
||||
System.setProperty(PREFIX + WRITER_TYPE, DDAgentWriter.simpleName)
|
||||
System.setProperty(PREFIX + AGENT_HOST, "somewhere")
|
||||
System.setProperty(PREFIX + AGENT_PORT, "9999")
|
||||
|
||||
def tracer = new DDTracer()
|
||||
|
||||
then:
|
||||
tracer.serviceName == "what we actually want"
|
||||
tracer.writer.toString() == "DDAgentWriter { api=DDApi { tracesEndpoint=http://somewhere:9999/v0.3/traces } }"
|
||||
}
|
||||
|
||||
def "verify defaults on tracer"() {
|
||||
when:
|
||||
def tracer = new DDTracer()
|
||||
|
||||
then:
|
||||
tracer.serviceName == "unnamed-java-app"
|
||||
tracer.sampler instanceof AllSampler
|
||||
tracer.writer.toString() == "DDAgentWriter { api=DDApi { tracesEndpoint=http://localhost:8126/v0.3/traces } }"
|
||||
|
||||
tracer.spanContextDecorators.size() == 12
|
||||
}
|
||||
|
||||
def "verify mapping configs on tracer"() {
|
||||
setup:
|
||||
System.setProperty(PREFIX + SERVICE_MAPPING, mapString)
|
||||
System.setProperty(PREFIX + SPAN_TAGS, mapString)
|
||||
System.setProperty(PREFIX + HEADER_TAGS, mapString)
|
||||
|
||||
when:
|
||||
def tracer = new DDTracer()
|
||||
def taggedHeaders = tracer.registry.codecs.values().first().taggedHeaders
|
||||
|
||||
then:
|
||||
tracer.defaultSpanTags == map
|
||||
tracer.serviceNameMappings == map
|
||||
taggedHeaders == map
|
||||
|
||||
where:
|
||||
mapString | map
|
||||
"a:1, a:2, a:3" | [a: "3"]
|
||||
"a:b,c:d,e:" | [a: "b", c: "d"]
|
||||
}
|
||||
|
||||
def "verify single override on #source for #key"() {
|
||||
when:
|
||||
System.setProperty(PREFIX + key, value)
|
||||
def tracer = new DDTracer()
|
||||
|
||||
then:
|
||||
tracer."$source".toString() == expected
|
||||
|
||||
where:
|
||||
|
||||
source | key | value | expected
|
||||
"writer" | "default" | "default" | "DDAgentWriter { api=DDApi { tracesEndpoint=http://localhost:8126/v0.3/traces } }"
|
||||
"writer" | "writer.type" | "LoggingWriter" | "LoggingWriter { }"
|
||||
"writer" | "agent.host" | "somethingelse" | "DDAgentWriter { api=DDApi { tracesEndpoint=http://somethingelse:8126/v0.3/traces } }"
|
||||
"writer" | "agent.port" | "9999" | "DDAgentWriter { api=DDApi { tracesEndpoint=http://localhost:9999/v0.3/traces } }"
|
||||
}
|
||||
|
||||
def "parsing valid string returns a map"() {
|
||||
expect:
|
||||
parseMap(str, "test") == map
|
||||
|
||||
where:
|
||||
str | map
|
||||
"a:" | [:]
|
||||
"a:a;" | [a: "a;"]
|
||||
"a:1, a:2, a:3" | [a: "3"]
|
||||
"a:b,c:d,e:" | [a: "b", c: "d"]
|
||||
"key 1!:va|ue_1," | ["key 1!": "va|ue_1"]
|
||||
" key1 :value1 ,\t key2: value2" | [key1: "value1", key2: "value2"]
|
||||
}
|
||||
|
||||
def "parsing an invalid string returns an empty map"() {
|
||||
expect:
|
||||
parseMap(str, "test") == [:]
|
||||
|
||||
where:
|
||||
str | _
|
||||
null | _
|
||||
"" | _
|
||||
"1" | _
|
||||
"a" | _
|
||||
"a,1" | _
|
||||
"in:val:id" | _
|
||||
"a:b:c:d" | _
|
||||
"a:b,c,d" | _
|
||||
"!a" | _
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package datadog.trace
|
||||
|
||||
import datadog.opentracing.DDTracer
|
||||
import datadog.trace.api.Config
|
||||
import datadog.trace.common.sampling.AllSampler
|
||||
import datadog.trace.common.sampling.RateByServiceSampler
|
||||
import datadog.trace.common.writer.LoggingWriter
|
||||
import org.junit.Rule
|
||||
import org.junit.contrib.java.lang.system.EnvironmentVariables
|
||||
import org.junit.contrib.java.lang.system.RestoreSystemProperties
|
||||
import spock.lang.Specification
|
||||
|
||||
import static datadog.trace.api.Config.HEADER_TAGS
|
||||
import static datadog.trace.api.Config.PREFIX
|
||||
import static datadog.trace.api.Config.PRIORITY_SAMPLING
|
||||
import static datadog.trace.api.Config.SERVICE_MAPPING
|
||||
import static datadog.trace.api.Config.SPAN_TAGS
|
||||
import static datadog.trace.api.Config.WRITER_TYPE
|
||||
|
||||
class DDTracerTest extends Specification {
|
||||
@Rule
|
||||
public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties()
|
||||
@Rule
|
||||
public final EnvironmentVariables environmentVariables = new EnvironmentVariables()
|
||||
|
||||
def "verify defaults on tracer"() {
|
||||
when:
|
||||
def tracer = new DDTracer()
|
||||
|
||||
then:
|
||||
tracer.serviceName == "unnamed-java-app"
|
||||
tracer.sampler instanceof AllSampler
|
||||
tracer.writer.toString() == "DDAgentWriter { api=DDApi { tracesEndpoint=http://localhost:8126/v0.3/traces } }"
|
||||
|
||||
tracer.spanContextDecorators.size() == 12
|
||||
}
|
||||
|
||||
def "verify overriding sampler"() {
|
||||
setup:
|
||||
System.setProperty(PREFIX + PRIORITY_SAMPLING, "true")
|
||||
|
||||
when:
|
||||
def tracer = new DDTracer(new Config())
|
||||
|
||||
then:
|
||||
tracer.sampler instanceof RateByServiceSampler
|
||||
}
|
||||
|
||||
def "verify overriding writer"() {
|
||||
setup:
|
||||
System.setProperty(PREFIX + WRITER_TYPE, "LoggingWriter")
|
||||
|
||||
when:
|
||||
def tracer = new DDTracer(new Config())
|
||||
|
||||
then:
|
||||
tracer.writer instanceof LoggingWriter
|
||||
}
|
||||
|
||||
def "verify mapping configs on tracer"() {
|
||||
setup:
|
||||
System.setProperty(PREFIX + SERVICE_MAPPING, mapString)
|
||||
System.setProperty(PREFIX + SPAN_TAGS, mapString)
|
||||
System.setProperty(PREFIX + HEADER_TAGS, mapString)
|
||||
|
||||
when:
|
||||
def tracer = new DDTracer(new Config())
|
||||
def taggedHeaders = tracer.registry.codecs.values().first().taggedHeaders
|
||||
|
||||
then:
|
||||
tracer.defaultSpanTags == map
|
||||
tracer.serviceNameMappings == map
|
||||
taggedHeaders == map
|
||||
|
||||
where:
|
||||
mapString | map
|
||||
"a:1, a:2, a:3" | [a: "3"]
|
||||
"a:b,c:d,e:" | [a: "b", c: "d"]
|
||||
}
|
||||
|
||||
def "verify single override on #source for #key"() {
|
||||
when:
|
||||
System.setProperty(PREFIX + key, value)
|
||||
def tracer = new DDTracer(new Config())
|
||||
|
||||
then:
|
||||
tracer."$source".toString() == expected
|
||||
|
||||
where:
|
||||
|
||||
source | key | value | expected
|
||||
"writer" | "default" | "default" | "DDAgentWriter { api=DDApi { tracesEndpoint=http://localhost:8126/v0.3/traces } }"
|
||||
"writer" | "writer.type" | "LoggingWriter" | "LoggingWriter { }"
|
||||
"writer" | "agent.host" | "somethingelse" | "DDAgentWriter { api=DDApi { tracesEndpoint=http://somethingelse:8126/v0.3/traces } }"
|
||||
"writer" | "agent.port" | "9999" | "DDAgentWriter { api=DDApi { tracesEndpoint=http://localhost:9999/v0.3/traces } }"
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import datadog.opentracing.DDSpanContext
|
|||
import datadog.opentracing.DDTracer
|
||||
import datadog.opentracing.PendingTrace
|
||||
import datadog.trace.api.sampling.PrioritySampling
|
||||
import datadog.trace.common.writer.DDAgentWriter
|
||||
import datadog.trace.common.writer.DDApi
|
||||
import datadog.trace.common.writer.ListWriter
|
||||
import spock.lang.Specification
|
||||
|
@ -12,6 +11,9 @@ import spock.lang.Specification
|
|||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
import static datadog.trace.api.Config.DEFAULT_AGENT_HOST
|
||||
import static datadog.trace.api.Config.DEFAULT_AGENT_PORT
|
||||
|
||||
class DDApiIntegrationTest {
|
||||
static class DDApiIntegrationV4Test extends Specification {
|
||||
static final WRITER = new ListWriter()
|
||||
|
@ -31,7 +33,7 @@ class DDApiIntegrationTest {
|
|||
new PendingTrace(TRACER, "1", [:]),
|
||||
TRACER)
|
||||
|
||||
def api = new DDApi(DDAgentWriter.DEFAULT_HOSTNAME, DDAgentWriter.DEFAULT_PORT, v4())
|
||||
def api = new DDApi(DEFAULT_AGENT_HOST, DEFAULT_AGENT_PORT, v4())
|
||||
|
||||
def endpoint = new AtomicReference<String>(null)
|
||||
def agentResponse = new AtomicReference<String>(null)
|
||||
|
|
Loading…
Reference in New Issue