Skip to content

Commit 920b9b5

Browse files
authored
Merge pull request #827 from DataDog/labbati/hostname
Detect hostname
2 parents 47e6216 + 88b6a2c commit 920b9b5

9 files changed

Lines changed: 175 additions & 34 deletions

File tree

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ Other source files (Groovy, Scala, etc) should ideally be formatted by Intellij
2020
Suggested plugins and settings:
2121

2222
* Editor > Code Style > Java/Groovy > Imports
23-
* Class count to use import with '*': `10` (some number sufficiently large that is unlikely to matter)
24-
* Names count to use static import with '*': `10`
23+
* Class count to use import with '*': `50` (some number sufficiently large that is unlikely to matter)
24+
* Names count to use static import with '*': `50`
2525
* With java use the following import layout (groovy should still use the default) to ensure consistency with google-java-format:
2626
![import layout](https://user-images.githubusercontent.com/734411/43430811-28442636-94ae-11e8-86f1-f270ddcba023.png)
2727
* [Google Java Format](https://plugins.jetbrains.com/plugin/8527-google-java-format)

dd-trace-api/src/main/java/datadog/trace/api/Config.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package datadog.trace.api;
22

3+
import java.net.InetAddress;
4+
import java.net.UnknownHostException;
35
import java.util.Arrays;
46
import java.util.Collections;
57
import java.util.HashMap;
@@ -51,6 +53,7 @@ public class Config {
5153
public static final String TRACE_ANNOTATIONS = "trace.annotations";
5254
public static final String TRACE_METHODS = "trace.methods";
5355
public static final String TRACE_CLASSES_EXCLUDE = "trace.classes.exclude";
56+
public static final String TRACE_REPORT_HOSTNAME = "trace.report-hostname";
5457
public static final String HEADER_TAGS = "trace.header.tags";
5558
public static final String HTTP_SERVER_ERROR_STATUSES = "http.server.error.statuses";
5659
public static final String HTTP_CLIENT_ERROR_STATUSES = "http.client.error.statuses";
@@ -105,11 +108,16 @@ public class Config {
105108

106109
private static final String SPLIT_BY_SPACE_OR_COMMA_REGEX = "[,\\s]+";
107110

111+
private static final boolean DEFAULT_TRACE_REPORT_HOSTNAME = false;
112+
108113
public enum PropagationStyle {
109114
DATADOG,
110115
B3
111116
}
112117

118+
/** A tag intended for internal use only, hence not added to the public api DDTags class. */
119+
private static final String INTERNAL_HOST_NAME = "_dd.hostname";
120+
113121
/**
114122
* this is a random UUID that gets generated on JVM start up and is attached to every root span
115123
* and every JMX metric that is sent out.
@@ -147,6 +155,8 @@ public enum PropagationStyle {
147155

148156
@Getter private final boolean logsInjectionEnabled;
149157

158+
@Getter private final boolean reportHostName;
159+
150160
// Read order: System Properties -> Env Variables, [-> default value]
151161
// Visible for testing
152162
Config() {
@@ -221,6 +231,9 @@ public enum PropagationStyle {
221231
logsInjectionEnabled =
222232
getBooleanSettingFromEnvironment(LOGS_INJECTION_ENABLED, DEFAULT_LOGS_INJECTION_ENABLED);
223233

234+
reportHostName =
235+
getBooleanSettingFromEnvironment(TRACE_REPORT_HOSTNAME, DEFAULT_TRACE_REPORT_HOSTNAME);
236+
224237
log.debug("New instance: {}", this);
225238
}
226239

@@ -301,9 +314,24 @@ private Config(final Properties properties, final Config parent) {
301314
logsInjectionEnabled =
302315
getBooleanSettingFromEnvironment(LOGS_INJECTION_ENABLED, DEFAULT_LOGS_INJECTION_ENABLED);
303316

317+
reportHostName =
318+
getPropertyBooleanValue(properties, TRACE_REPORT_HOSTNAME, parent.reportHostName);
319+
304320
log.debug("New instance: {}", this);
305321
}
306322

323+
/** @return A map of tags to be applied only to the local application root span. */
324+
public Map<String, String> getLocalRootSpanTags() {
325+
final Map<String, String> runtimeTags = getRuntimeTags();
326+
final Map<String, String> result =
327+
newHashMap(reportHostName ? (runtimeTags.size() + 1) : runtimeTags.size());
328+
result.putAll(runtimeTags);
329+
if (reportHostName) {
330+
result.put(INTERNAL_HOST_NAME, getHostname());
331+
}
332+
return Collections.unmodifiableMap(result);
333+
}
334+
307335
public Map<String, String> getMergedSpanTags() {
308336
// DO not include runtimeId into span tags: we only want that added to the root span
309337
final Map<String, String> result = newHashMap(globalTags.size() + spanTags.size());
@@ -336,7 +364,7 @@ public Map<String, String> getMergedJmxTags() {
336364
*
337365
* @return A map of tag-name -> tag-value
338366
*/
339-
public Map<String, String> getRuntimeTags() {
367+
private Map<String, String> getRuntimeTags() {
340368
final Map<String, String> result = newHashMap(2);
341369
result.put(RUNTIME_ID_TAG, runtimeId);
342370
result.put(LANGUAGE_TAG_KEY, LANGUAGE_TAG_VALUE);
@@ -636,6 +664,20 @@ private static <V extends Enum<V>> Set<V> convertStringSetToEnumSet(
636664
return Collections.unmodifiableSet(result);
637665
}
638666

667+
/**
668+
* Returns the detected hostname. This operation is time consuming so if the usage changes and
669+
* this method will be called several times then we should implement some sort of caching.
670+
*/
671+
private String getHostname() {
672+
try {
673+
return InetAddress.getLocalHost().getHostName();
674+
} catch (UnknownHostException e) {
675+
// If we are not able to detect the hostname we do not throw an exception.
676+
}
677+
678+
return null;
679+
}
680+
639681
// This has to be placed after all other static fields to give them a chance to initialize
640682
private static final Config INSTANCE = new Config();
641683

dd-trace-api/src/main/java/datadog/trace/api/interceptor/MutableSpan.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,16 @@ public interface MutableSpan {
5050

5151
MutableSpan setError(boolean value);
5252

53+
/** @deprecated Use {@link #getLocalRootSpan()} instead. */
54+
@Deprecated
5355
MutableSpan getRootSpan();
56+
57+
/**
58+
* Returns the root span for current the trace fragment. In the context of distributed tracing
59+
* this method returns the root span only for the fragment generated by the currently traced
60+
* application.
61+
*
62+
* @return The root span for the current trace fragment.
63+
*/
64+
MutableSpan getLocalRootSpan();
5465
}

dd-trace-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import static datadog.trace.api.Config.SERVICE_MAPPING
3535
import static datadog.trace.api.Config.SERVICE_NAME
3636
import static datadog.trace.api.Config.SPAN_TAGS
3737
import static datadog.trace.api.Config.TRACE_AGENT_PORT
38+
import static datadog.trace.api.Config.TRACE_REPORT_HOSTNAME
3839
import static datadog.trace.api.Config.TRACE_ENABLED
3940
import static datadog.trace.api.Config.TRACE_RESOLVER_ENABLED
4041
import static datadog.trace.api.Config.WRITER_TYPE
@@ -56,6 +57,7 @@ class ConfigTest extends Specification {
5657
private static final DD_JMXFETCH_METRICS_CONFIGS_ENV = "DD_JMXFETCH_METRICS_CONFIGS"
5758
private static final DD_TRACE_AGENT_PORT_ENV = "DD_TRACE_AGENT_PORT"
5859
private static final DD_AGENT_PORT_LEGACY_ENV = "DD_AGENT_PORT"
60+
private static final DD_TRACE_REPORT_HOSTNAME = "DD_TRACE_REPORT_HOSTNAME"
5961

6062
def "verify defaults"() {
6163
when:
@@ -78,6 +80,7 @@ class ConfigTest extends Specification {
7880
config.httpClientErrorStatuses == (400..499).toSet()
7981
config.httpClientSplitByDomain == false
8082
config.partialFlushMinSpans == 1000
83+
config.reportHostName == false
8184
config.runtimeContextFieldInjection == true
8285
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG]
8386
config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG]
@@ -118,6 +121,7 @@ class ConfigTest extends Specification {
118121
prop.setProperty(HTTP_CLIENT_ERROR_STATUSES, "111")
119122
prop.setProperty(HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "true")
120123
prop.setProperty(PARTIAL_FLUSH_MIN_SPANS, "15")
124+
prop.setProperty(TRACE_REPORT_HOSTNAME, "true")
121125
prop.setProperty(RUNTIME_CONTEXT_FIELD_INJECTION, "false")
122126
prop.setProperty(PROPAGATION_STYLE_EXTRACT, "Datadog, B3")
123127
prop.setProperty(PROPAGATION_STYLE_INJECT, "B3, Datadog")
@@ -148,6 +152,7 @@ class ConfigTest extends Specification {
148152
config.httpClientErrorStatuses == (111..111).toSet()
149153
config.httpClientSplitByDomain == true
150154
config.partialFlushMinSpans == 15
155+
config.reportHostName == true
151156
config.runtimeContextFieldInjection == false
152157
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
153158
config.propagationStylesToInject.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
@@ -179,6 +184,7 @@ class ConfigTest extends Specification {
179184
System.setProperty(PREFIX + HTTP_CLIENT_ERROR_STATUSES, "111")
180185
System.setProperty(PREFIX + HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "true")
181186
System.setProperty(PREFIX + PARTIAL_FLUSH_MIN_SPANS, "25")
187+
System.setProperty(PREFIX + TRACE_REPORT_HOSTNAME, "true")
182188
System.setProperty(PREFIX + RUNTIME_CONTEXT_FIELD_INJECTION, "false")
183189
System.setProperty(PREFIX + PROPAGATION_STYLE_EXTRACT, "Datadog, B3")
184190
System.setProperty(PREFIX + PROPAGATION_STYLE_INJECT, "B3, Datadog")
@@ -209,6 +215,7 @@ class ConfigTest extends Specification {
209215
config.httpClientErrorStatuses == (111..111).toSet()
210216
config.httpClientSplitByDomain == true
211217
config.partialFlushMinSpans == 25
218+
config.reportHostName == true
212219
config.runtimeContextFieldInjection == false
213220
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
214221
config.propagationStylesToInject.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
@@ -228,6 +235,7 @@ class ConfigTest extends Specification {
228235
environmentVariables.set(DD_PROPAGATION_STYLE_EXTRACT, "B3 Datadog")
229236
environmentVariables.set(DD_PROPAGATION_STYLE_INJECT, "Datadog B3")
230237
environmentVariables.set(DD_JMXFETCH_METRICS_CONFIGS_ENV, "some/file")
238+
environmentVariables.set(DD_TRACE_REPORT_HOSTNAME, "true")
231239

232240
when:
233241
def config = new Config()
@@ -239,6 +247,7 @@ class ConfigTest extends Specification {
239247
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
240248
config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
241249
config.jmxFetchMetricsConfigs == ["some/file"]
250+
config.reportHostName == true
242251
}
243252

244253
def "sys props override env vars"() {
@@ -649,4 +658,27 @@ class ConfigTest extends Specification {
649658
listString | list
650659
"" | []
651660
}
661+
662+
def "verify hostname not added to root span tags by default"() {
663+
setup:
664+
Properties properties = new Properties()
665+
666+
when:
667+
def config = Config.get(properties)
668+
669+
then:
670+
!config.localRootSpanTags.containsKey('_dd.hostname')
671+
}
672+
673+
def "verify configuration to add hostname to root span tags"() {
674+
setup:
675+
Properties properties = new Properties()
676+
properties.setProperty(TRACE_REPORT_HOSTNAME, 'true')
677+
678+
when:
679+
def config = Config.get(properties)
680+
681+
then:
682+
config.localRootSpanTags.get('_dd.hostname') == InetAddress.localHost.hostName
683+
}
652684
}

dd-trace-ot/src/main/java/datadog/opentracing/DDSpan.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,16 @@ public final void finish(final long stoptimeMicros) {
110110
finishAndAddToTrace(TimeUnit.MICROSECONDS.toNanos(stoptimeMicros - startTimeMicro));
111111
}
112112

113+
@Override
114+
public DDSpan setError(final boolean error) {
115+
context.setErrorFlag(true);
116+
return this;
117+
}
118+
113119
/**
114-
* Check if the span is the root parent. It means that the traceId is the same as the spanId
120+
* Check if the span is the root parent. It means that the traceId is the same as the spanId. In
121+
* the context of distributed tracing this will return true if an only if this is the application
122+
* initializing the trace.
115123
*
116124
* @return true if root, false otherwise
117125
*/
@@ -121,13 +129,15 @@ public final boolean isRootSpan() {
121129
}
122130

123131
@Override
124-
public DDSpan setError(final boolean error) {
125-
context.setErrorFlag(true);
126-
return this;
132+
@Deprecated
133+
@JsonIgnore
134+
public MutableSpan getRootSpan() {
135+
return getLocalRootSpan();
127136
}
128137

129138
@Override
130-
public MutableSpan getRootSpan() {
139+
@JsonIgnore
140+
public MutableSpan getLocalRootSpan() {
131141
return context().getTrace().getRootSpan();
132142
}
133143

0 commit comments

Comments
 (0)