Skip to content

feat(openfeature): add direct flagevaluation fallback - #12204

Open
leoromanovsky wants to merge 3 commits into
agent/java-direct-exposure-egressfrom
agent/java-direct-flagevaluation-egress
Open

feat(openfeature): add direct flagevaluation fallback#12204
leoromanovsky wants to merge 3 commits into
agent/java-direct-exposure-egressfrom
agent/java-direct-flagevaluation-egress

Conversation

@leoromanovsky

@leoromanovsky leoromanovsky commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Motivation

The base PR gives exposure events direct EVP capability. Agentless Feature Flags also need direct EVP capability for aggregate flagevaluation events when no compatible local receiver exists.

flowchart TD
    A[Agentless Feature Flags] --> E[Exposure writer from PR 12195]
    A --> F[Flagevaluation writer in this PR]
    E --> ER{Compatible local EVP route?}
    F --> FR{Compatible local EVP route?}
    ER -->|Yes| L[Local EVP proxy]
    FR -->|Yes| L
    ER -->|No, API key available| DE[Direct EVP<br/>/api/v2/exposures]
    FR -->|No, API key available| DF[Direct EVP<br/>/api/v2/flagevaluation]
    L --> P[Event Platform]
    DE --> P
    DF --> P
Loading

Changes and Decisions

This stacked PR retains direct EVP exposure delivery from PR #12195 and adds direct EVP flagevaluation delivery.

  • Use one Feature Flag transport selector for both exposures and flagevaluations.
  • Preserve exposure response compression and disable response compression for flagevaluations.
  • Prefer a compatible local EVP proxy for both event types.
  • Use authenticated direct EVP intake when no compatible local route exists.
  • Switch from local to direct intake only after connection refusal or HTTP 403, 404, or 405.
  • Do not replay after timeouts, resets, rate limits, or server errors. This prevents possible duplicate events.
  • Keep /api/v2/exposures and /api/v2/flagevaluation as separate direct routes.
  • Cover the shared fallback behavior for both event routes.

@datadog-official

This comment has been minimized.

@leoromanovsky
leoromanovsky marked this pull request as ready for review August 13, 2026 15:28
@leoromanovsky
leoromanovsky requested a review from a team as a code owner August 13, 2026 15:28
@dd-octo-sts

dd-octo-sts Bot commented Aug 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 14.87 s 14.70 s [+0.3%; +2.2%] (maybe worse)
startup:insecure-bank:tracing:Agent 13.56 s 13.72 s [-2.0%; -0.3%] (maybe better)
startup:petclinic:appsec:Agent 17.29 s 17.21 s [-0.7%; +1.6%] (no difference)
startup:petclinic:iast:Agent 17.40 s 17.13 s [-2.9%; +6.0%] (no difference)
startup:petclinic:profiling:Agent 17.43 s 17.26 s [-0.5%; +2.5%] (no difference)
startup:petclinic:sca:Agent 16.77 s 16.14 s [-3.6%; +11.4%] (unstable)
startup:petclinic:tracing:Agent 16.52 s 16.69 s [-1.9%; -0.1%] (maybe better)

Commit: 792a754d · 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.

@datadog-official datadog-official Bot 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.

Datadog Autotest: FAIL

Direct flag-evaluation delivery still negotiates gzip because IntakeApi leaves Accept-Encoding unset when compression is disabled, allowing OkHttp to add gzip automatically. This defeats the explicit no-compression contract on every new direct or fallback route, although the local EVP path correctly sends identity.

Open Bits AI session

🤖 Datadog Autotest · Commit 5916539 · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

return null;
}
try {
return backendApiFactory.createDirectIntakeApi(Intake.EVENT_PLATFORM, responseCompression);

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.

P1 Direct intake ignores disabled response compression

Every agentless flag-evaluation request using the new direct or fallback route still negotiates gzip, defeating the route’s stated no-compression compatibility contract.

Assertion details
  • Input: Agentless feature flagging with an API key when the local EVP proxy is unavailable or definitively rejects flag-evaluation delivery.
  • Expected: Direct flag-evaluation requests should send Accept-Encoding: identity so response compression is genuinely disabled on both local and direct routes.
  • Actual: The new direct path passes responseCompression=false to createDirectIntakeApi, but IntakeApi only adds Accept-Encoding when the value is true. OkHttp therefore automatically adds Accept-Encoding: gzip. The sibling EvpProxyApi explicitly sends identity on its false path to prevent exactly this behavior. FeatureFlagBackendApiFactoryTest only verifies the boolean argument, while the direct writer test does not inspect Accept-Encoding. A complete fix must update IntakeApi to send Accept-Encoding: identity when compression is disabled and cover that shared-client behavior; changing this factory line alone is insufficient.

Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

capacity,
flushInterval,
timeUnit,
new FeatureFlagBackendApiFactory(config, sco, "exposure", true),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nitpick: reading the code, I've no idea what true means here. Not sure what java conventions are but an enum or a builder would help. (although builder for a factory is a bit 🤪.) A builder-like setter also works

final Config config,
final SharedCommunicationObjects sharedCommunicationObjects,
final String eventType,
final boolean responseCompression) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Q: What is "response compression?" Why is it disabled for flag evaluations?

private static final Logger LOGGER =
LoggerFactory.getLogger(AgentlessFeatureFlagBackendApi.class);

private final BackendApi localApi;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

aside: probably not in scope of this PR but it took me a bit to figure out what "local API" means. I think that "proxy" is the more important part of the name, and "direct vs. proxy" makes more sense as a dichotomy

I guess "local" part might also be false when agent is deployed to a different node in a cluster

…ct-flagevaluation-egress

# Conflicts:
#	products/feature-flagging/feature-flagging-lib/src/main/java/com/datadog/featureflag/AgentlessFeatureFlagBackendApi.java
#	products/feature-flagging/feature-flagging-lib/src/main/java/com/datadog/featureflag/ExposureBackendApiFactory.java
#	products/feature-flagging/feature-flagging-lib/src/test/java/com/datadog/featureflag/AgentlessFeatureFlagBackendApiTest.java
#	products/feature-flagging/feature-flagging-lib/src/test/java/com/datadog/featureflag/FeatureFlagBackendApiFactoryTest.java
@dd-octo-sts

dd-octo-sts Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Hi! 👋 Thanks for your pull request! 🎉

To help us review it, please make sure to:

  • Add at least one type, and one component or instrumentation label to the pull request

If you need help, please check our contributing guidelines.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants