Add option to configure Datadog site used to send profiling information
MODIFY
dd-java-agent/agent-profiling/profiling-uploader/src/main/java/com/datadog/profiling/uploader/RecordingUploader.java
dd-java-agent/agent-profiling/profiling-uploader/src/main/java/com/datadog/profiling/uploader/RecordingUploader.java
@@ -53,6 +53,7 @@ import okhttp3.Response;
/** The class for uploading recordings to the backend. */
@Slf4j
public final class RecordingUploader {
+
private static final MediaType OCTET_STREAM = MediaType.parse("application/octet-stream");
static final String RECORDING_NAME_PARAM = "recording-name";
@@ -120,7 +121,7 @@ public final class RecordingUploader {
private final Deque<Integer> requestSizeHistory;
public RecordingUploader(final Config config) {
- url = config.getProfilingUrl();
+ url = config.getFinalProfilingUrl();
apiKey = config.getProfilingApiKey();
/*
@@ -233,6 +234,7 @@ public final class RecordingUploader {
@FunctionalInterface
private interface Compression {
+
RequestBody compress(InputStream is, int expectedSize) throws IOException;
}

MODIFY
dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/RecordingUploaderTest.java
dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/RecordingUploaderTest.java
@@ -120,7 +120,7 @@ public class RecordingUploaderTest {
server.start();
url = server.url(URL_PATH);
- when(config.getProfilingUrl()).thenReturn(server.url(URL_PATH).toString());
+ when(config.getFinalProfilingUrl()).thenReturn(server.url(URL_PATH).toString());
when(config.getProfilingApiKey()).thenReturn(APIKEY_VALUE);
when(config.getMergedProfilingTags()).thenReturn(TAGS);
when(config.getProfilingUploadTimeout()).thenReturn((int) REQUEST_TIMEOUT.getSeconds());
@@ -199,7 +199,7 @@ public class RecordingUploaderTest {
public void testRequestWithProxy() throws IOException, InterruptedException {
final String backendHost = "intake.profiling.datadoghq.com:1234";
final String backendUrl = "http://intake.profiling.datadoghq.com:1234" + URL_PATH;
- when(config.getProfilingUrl())
+ when(config.getFinalProfilingUrl())
.thenReturn("http://intake.profiling.datadoghq.com:1234" + URL_PATH);
when(config.getProfilingProxyHost()).thenReturn(server.url("").host());
when(config.getProfilingProxyPort()).thenReturn(server.url("").port());
@@ -235,7 +235,7 @@ public class RecordingUploaderTest {
@Test
public void testRequestWithProxyDefaultPassword() throws IOException, InterruptedException {
final String backendUrl = "http://intake.profiling.datadoghq.com:1234" + URL_PATH;
- when(config.getProfilingUrl())
+ when(config.getFinalProfilingUrl())
.thenReturn("http://intake.profiling.datadoghq.com:1234" + URL_PATH);
when(config.getProfilingProxyHost()).thenReturn(server.url("").host());
when(config.getProfilingProxyPort()).thenReturn(server.url("").port());

MODIFY
dd-trace-api/src/main/java/datadog/trace/api/Config.java
dd-trace-api/src/main/java/datadog/trace/api/Config.java
@@ -40,9 +40,12 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
@ToString(includeFieldNames = true)
public class Config {
+
/** Config keys below */
private static final String PREFIX = "dd.";
+ public static final String PROFILING_URL_TEMPLATE = "https://intake.profile.%s/v1/input";
+
private static final Pattern ENV_REPLACEMENT = Pattern.compile("[^a-zA-Z0-9_]");
public static final String CONFIGURATION_FILE = "trace.config";
@@ -106,6 +109,7 @@ public class Config {
public static final String LOGS_INJECTION_ENABLED = "logs.injection";
public static final String PROFILING_ENABLED = "profiling.enabled";
+ public static final String PROFILING_SITE = "profiling.site";
public static final String PROFILING_URL = "profiling.url";
public static final String PROFILING_API_KEY = "profiling.api-key";
@@ -173,8 +177,7 @@ public class Config {
public static final boolean DEFAULT_LOGS_INJECTION_ENABLED = false;
public static final boolean DEFAULT_PROFILING_ENABLED = false;
- public static final String DEFAULT_PROFILING_URL =
- "https://intake.profile.datadoghq.com/v1/input";
+ public static final String DEFAULT_PROFILING_SITE = "datadoghq.com";
public static final int DEFAULT_PROFILING_START_DELAY = 10;
public static final boolean DEFAULT_PROFILING_START_FORCE_FIRST = false;
public static final int DEFAULT_PROFILING_UPLOAD_PERIOD = 60; // 1 min
@@ -269,7 +272,8 @@ public class Config {
@Getter private final Double traceRateLimit;
@Getter private final boolean profilingEnabled;
- @Getter private final String profilingUrl;
+ @Getter private final String profilingSite;
+ private final String profilingUrl;
@Getter private final String profilingApiKey;
private final Map<String, String> profilingTags;
@Getter private final int profilingStartDelay;
@@ -415,7 +419,8 @@ public class Config {
profilingEnabled =
getBooleanSettingFromEnvironment(PROFILING_ENABLED, DEFAULT_PROFILING_ENABLED);
- profilingUrl = getSettingFromEnvironment(PROFILING_URL, DEFAULT_PROFILING_URL);
+ profilingSite = getSettingFromEnvironment(PROFILING_SITE, DEFAULT_PROFILING_SITE);
+ profilingUrl = getSettingFromEnvironment(PROFILING_URL, null);
// Note: We do not want APiKey to be loaded from property for security reasons
// Note: we do not use defined default here
// FIXME: We should use better authentication mechanism
@@ -609,6 +614,7 @@ public class Config {
profilingEnabled =
getPropertyBooleanValue(properties, PROFILING_ENABLED, parent.profilingEnabled);
+ profilingSite = properties.getProperty(PROFILING_SITE, parent.profilingSite);
profilingUrl = properties.getProperty(PROFILING_URL, parent.profilingUrl);
profilingApiKey = properties.getProperty(PROFILING_API_KEY, parent.profilingApiKey);
profilingTags = getPropertyMapValue(properties, PROFILING_TAGS, parent.profilingTags);
@@ -734,17 +740,25 @@ public class Config {
return Collections.unmodifiableMap(result);
}
+ public String getFinalProfilingUrl() {
+ if (profilingUrl == null) {
+ return String.format(PROFILING_URL_TEMPLATE, profilingSite);
+ } else {
+ return profilingUrl;
+ }
+ }
+
public boolean isIntegrationEnabled(
final SortedSet<String> integrationNames, final boolean defaultEnabled) {
return integrationEnabled(integrationNames, defaultEnabled);
}
/**
- * @deprecated This method should only be used internally. Use the instance getter instead {@link
- * #isIntegrationEnabled(SortedSet, boolean)}.
* @param integrationNames
* @param defaultEnabled
* @return
+ * @deprecated This method should only be used internally. Use the instance getter instead {@link
+ * #isIntegrationEnabled(SortedSet, boolean)}.
*/
public static boolean integrationEnabled(
final SortedSet<String> integrationNames, final boolean defaultEnabled) {
@@ -774,11 +788,11 @@ public class Config {
}
/**
- * @deprecated This method should only be used internally. Use the instance getter instead {@link
- * #isJmxFetchIntegrationEnabled(SortedSet, boolean)}.
* @param integrationNames
* @param defaultEnabled
* @return
+ * @deprecated This method should only be used internally. Use the instance getter instead {@link
+ * #isJmxFetchIntegrationEnabled(SortedSet, boolean)}.
*/
public static boolean jmxFetchIntegrationEnabled(
final SortedSet<String> integrationNames, final boolean defaultEnabled) {
@@ -803,11 +817,11 @@ public class Config {
}
/**
- * @deprecated This method should only be used internally. Use the instance getter instead {@link
- * #isTraceAnalyticsIntegrationEnabled(SortedSet, boolean)}.
* @param integrationNames
* @param defaultEnabled
* @return
+ * @deprecated This method should only be used internally. Use the instance getter instead {@link
+ * #isTraceAnalyticsIntegrationEnabled(SortedSet, boolean)}.
*/
public static boolean traceAnalyticsIntegrationEnabled(
final SortedSet<String> integrationNames, final boolean defaultEnabled) {

MODIFY
dd-trace-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy
dd-trace-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy
@@ -40,6 +40,7 @@ import static datadog.trace.api.Config.PROFILING_PROXY_HOST
import static datadog.trace.api.Config.PROFILING_PROXY_PASSWORD
import static datadog.trace.api.Config.PROFILING_PROXY_PORT
import static datadog.trace.api.Config.PROFILING_PROXY_USERNAME
+import static datadog.trace.api.Config.PROFILING_SITE
import static datadog.trace.api.Config.PROFILING_START_DELAY
import static datadog.trace.api.Config.PROFILING_START_FORCE_FIRST
import static datadog.trace.api.Config.PROFILING_TAGS
@@ -133,7 +134,8 @@ class ConfigTest extends DDSpecification {
config.healthMetricsStatsdPort == null
config.profilingEnabled == false
- config.profilingUrl == Config.DEFAULT_PROFILING_URL
+ config.profilingSite == Config.DEFAULT_PROFILING_SITE
+ config.profilingUrl == null
config.profilingApiKey == null
config.mergedProfilingTags == [(HOST_TAG): config.getHostName(), (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
config.profilingStartDelay == 10
@@ -198,6 +200,7 @@ class ConfigTest extends DDSpecification {
prop.setProperty(TRACE_RATE_LIMIT, "200")
prop.setProperty(PROFILING_ENABLED, "true")
+ prop.setProperty(PROFILING_SITE, "new site")
prop.setProperty(PROFILING_URL, "new url")
prop.setProperty(PROFILING_API_KEY, "new api key")
prop.setProperty(PROFILING_TAGS, "f:6,host:test-host")
@@ -254,6 +257,7 @@ class ConfigTest extends DDSpecification {
config.traceRateLimit == 200
config.profilingEnabled == true
+ config.profilingSite == "new site"
config.profilingUrl == "new url"
config.profilingApiKey == "new api key" // we can still override via internal properties object
config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
@@ -310,6 +314,7 @@ class ConfigTest extends DDSpecification {
System.setProperty(PREFIX + TRACE_RATE_LIMIT, "200")
System.setProperty(PREFIX + PROFILING_ENABLED, "true")
+ System.setProperty(PREFIX + PROFILING_SITE, "new site")
System.setProperty(PREFIX + PROFILING_URL, "new url")
System.setProperty(PREFIX + PROFILING_API_KEY, "new api key")
System.setProperty(PREFIX + PROFILING_TAGS, "f:6,host:test-host")
@@ -366,6 +371,7 @@ class ConfigTest extends DDSpecification {
config.traceRateLimit == 200
config.profilingEnabled == true
+ config.profilingSite == "new site"
config.profilingUrl == "new url"
config.profilingApiKey == null // system properties cannot be used to provide a key
config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
@@ -1105,4 +1111,29 @@ class ConfigTest extends DDSpecification {
config.mergedProfilingTags == [a: "1", f: "6", (HOST_TAG): config.getHostName(), (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
}
+
+ def "custom datadog site"() {
+ setup:
+ def prop = new Properties()
+ prop.setProperty(PROFILING_SITE, "some.new.site")
+
+ when:
+ Config config = Config.get(prop)
+
+ then:
+ config.getFinalProfilingUrl() == "https://intake.profile.some.new.site/v1/input"
+ }
+
+ def "custom profiling url override"() {
+ setup:
+ def prop = new Properties()
+ prop.setProperty(PROFILING_SITE, "some.new.site")
+ prop.setProperty(PROFILING_URL, "https://some.new.url/goes/here")
+
+ when:
+ Config config = Config.get(prop)
+
+ then:
+ config.getFinalProfilingUrl() == "https://some.new.url/goes/here"
+ }
}

Add option to configure Datadog site used to send profiling information