Repository navigation
Add dd-openfeature SDK OpenFeature provider - #12843
Conversation
🟢 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. |
afa5b21 to
a5c7a57
Compare
a5c7a57 to
7858ad8
Compare
7858ad8 to
63abca3
Compare
63abca3 to
0fb68c6
Compare
0fb68c6 to
3f9d8b8
Compare
3f9d8b8 to
27d4862
Compare
27d4862 to
107bf8b
Compare
107bf8b to
6a0427d
Compare
The evaluator now takes the OpenFeature context and returns the ProviderEvaluation, so the provider no longer adapts the context and converts the result on every evaluation. Exposures are dispatched through the evaluator ExposureListener. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep notifying the other configuration listeners when one of them fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port #12774 to the dd-openfeature provider. Exposures are sent from a finally-stage hook once the evaluation succeeded, deduplicated by a provider-side cache that replaces the exposure pipeline cache, and applications can record them with ExposureHook. Split features are added to the flag metadata. Require OpenFeature SDK 1.23.0 so provider hooks run inside a MultiProvider. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
14961b2 to
2d1dcc6
Compare
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2d1dcc6561
ℹ️ 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".
There was a problem hiding this comment.
Shutting down the last provider can discard buffered exposures from successful evaluations. Initialization can also exceed its configured timeout and block concurrent shutdown while waiting for configuration.
🤖 Bits Code Review · Commit 2d1dcc6
The type mapping moved to FlagEvaluator, which owns its own copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No OpenTelemetry type is exposed by the SDK public API, so declare it as an implementation dependency rather than leaking it onto the consumers' compile classpath. It remains a runtime dependency. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Pushed 2 other minor fixes and resolved thread where reports are not a regression from master. |
|
/merge |
|
View all feedbacks in Devflow UI.
It will be processed automatically as soon as GitHub reports it as mergeable. View in MergeQueue UI.
The expected merge time in
|
What Does This Do
Adds
com.datadog.openfeature.Provider, its evaluator (DDEvaluator), hooks (metrics, logging, span enrichment) andFeatureFlagsRuntimewiring configuration delivery and event pipelines together. Also ports #12774:ExposureHook;MultiProvider.The SDK is still not published; the agent-coupled provider remains the shipped one.
Motivation
Completes the standalone SDK (APMLP-1512).
Additional Notes
Most of this PR moves code from master's
products/feature-flagging/feature-flagging-api(datadog.trace.api.openfeature). Review carefully the newinternal/FeatureFlagsRuntime, the newProvider/DDEvaluatorwiring (agent bridge SPI andSettingsinstead ofFeatureFlaggingGateway, bootstrap classes and reflection), and the lazy OTel resolution inFlagEvalMetrics.New files
internal/FeatureFlagsRuntimeacquire()/release()), replacing the agent-side gateway. Picks the configuration source fromSettings(Remote Config through the bridge, failing without the agent, or the CDN) and the event transport (agent event proxy, direct intake, or proxy → direct fallback). Owns the exposure and flag evaluation pipelines (evaluation pipeline skipped by the evaluation counts kill switch, both skipped without transport). Fans configuration out to listeners and replays it to late ones. A failed start is rolled back and not cachedinternal/FeatureFlagsRuntimeTestinternal/evaluation/ConfigurationStoreDDEvaluator, previously fields of the oldDDEvaluatorCanonicalFixtureTestDDEvaluatorTest. Reads theffe-system-test-datasubmodule (dd-smoke-tests/openfeature/src/test/resources/ffe-system-test-data) withJsonReadinginstead of MoshiFlagEvalMetricsLateSdkForkedTestGlobalOpenTelemetry, and metrics flow once the SDK is setMoved, package rename only (no logic change)
Evaluator,FlagEvalMetricsHookFlagEvalMetricsHookTest,FlagEvalMetricsTestMoved with significant changes
ProviderProviderAgentBridges.detect()andSettings.load(bridge), buildsDDEvaluatordirectly (reflectiveloadEvaluatorClass()/EVALUATOR_IMPLremoved). Span enrichment gate read fromSettings(SpanEnrichmentGateremoved);SpanEnrichmentHookgetsbridge.spanEnricher().FlagEvalLoggingHookalways added, resolving its writer lazily from the runtime;LinkageErrorguard dropped.FatalErrormessage now uses the cause message. Public constructors andOptionsunchangedDDEvaluatorDDEvaluatorinternal/evaluation/FlagEvaluator(#12840). Kept:evaluate()delegating toFlagEvaluator(OpenFeature types end to end, no conversion), exposure building (via theFlagEvaluatorExposureListener) and recording, context snapshot / flatten / prune helpers. Lifecycle: package-private(Runnable, AgentBridge, Settings)constructor; synchronizedinitialize()/shutdown()acquire / releaseFeatureFlagsRuntimeand register aConsumer<ServerConfiguration>(wasFeatureFlaggingGateway.activate()/ConfigListener);ConfigurationStorereplaces latch +AtomicReference. Removed: agent compatibility probes (SPLIT_SERIAL_ID_SUPPORTED,USE_LEGACY_EXPOSURE_API, legacyExposureEventconstructor) and static span enrichment gate. Exposures go toruntime.recordExposure()instead ofFeatureFlaggingGateway.dispatch()FlagEvalMetricsFlagEvalMetricsGlobalOpenTelemetry.get(). Now resolves the counter lazily onrecord()withgetOrNoop(), rebuilds it when the global instance changes, falls back toget()only for OTel API < 1.57 or a legacy OTel javaagent bridge, disables itself onLinkageError. Synchronizedshutdown()with aclosedflagFlagEvalLoggingHookFlagEvalLoggingHookSupplier<FlagEvaluationWriter>constructor;INSTANCEsingleton, gateway constructors andisFlagEvaluationEnqueueEnabled()check removedSpanEnrichmentHookSpanEnrichmentHookSpanEnricher(serialId/runtimeDefault) instead of dispatchingSpanEnrichmentEventon the gateway. Capture logic unchangedjmh/FlagEvalHookHotPathBenchmark@TearDownremoved, writer injected through a supplier, run command now:dd-openfeature:jmhProviderTestProviderTestProxyAgentBridge,LocalHttpServer,TestSettings). Internal API linkage failure tests removed. New: product disabled, Remote Config without agent, end-to-end evaluation posted through the pipelineDDEvaluatorTestDDEvaluatorTestCanonicalFixtureTest. Exposures captured by overridingrecordExposure. New: type compatibility, container cycles in context copy / flatten, empty and scalar valuesDDEvaluatorSpanEnrichmentTestDDEvaluatorSpanEnrichmentForkedTestTestSettingsinstead of a static. Tests for agents without serial id support removedFlagEvalLoggingHookTestFlagEvalLoggingHookTestSpanEnrichmentHookTestSpanEnrichmentHookTestSpanEnricherreplaces the gateway listenerShared files
dd-openfeature/build.gradle.kts: addsapi("io.opentelemetry:opentelemetry-api:1.66.0"); OTel API becomes a hard transitive dependency (master had itcompileOnly1.47.0 and handled its absence)dd-openfeature/gradle.lockfile: updated for the OTel dependencyStack
The full change is in #12709. It was split into this stack to ease the review.
Jira ticket: APMLP-1512
🤖 Generated with Claude Code