镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Add a flag selection option to the OpenFeature provider - #13291

Open
mark-caii wants to merge 6 commits into
masterfrom
mark.cai/FFL-3572
Open

mark-caii wants to merge 6 commits into
masterfrom
mark.cai/FFL-3572

Conversation

@mark-caii

@mark-caii mark-caii commented Nov 6, 2026 •

Copy link
Copy Markdown

What Does This Do

Lets an application load only part of its flag configuration:

new Provider(new Provider.Options()
    .flagSelection(new FlagSelection()
        .tags(List.of("checkout"))
        .keyPatterns(List.of("checkout.*"))));

With a selection, the agentless configuration request carries repeated selected_flag_tags and selected_flag_key_patterns query parameters, and the provider serves only the flags the backend returns. A flag outside the selection evaluates to the default value with FLAG_NOT_FOUND. Without a selection, the request, the ETag handling and the loaded configuration are unchanged.

Motivation

A service that uses a few flags of a large Datadog project still downloads, parses and holds the whole flag configuration. A flag selection lets it fetch and keep only the flags it needs, which shrinks the payload and the memory it holds. The browser, iOS and Android SDKs already support it; this gives the Java server SDK the same option, with the same canonical form and diagnostics.

Additional Notes

  • Same canonical form as the other SDKs. Each list is trimmed of Unicode White_Space, deduplicated and sorted by UTF-8 bytes, then percent-encoded per RFC 3986. The JDK helpers don't fit: String.trim() and String.strip() each disagree with White_Space, String.compareTo sorts by UTF-16 code units, and URLEncoder is form encoding (+ for a space, * kept). FlagSelectionVectorsTest runs the 38 SDK cases of the shared flag-selection/selection-vectors.json and skips the 6 rawQuery cases, which test the server's percent-decoding. The ffe-system-test-data submodule moves from 8c4d241 to e8777633, a single commit that adds these vectors and their validator.
  • Invalid input never throws. A null selection or a null list means no selection. A null or non-String element (possible through a raw list) or an unpaired surrogate is malformed_selection. More than 31 values in a list, a value over 200 UTF-8 bytes, or a request URL over 8192 bytes also drops the selection. A dropped selection is not sent: the provider logs one error per provider initialization, naming the reason and the limit but never the values, and loads all the flags. For malformed_selection the limit text is the browser SDK's, with "lists" for the Java type: flagSelection must be an object with optional tags and keyPatterns string lists.
  • Selections the server ignores. The DD-Flag-Selection-Ignored response header is read only on a 200 to a request that carried a selection. Its value is kept only when it is exactly one of the five known reasons, and is unknown otherwise. It is logged once per reason, after the configuration is applied.
  • One selection per class loader. The providers of a class loader share one configuration runtime, so the first provider initialized claims the selection until the last provider shuts down. A provider without a selection claims too, meaning all the flags. A later provider with a different selection uses the first selection; the first such provider logs a warning, once per class loader. A custom configuration endpoint must forward the selected_flag_* query parameters and the DD-Flag-Selection-Ignored header.
  • Remote Config delivers the full configuration and does not support a selection. The first provider with a selection logs a warning, once per class loader, and no provider gets the second-selection warning, since no selection is in use.
  • Telemetry. flag_selection.dropped and flag_selection.ignored, tagged with reason, go through the existing health metrics once per reason, so they need dd-java-agent. Without the agent, the error logs are the only signal. The telemetry intake drops these two counts until they are registered there, which is separate work.
  • API. FlagSelection and Options.flagSelection are new public API, also on the deprecated datadog.trace.api.openfeature.Provider.Options alias. The option is set in code only: there is no environment variable or system property.
  • Test data pin. This PR and the bot bump Bump dd-smoke-tests/openfeature/src/test/resources/ffe-system-test-data from 8c4d241 to d8911fd #13183 both move the ffe-system-test-data submodule. Whichever merges second should take d8911fd, Bump dd-smoke-tests/openfeature/src/test/resources/ffe-system-test-data from 8c4d241 to d8911fd #13183's commit, whose flag-selection/ is identical to e8777633.
  • Known issues. ProviderTest.testNullConfigurationAfterReadyTransitionsToErrorAndRecovers failed once in a full local run of the module (a Mockito invocation count on a configuration-change handler) and passed in isolated runs on this branch and on master. The test and its no-selection path are unchanged here, so it looks like an existing timing flake.
  • Validation. No end-to-end run is part of this PR yet. The system-tests suite for flag selection is in test(ffe): apply server flag selection in the mocked backend system-tests#8304; wiring the Java parametric app to this option and running it, and the ffe-dogfooding Java app, are follow-ups.

Contributor Checklist

Jira ticket: FFL-3572

Move the ffe-system-test-data submodule from 8c4d241 to e8777633, which
adds the shared flag-selection/selection-vectors.json.

