Skip to content

Add dd-openfeature SDK settings and configuration delivery - #12841

Draft
PerfectSlayer wants to merge 2 commits into
bbujon/ffe-sdk-corefrom
bbujon/ffe-sdk-infra
Draft

PerfectSlayer wants to merge 2 commits into
bbujon/ffe-sdk-corefrom
bbujon/ffe-sdk-infra

Conversation

@PerfectSlayer

@PerfectSlayer PerfectSlayer commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

What Does This Do

Adds to the dd-openfeature SDK:

  • internal/config: SDK settings (agent config when attached, then dd. system properties, then env vars)
  • internal/connector: the SPI the agent can implement (configuration source, event transport, health metrics, span enricher)
  • internal/delivery: agentless configuration polling from the Datadog CDN, direct intake event transport, fallback transport, retries

Motivation

Lets the SDK work without the agent (APMLP-1512). The connector SPI is the only contract crossing SDK and agent versions.

Additional Notes

All SDK files are new code: none is a straight move from master. Review carefully the delivery classes ported from feature-flagging-lib: their HTTP stack moved from OkHttp / the agent communication module to the JDK 11 HttpClient, with retries, gzip and headers rewritten.

New files (no master equivalent)
File Notes
internal/connector/Connector, Connectors, NoConnector SPI the agent plugs into: agent settings, Remote Config source, event proxy transport, health metrics, span enricher. Connectors.detect() returns NONE and is instrumented by the agent
internal/connector/ConfigurationSource Raw UFC byte[] subscription (null = configuration removed)
internal/connector/EventTransport, EventProxyUnavailableException Minimal post(route, json) transport; the exception signals a definitive proxy rejection, triggering the fallback
internal/connector/HealthMetrics, SpanEnricher Agent-side sinks with NOOP defaults
internal/EventQueue Bounded lock-free MPSC queue, replaces JCTools mpscBlockingConsumerArrayQueue
internal/JsonWriting Jackson streaming helpers, replaces Moshi adapters
internal/RuntimeServices Daemon dd-openfeature-<role> threads and health counter wrapper, replaces AgentThreadFactory
internal/delivery/Gzip Decodes Content-Encoding: gzip, which the JDK client does not do
internal/delivery/DirectIntakeTransport Direct EVP intake POST, re-implementing master's BackendApiFactory.createDirectIntakeApi. Same headers and 5 retries with 100 ms × 2 backoff. Differences: no X-RateLimit-Reset handling, 408 retried, no compression, fixed 10 s timeout, random trace id, create() returns null without API key (master threw FatalAgentMisconfigurationError)
Tests: EventQueueTest, DirectIntakeTransportTest, JsonReading, LocalHttpServer, config/TestSettings Tests and helpers; LocalHttpServer is a JDK HttpServer replaying scripted responses
Derived from master with significant changes
New file Master origin Changes
delivery/CdnConfigurationSource lib AgentlessConfigurationSource OkHttp → JDK HttpClient (redirects disabled); UfcHttpClient / AgentlessRetryPolicy layers replaced by Retries. Lifecycle, ETag, last-known-good, 3-attempt retry and jittered backoff kept. Differences: gzip requested and decoded explicitly; configuration pushed to a Consumer instead of the gateway; API key sent whenever no custom base URL is set (master also checked https and the CDN host); close() interrupts the polling thread without cancelling the in-flight call; inline 5 min log throttle replaces RatelimitedLogger
delivery/Retries AgentlessRetryPolicy + OkHttpUtils.sendWithRetries One send loop shared by the CDN source and direct intake: retries IOException and 408 / 429 / 5xx, caller-supplied attempts, delays, sleeper and cancellation. No X-RateLimit-Reset support
delivery/FallbackTransport lib AgentlessFeatureFlagBackendApi Same one-way proxy → direct switch, no replay of ambiguous failures. Definitive failures are now signalled by the proxy transport (EventProxyUnavailableException) instead of classified here (ConnectException, 403 / 404 / 405)
delivery/RemoteConfigurationService lib RemoteConfigServiceImpl Subscribes through the connector ConfigurationSource instead of ConfigurationPoller; parses raw UFC bytes in the SDK, malformed payloads logged at debug
delivery/Headers OkHttpUtils.prepareRequest Keeps Datadog-Meta-Lang*, adds Datadog-Meta-Tracer-Version (SDK version), drops container / entity id headers
ConfigurationService lib ConfigurationSourceService init() → start(Consumer<ServerConfiguration>), AutoCloseable
config/Settings FeatureFlaggingConfig + Config feature flag settings Lookup order: connector, dd.* system property, DD_* env var. Same source resolution semantics, plus API key, site, env, service, version, span enrichment, evaluation counts. Differences: no legacy toggle deprecation warning, unsupported source disables with a warning, invalid booleans read false, invalid / non-positive ints fall back to defaults
config/SdkVersion communication TracerVersion Reads /dd-openfeature.version written by the version-file plugin, strips the git hash suffix
CdnConfigurationSourceTest lib AgentlessConfigurationSourceTest Rewritten against LocalHttpServer. Reduced coverage (~28 vs ~50 cases): in-flight cancellation, request timeout, overlapping polls, repeated init and API key stripping for http / unexpected hosts not ported
FallbackTransportTest lib AgentlessFeatureFlagBackendApiTest Three cases (proxy OK, unavailable switches for good, no replay); status classification moved to the connector
SettingsTest FeatureFlaggingConfigTest Source resolution cases plus lookup order, env var naming, defaults, trimming and toggles
Shared files
  • dd-openfeature/build.gradle.kts: applies dd-trace-java.version-file, generating the version resource read by SdkVersion
  • dd-openfeature/gradle.lockfile: regenerated

