Repository navigation
Ship dd-openfeature as a standalone SDK extended by the Java agent (AI prototype) - #12709
Draft
PerfectSlayer wants to merge 100 commits into
Draft
PerfectSlayer wants to merge 100 commits into
PerfectSlayer wants to merge 100 commits into
Conversation
This comment has been minimized.
This comment has been minimized.
Contributor
🟢 Java Benchmark SLOs — All performance SLOs passed
PR vs. master results
Commit: Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion. |
This was referenced Oct 13, 2026
Port #12575 to the SDK and the agent bridge: exposures and flag evaluations carry the DD-EVP-ORIGIN and DD-EVP-ORIGIN-VERSION headers, dd-trace-java and the library version, through the agent event proxy and direct intake alike. An agentless proxy endpoint is used only when the Agent forwards both headers. The smoke tests mock Agent advertises them like the Agent does.
This was referenced Oct 21, 2026
Upload the agent and dd-openfeature jars from a dedicated folder instead of copying dd-openfeature into the agent build output.
PerfectSlayer
force-pushed
the
bbujon/ffe
branch
from
October 21, 2026 14:17
865279f to
6947b97
Compare
Add the deprecated datadog.trace.api.openfeature.ExposureHook, and its Evaluation type, delegating to com.datadog.openfeature.ExposureHook: master documents the hook under its former package name.
The build job keeps the dd-openfeature jar: also preserve it as a validate_build reference, and enable its compareToReferenceJar check.
Master removed the Gradle IDEA plugin configuration: the Java toolchain and compiler settings already give IntelliJ the right JDK.
Replace the legacy provider instrumentation tests, which loaded a released provider in a dedicated class loader, with a smoke test running an application built with the released dd-openfeature 1.67.1, with and without Feature Flags enabled. Drop the IDEA module configuration and use the static VERSION_11 import in the legacy provider instrumentation build.
Mark the instrumentation module and advice classes as unused, as they are only referenced through AutoService and advice class names, and import the Advice annotations statically.
Move the agent bridge SPI to a versioned package, bridge.v1: once released, a version is frozen and only gets default methods, and a breaking change goes to a new package. Check each released SPI version against the first SDK release that shipped it with japicmp, failing on any change breaking the agent implementation. The v1 baseline is set once the first SDK release with the agent bridge is published.
Check the API outside the internal packages with japicmp against the previous dd-openfeature release, failing on binary or source incompatible changes. The baseline is the latest release before the version being built, so release branches compare against their own line and each release keeps the API of all the previous ones.
…y errors The SDK dropped malformed Remote Configuration documents and the agent swallowed subscriber failures, so the poller acknowledged documents the SDK never applied. The SDK now rejects malformed documents by throwing, and the agent rethrows the first subscriber failure once every subscriber is notified, so the poller reports an apply error as before the switch.
…e Flags The poller reference-counts start and stop calls, but closing the Feature Flags Remote Configuration service no longer stopped it, keeping it polling once Feature Flags closed and leaking a reference on each restart.
…e SDK The bridge was only installed when the agent enabled Feature Flags, so when only an agent configuration source the SDK cannot read (stable configuration, configuration file) disabled them, the SDK fell back to its own settings and started agentless. The bridge is now installed regardless, and reports Feature Flags as disabled when the agent configuration disables them.
…on is disabled The Feature Flags shutdown hook was only registered when tracing was disabled, but the tracing shutdown path also relies on the shutdown instrumentation, which can be disabled on its own. The hook is now always registered once the SDK subscribes to the shutdown; stopping is idempotent, so it does nothing after the tracing shutdown path already stopped Feature Flags.
The test rewrote the SPI classes to check the runtime SPI guard. The japicmp bridge SPI check covers SPI compatibility once the SPI is released.
Once dd-openfeature 1.69.0 is released, the japicmpBridgeV1 task checks the frozen bridge.v1 SPI, so the runtime check of the helpers becomes redundant.
…0 release Reference APMLP-1512 in the TODOs waiting for the first SDK release with the agent bridge, and prepare the muzzle pass directive of the bridge instrumentation, to enable once 1.69.0 is published.
The agent bridge ships with dd-java-agent 1.69.0, and the providers released before 1.69.0 return the caller defaults with it.
Remote Configuration without the Datadog Java agent is out of scope.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Warning
AI-generated prototype, not human reviewed.
Claude Code generated all the code, tests and docs in this PR from a design brief. No human has reviewed any of it yet. It is a draft to discuss the design proposal, not a merge candidate. Review it as a design sketch and expect rough edges.
What Does This Do
This prototypes a different architecture for running Datadog Feature Flags without
dd-java-agent. It covers the same need as #12576, but under different constraints.dd-openfeatureis a standalone SDK in a new root module,:dd-openfeature(JDK 11+), published ascom.datadoghq:dd-openfeature.jackson-core, all as plain POM dependencies.java.net.http.HttpClient.dd-java-agentis optional. When attached, it connects to the SDK through library instrumentation. The SDK then uses the agent's Remote Configuration, its Datadog Agent event proxy, agent telemetry and APM span enrichment.Motivation
The design brief ("[DRAFT] FFE Design Doc", following the product brief Java Feature Flags: organize as standalone and SSI) rejects the shape of #12576 for two reasons:
The brief also notes the following:
So the install path follows OpenFeature practice: always add the SDK, and optionally attach the agent.
Design differences with #12576
internal-api,communication,config-utils, OkHttp, Moshi, JCTools…, relocated and shrunk withminimize()(~1.84 MB)dev.openfeature:sdk,io.opentelemetry:opentelemetry-apiandjackson-core. No shading, nominimize()java.net.http.HttpClientandjackson-corestreaming (no old HTTP client for security scanners to flag)ExposureEvent,FlagEvalEvent) onFeatureFlaggingGateway, plus anAGENT/STANDALONEruntime ownership claimcom.datadog.openfeature.internal.connector). Instrumentation exit advice onConnectors.detect()fills it in. The bootstrap gateway is internal to the agent, uses JDK types only and can change freelyLinkageErrorcatchesOpenFeatureAPI.getInstance()is called (openfeature-1.20instrumentation)new Provider()corepackage; the agent parses with Moshi; the evaluator is injected as helpersdd-openfeature-remote-configartifact (~4.17 MB, bundlesremote-config-core)// TODO).remote_configrequires the agentdatadog.trace.api.openfeature.Providercom.datadog.openfeature.Provider. The old class name stays as a deprecated subclass. The SDK can't sit underdatadog.trace.*, which the agent never instruments and loads bootstrap-firstChanges
:dd-openfeature(new root module), ported fromfeature-flagging-api/-liband Prototype standalone and injected Java Feature Flags together #12576:Provider;Settings, which reads the agent configuration first, thendd.*system properties, thenDD_*environment variables, with the same keys and rules as before.jackson-core) and theFlagEvaluatorfrom Prototype standalone and injected Java Feature Flags together #12576.dd-openfeature-connectorinstrumentation (dd-java-agent/instrumentation/datadog/openfeature/):Connectors.detect().TargetSystem.FEATURE_FLAGS, which follows the resolvedDD_FEATURE_FLAGS_*settings.java11source set.DD_TRACE_OPENFEATURE_ENABLED(aliasesDD_TRACE_INTEGRATION_OPENFEATURE_ENABLED,DD_INTEGRATION_OPENFEATURE_ENABLED), declared inmetadata/supported-configurations.json.products/feature-flagging):FeatureFlaggingGateway.Backendregistry.FeatureFlagsBackendprovides:FFE_FLAGSdocuments. The product is registered at agent startup inremote_configmode, so the first poll asks for it.FeatureFlaggingConfigonly keeps the product switch and the configuration source. The CDN, span-enrichment and evaluation-count keys are read by the SDK only.feature-flagging-apimodule, and the agent-side CDN poller, parsers, event writers and bootstrap POJOs.Configgetters, which the SDK now owns.:dd-openfeature.dd-openfeatureand ships it next to the agent jar, as system tests would otherwise use the published SDK (see breaking change).dd-smoke-tests/openfeature) now cover three setups:dd-openfeature/README.md.Features by setup
dd-java-agentagentless, the default)remote_config)DD_API_KEY)agentlessmodefeature_flag.evaluationsOTel metricBreaking change
dd-openfeature1.66.0 and earlier link against bootstrap types this PR removes, so they no longer work with this agent.dd-openfeatureanddd-java-agentmust be upgraded together. This was a deliberate choice to avoid keeping the legacy bridge. For the same reason, system tests now run with thedd-openfeaturejar built from this branch.Testing
All suites below were run locally on this branch. The smoke tests and
ConfigTestran on an earlier commit of it.:dd-openfeature:test+forkedTestfeature-flagging-lib/-agent/-bootstrap/-configdd-openfeature-connectorinstrumentation (test+forkedTest), including the agent/SDK configuration parity test:dd-smoke-tests:openfeature(3 setups)internal-apiConfigTestNot covered:
passdirective can't exist until the SDK is published (// TODO).:dd-openfeatureclasses are below the 90% per-class coverage threshold. CI doesn't enforce it for this module, as coverage is only checked on Java 8.// TODO)./techdebtand/perf-reviewhave not been run.Open questions
dd-openfeatureversions on a new agent acceptable, or do we need a deprecation window?jackson-coreas a plain dependency: what minimum version do we support against customer BOMs?Additional Notes
CODEOWNERSis not updated yet for/dd-openfeature/and/dd-java-agent/instrumentation/datadog/openfeature/.Jira ticket: APMLP-1512
🤖 Generated with Claude Code