Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
cd24d56
WIP
PerfectSlayer Oct 1, 2026
eb82d39
feat(ffe): Add new instrumentation config
PerfectSlayer Oct 1, 2026
90c1f31
feat(ffe): Allow vm props and env vars access
PerfectSlayer Oct 1, 2026
ff86e4f
feat(ffe): Suppress static sync warning
PerfectSlayer Oct 1, 2026
f9a0f80
fix(ffe): Fix dd-openfeature system test versions
PerfectSlayer Oct 1, 2026
4704d9a
fix(ffe): Fix reader not closed
PerfectSlayer Oct 1, 2026
b9604aa
fix(ffe): Fix code test coverage
PerfectSlayer Oct 2, 2026
8f6d55b
feat(ffe): Refine instrumentation
PerfectSlayer Oct 2, 2026
4e6c0de
feat(ffe): Refine gradle configuration
PerfectSlayer Oct 2, 2026
e5403cc
feat(ffe): Clean up config
PerfectSlayer Oct 2, 2026
c86267f
feat(ffe): Add support for older OTel APIs
PerfectSlayer Oct 2, 2026
570ac5d
feat(ffe): Clean up config
PerfectSlayer Oct 2, 2026
1227691
feat(doc): Update ARCHITECTURE.md
PerfectSlayer Oct 2, 2026
8410be5
chore(ffe): Clean up code
PerfectSlayer Oct 2, 2026
c5fcf22
feat(ffe): Port benchmarks
PerfectSlayer Oct 2, 2026
8eed26a
fix(ffe): Fix failed start leaving broken runtime
PerfectSlayer Oct 2, 2026
beadf46
fix(ffe): Fix no rollback when backend start fails
PerfectSlayer Oct 2, 2026
5c03ef0
fix(ffe): Fix config on agent initialization
PerfectSlayer Oct 2, 2026
8c8dddd
chore: Update CODEOWNERS
PerfectSlayer Oct 2, 2026
3db3662
chore(ffe): Remove dead fixtures
PerfectSlayer Oct 2, 2026
c21205e
fix(ffe): Deduplicate retry mechanism
PerfectSlayer Oct 2, 2026
d6f7005
fix(ffe): Drop EvaluationMetadata in favor of OpenFeature metadata
PerfectSlayer Oct 13, 2026
cb45873
fix(ffe): Evaluate flags on OpenFeature types directly
PerfectSlayer Oct 13, 2026
8f13153
fix(ffe): Reject flags with an explicit null enabled field
PerfectSlayer Oct 13, 2026
2b91f39
fix(ffe): Reject flags with non-string allocation dates
PerfectSlayer Oct 13, 2026
85bebd9
fix(ffe): Reject configurations with non-finite numbers
PerfectSlayer Oct 13, 2026
2b601fd
fix(ffe): Detect Feature Flags activation like other products
PerfectSlayer Oct 14, 2026
7af9380
refactor(ffe): Remove the feature-flagging-config module
PerfectSlayer Oct 14, 2026
31d0840
refactor(ffe): Parse the Feature Flags configuration source as an enum
PerfectSlayer Oct 14, 2026
c2682ef
fix(ffe): Fix FFE activation on the product switch only
PerfectSlayer Oct 14, 2026
03695e8
chore(ffe): Sort ConfigTest feature flags imports
PerfectSlayer Oct 14, 2026
530ac88
feat(ffe): Parse features on UFC splits
PerfectSlayer Oct 14, 2026
4fdfe4d
fix(ffe): Initialize FeatureFlaggingSource at native-image build time
PerfectSlayer Oct 14, 2026
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
6 changes: 4 additions & 2 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,10 @@
/dd-smoke-tests/kafka-3/ @DataDog/data-streams-monitoring @DataDog/apm-idm-java

# @DataDog/feature-flagging-and-experimentation-sdk
/dd-smoke-tests/openfeature/ @DataDog/feature-flagging-and-experimentation-sdk
/products/feature-flagging/ @DataDog/feature-flagging-and-experimentation-sdk
/dd-java-agent/instrumentation/datadog/openfeature/ @DataDog/feature-flagging-and-experimentation-sdk
/dd-openfeature/ @DataDog/feature-flagging-and-experimentation-sdk
/dd-smoke-tests/openfeature/ @DataDog/feature-flagging-and-experimentation-sdk
/products/feature-flagging/ @DataDog/feature-flagging-and-experimentation-sdk