Stack

The full change is in #12709. It was split into this stack to ease the review.

  1. Resolve Feature Flags enablement from instrumenter config #12845
  2. Add dd-openfeature SDK flag configuration and evaluation core #12840
  3. Add dd-openfeature SDK settings and configuration delivery #12841 👈 this PR
  4. Add dd-openfeature SDK exposure and flag evaluation pipelines #12842
  5. Add dd-openfeature SDK OpenFeature provider #12843
  6. Connect the dd-openfeature SDK to the agent #12844
  7. Add agentless and standalone OpenFeature smoke tests #12846

Jira ticket: APMLP-1512

🤖 Generated with Claude Code

@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

🎯 Code Coverage (details)
• Patch Coverage: 100.00%
• Overall Coverage: 59.53% (+0.01%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: f411f22 | Docs | Give us feedback!

@dd-octo-sts

dd-octo-sts Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 13.97 s 13.97 s [-0.7%; +0.7%] (no difference)
startup:insecure-bank:tracing:Agent 12.91 s 12.97 s [-1.1%; +0.3%] (no difference)
startup:petclinic:appsec:Agent 17.07 s 16.99 s [-0.4%; +1.3%] (no difference)
startup:petclinic:iast:Agent 16.81 s 17.02 s [-2.3%; -0.2%] (maybe better)
startup:petclinic:profiling:Agent 16.43 s 16.59 s [-2.0%; +0.0%] (no difference)
startup:petclinic:sca:Agent 17.01 s 16.83 s [-0.0%; +2.1%] (no difference)
startup:petclinic:tracing:Agent 16.03 s 16.22 s [-2.0%; -0.3%] (maybe better)

Commit: f411f220 · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

@PerfectSlayer
PerfectSlayer force-pushed the bbujon/ffe-sdk-infra branch 4 times, most recently from 656cc15 to ec1fa25 Compare October 13, 2026 10:27
@PerfectSlayer
PerfectSlayer force-pushed the bbujon/ffe-sdk-infra branch 2 times, most recently from ac0d5b6 to f5c7297 Compare October 13, 2026 13:49
PerfectSlayer and others added 2 commits October 14, 2026 09:01
Add the SDK settings, the connector SPI the agent can implement, the
agentless configuration delivery from the CDN and the direct intake
event transport.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Parse the Feature Flags configuration source like the agent enum config
parsing: case insensitive, with no trimming of surrounding spaces, so
the SDK and the agent keep resolving the same configuration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: openfeature OpenFeature tag: ai generated Largely based on code generated by an AI or LLM tag: no release notes Changes to exclude from release notes type: feature Enhancements and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant