Skip to content

Commit 32b5c4f

Browse files
manuel-alvarez-alvarezamarziali
authored andcommitted
Implementation of the open feature SDK in the java tracer (#9885)
Implement OpenFeature Provider interface
1 parent a847c96 commit 32b5c4f

File tree

53 files changed

+3986
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+3986
-3
lines changed

.github/CODEOWNERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@
115115
**/datastreams/ @DataDog/data-streams-monitoring
116116
**/DataStreams* @DataDog/data-streams-monitoring
117117

118+
# @DataDog/feature-flagging-and-experimentation-sdk
119+
/products/feature-flagging/ @DataDog/feature-flagging-and-experimentation-sdk
120+
118121
# @DataDog/profiling-java
119122
/dd-java-agent/agent-profiling/ @DataDog/profiling-java
120123
/dd-java-agent/agent-crashtracking/ @DataDog/profiling-java

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Agent.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import datadog.trace.api.config.CrashTrackingConfig;
3333
import datadog.trace.api.config.CwsConfig;
3434
import datadog.trace.api.config.DebuggerConfig;
35+
import datadog.trace.api.config.FeatureFlaggingConfig;
3536
import datadog.trace.api.config.GeneralConfig;
3637
import datadog.trace.api.config.IastConfig;
3738
import datadog.trace.api.config.JmxFetchConfig;
@@ -125,7 +126,8 @@ private enum AgentFeature {
125126
DATA_JOBS(GeneralConfig.DATA_JOBS_ENABLED, false),
126127
AGENTLESS_LOG_SUBMISSION(GeneralConfig.AGENTLESS_LOG_SUBMISSION_ENABLED, false),
127128
LLMOBS(LlmObsConfig.LLMOBS_ENABLED, false),
128-
LLMOBS_AGENTLESS(LlmObsConfig.LLMOBS_AGENTLESS_ENABLED, false);
129+
LLMOBS_AGENTLESS(LlmObsConfig.LLMOBS_AGENTLESS_ENABLED, false),
130+
FEATURE_FLAGGING(FeatureFlaggingConfig.FLAGGING_PROVIDER_ENABLED, false);
129131

130132
private final String configKey;
131133
private final String systemProp;
@@ -184,6 +186,7 @@ public boolean isEnabledByDefault() {
184186
private static boolean codeOriginEnabled = false;
185187
private static boolean distributedDebuggerEnabled = false;
186188
private static boolean agentlessLogSubmissionEnabled = false;
189+
private static boolean featureFlaggingEnabled = false;
187190

188191
private static void safelySetContextClassLoader(ClassLoader classLoader) {
189192
try {
@@ -268,6 +271,7 @@ public static void start(
268271
codeOriginEnabled = isFeatureEnabled(AgentFeature.CODE_ORIGIN);
269272
agentlessLogSubmissionEnabled = isFeatureEnabled(AgentFeature.AGENTLESS_LOG_SUBMISSION);
270273
llmObsEnabled = isFeatureEnabled(AgentFeature.LLMOBS);
274+
featureFlaggingEnabled = isFeatureEnabled(AgentFeature.FEATURE_FLAGGING);
271275

272276
// setup writers when llmobs is enabled to accomodate apm and llmobs
273277
if (llmObsEnabled) {
@@ -662,6 +666,7 @@ public void execute() {
662666
maybeStartDebugger(instrumentation, scoClass, sco);
663667
maybeStartRemoteConfig(scoClass, sco);
664668
maybeStartAiGuard();
669+
maybeStartFeatureFlagging(scoClass, sco);
665670

666671
if (telemetryEnabled) {
667672
startTelemetry(instrumentation, scoClass, sco);
@@ -1083,6 +1088,23 @@ private static void maybeStartLLMObs(Instrumentation inst, Class<?> scoClass, Ob
10831088
}
10841089
}
10851090

1091+
private static void maybeStartFeatureFlagging(final Class<?> scoClass, final Object sco) {
1092+
if (featureFlaggingEnabled) {
1093+
StaticEventLogger.begin("Feature Flagging");
1094+
1095+
try {
1096+
final Class<?> ffSysClass =
1097+
AGENT_CLASSLOADER.loadClass("com.datadog.featureflag.FeatureFlaggingSystem");
1098+
final Method ffSysMethod = ffSysClass.getMethod("start", scoClass);
1099+
ffSysMethod.invoke(null, sco);
1100+
} catch (final Throwable e) {
1101+
log.warn("Not starting Feature Flagging subsystem", e);
1102+
}
1103+
1104+
StaticEventLogger.end("Feature Flagging");
1105+
}
1106+
}
1107+
10861108
private static void maybeInstallLogsIntake(Class<?> scoClass, Object sco) {
10871109
if (agentlessLogSubmissionEnabled) {
10881110
StaticEventLogger.begin("Logs Intake");

dd-java-agent/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ includeSubprojShadowJar(project(':dd-java-agent:agent-ci-visibility'), 'ci-visib
189189
includeSubprojShadowJar(project(':dd-java-agent:agent-llmobs'), 'llm-obs', includedJarFileTree)
190190
includeSubprojShadowJar(project(':dd-java-agent:agent-logs-intake'), 'logs-intake', includedJarFileTree)
191191
includeSubprojShadowJar(project(':dd-java-agent:cws-tls'), 'cws-tls', includedJarFileTree)
192+
includeSubprojShadowJar(project(':products:feature-flagging:agent'), 'feature-flagging', includedJarFileTree)
192193

193194
def sharedShadowJar = tasks.register('sharedShadowJar', ShadowJar) {
194195
it.configurations = [project.configurations.sharedShadowInclude]
@@ -318,6 +319,7 @@ dependencies {
318319
shadowInclude project(path: ':dd-java-agent:agent-bootstrap')
319320
shadowInclude project(path: ':dd-java-agent:agent-debugger:debugger-bootstrap')
320321
shadowInclude project(path: ':dd-java-agent:agent-otel:otel-bootstrap', configuration: 'shadow')
322+
shadowInclude project(path: ':products:feature-flagging:bootstrap')
321323

322324
// Includes for the shared internal shadow jar
323325
sharedShadowInclude deps.shared

dd-trace-api/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ val excludedClassesCoverage by extra(
3535
"datadog.trace.api.civisibility.noop.NoOpDDTestSession",
3636
"datadog.trace.api.civisibility.noop.NoOpDDTestSuite",
3737
"datadog.trace.api.config.AIGuardConfig",
38+
"datadog.trace.api.config.FeatureFlaggingConfig",
3839
"datadog.trace.api.config.ProfilingConfig",
3940
"datadog.trace.api.interceptor.MutableSpan",
4041
"datadog.trace.api.profiling.Profiling",
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package datadog.trace.api.config;
2+
3+
public class FeatureFlaggingConfig {
4+
5+
public static final String FLAGGING_PROVIDER_ENABLED = "experimental.flagging.provider.enabled";
6+
}

gradle/dependencies.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ final class CachedData {
2020
exclude(project(':components:environment'))
2121
exclude(project(':components:json'))
2222
exclude(project(':components:yaml'))
23+
exclude(project(':products:feature-flagging:bootstrap'))
2324
exclude(project(':remote-config:remote-config-api'))
2425
exclude(project(':remote-config:remote-config-core'))
2526
exclude(project(':telemetry'))

internal-api/src/main/java/datadog/trace/api/intake/Intake.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@ public enum Intake {
1515
"ci-intake",
1616
"v2",
1717
Config::isCiVisibilityAgentlessEnabled,
18-
Config::getCiVisibilityIntakeAgentlessUrl);
18+
Config::getCiVisibilityIntakeAgentlessUrl),
19+
EVENT_PLATFORM("event-platform-intake", "v2");
1920

2021
public final String urlPrefix;
2122
public final String version;
2223
public final Function<Config, Boolean> agentlessModeEnabled;
2324
public final Function<Config, String> customUrl;
2425

26+
Intake(String urlPrefix, String version) {
27+
this(urlPrefix, version, config -> false, config -> null);
28+
}
29+
2530
Intake(
2631
String urlPrefix,
2732
String version,

internal-api/src/main/java/datadog/trace/util/AgentThreadFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ public enum AgentThread {
5959

6060
LOGS_INTAKE("dd-logs-intake"),
6161

62-
LLMOBS_EVALS_PROCESSOR("dd-llmobs-evals-processor");
62+
LLMOBS_EVALS_PROCESSOR("dd-llmobs-evals-processor"),
63+
64+
FEATURE_FLAG_EXPOSURE_PROCESSOR("dd-ffe-exposure-processor");
6365

6466
public final String threadName;
6567

metadata/supported-configurations.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@
184184
"DD_EXCEPTION_REPLAY_MAX_FRAMES_TO_CAPTURE": ["A"],
185185
"DD_EXPERIMENTAL_API_SECURITY_ENABLED": ["A"],
186186
"DD_EXPERIMENTAL_DEFER_INTEGRATIONS_UNTIL": ["A"],
187+
"DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED": ["A"],
187188
"DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED": ["A"],
188189
"DD_FORCE_CLEAR_TEXT_HTTP_FOR_INTAKE_CLIENT": ["A"],
189190
"DD_GIT_BRANCH": ["A"],
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2+
import org.gradle.kotlin.dsl.project
3+
4+
plugins {
5+
`java-library`
6+
id("com.gradleup.shadow")
7+
}
8+
9+
apply(from = "$rootDir/gradle/java.gradle")
10+
apply(from = "$rootDir/gradle/version.gradle")
11+
12+
description = "Feature flagging agent system"
13+
14+
dependencies {
15+
api(libs.slf4j)
16+
api(project(":products:feature-flagging:lib"))
17+
api(project(":internal-api"))
18+
19+
testImplementation(project(":utils:test-utils"))
20+
testRuntimeOnly(project(":dd-trace-core"))
21+
}
22+
23+
tasks.named<ShadowJar>("shadowJar") {
24+
dependencies {
25+
val deps = project.extra["deps"] as Map<*, *>
26+
val excludeShared = deps["excludeShared"] as groovy.lang.Closure<*>
27+
excludeShared.delegate = this
28+
excludeShared.call()
29+
}
30+
}

0 commit comments

Comments
 (0)