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
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,10 @@
/dd-smoke-tests/kafka-3/ @DataDog/data-streams-monitoring @DataDog/apm-idm-java

# @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
/dd-java-agent/instrumentation/datadog/openfeature/ @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
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,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 @@ -194,7 +193,7 @@ public boolean isEnabledByDefault() {
private static boolean distributedDebuggerEnabled = false;
private static boolean agentlessLogSubmissionEnabled = false;
private static boolean appLogsCollectionEnabled = false;
private static boolean featureFlaggingEnabled = false;
private static volatile boolean featureFlaggingEnabled = false;

private static void safelySetContextClassLoader(ClassLoader classLoader) {
try {
Expand Down Expand Up @@ -283,7 +282,6 @@ public static void start(
agentlessLogSubmissionEnabled = isFeatureEnabled(AgentFeature.AGENTLESS_LOG_SUBMISSION);
appLogsCollectionEnabled = isFeatureEnabled(AgentFeature.APP_LOGS_COLLECTION);
llmObsEnabled = isFeatureEnabled(AgentFeature.LLMOBS);
featureFlaggingEnabled = isFeatureFlaggingEnabled();

// setup writers when llmobs is enabled to accomodate apm and llmobs
if (llmObsEnabled) {
Expand Down Expand Up @@ -1275,6 +1273,7 @@ private static void maybeStartLLMObs(Instrumentation inst, Class<?> scoClass, Ob
}

private static void maybeStartFeatureFlagging(final Class<?> scoClass, final Object sco) {
featureFlaggingEnabled = Config.get().isFeatureFlaggingProviderEnabled();
if (featureFlaggingEnabled) {
StaticEventLogger.begin("Feature Flagging");

Expand Down Expand Up @@ -1730,45 +1729,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 @@ -359,6 +359,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,39 @@
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 project(':products:feature-flagging:feature-flagging-config')
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