# @DataDog/profiling-java
/dd-java-agent/ddprof-lib/ @DataDog/profiling-java
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/run-system-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ jobs:
JAVA_11_HOME=$JAVA_HOME_11_X64 \
JAVA_17_HOME=$JAVA_HOME_17_X64 \
JAVA_21_HOME=$JAVA_HOME_21_X64 \
./gradlew clean :dd-java-agent:shadowJar \
./gradlew clean :dd-java-agent:shadowJar :dd-openfeature:jar \
--build-cache --parallel --stacktrace --no-daemon --max-workers=4
# System tests install a dd-openfeature jar found next to the agent instead of the published one,
# as the agent supports only the dd-openfeature version built along with it.
cp workspace/dd-openfeature/build/libs/dd-openfeature-*.jar workspace/dd-java-agent/build/libs/

- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
Expand Down
8 changes: 4 additions & 4 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ build:
script:
- if [ $CI_PIPELINE_SOURCE == "schedule" ] ; then ./gradlew resolveAndLockAll --write-locks $GRADLE_ARGS; fi
- ./gradlew --version
- ./gradlew clean :dd-java-agent:shadowJar :dd-java-agent:check :dd-trace-api:jar :dd-trace-ot:shadowJar :products:feature-flagging:feature-flagging-api:jar -PskipTests -x spotlessCheck $GRADLE_ARGS
- ./gradlew clean :dd-java-agent:shadowJar :dd-java-agent:check :dd-trace-api:jar :dd-trace-ot:shadowJar :dd-openfeature:jar -PskipTests -x spotlessCheck $GRADLE_ARGS
- echo UPSTREAM_TRACER_VERSION=$(java -jar workspace/dd-java-agent/build/libs/*.jar) >> upstream.env
- echo "BUILD_JOB_NAME=$CI_JOB_NAME" >> build.env
- echo "BUILD_JOB_ID=$CI_JOB_ID" >> build.env
Expand All @@ -365,7 +365,7 @@ build:
- 'workspace/dd-java-agent/build/libs/*.jar'
- 'workspace/dd-trace-api/build/libs/*.jar'
- 'workspace/dd-trace-ot/build/libs/*.jar'
- 'workspace/products/feature-flagging/feature-flagging-api/build/libs/*.jar'
- 'workspace/dd-openfeature/build/libs/*.jar'
- 'upstream.env'
- '.gradle/daemon/*/*.out.log'
reports:
Expand Down Expand Up @@ -482,11 +482,11 @@ publish-artifacts-to-s3:
- aws s3 cp workspace/dd-java-agent/build/libs/dd-java-agent-${VERSION}.jar s3://dd-trace-java-builds/${CI_COMMIT_REF_NAME}/dd-java-agent.jar
- aws s3 cp workspace/dd-trace-api/build/libs/dd-trace-api-${VERSION}.jar s3://dd-trace-java-builds/${CI_COMMIT_REF_NAME}/dd-trace-api.jar
- aws s3 cp workspace/dd-trace-ot/build/libs/dd-trace-ot-${VERSION}.jar s3://dd-trace-java-builds/${CI_COMMIT_REF_NAME}/dd-trace-ot.jar
- aws s3 cp workspace/products/feature-flagging/feature-flagging-api/build/libs/dd-openfeature-${VERSION}.jar s3://dd-trace-java-builds/${CI_COMMIT_REF_NAME}/dd-openfeature.jar
- aws s3 cp workspace/dd-openfeature/build/libs/dd-openfeature-${VERSION}.jar s3://dd-trace-java-builds/${CI_COMMIT_REF_NAME}/dd-openfeature.jar
- aws s3 cp workspace/dd-java-agent/build/libs/dd-java-agent-${VERSION}.jar s3://dd-trace-java-builds/${CI_PIPELINE_ID}/dd-java-agent.jar
- aws s3 cp workspace/dd-trace-api/build/libs/dd-trace-api-${VERSION}.jar s3://dd-trace-java-builds/${CI_PIPELINE_ID}/dd-trace-api.jar
- aws s3 cp workspace/dd-trace-ot/build/libs/dd-trace-ot-${VERSION}.jar s3://dd-trace-java-builds/${CI_PIPELINE_ID}/dd-trace-ot.jar
- aws s3 cp workspace/products/feature-flagging/feature-flagging-api/build/libs/dd-openfeature-${VERSION}.jar s3://dd-trace-java-builds/${CI_PIPELINE_ID}/dd-openfeature.jar
- aws s3 cp workspace/dd-openfeature/build/libs/dd-openfeature-${VERSION}.jar s3://dd-trace-java-builds/${CI_PIPELINE_ID}/dd-openfeature.jar
- |
cat << EOF > links.json
{
Expand Down
14 changes: 10 additions & 4 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ to `.classdata` to prevent unintended loading. See [`docs/how_to_work_with_gradl

- **`agent-tooling/`** — Instrumentation framework. Key types:
- `InstrumenterModule` — Base class for all instrumentation modules. Declares a target system
(Tracing, AppSec, IAST, Profiling, CiVisibility, USM, etc.) and one or more instrumentations.
(Tracing, AppSec, IAST, Profiling, CiVisibility, USM, FeatureFlags, etc.) and one or more
instrumentations.
- `Instrumenter` — Type matching interface: `ForSingleType`, `ForKnownTypes`,
`ForTypeHierarchy`, `ForBootstrap`.
- `muzzle/` — Build-time and runtime safety checks. Verifies that expected types and methods
Expand Down Expand Up @@ -229,9 +230,8 @@ Current products:

- `metrics/` — StatsD client and monitoring abstraction. Provides `Monitoring` interface with
counters, timers, and histograms for internal agent metrics collection.
- `feature-flagging/` — Server-side feature flag evaluation driven by remote configuration.
Implements the OpenFeature SDK, handles the Unified Feature Control (UFC) protocol,
and tracks flag exposure per user/session.
- `feature-flagging/` — Agent services for the [`dd-openfeature/`](#dd-openfeature) SDK:
remote configuration, event delivery through the Datadog Agent, and span enrichment.

### `communication/`

Expand Down Expand Up @@ -279,6 +279,12 @@ that implements the `io.opentracing.Tracer` interface by wrapping the Datadog `C
This is a pure library for manual instrumentation only — there is no auto-instrumentation or
bytecode advice.

### `dd-openfeature/`

Feature Flags OpenFeature provider. Publishes a standalone JAR artifact (`dd-openfeature.jar`, Java 11+)
that works without the agent. When the agent is attached, an instrumentation connects it to the
`products/feature-flagging/` agent services.

### `dd-smoke-tests/`

End-to-end smoke tests. Each boots a real application with the agent jar and verifies traces, spans,
Expand Down
1 change: 0 additions & 1 deletion dd-java-agent/agent-bootstrap/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ dependencies {
api project(':dd-java-agent:agent-debugger:debugger-bootstrap')
api project(':components:environment')
api project(':components:json')
api project(':products:feature-flagging:feature-flagging-config')
api project(':products:metrics:metrics-agent')
api libs.instrument.java
api libs.slf4j
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import datadog.trace.api.config.CrashTrackingConfig;
import datadog.trace.api.config.CwsConfig;
import datadog.trace.api.config.DebuggerConfig;
import datadog.trace.api.config.FeatureFlaggingConfig;
import datadog.trace.api.config.GeneralConfig;
import datadog.trace.api.config.IastConfig;
import datadog.trace.api.config.JmxFetchConfig;
Expand All @@ -44,7 +45,6 @@
import datadog.trace.api.config.TraceInstrumentationConfig;
import datadog.trace.api.config.TracerConfig;
import datadog.trace.api.config.UsmConfig;
import datadog.trace.api.featureflag.config.FeatureFlaggingConfig;
import datadog.trace.api.gateway.RequestContextSlot;
import datadog.trace.api.gateway.SubscriptionService;
import datadog.trace.api.git.EmbeddedGitInfoBuilder;
Expand Down Expand Up @@ -135,7 +135,8 @@ private enum AgentFeature {
AGENTLESS_LOG_SUBMISSION(GeneralConfig.AGENTLESS_LOG_SUBMISSION_ENABLED, false),
APP_LOGS_COLLECTION(GeneralConfig.APP_LOGS_COLLECTION_ENABLED, false),
LLMOBS(LlmObsConfig.LLMOBS_ENABLED, false),
LLMOBS_AGENTLESS(LlmObsConfig.LLMOBS_AGENTLESS_ENABLED, false);
LLMOBS_AGENTLESS(LlmObsConfig.LLMOBS_AGENTLESS_ENABLED, false),
FEATURE_FLAGS(FeatureFlaggingConfig.FEATURE_FLAGS_ENABLED, true);

private final String configKey;
private final String systemProp;
Expand Down Expand Up @@ -284,7 +285,7 @@ public static void start(
agentlessLogSubmissionEnabled = isFeatureEnabled(AgentFeature.AGENTLESS_LOG_SUBMISSION);
appLogsCollectionEnabled = isFeatureEnabled(AgentFeature.APP_LOGS_COLLECTION);
llmObsEnabled = isFeatureEnabled(AgentFeature.LLMOBS);
featureFlaggingEnabled = isFeatureFlaggingEnabled();
featureFlaggingEnabled = isFeatureEnabled(AgentFeature.FEATURE_FLAGS);

// setup writers when llmobs is enabled to accomodate apm and llmobs
if (llmObsEnabled) {
Expand Down Expand Up @@ -1796,45 +1797,6 @@ private static boolean isFeatureEnabled(AgentFeature feature) {
}
}

private static boolean isFeatureFlaggingEnabled() {
final Boolean providerEnabled =
featureFlaggingBooleanSetting(FeatureFlaggingConfig.FEATURE_FLAGS_ENABLED);
final String configurationSource =
featureFlaggingSetting(FeatureFlaggingConfig.FEATURE_FLAGS_CONFIGURATION_SOURCE);
final Boolean legacyProviderEnabled =
featureFlaggingBooleanSetting(FeatureFlaggingConfig.EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED);

return FeatureFlaggingConfig.resolveConfiguration(
providerEnabled, configurationSource, legacyProviderEnabled)
.isEnabled();
}

@SuppressFBWarnings(
value = "NP_BOOLEAN_RETURN_NULL",
justification = "A null value preserves the distinction between absent and explicitly false")
private static Boolean featureFlaggingBooleanSetting(final String configKey) {
final String value = featureFlaggingSetting(configKey);
if (value == null) {
return null;
}
return Boolean.parseBoolean(value) || "1".equals(value);
}

private static String featureFlaggingSetting(final String configKey) {
final String systemProperty = propertyNameToSystemPropertyName(configKey);
String value = SystemProperties.get(systemProperty);
if (value == null) {
value = getStableConfig(FLEET, configKey);
}
if (value == null) {
value = ddGetEnv(systemProperty);
}
if (value == null) {
value = getStableConfig(LOCAL, configKey);
}
return value;
}

/**
* @see datadog.trace.api.ProductActivation#fromString(String)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ public static Set<InstrumenterModule.TargetSystem> getEnabledSystems() {
if (cfg.isLlmObsEnabled()) {
enabledSystems.add(InstrumenterModule.TargetSystem.LLMOBS);
}
if (cfg.isFeatureFlaggingEnabled()) {
enabledSystems.add(InstrumenterModule.TargetSystem.FEATURE_FLAGS);
}
return enabledSystems;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public abstract class InstrumenterModule implements Instrumenter {
* <li>{@link TargetSystem#USM usm}
* <li>{@link TargetSystem#CONTEXT_TRACKING context-tracking}
* <li>{@link TargetSystem#RASP rasp}
* <li>{@link TargetSystem#FEATURE_FLAGS feature-flags}
* </ul>
*/
public enum TargetSystem {
Expand All @@ -56,6 +57,7 @@ public enum TargetSystem {
LLMOBS,
CONTEXT_TRACKING,
RASP,
FEATURE_FLAGS,
}

private static final Logger log = LoggerFactory.getLogger(InstrumenterModule.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
plugins {
id 'dd-trace-java.module.instrumentation'
id 'idea'
}

idea {
module {
jdkName = '11'
}
}

// TODO Add a muzzle pass directive on com.datadoghq:dd-openfeature once the SDK is published.

tracerJava {
addSourceSetFor(JavaVersion.VERSION_11)
}

testJvmConstraints {
minJavaVersion = JavaVersion.VERSION_11
}

dependencies {
main_java11CompileOnly project(':dd-openfeature')
main_java11CompileOnly project(':products:feature-flagging:feature-flagging-bootstrap')
main_java11CompileOnly libs.spotbugs.annotations

testImplementation project(':dd-openfeature')
testImplementation project(':products:feature-flagging:feature-flagging-bootstrap')
testImplementation libs.bundles.mockito
}

tasks.named("compileMain_java11Java", JavaCompile) {
configureCompiler(it, JavaVersion.VERSION_11)
}

tasks.named("compileTestJava", JavaCompile) {
configureCompiler(it, JavaVersion.VERSION_11)
}
Loading
Loading