commit
920b9b5ad3
|
@ -20,8 +20,8 @@ Other source files (Groovy, Scala, etc) should ideally be formatted by Intellij
|
||||||
Suggested plugins and settings:
|
Suggested plugins and settings:
|
||||||
|
|
||||||
* Editor > Code Style > Java/Groovy > Imports
|
* Editor > Code Style > Java/Groovy > Imports
|
||||||
* Class count to use import with '*': `10` (some number sufficiently large that is unlikely to matter)
|
* Class count to use import with '*': `50` (some number sufficiently large that is unlikely to matter)
|
||||||
* Names count to use static import with '*': `10`
|
* Names count to use static import with '*': `50`
|
||||||
* With java use the following import layout (groovy should still use the default) to ensure consistency with google-java-format:
|
* With java use the following import layout (groovy should still use the default) to ensure consistency with google-java-format:
|
||||||

|

|
||||||
* [Google Java Format](https://plugins.jetbrains.com/plugin/8527-google-java-format)
|
* [Google Java Format](https://plugins.jetbrains.com/plugin/8527-google-java-format)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package datadog.trace.api;
|
package datadog.trace.api;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -51,6 +53,7 @@ public class Config {
|
||||||
public static final String TRACE_ANNOTATIONS = "trace.annotations";
|
public static final String TRACE_ANNOTATIONS = "trace.annotations";
|
||||||
public static final String TRACE_METHODS = "trace.methods";
|
public static final String TRACE_METHODS = "trace.methods";
|
||||||
public static final String TRACE_CLASSES_EXCLUDE = "trace.classes.exclude";
|
public static final String TRACE_CLASSES_EXCLUDE = "trace.classes.exclude";
|
||||||
|
public static final String TRACE_REPORT_HOSTNAME = "trace.report-hostname";
|
||||||
public static final String HEADER_TAGS = "trace.header.tags";
|
public static final String HEADER_TAGS = "trace.header.tags";
|
||||||
public static final String HTTP_SERVER_ERROR_STATUSES = "http.server.error.statuses";
|
public static final String HTTP_SERVER_ERROR_STATUSES = "http.server.error.statuses";
|
||||||
public static final String HTTP_CLIENT_ERROR_STATUSES = "http.client.error.statuses";
|
public static final String HTTP_CLIENT_ERROR_STATUSES = "http.client.error.statuses";
|
||||||
|
@ -105,11 +108,16 @@ public class Config {
|
||||||
|
|
||||||
private static final String SPLIT_BY_SPACE_OR_COMMA_REGEX = "[,\\s]+";
|
private static final String SPLIT_BY_SPACE_OR_COMMA_REGEX = "[,\\s]+";
|
||||||
|
|
||||||
|
private static final boolean DEFAULT_TRACE_REPORT_HOSTNAME = false;
|
||||||
|
|
||||||
public enum PropagationStyle {
|
public enum PropagationStyle {
|
||||||
DATADOG,
|
DATADOG,
|
||||||
B3
|
B3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A tag intended for internal use only, hence not added to the public api DDTags class. */
|
||||||
|
private static final String INTERNAL_HOST_NAME = "_dd.hostname";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this is a random UUID that gets generated on JVM start up and is attached to every root span
|
* this is a random UUID that gets generated on JVM start up and is attached to every root span
|
||||||
* and every JMX metric that is sent out.
|
* and every JMX metric that is sent out.
|
||||||
|
@ -147,6 +155,8 @@ public class Config {
|
||||||
|
|
||||||
@Getter private final boolean logsInjectionEnabled;
|
@Getter private final boolean logsInjectionEnabled;
|
||||||
|
|
||||||
|
@Getter private final boolean reportHostName;
|
||||||
|
|
||||||
// Read order: System Properties -> Env Variables, [-> default value]
|
// Read order: System Properties -> Env Variables, [-> default value]
|
||||||
// Visible for testing
|
// Visible for testing
|
||||||
Config() {
|
Config() {
|
||||||
|
@ -221,6 +231,9 @@ public class Config {
|
||||||
logsInjectionEnabled =
|
logsInjectionEnabled =
|
||||||
getBooleanSettingFromEnvironment(LOGS_INJECTION_ENABLED, DEFAULT_LOGS_INJECTION_ENABLED);
|
getBooleanSettingFromEnvironment(LOGS_INJECTION_ENABLED, DEFAULT_LOGS_INJECTION_ENABLED);
|
||||||
|
|
||||||
|
reportHostName =
|
||||||
|
getBooleanSettingFromEnvironment(TRACE_REPORT_HOSTNAME, DEFAULT_TRACE_REPORT_HOSTNAME);
|
||||||
|
|
||||||
log.debug("New instance: {}", this);
|
log.debug("New instance: {}", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,9 +314,24 @@ public class Config {
|
||||||
logsInjectionEnabled =
|
logsInjectionEnabled =
|
||||||
getBooleanSettingFromEnvironment(LOGS_INJECTION_ENABLED, DEFAULT_LOGS_INJECTION_ENABLED);
|
getBooleanSettingFromEnvironment(LOGS_INJECTION_ENABLED, DEFAULT_LOGS_INJECTION_ENABLED);
|
||||||
|
|
||||||
|
reportHostName =
|
||||||
|
getPropertyBooleanValue(properties, TRACE_REPORT_HOSTNAME, parent.reportHostName);
|
||||||
|
|
||||||
log.debug("New instance: {}", this);
|
log.debug("New instance: {}", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return A map of tags to be applied only to the local application root span. */
|
||||||
|
public Map<String, String> getLocalRootSpanTags() {
|
||||||
|
final Map<String, String> runtimeTags = getRuntimeTags();
|
||||||
|
final Map<String, String> result =
|
||||||
|
newHashMap(reportHostName ? (runtimeTags.size() + 1) : runtimeTags.size());
|
||||||
|
result.putAll(runtimeTags);
|
||||||
|
if (reportHostName) {
|
||||||
|
result.put(INTERNAL_HOST_NAME, getHostname());
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableMap(result);
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String, String> getMergedSpanTags() {
|
public Map<String, String> getMergedSpanTags() {
|
||||||
// DO not include runtimeId into span tags: we only want that added to the root span
|
// DO not include runtimeId into span tags: we only want that added to the root span
|
||||||
final Map<String, String> result = newHashMap(globalTags.size() + spanTags.size());
|
final Map<String, String> result = newHashMap(globalTags.size() + spanTags.size());
|
||||||
|
@ -336,7 +364,7 @@ public class Config {
|
||||||
*
|
*
|
||||||
* @return A map of tag-name -> tag-value
|
* @return A map of tag-name -> tag-value
|
||||||
*/
|
*/
|
||||||
public Map<String, String> getRuntimeTags() {
|
private Map<String, String> getRuntimeTags() {
|
||||||
final Map<String, String> result = newHashMap(2);
|
final Map<String, String> result = newHashMap(2);
|
||||||
result.put(RUNTIME_ID_TAG, runtimeId);
|
result.put(RUNTIME_ID_TAG, runtimeId);
|
||||||
result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE);
|
result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE);
|
||||||
|
@ -636,6 +664,20 @@ public class Config {
|
||||||
return Collections.unmodifiableSet(result);
|
return Collections.unmodifiableSet(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the detected hostname. This operation is time consuming so if the usage changes and
|
||||||
|
* this method will be called several times then we should implement some sort of caching.
|
||||||
|
*/
|
||||||
|
private String getHostname() {
|
||||||
|
try {
|
||||||
|
return InetAddress.getLocalHost().getHostName();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
// If we are not able to detect the hostname we do not throw an exception.
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// This has to be placed after all other static fields to give them a chance to initialize
|
// This has to be placed after all other static fields to give them a chance to initialize
|
||||||
private static final Config INSTANCE = new Config();
|
private static final Config INSTANCE = new Config();
|
||||||
|
|
||||||
|
|
|
@ -50,5 +50,16 @@ public interface MutableSpan {
|
||||||
|
|
||||||
MutableSpan setError(boolean value);
|
MutableSpan setError(boolean value);
|
||||||
|
|
||||||
|
/** @deprecated Use {@link #getLocalRootSpan()} instead. */
|
||||||
|
@Deprecated
|
||||||
MutableSpan getRootSpan();
|
MutableSpan getRootSpan();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the root span for current the trace fragment. In the context of distributed tracing
|
||||||
|
* this method returns the root span only for the fragment generated by the currently traced
|
||||||
|
* application.
|
||||||
|
*
|
||||||
|
* @return The root span for the current trace fragment.
|
||||||
|
*/
|
||||||
|
MutableSpan getLocalRootSpan();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import static datadog.trace.api.Config.SERVICE_MAPPING
|
||||||
import static datadog.trace.api.Config.SERVICE_NAME
|
import static datadog.trace.api.Config.SERVICE_NAME
|
||||||
import static datadog.trace.api.Config.SPAN_TAGS
|
import static datadog.trace.api.Config.SPAN_TAGS
|
||||||
import static datadog.trace.api.Config.TRACE_AGENT_PORT
|
import static datadog.trace.api.Config.TRACE_AGENT_PORT
|
||||||
|
import static datadog.trace.api.Config.TRACE_REPORT_HOSTNAME
|
||||||
import static datadog.trace.api.Config.TRACE_ENABLED
|
import static datadog.trace.api.Config.TRACE_ENABLED
|
||||||
import static datadog.trace.api.Config.TRACE_RESOLVER_ENABLED
|
import static datadog.trace.api.Config.TRACE_RESOLVER_ENABLED
|
||||||
import static datadog.trace.api.Config.WRITER_TYPE
|
import static datadog.trace.api.Config.WRITER_TYPE
|
||||||
|
@ -56,6 +57,7 @@ class ConfigTest extends Specification {
|
||||||
private static final DD_JMXFETCH_METRICS_CONFIGS_ENV = "DD_JMXFETCH_METRICS_CONFIGS"
|
private static final DD_JMXFETCH_METRICS_CONFIGS_ENV = "DD_JMXFETCH_METRICS_CONFIGS"
|
||||||
private static final DD_TRACE_AGENT_PORT_ENV = "DD_TRACE_AGENT_PORT"
|
private static final DD_TRACE_AGENT_PORT_ENV = "DD_TRACE_AGENT_PORT"
|
||||||
private static final DD_AGENT_PORT_LEGACY_ENV = "DD_AGENT_PORT"
|
private static final DD_AGENT_PORT_LEGACY_ENV = "DD_AGENT_PORT"
|
||||||
|
private static final DD_TRACE_REPORT_HOSTNAME = "DD_TRACE_REPORT_HOSTNAME"
|
||||||
|
|
||||||
def "verify defaults"() {
|
def "verify defaults"() {
|
||||||
when:
|
when:
|
||||||
|
@ -78,6 +80,7 @@ class ConfigTest extends Specification {
|
||||||
config.httpClientErrorStatuses == (400..499).toSet()
|
config.httpClientErrorStatuses == (400..499).toSet()
|
||||||
config.httpClientSplitByDomain == false
|
config.httpClientSplitByDomain == false
|
||||||
config.partialFlushMinSpans == 1000
|
config.partialFlushMinSpans == 1000
|
||||||
|
config.reportHostName == false
|
||||||
config.runtimeContextFieldInjection == true
|
config.runtimeContextFieldInjection == true
|
||||||
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG]
|
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG]
|
||||||
config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG]
|
config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG]
|
||||||
|
@ -118,6 +121,7 @@ class ConfigTest extends Specification {
|
||||||
prop.setProperty(HTTP_CLIENT_ERROR_STATUSES, "111")
|
prop.setProperty(HTTP_CLIENT_ERROR_STATUSES, "111")
|
||||||
prop.setProperty(HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "true")
|
prop.setProperty(HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "true")
|
||||||
prop.setProperty(PARTIAL_FLUSH_MIN_SPANS, "15")
|
prop.setProperty(PARTIAL_FLUSH_MIN_SPANS, "15")
|
||||||
|
prop.setProperty(TRACE_REPORT_HOSTNAME, "true")
|
||||||
prop.setProperty(RUNTIME_CONTEXT_FIELD_INJECTION, "false")
|
prop.setProperty(RUNTIME_CONTEXT_FIELD_INJECTION, "false")
|
||||||
prop.setProperty(PROPAGATION_STYLE_EXTRACT, "Datadog, B3")
|
prop.setProperty(PROPAGATION_STYLE_EXTRACT, "Datadog, B3")
|
||||||
prop.setProperty(PROPAGATION_STYLE_INJECT, "B3, Datadog")
|
prop.setProperty(PROPAGATION_STYLE_INJECT, "B3, Datadog")
|
||||||
|
@ -148,6 +152,7 @@ class ConfigTest extends Specification {
|
||||||
config.httpClientErrorStatuses == (111..111).toSet()
|
config.httpClientErrorStatuses == (111..111).toSet()
|
||||||
config.httpClientSplitByDomain == true
|
config.httpClientSplitByDomain == true
|
||||||
config.partialFlushMinSpans == 15
|
config.partialFlushMinSpans == 15
|
||||||
|
config.reportHostName == true
|
||||||
config.runtimeContextFieldInjection == false
|
config.runtimeContextFieldInjection == false
|
||||||
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
|
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
|
||||||
config.propagationStylesToInject.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
|
config.propagationStylesToInject.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
|
||||||
|
@ -179,6 +184,7 @@ class ConfigTest extends Specification {
|
||||||
System.setProperty(PREFIX + HTTP_CLIENT_ERROR_STATUSES, "111")
|
System.setProperty(PREFIX + HTTP_CLIENT_ERROR_STATUSES, "111")
|
||||||
System.setProperty(PREFIX + HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "true")
|
System.setProperty(PREFIX + HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "true")
|
||||||
System.setProperty(PREFIX + PARTIAL_FLUSH_MIN_SPANS, "25")
|
System.setProperty(PREFIX + PARTIAL_FLUSH_MIN_SPANS, "25")
|
||||||
|
System.setProperty(PREFIX + TRACE_REPORT_HOSTNAME, "true")
|
||||||
System.setProperty(PREFIX + RUNTIME_CONTEXT_FIELD_INJECTION, "false")
|
System.setProperty(PREFIX + RUNTIME_CONTEXT_FIELD_INJECTION, "false")
|
||||||
System.setProperty(PREFIX + PROPAGATION_STYLE_EXTRACT, "Datadog, B3")
|
System.setProperty(PREFIX + PROPAGATION_STYLE_EXTRACT, "Datadog, B3")
|
||||||
System.setProperty(PREFIX + PROPAGATION_STYLE_INJECT, "B3, Datadog")
|
System.setProperty(PREFIX + PROPAGATION_STYLE_INJECT, "B3, Datadog")
|
||||||
|
@ -209,6 +215,7 @@ class ConfigTest extends Specification {
|
||||||
config.httpClientErrorStatuses == (111..111).toSet()
|
config.httpClientErrorStatuses == (111..111).toSet()
|
||||||
config.httpClientSplitByDomain == true
|
config.httpClientSplitByDomain == true
|
||||||
config.partialFlushMinSpans == 25
|
config.partialFlushMinSpans == 25
|
||||||
|
config.reportHostName == true
|
||||||
config.runtimeContextFieldInjection == false
|
config.runtimeContextFieldInjection == false
|
||||||
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
|
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
|
||||||
config.propagationStylesToInject.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
|
config.propagationStylesToInject.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
|
||||||
|
@ -228,6 +235,7 @@ class ConfigTest extends Specification {
|
||||||
environmentVariables.set(DD_PROPAGATION_STYLE_EXTRACT, "B3 Datadog")
|
environmentVariables.set(DD_PROPAGATION_STYLE_EXTRACT, "B3 Datadog")
|
||||||
environmentVariables.set(DD_PROPAGATION_STYLE_INJECT, "Datadog B3")
|
environmentVariables.set(DD_PROPAGATION_STYLE_INJECT, "Datadog B3")
|
||||||
environmentVariables.set(DD_JMXFETCH_METRICS_CONFIGS_ENV, "some/file")
|
environmentVariables.set(DD_JMXFETCH_METRICS_CONFIGS_ENV, "some/file")
|
||||||
|
environmentVariables.set(DD_TRACE_REPORT_HOSTNAME, "true")
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def config = new Config()
|
def config = new Config()
|
||||||
|
@ -239,6 +247,7 @@ class ConfigTest extends Specification {
|
||||||
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
|
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
|
||||||
config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
|
config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
|
||||||
config.jmxFetchMetricsConfigs == ["some/file"]
|
config.jmxFetchMetricsConfigs == ["some/file"]
|
||||||
|
config.reportHostName == true
|
||||||
}
|
}
|
||||||
|
|
||||||
def "sys props override env vars"() {
|
def "sys props override env vars"() {
|
||||||
|
@ -649,4 +658,27 @@ class ConfigTest extends Specification {
|
||||||
listString | list
|
listString | list
|
||||||
"" | []
|
"" | []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "verify hostname not added to root span tags by default"() {
|
||||||
|
setup:
|
||||||
|
Properties properties = new Properties()
|
||||||
|
|
||||||
|
when:
|
||||||
|
def config = Config.get(properties)
|
||||||
|
|
||||||
|
then:
|
||||||
|
!config.localRootSpanTags.containsKey('_dd.hostname')
|
||||||
|
}
|
||||||
|
|
||||||
|
def "verify configuration to add hostname to root span tags"() {
|
||||||
|
setup:
|
||||||
|
Properties properties = new Properties()
|
||||||
|
properties.setProperty(TRACE_REPORT_HOSTNAME, 'true')
|
||||||
|
|
||||||
|
when:
|
||||||
|
def config = Config.get(properties)
|
||||||
|
|
||||||
|
then:
|
||||||
|
config.localRootSpanTags.get('_dd.hostname') == InetAddress.localHost.hostName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,8 +110,16 @@ public class DDSpan implements Span, MutableSpan {
|
||||||
finishAndAddToTrace(TimeUnit.MICROSECONDS.toNanos(stoptimeMicros - startTimeMicro));
|
finishAndAddToTrace(TimeUnit.MICROSECONDS.toNanos(stoptimeMicros - startTimeMicro));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DDSpan setError(final boolean error) {
|
||||||
|
context.setErrorFlag(true);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the span is the root parent. It means that the traceId is the same as the spanId
|
* Check if the span is the root parent. It means that the traceId is the same as the spanId. In
|
||||||
|
* the context of distributed tracing this will return true if an only if this is the application
|
||||||
|
* initializing the trace.
|
||||||
*
|
*
|
||||||
* @return true if root, false otherwise
|
* @return true if root, false otherwise
|
||||||
*/
|
*/
|
||||||
|
@ -121,13 +129,15 @@ public class DDSpan implements Span, MutableSpan {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DDSpan setError(final boolean error) {
|
@Deprecated
|
||||||
context.setErrorFlag(true);
|
@JsonIgnore
|
||||||
return this;
|
public MutableSpan getRootSpan() {
|
||||||
|
return getLocalRootSpan();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MutableSpan getRootSpan() {
|
@JsonIgnore
|
||||||
|
public MutableSpan getLocalRootSpan() {
|
||||||
return context().getTrace().getRootSpan();
|
return context().getTrace().getRootSpan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,8 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
/** Scope manager is in charge of managing the scopes from which spans are created */
|
/** Scope manager is in charge of managing the scopes from which spans are created */
|
||||||
final ContextualScopeManager scopeManager = new ContextualScopeManager();
|
final ContextualScopeManager scopeManager = new ContextualScopeManager();
|
||||||
|
|
||||||
/** Tags required to link apm traces to runtime metrics */
|
/** A set of tags that are added only to the application's root span */
|
||||||
final Map<String, String> runtimeTags;
|
private final Map<String, String> localRootSpanTags;
|
||||||
/** A set of tags that are added to every span */
|
/** A set of tags that are added to every span */
|
||||||
private final Map<String, String> defaultSpanTags;
|
private final Map<String, String> defaultSpanTags;
|
||||||
/** A configured mapping of service names to update with new values */
|
/** A configured mapping of service names to update with new values */
|
||||||
|
@ -107,7 +107,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
|
|
||||||
// This constructor is already used in the wild, so we have to keep it inside this API for now.
|
// This constructor is already used in the wild, so we have to keep it inside this API for now.
|
||||||
public DDTracer(final String serviceName, final Writer writer, final Sampler sampler) {
|
public DDTracer(final String serviceName, final Writer writer, final Sampler sampler) {
|
||||||
this(serviceName, writer, sampler, Config.get().getRuntimeTags());
|
this(serviceName, writer, sampler, Config.get().getLocalRootSpanTags());
|
||||||
}
|
}
|
||||||
|
|
||||||
private DDTracer(final String serviceName, final Config config) {
|
private DDTracer(final String serviceName, final Config config) {
|
||||||
|
@ -115,7 +115,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
serviceName,
|
serviceName,
|
||||||
Writer.Builder.forConfig(config),
|
Writer.Builder.forConfig(config),
|
||||||
Sampler.Builder.forConfig(config),
|
Sampler.Builder.forConfig(config),
|
||||||
config.getRuntimeTags(),
|
config.getLocalRootSpanTags(),
|
||||||
config.getMergedSpanTags(),
|
config.getMergedSpanTags(),
|
||||||
config.getServiceMapping(),
|
config.getServiceMapping(),
|
||||||
config.getHeaderTags(),
|
config.getHeaderTags(),
|
||||||
|
@ -149,7 +149,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
config.getServiceName(),
|
config.getServiceName(),
|
||||||
writer,
|
writer,
|
||||||
Sampler.Builder.forConfig(config),
|
Sampler.Builder.forConfig(config),
|
||||||
config.getRuntimeTags(),
|
config.getLocalRootSpanTags(),
|
||||||
config.getMergedSpanTags(),
|
config.getMergedSpanTags(),
|
||||||
config.getServiceMapping(),
|
config.getServiceMapping(),
|
||||||
config.getHeaderTags(),
|
config.getHeaderTags(),
|
||||||
|
@ -165,6 +165,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
final Writer writer,
|
final Writer writer,
|
||||||
final Sampler sampler,
|
final Sampler sampler,
|
||||||
final String runtimeId,
|
final String runtimeId,
|
||||||
|
final Map<String, String> localRootSpanTags,
|
||||||
final Map<String, String> defaultSpanTags,
|
final Map<String, String> defaultSpanTags,
|
||||||
final Map<String, String> serviceNameMappings,
|
final Map<String, String> serviceNameMappings,
|
||||||
final Map<String, String> taggedHeaders) {
|
final Map<String, String> taggedHeaders) {
|
||||||
|
@ -172,7 +173,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
serviceName,
|
serviceName,
|
||||||
writer,
|
writer,
|
||||||
sampler,
|
sampler,
|
||||||
customRuntimeTags(runtimeId),
|
customRuntimeTags(runtimeId, localRootSpanTags),
|
||||||
defaultSpanTags,
|
defaultSpanTags,
|
||||||
serviceNameMappings,
|
serviceNameMappings,
|
||||||
taggedHeaders,
|
taggedHeaders,
|
||||||
|
@ -187,7 +188,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
final String serviceName,
|
final String serviceName,
|
||||||
final Writer writer,
|
final Writer writer,
|
||||||
final Sampler sampler,
|
final Sampler sampler,
|
||||||
final Map<String, String> runtimeTags,
|
final Map<String, String> localRootSpanTags,
|
||||||
final Map<String, String> defaultSpanTags,
|
final Map<String, String> defaultSpanTags,
|
||||||
final Map<String, String> serviceNameMappings,
|
final Map<String, String> serviceNameMappings,
|
||||||
final Map<String, String> taggedHeaders) {
|
final Map<String, String> taggedHeaders) {
|
||||||
|
@ -195,7 +196,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
serviceName,
|
serviceName,
|
||||||
writer,
|
writer,
|
||||||
sampler,
|
sampler,
|
||||||
runtimeTags,
|
localRootSpanTags,
|
||||||
defaultSpanTags,
|
defaultSpanTags,
|
||||||
serviceNameMappings,
|
serviceNameMappings,
|
||||||
taggedHeaders,
|
taggedHeaders,
|
||||||
|
@ -206,12 +207,12 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
final String serviceName,
|
final String serviceName,
|
||||||
final Writer writer,
|
final Writer writer,
|
||||||
final Sampler sampler,
|
final Sampler sampler,
|
||||||
final Map<String, String> runtimeTags,
|
final Map<String, String> localRootSpanTags,
|
||||||
final Map<String, String> defaultSpanTags,
|
final Map<String, String> defaultSpanTags,
|
||||||
final Map<String, String> serviceNameMappings,
|
final Map<String, String> serviceNameMappings,
|
||||||
final Map<String, String> taggedHeaders,
|
final Map<String, String> taggedHeaders,
|
||||||
final int partialFlushMinSpans) {
|
final int partialFlushMinSpans) {
|
||||||
assert runtimeTags != null;
|
assert localRootSpanTags != null;
|
||||||
assert defaultSpanTags != null;
|
assert defaultSpanTags != null;
|
||||||
assert serviceNameMappings != null;
|
assert serviceNameMappings != null;
|
||||||
assert taggedHeaders != null;
|
assert taggedHeaders != null;
|
||||||
|
@ -220,8 +221,8 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
this.writer.start();
|
this.writer.start();
|
||||||
this.sampler = sampler;
|
this.sampler = sampler;
|
||||||
|
this.localRootSpanTags = localRootSpanTags;
|
||||||
this.defaultSpanTags = defaultSpanTags;
|
this.defaultSpanTags = defaultSpanTags;
|
||||||
this.runtimeTags = runtimeTags;
|
|
||||||
this.serviceNameMappings = serviceNameMappings;
|
this.serviceNameMappings = serviceNameMappings;
|
||||||
this.partialFlushMinSpans = partialFlushMinSpans;
|
this.partialFlushMinSpans = partialFlushMinSpans;
|
||||||
|
|
||||||
|
@ -439,9 +440,9 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private static Map<String, String> customRuntimeTags(final String runtimeId) {
|
private static Map<String, String> customRuntimeTags(
|
||||||
final Map<String, String> runtimeTags = new HashMap<>();
|
final String runtimeId, Map<String, String> applicationRootSpanTags) {
|
||||||
runtimeTags.putAll(Config.get().getRuntimeTags());
|
final Map<String, String> runtimeTags = new HashMap<>(applicationRootSpanTags);
|
||||||
runtimeTags.put(Config.RUNTIME_ID_TAG, runtimeId);
|
runtimeTags.put(Config.RUNTIME_ID_TAG, runtimeId);
|
||||||
return Collections.unmodifiableMap(runtimeTags);
|
return Collections.unmodifiableMap(runtimeTags);
|
||||||
}
|
}
|
||||||
|
@ -623,7 +624,9 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propagate internal trace
|
// Propagate internal trace.
|
||||||
|
// Note: if we are not in the context of distributed tracing and we are starting the first
|
||||||
|
// root span, parentContext will be null at this point.
|
||||||
if (parentContext instanceof DDSpanContext) {
|
if (parentContext instanceof DDSpanContext) {
|
||||||
final DDSpanContext ddsc = (DDSpanContext) parentContext;
|
final DDSpanContext ddsc = (DDSpanContext) parentContext;
|
||||||
traceId = ddsc.getTraceId();
|
traceId = ddsc.getTraceId();
|
||||||
|
@ -660,10 +663,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
||||||
origin = null;
|
origin = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add runtime tags to the root span
|
tags.putAll(localRootSpanTags);
|
||||||
for (final Map.Entry<String, String> runtimeTag : runtimeTags.entrySet()) {
|
|
||||||
tags.put(runtimeTag.getKey(), runtimeTag.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
parentTrace = new PendingTrace(DDTracer.this, traceId, serviceNameMappings);
|
parentTrace = new PendingTrace(DDTracer.this, traceId, serviceNameMappings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import datadog.opentracing.propagation.TagContext
|
||||||
import datadog.trace.api.sampling.PrioritySampling
|
import datadog.trace.api.sampling.PrioritySampling
|
||||||
import datadog.trace.common.sampling.RateByServiceSampler
|
import datadog.trace.common.sampling.RateByServiceSampler
|
||||||
import datadog.trace.common.writer.ListWriter
|
import datadog.trace.common.writer.ListWriter
|
||||||
|
import io.opentracing.SpanContext
|
||||||
import spock.lang.Shared
|
import spock.lang.Shared
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
|
@ -207,18 +208,45 @@ class DDSpanTest extends Specification {
|
||||||
new ExtractedContext("1", "2", 0, "some-origin", [:], [:]) | _
|
new ExtractedContext("1", "2", 0, "some-origin", [:], [:]) | _
|
||||||
}
|
}
|
||||||
|
|
||||||
def "getRootSpan returns the root span"() {
|
def "isRootSpan() in and not in the context of distributed tracing"() {
|
||||||
setup:
|
setup:
|
||||||
def root = tracer.buildSpan("root").start()
|
def root = tracer.buildSpan("root").asChildOf((SpanContext)extractedContext).start()
|
||||||
def child = tracer.buildSpan("child").asChildOf(root).start()
|
def child = tracer.buildSpan("child").asChildOf(root).start()
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
root.getRootSpan() == root
|
root.isRootSpan() == isTraceRootSpan
|
||||||
child.getRootSpan() == root
|
!child.isRootSpan()
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
child.finish()
|
child.finish()
|
||||||
root.finish()
|
root.finish()
|
||||||
|
|
||||||
|
where:
|
||||||
|
extractedContext | isTraceRootSpan
|
||||||
|
null | true
|
||||||
|
new ExtractedContext("123", "456", 1, "789", [:], [:]) | false
|
||||||
|
}
|
||||||
|
|
||||||
|
def "getApplicationRootSpan() in and not in the context of distributed tracing"() {
|
||||||
|
setup:
|
||||||
|
def root = tracer.buildSpan("root").asChildOf((SpanContext)extractedContext).start()
|
||||||
|
def child = tracer.buildSpan("child").asChildOf(root).start()
|
||||||
|
|
||||||
|
expect:
|
||||||
|
root.localRootSpan == root
|
||||||
|
child.localRootSpan == root
|
||||||
|
// Checking for backward compatibility method names
|
||||||
|
root.rootSpan == root
|
||||||
|
child.rootSpan == root
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
child.finish()
|
||||||
|
root.finish()
|
||||||
|
|
||||||
|
where:
|
||||||
|
extractedContext | isTraceRootSpan
|
||||||
|
null | true
|
||||||
|
new ExtractedContext("123", "456", 1, "789", [:], [:]) | false
|
||||||
}
|
}
|
||||||
|
|
||||||
def "setting forced tracing via tag"() {
|
def "setting forced tracing via tag"() {
|
||||||
|
|
|
@ -49,6 +49,7 @@ class SpanDecoratorTest extends Specification {
|
||||||
new AllSampler(),
|
new AllSampler(),
|
||||||
"some-runtime-id",
|
"some-runtime-id",
|
||||||
emptyMap(),
|
emptyMap(),
|
||||||
|
emptyMap(),
|
||||||
mapping,
|
mapping,
|
||||||
emptyMap()
|
emptyMap()
|
||||||
)
|
)
|
||||||
|
@ -80,6 +81,7 @@ class SpanDecoratorTest extends Specification {
|
||||||
new AllSampler(),
|
new AllSampler(),
|
||||||
"some-runtime-id",
|
"some-runtime-id",
|
||||||
emptyMap(),
|
emptyMap(),
|
||||||
|
emptyMap(),
|
||||||
mapping,
|
mapping,
|
||||||
emptyMap()
|
emptyMap()
|
||||||
)
|
)
|
||||||
|
@ -126,6 +128,7 @@ class SpanDecoratorTest extends Specification {
|
||||||
new AllSampler(),
|
new AllSampler(),
|
||||||
"some-runtime-id",
|
"some-runtime-id",
|
||||||
emptyMap(),
|
emptyMap(),
|
||||||
|
emptyMap(),
|
||||||
mapping,
|
mapping,
|
||||||
emptyMap()
|
emptyMap()
|
||||||
)
|
)
|
||||||
|
|
|
@ -31,7 +31,7 @@ class DDTracerTest extends Specification {
|
||||||
// assert that a trace agent isn't running locally as that messes up the test.
|
// assert that a trace agent isn't running locally as that messes up the test.
|
||||||
try {
|
try {
|
||||||
(new Socket("localhost", 8126)).close()
|
(new Socket("localhost", 8126)).close()
|
||||||
throw new IllegalStateException("Trace Agent unexpectedly running locally.")
|
throw new IllegalStateException("An agent is already running locally on port 8126. Please stop it if you want to run tests locally.")
|
||||||
} catch (final ConnectException ioe) {
|
} catch (final ConnectException ioe) {
|
||||||
// trace agent is not running locally.
|
// trace agent is not running locally.
|
||||||
}
|
}
|
||||||
|
@ -126,8 +126,8 @@ class DDTracerTest extends Specification {
|
||||||
tracer.serviceName == DEFAULT_SERVICE_NAME
|
tracer.serviceName == DEFAULT_SERVICE_NAME
|
||||||
tracer.sampler == sampler
|
tracer.sampler == sampler
|
||||||
tracer.writer == writer
|
tracer.writer == writer
|
||||||
tracer.runtimeTags[Config.RUNTIME_ID_TAG].size() > 0 // not null or empty
|
tracer.localRootSpanTags[Config.RUNTIME_ID_TAG].size() > 0 // not null or empty
|
||||||
tracer.runtimeTags[Config.LANGUAGE_TAG_KEY] == Config.LANGUAGE_TAG_VALUE
|
tracer.localRootSpanTags[Config.LANGUAGE_TAG_KEY] == Config.LANGUAGE_TAG_VALUE
|
||||||
}
|
}
|
||||||
|
|
||||||
def "Shares TraceCount with DDApi with #key = #value"() {
|
def "Shares TraceCount with DDApi with #key = #value"() {
|
||||||
|
@ -144,4 +144,19 @@ class DDTracerTest extends Specification {
|
||||||
PRIORITY_SAMPLING | "true"
|
PRIORITY_SAMPLING | "true"
|
||||||
PRIORITY_SAMPLING | "false"
|
PRIORITY_SAMPLING | "false"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "root tags are applied only to root spans"() {
|
||||||
|
setup:
|
||||||
|
def tracer = new DDTracer('my_service', new ListWriter(), new AllSampler(), '', ['only_root': 'value'], [:], [:], [:])
|
||||||
|
def root = tracer.buildSpan('my_root').start()
|
||||||
|
def child = tracer.buildSpan('my_child').asChildOf(root).start()
|
||||||
|
|
||||||
|
expect:
|
||||||
|
root.context().tags.containsKey('only_root')
|
||||||
|
!child.context().tags.containsKey('only_root')
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
child.finish()
|
||||||
|
root.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue