feat(openfeature): add agentless EVP fallback - #5280
Conversation
Discover compatible Agent EVP routes lazily and fall back to authenticated direct intake for exposure and flag-evaluation events. Environment: Datadog workspace
🎉 All green!🧪 All tests passed 🔄 Datadog auto-retried 2 jobs - 2 passed on retry 🎯 Code Coverage (details) 🔗 Commit SHA: 9b9388f | Docs | View more details | Give us feedback! |
BenchmarksBenchmark execution time: 2026-08-27 08:59:12 Comparing candidate commit 9b9388f in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 335 metrics, 0 unstable metrics, 1 flaky benchmarks without significant changes.
|
Update the OpenFeature SDK to v1.17.2 so provider replacement uses non-blocking event-handler shutdown and consistent SetProviderAndWait initialization. Environment: Datadog workspace
Record the workspace checksum required by the OpenFeature SDK update. Environment: Datadog workspace
There was a problem hiding this comment.
Pull request overview
This PR adds an agentless EVP delivery fallback for the OpenFeature provider so exposure and flag-evaluation events can still be delivered when the local Agent EVP proxy is unavailable or unsupported. It introduces lazy /info discovery to choose the best local EVP proxy version (v4 → v2) and falls back to direct intake using DD_API_KEY + a validated DD_SITE-derived host, with redirect refusal for credential safety.
Changes:
- Implement agentless EVP route discovery and routing (local v4/v2 → direct intake fallback) with redirect refusal and site validation.
- Switch exposure + flagevaluation endpoints to direct-intake paths and let routing prepend the selected EVP proxy base when using the Agent.
- Add focused tests for route selection, headers, redirects, error/fallback behavior, and concurrency; update docs and bump OpenFeature Go SDK to v1.17.2.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| openfeature/provider.go | Constructs agentless EVP client for agentless configuration source. |
| openfeature/integration_test.go | Updates end-to-end tests to expect EVP proxy base-path + direct endpoint join behavior. |
| openfeature/flageval_logging.go | Switches flagevaluation endpoint constant to direct-intake path. |
| openfeature/flageval_logging_test.go | Updates endpoint expectations and EVP proxy path joining in tests. |
| openfeature/exposure.go | Switches exposure endpoint constant to direct-intake path. |
| openfeature/evp.go | Adds route discovery, local/direct routing, redirect refusal, site validation, and error-based fallback logic. |
| openfeature/evp_test.go | Adds unit tests for routing, headers, redirects, failure matrix, and concurrency. |
| openfeature/doc.go | Documents EVP discovery/fallback behavior and Agent address env vars used for discovery. |
| go.mod | Bumps github.com/open-feature/go-sdk to v1.17.2. |
| go.sum | Updates sums for OpenFeature Go SDK bump. |
| go.work.sum | Updates workspace sums (includes an additional go.mod checksum entry). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| func newDatadogProviderWithSource(config ProviderConfig, source internalffe.Source) *DatadogProvider { | ||
| evp := newEVPClient() | ||
| if source == internalffe.SourceAgentless { | ||
| evp = newAgentlessEVPClient(internalffe.ResolveSettings(internalconfig.Get())) | ||
| } |
Motivation
FFL-1485
Go agentless Feature Flags must deliver exposure and flagevaluation events when the local Agent EVP proxy is unavailable.
Changes
/api/v2/exposuresand/api/v2/flagevaluation./evp_proxy/v4, then/evp_proxy/v2, then authenticated direct intake.DD_SITEas bounded ASCII DNS labels before constructing the direct intake host.DD-API-KEY.Decisions
X-Datadog-EVP-Subdomain; direct requests sendDD-API-KEY.https://event-platform-intake.<site>:443.Validation
Local SDK validation:
go test ./openfeaturego test -race ./openfeaturego test ./openfeature -run '^TestEndToEnd_(ConfigurationUpdate|TrafficSharding)$' -count=100GOTOOLCHAIN=go1.26.4 go test ./openfeature -run '^TestEndToEnd_(ConfigurationUpdate|TrafficSharding)$' -count=100GOOS=windows GOARCH=amd64 GOTOOLCHAIN=go1.26.4 go test -c ./openfeaturego mod tidy -diff./bin/golangci-lint run ./openfeature(0 issues)gofmtandgit diff --checkThe Go system tests are defined and enabled in DataDog/system-tests#7604.
Ran the system-test stack against the locally built Go branch artifact in these scenarios:
FEATURE_FLAGGING_AND_EXPERIMENTATION: exposure and flag-evaluation egressFEATURE_FLAGGING_AND_EXPERIMENTATION_AGENTLESS_DIRECT: exposure and flag-evaluation egressFEATURE_FLAGGING_AND_EXPERIMENTATION_AGENTLESS_SERVERLESS: exposure and flag-evaluation egressIn each topology, both egress tests completed successfully. They verified the selected route, direct-intake host, response status and API-key header where applicable, aggregate evaluation counts, and zero events on the unused route.