Skip to content

Add dd-openfeature SDK flag configuration and evaluation core - #12840

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 8 commits into
masterfrom
bbujon/ffe-sdk-core
Oct 14, 2026
Merged

gh-worker-dd-mergequeue-cf854d[bot] merged 8 commits into
masterfrom
bbujon/ffe-sdk-core

Conversation

@PerfectSlayer

@PerfectSlayer PerfectSlayer commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

What Does This Do

Adds the new :dd-openfeature module (not published yet) with:

  • the Universal Flag Configuration model and parser (internal/ufc), including split features (port of Parse features on UFC splits #12772)
  • the local flag evaluator (internal/evaluation)

Motivation

dd-openfeature becomes a standalone Java 11 SDK depending on no dd-trace-java internal module (APMLP-1512). The new module is built alongside the existing feature-flagging-api module, which keeps owning the dd-openfeature artifact until the switch PR of the stack.

Additional Notes

Most files are moved from master. Only the parser and the evaluator need a full review: everything else is a package move or a small model change. The parser rejects documents nested deeper than 32 levels.

New files (build only)
File Notes
build.gradle.kts, gradle.lockfile Temporary build, publishing comes with #12844
Moved, package rename only (no logic change)

From datadog.trace.api.featureflag.ufc.v1 (feature-flagging-bootstrap) to com.datadog.openfeature.internal.ufc, some classes made final:

  • ConditionConfiguration, ConditionOperator, Environment, Flag, ParsedSemver, Rule, ValueType, Variant
  • ServerConfiguration, Split: Moshi-specific comments reduced to Javadoc
  • ParsedSemverTest: package only
  • remote-config/*.json fixtures (from feature-flagging-lib test resources): identical
Moved with significant changes
New file Master origin Changes
ufc/Allocation bootstrap ufc/v1/Allocation Date → Instant; drops the dual Date / precise Instant constructors and accessors
ufc/Shard, ufc/ShardRange bootstrap ufc/v1/Shard, ShardRange int → long for unsigned 32-bit values, no bootstrap binary compatibility to preserve
ufc/UniversalFlagConfigParser lib UniversalFlagConfigParser + JsonApiUfcResponseParser Rewritten: merged into one class (parse / parseJsonApi), Moshi reflective adapters replaced by jackson-core streaming + explicit mapping with strict / lenient coercion; rejects duplicate keys and non-object documents. Same per-flag rejection rules as master. Review as new code
evaluation/FlagEvaluator api DDEvaluator (~43% similar) Pure evaluation logic extracted, see below. Exposure recording stays in the new DDEvaluator (#12843)
UniversalFlagConfigParserJsonApiTest lib JsonApiUfcResponseParserTest Adapted to the merged parser API
UniversalFlagConfigParserTest lib RemoteConfigServiceImplTest (~52% similar) Parsing tests kept; Moshi adapter tests dropped; new tests for duplicate keys, non-object documents, wrong-typed fields and number coercion

FlagEvaluator changes against the extracted DDEvaluator logic (~25 of ~340 lines):

  • still works on OpenFeature types (EvaluationContext, ProviderEvaluation, ImmutableMetadata, Value)
  • exposures reported through an ExposureListener callback instead of dispatched to the gateway
  • span enrichment gate is an instance field; reflective SPLIT_SERIAL_ID_SUPPORTED probe removed (no version skew inside the SDK)
  • reads Allocation Instant fields directly, no unsigned int conversions
  • evaluate() entry point nearly unchanged
Shared files
  • .github/CODEOWNERS: adds /dd-openfeature/
  • settings.gradle.kts: includes :dd-openfeature
  • gradle/libs.versions.toml: adds jackson-core alias

The evaluator is covered by DDEvaluatorTest and CanonicalFixtureTest, which come with the provider PR (#12843).

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 👈 this PR
  3. Add dd-openfeature SDK settings and configuration delivery #12841
  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-us1-prod

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

Copy link
Copy Markdown

🎯 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: de691e4 | 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.98 s 13.86 s [+0.2%; +1.5%] (maybe worse)
startup:insecure-bank:tracing:Agent 12.80 s 12.98 s [-2.2%; -0.7%] (maybe better)
startup:petclinic:appsec:Agent 16.97 s 16.94 s [-0.7%; +1.1%] (no difference)
startup:petclinic:iast:Agent 16.42 s 16.41 s [-6.1%; +6.3%] (unstable)
startup:petclinic:profiling:Agent 16.56 s 16.22 s [-2.5%; +6.7%] (no difference)
startup:petclinic:sca:Agent 16.90 s 16.77 s [-0.1%; +1.6%] (no difference)
startup:petclinic:tracing:Agent 16.09 s 16.07 s [-0.7%; +0.9%] (no difference)

Commit: de691e46 · 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 marked this pull request as ready for review October 13, 2026 09:33
@PerfectSlayer
PerfectSlayer requested a review from a team as a code owner October 13, 2026 09:33
@PerfectSlayer
PerfectSlayer requested review from bric3 and removed request for a team October 13, 2026 09:33
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T09:42:08.294852Z e889852 Draft marked ready
🔒 Security Review ✅ Completed 2026-10-13T09:39:58.346526Z e889852 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e88985265a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@datadog-datadog-us1-prod datadog-datadog-us1-prod Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: FAIL

Malformed scheduling fields can silently remove allocation bounds, and explicit null enablement is reported as disabled instead of a parse error. Focused execution confirmed both regressions and verified that the inline replacements reject affected flags while retaining valid siblings.

Open Bits AI session

🤖 Bits Code Review · Commit e889852

@PerfectSlayer

Copy link
Copy Markdown
Collaborator Author

@DataDog review

@datadog-datadog-us1-prod datadog-datadog-us1-prod Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: FAIL

The parser accepts 1e400 as infinity, allowing a NUMERIC flag to resolve successfully with a non-finite value instead of rejecting the configuration.

Open Bits AI session

🤖 Bits Code Review · Commit bbd00b2

@PerfectSlayer

Copy link
Copy Markdown
Collaborator Author

@DataDog review

@sarahchen6 sarahchen6 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! IIUC most of these changes look straightforward - just duplicating files over from products/feature-flagging/ - which are then removed in a later stacked PR. The "new" jackson parser looks reasonable. I ran the changes through Codex again, and it mentioned one potential StackOverflowError that I think could be addressed. Otherwise LGTM!

@PerfectSlayer
PerfectSlayer force-pushed the bbujon/ffe-sdk-core branch 3 times, most recently from 5995b85 to 7005e85 Compare October 14, 2026 06:13
@PerfectSlayer
PerfectSlayer requested a review from a team as a code owner October 14, 2026 07:06

@datadog-datadog-us1-prod datadog-datadog-us1-prod Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: PASS

More details

Allocation timing, shard matching, and evaluator type conversion remain consistent with the existing implementation. The completed static review identified no reportable defect; tests were not run.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 7005e85

@PerfectSlayer
PerfectSlayer force-pushed the bbujon/ffe-sdk-core branch 2 times, most recently from 75a7cf0 to 73f361a Compare October 14, 2026 08:41
@greghuels
greghuels requested review from sameerank and typotter and removed request for greghuels October 14, 2026 12:52
Base automatically changed from bbujon/ffe-agent-config to master October 14, 2026 13:41
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot requested a review from a team as a code owner October 14, 2026 13:41
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot requested review from jordan-wong and removed request for a team October 14, 2026 13:41
PerfectSlayer and others added 7 commits October 14, 2026 13:41
Introduce the standalone :dd-openfeature module, not published yet, with
the Universal Flag Configuration model and parser and the local flag
evaluator. It depends on no dd-trace-java internal module.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The evaluator built its own metadata type that the provider copied into
an OpenFeature ImmutableMetadata on every evaluation. The SDK already
depends on the OpenFeature SDK, so build ImmutableMetadata directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the EvaluationContext and EvaluationResult mirrors of the
OpenFeature types: the evaluator takes the OpenFeature context and
returns a ProviderEvaluation, removing the per-evaluation context
adapter and result conversion. Exposures are reported through an
ExposureListener at resolution time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An explicit "enabled": null was read as false, keeping the malformed
flag as disabled instead of reporting it invalid. Only an absent field
now defaults to false, as with the previous Moshi parsing. Also convert
the serial id coercion cases to @TableTest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A boolean, object or array startAt / endAt was read as null, silently
removing the allocation bound. Reject the flag as invalid instead, as
with the previous Moshi parsing, while still ignoring numbers and
unparsable date strings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A number overflowing double, like 1e400, was read as infinity and could
resolve as a valid NUMERIC flag value. Reject the configuration
instead, as the previous strict Moshi reader did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port the UFC split features parsing from #12772 to the dd-openfeature
SDK parser. Features only feed exposure hooks, so a malformed list or
entry is dropped instead of rejecting the flag, and a feature without
destinations is dropped.

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

@datadog-datadog-us1-prod datadog-datadog-us1-prod Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: PASS

More details

Confidence rests on source comparison with the existing parser and evaluator, plus inspection of parsing tests. Tests were not executed, so runtime behavior remains unverified.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 73f361a

@PerfectSlayer

Copy link
Copy Markdown
Collaborator Author

/merge

@gh-worker-devflow-routing-ef8351

gh-worker-devflow-routing-ef8351 Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

View all feedbacks in Devflow UI.

2026-10-14 14:09:25 UTC ℹ️ Start processing command /merge


2026-10-14 14:09:32 UTC ℹ️ MergeQueue: Pull request is not mergeable yet

It will be processed automatically as soon as GitHub reports it as mergeable. View in MergeQueue UI.

  • Run /code blockers to see what is blocking it.
  • Run /remove to cancel it.

2026-10-14 16:29:21 UTC ℹ️ MergeQueue: merge request added to the queue

The expected merge time in master is approximately 1h (p90).


2026-10-14 18:11:23 UTC ℹ️ MergeQueue: This merge request was merged

@PerfectSlayer

Copy link
Copy Markdown
Collaborator Author

/code blockers

@gh-worker-devflow-routing-ef8351

gh-worker-devflow-routing-ef8351 Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

View all feedbacks in Devflow UI.

2026-10-14 14:58:32 UTC ℹ️ Start processing command /code blockers


2026-10-14 14:58:33 UTC ℹ️ Devflow:

Checking merge blockers for #12840...


2026-10-14 14:58:39 UTC ℹ️ Devflow: /code blockers

Detected 1 merge blocker(s) to address:

🔴 Blocking

  • Required check dd-gitlab/default-pipeline has not reported
    Hint: Ensure the workflow that produces this check is triggered.

The UFC parser reads the document recursively, including ignored fields,
so a deeply nested document could overflow the stack with an error the
configuration sources do not catch. Reject documents nested deeper than
32 levels, as Moshi capped them at 255 before. The cap is enforced by the
reader rather than Jackson StreamReadConstraints, which jackson-core
older than 2.15 (e.g. Spring Boot 2.7) does not provide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot merged commit 52f31b8 into master Oct 14, 2026
822 of 824 checks passed
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot deleted the bbujon/ffe-sdk-core branch October 14, 2026 18:11
@github-actions github-actions Bot added this to the 1.68.0 milestone Oct 14, 2026
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.

2 participants