Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package datadog.communication;

import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableMap;

import datadog.communication.ddagent.DDAgentFeaturesDiscovery;
import datadog.communication.ddagent.SharedCommunicationObjects;
import datadog.communication.http.HttpRetryPolicy;
import datadog.trace.api.Config;
import datadog.trace.api.intake.Intake;
import datadog.trace.util.throwable.FatalAgentMisconfigurationError;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -17,10 +24,19 @@ public class BackendApiFactory {

private final Config config;
private final SharedCommunicationObjects sharedCommunicationObjects;
private final Map<String, String> requestHeaders;

public BackendApiFactory(Config config, SharedCommunicationObjects sharedCommunicationObjects) {
this(config, sharedCommunicationObjects, emptyMap());
}

public BackendApiFactory(
Config config,
SharedCommunicationObjects sharedCommunicationObjects,
Map<String, String> requestHeaders) {
this.config = config;
this.sharedCommunicationObjects = sharedCommunicationObjects;
this.requestHeaders = unmodifiableMap(new HashMap<>(requestHeaders));
}

public @Nullable BackendApi createBackendApi(Intake intake) {
Expand Down Expand Up @@ -60,7 +76,7 @@ public BackendApi createDirectIntakeApi(Intake intake, boolean responseCompressi
apiKey,
traceId,
retryPolicyFactory(),
sharedCommunicationObjects.getIntakeHttpClient(),
withRequestHeaders(sharedCommunicationObjects.getIntakeHttpClient()),
responseCompression);
}

Expand Down Expand Up @@ -98,10 +114,27 @@ public BackendApi createDirectIntakeApi(Intake intake, boolean responseCompressi
evpProxyUrl,
subdomain,
retryPolicyFactory,
sharedCommunicationObjects.agentHttpClient,
withRequestHeaders(sharedCommunicationObjects.agentHttpClient),
responseCompression);
}

private OkHttpClient withRequestHeaders(final OkHttpClient httpClient) {
if (requestHeaders.isEmpty()) {
return httpClient;
}
return httpClient
.newBuilder()
.addInterceptor(
chain -> {
final Request.Builder requestBuilder = chain.request().newBuilder();
for (Map.Entry<String, String> header : requestHeaders.entrySet()) {
requestBuilder.header(header.getKey(), header.getValue());
}
return chain.proceed(requestBuilder.build());
})
.build();
}

private static HttpRetryPolicy.Factory retryPolicyFactory() {
return new HttpRetryPolicy.Factory(5, 100, 2.0, true);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package datadog.communication;

import static datadog.communication.ddagent.DDAgentFeaturesDiscovery.V4_EVP_PROXY_ENDPOINT;
import static java.util.Collections.singletonMap;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
Expand Down Expand Up @@ -45,7 +46,9 @@ void advertisedEvpProxyEndpointSupportsDisabledResponseCompression() throws Exce
final FakeFeaturesDiscovery discovery = new FakeFeaturesDiscovery(V4_EVP_PROXY_ENDPOINT);
final BackendApiFactory factory =
new BackendApiFactory(
Config.get(), sharedCommunicationObjects(discovery, agent.url("/")));
Config.get(),
sharedCommunicationObjects(discovery, agent.url("/")),
singletonMap("DD-EVP-ORIGIN", "dd-trace-java"));
final BackendApi api = factory.createBackendApi(Intake.EVENT_PLATFORM, false);

assertNotNull(api);
Expand All @@ -58,6 +61,9 @@ void advertisedEvpProxyEndpointSupportsDisabledResponseCompression() throws Exce

final RecordedRequest request = agent.takeRequest();
assertEquals("/evp_proxy/v4/api/v2/flagevaluation", request.getPath());
assertEquals("event-platform-intake", request.getHeader("X-Datadog-EVP-Subdomain"));
assertEquals("dd-trace-java", request.getHeader("DD-EVP-ORIGIN"));
assertEquals("identity", request.getHeader("Accept-Encoding"));
} finally {
agent.shutdown();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.datadog.featureflag;

import static datadog.trace.api.featureflag.config.FeatureFlaggingConfig.CONFIGURATION_SOURCE_AGENTLESS;
import static java.util.Collections.unmodifiableMap;

import datadog.communication.BackendApi;
import datadog.communication.BackendApiFactory;
import datadog.communication.ddagent.SharedCommunicationObjects;
import datadog.communication.ddagent.TracerVersion;
import datadog.communication.http.HttpRetryPolicy;
import datadog.trace.api.Config;
import datadog.trace.api.intake.Intake;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -16,6 +20,7 @@
final class FeatureFlagBackendApiFactory {

private static final Logger LOGGER = LoggerFactory.getLogger(FeatureFlagBackendApiFactory.class);
static final Map<String, String> REQUEST_HEADERS = requestHeaders();

private final Config config;
private final BackendApiFactory backendApiFactory;
Expand All @@ -25,7 +30,10 @@ final class FeatureFlagBackendApiFactory {
final Config config,
final SharedCommunicationObjects sharedCommunicationObjects,
final FeatureFlagEventType eventType) {
this(config, new BackendApiFactory(config, sharedCommunicationObjects), eventType);
this(
config,
new BackendApiFactory(config, sharedCommunicationObjects, REQUEST_HEADERS),
eventType);
}

FeatureFlagBackendApiFactory(
Expand Down Expand Up @@ -78,6 +86,13 @@ BackendApi create() {
return null;
}

private static Map<String, String> requestHeaders() {
final Map<String, String> headers = new HashMap<>(2);
headers.put("DD-EVP-ORIGIN", "dd-trace-java");
headers.put("DD-EVP-ORIGIN-VERSION", TracerVersion.TRACER_VERSION);
return unmodifiableMap(headers);
}

private boolean hasDirectCredentials() {
final String apiKey = config.getApiKey();
return apiKey != null && !apiKey.isEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static com.datadog.featureflag.FeatureFlagEventType.FLAG_EVALUATION;
import static datadog.trace.api.featureflag.config.FeatureFlaggingConfig.CONFIGURATION_SOURCE_AGENTLESS;
import static datadog.trace.api.featureflag.config.FeatureFlaggingConfig.CONFIGURATION_SOURCE_REMOTE_CONFIG;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
Expand All @@ -14,13 +15,23 @@

import datadog.communication.BackendApi;
import datadog.communication.BackendApiFactory;
import datadog.communication.ddagent.TracerVersion;
import datadog.communication.http.HttpRetryPolicy;
import datadog.trace.api.Config;
import datadog.trace.api.intake.Intake;
import org.junit.jupiter.api.Test;

class FeatureFlagBackendApiFactoryTest {

@Test
void configuresSdkIdentityHeadersForAllFeatureFlagEventTypes() {
assertEquals(
"dd-trace-java", FeatureFlagBackendApiFactory.REQUEST_HEADERS.get("DD-EVP-ORIGIN"));
assertEquals(
TracerVersion.TRACER_VERSION,
FeatureFlagBackendApiFactory.REQUEST_HEADERS.get("DD-EVP-ORIGIN-VERSION"));
}

@Test
void remoteConfigUsesOnlyLocalEvpProxy() {
final Config config = config(CONFIGURATION_SOURCE_REMOTE_CONFIG, "api-key");
Expand Down