Environment: Datadog workspace
Provider.Options.flagSelection(FlagSelection) sends the selected tags and
key patterns on the agentless configuration request, so the provider loads
only the flags the backend returns. The selection is canonicalized and
validated as in the other Datadog SDKs and checked against the shared
flag-selection vectors. A selection that cannot be sent is dropped with an
error log and the full configuration is loaded; a selection the server
ignores is logged once per reason after the configuration is applied. The
first provider initialized in a class loader claims the selection until
the last provider shuts down.

Solves FFL-3572.

Environment: Datadog workspace
A provider joining a Remote Config runtime with a selection now logs the
Remote Config warning too, once per class loader, instead of only the
provider that started the runtime. Also write the White_Space set and the
non-ASCII test values as escapes, and cover the legacy Remote Config
setting and repeated polls over the URL limit.

Environment: Datadog workspace
@mark-caii mark-caii added type: feature Enhancements and improvements comp: openfeature OpenFeature tag: ai generated Largely based on code generated by an AI or LLM labels Nov 6, 2026 — with ddtool CLI
@datadog-datadog-us1-prod

datadog-datadog-us1-prod Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

🎯 Code Coverage (details)
• Patch Coverage: 100.00%
• Overall Coverage: 59.98% (-0.01%)

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

@mark-caii mark-caii added the crucible: reviewing A Crucible review has started; this PR has reviewer attention. label Nov 6, 2026 — with ddtool CLI
@dd-octo-sts

dd-octo-sts Bot commented Nov 6, 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.91 s 13.93 s [-0.9%; +0.7%] (no difference)
startup:insecure-bank:tracing:Agent 12.86 s 12.97 s [-1.5%; -0.1%] (maybe better)
startup:petclinic:appsec:Agent 17.02 s 16.31 s [-1.2%; +10.0%] (unstable)
startup:petclinic:iast:Agent 16.91 s 17.10 s [-2.0%; -0.2%] (maybe better)
startup:petclinic:profiling:Agent 16.79 s 16.33 s [-1.6%; +7.2%] (no difference)
startup:petclinic:sca:Agent 17.06 s 16.92 s [-0.1%; +1.6%] (no difference)
startup:petclinic:tracing:Agent 15.76 s 16.23 s [-7.0%; +1.1%] (no difference)

Commit: 0f4d62b6 · 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.

Copy the arrays a selection list returns, so a list breaking the
toArray contract is malformed input instead of a NullPointerException.
Cover the Remote Config warning for an invalid selection, a joining
provider with a different dropped selection, the once-per-reason counts
across reasons and kinds, the deprecated alias return type and an
encoded endpoint path. Document the URL-length drop, the once per class
loader second-selection warning and the query parameters a custom
endpoint must forward, and use a non-team tag in examples.

Environment: Datadog workspace
Remote Configuration delivers the full configuration and uses no flag
selection, so a later provider with a different selection only gets the
Remote Config warning: "Using the first selection" would be inaccurate.

Environment: Datadog workspace
@mark-caii
mark-caii marked this pull request as ready for review November 6, 2026 20:10
@mark-caii
mark-caii requested review from a team as code owners November 6, 2026 20:10
@mark-caii
mark-caii requested review from ValentinZakharov and removed request for a team November 6, 2026 20:10
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

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

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-06T20:15:11.801933Z 0f4d62b 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.

@dd-octo-sts

dd-octo-sts Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

PR Blocked - Invalid Label

The pull request introduced unexpected labels:

  • crucible: reviewing

This PR is blocked until:

  1. The invalid labels are deleted, and
  2. A maintainer deletes this comment to unblock the PR

Note: Simply removing labels from the pull request is not enough - a maintainer must delete this comment then remove the label to remove the block.

@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: 0f4d62b6bf

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +279 to +281
final URI selected = URI.create(url.toString());
// Every character is ASCII once percent-encoded, so the length is the byte count.
return selected.toASCIIString().length() > MAX_URL_BYTES ? null : selected;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exclude URI fragments from the request-length limit

When a custom endpoint contains a fragment, this check counts the fragment's percent-encoded bytes toward the 8192-byte request limit, although URI fragments are never transmitted in an HTTP request. A sufficiently long fragment—or a near-limit endpoint followed by any fragment—therefore makes appendTo return null, causing the provider to discard a valid selection, load every flag, and report too_many_values even though the actual request URL is within the limit; measure only the URI through its query while retaining the fragment in the returned URI.

Useful? React with 👍 / 👎.

@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

Validation is limited to source review: backend interoperability remains unverified, and the shared canonicalization vectors could not be inspected because the test-data submodule was unavailable.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 0f4d62b

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 crucible: reviewing A Crucible review has started; this PR has reviewer attention. tag: ai generated Largely based on code generated by an AI or LLM type: feature Enhancements and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant