feat(feature-flags): add agentless configuration keys, settings, and endpoint derivation - #9040
Conversation
BenchmarksBenchmark execution time: 2026-08-27 07:29:10 Comparing candidate commit b3f5318 in PR branch Found 1 performance improvements and 0 performance regressions! Performance is the same for 71 metrics, 0 unstable metrics, 67 known flaky benchmarks, 59 flaky benchmarks without significant changes.
|
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (9040) and master. ✅ No regressions detected |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ac79e9b3c4
ℹ️ 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".
This comment has been minimized.
This comment has been minimized.
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (9040) and master.
|
|||||||||||||||||||||||||||||||||||
| Metric | Master (Mean ± 95% CI) | Current (Mean ± 95% CI) | Change | Status |
|---|---|---|---|---|
| .NET Framework 4.8 - Baseline | ||||
| duration | 190.35 ± (190.91 - 191.69) ms | 212.09 ± (212.06 - 212.91) ms | +11.4% | ❌⬆️ |
| .NET Framework 4.8 - Bailout | ||||
| duration | 194.19 ± (194.09 - 194.56) ms | 218.74 ± (218.21 - 219.21) ms | +12.6% | ❌⬆️ |
| .NET Framework 4.8 - CallTarget+Inlining+NGEN | ||||
| duration | 1151.33 ± (1150.44 - 1155.97) ms | 1259.84 ± (1259.66 - 1265.99) ms | +9.4% | ❌⬆️ |
leoromanovsky
left a comment
There was a problem hiding this comment.
functionality looks in-sync with other implementations 👍
92546cd to
ada921d
Compare
andrewlock
left a comment
There was a problem hiding this comment.
Thanks - there's unfortunately still an issue with env which annoyingly may mean we need to redesign this whole thing again 🤦♂️
…o.khrebto/EX-2703/ffe-config-and-endpoint
…o.khrebto/EX-2703/ffe-config-and-endpoint
… the other tracers
…o.khrebto/EX-2703/ffe-config-and-endpoint
## Summary of changes Adds the agentless delivery mechanism: a `UfcConfigurationParser` that validates the JSON:API envelope returned by the CDN endpoint, and an `AgentlessConfigurationSource` HTTP poller with retries, ETag caching, gzip decompression, and shutdown safety. This is PR 2 of a stacked PR series implementing agentless Feature Flags configuration delivery (FFL-2703), porting functionality from [dd-trace-py#19331](DataDog/dd-trace-py#19331) and [dd-trace-java#11892](DataDog/dd-trace-java#11892). Stacked on [PR 1 #9040](#9040). ## Reason for change PR 1 added the configuration layer (settings, endpoint derivation). This PR adds the actual HTTP delivery mechanism that polls the CDN endpoint for UFC flag configuration. It is self-contained: the poller and parser are fully testable in isolation and are not yet wired to the `FeatureFlagsModule` (that happens in PR 3). ## Implementation details - **`UfcConfigurationParser`** — validates the JSON:API Universal Flag Configuration response envelope, extracts `data.attributes` into `ServerConfiguration`. Rejects raw UFC documents (without the JSON:API wrapper) so all delivery sources agree on one wire format. Returns descriptive errors; never throws. - **`AgentlessConfigurationSource`** — HTTP poller with: - Fixed-delay polling (no overlap) - In-tick retries (max 3) for 408/429/5xx/network failures, with jittered backoff derived from the poll interval (`clamp(P/6, 2s, 10s)` then `clamp(P/3, 5s, 30s)`) - ETag / `If-None-Match` conditional polling; ETag advances only after parse + apply succeed - Gzip decompression (neither transport decompresses automatically) - Self-tracing suppression (`x-datadog-tracing-enabled: false` header) - API key sent only to managed (Datadog-derived) endpoints, never custom ones - Warn-once per failure category (authentication, http, request) to prevent log flooding - Shutdown safety: `CancellationTokenSource` cancels the loop; shutdown checks after request and before `ApplyAsync` prevent use-after-dispose - `Create()` factory returns `null` when endpoint can'"'t be built or API key is missing - Idempotent `Start()` via `Interlocked.CompareExchange` ## Test coverage - **`UfcConfigurationParserTests`** (16 tests) — valid envelope parsing, malformed JSON rejection, invalid envelope rejection (wrong type, missing data, raw UFC), invalid attributes rejection (missing format/createdAt/environment/flags, wrong types), flag parsing - **`AgentlessConfigurationSourceTests`** (12 tests) — 200 success, ETag forwarding, 304/401/malformed handling, disposal before/after request, retry on 500 then success, max retries on 500, no retry on 400, gzip response, network error, idempotent start ## Other details <!-- Fixes #{issue} --> Stacked PRs: - PR 1 [#9040](#9040): Configuration keys, settings, and endpoint derivation - PR 2 (this): UFC parser and agentless HTTP poller - PR 3: Module wiring and OpenFeature activation - PR 4: Manual API activation <!--⚠️ Note: Where possible, please obtain 2 approvals prior to merging. Unless CODEOWNERS specifies otherwise, for external teams it is typically best to have one review from a team member, and one review from apm-dotnet. Trivial changes do not require 2 reviews. MergeQueue is NOT enabled in this repository. If you have write access to the repo, the PR has 1-2 approvals (see above), and all of the required checks have passed, you can use the Squash and Merge button to merge the PR. If you don't have write access, or you need help, reach out in the #apm-dotnet channel in Slack. --> System tests: [DataDog/system-tests#7496](DataDog/system-tests#7496)
Summary of changes
Adds the foundational configuration layer for agentless Feature Flags delivery: new configuration keys, a
FeatureFlagsSettingsclass with source resolution and validation, and anAgentlessEndpointstruct for deriving the CDN URL from the Datadog site or a custom base URL.This is PR 1 of a stacked PR series implementing agentless Feature Flags configuration delivery (FFL-2703), porting functionality from dd-trace-py#19331 and dd-trace-java#11892.
Reason for change
The .NET tracer currently delivers Feature Flags configuration exclusively through the Datadog Agent's Remote Configuration. To support agentless (CDN-backed) delivery, we need a configuration layer that:
agentless(new default),remote_config, anddisabledsourcesDD_SITEor accepts a customDD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_BASE_URLDD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLEDusers onto Remote ConfigurationImplementation details
FeatureFlagsSourceenum —Disabled,Agentless,RemoteConfigFeatureFlagsSettings— reads all new env vars, resolves the source with the cross-SDK precedence contract (kill switch → explicit source → fail-closed → legacy grandfathering → default agentless), validates poll interval (1–3600s) and request timeout (>0s)AgentlessEndpoint— deriveshttps://ufc-server.ff-cdn.<site>/api/v2/feature-flagging/config/rules-based/serverfrom the site, appendsdd_envwhen configured, accepts custom HTTP/HTTPS URLs, and never echoes URLs in error messages (credentials safety)supported-configurations.yaml+ generatedConfigurationKeys.FeatureFlags.g.cs:DD_FEATURE_FLAGS_ENABLED(defaulttrue, supersedesDD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED)DD_FEATURE_FLAGS_CONFIGURATION_SOURCE(defaultagentless)DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_BASE_URLDD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_POLL_INTERVAL_SECONDS(default 30, typeint)DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_REQUEST_TIMEOUT_SECONDS(default 5, typeint)DD_EXPERIMENTAL_FLAGGING_PROVIDER_INITIALIZATION_TIMEOUT_MS(default 10000, implementation B)[Obsolete]onFlaggingProviderEnabledwith pragma suppression inFeatureFlagsSettingsThis PR does not wire anything to
FeatureFlagsModuleyet — that happens in a later PR in the stack.Test coverage
FeatureFlagsSettingsTests— 43 test cases covering source resolution (kill switch, explicit source, legacy grandfathering,offlinesentinel, invalid values), blank/whitespace handling, casing normalization, defaults, poll interval validation, request timeout validation, initialization timeout, and base URL readingAgentlessEndpointTests— 18 test cases covering managed endpoint derivation (site lowercasing, staging, govcloud),dd_envquery parameter (addition, null, escaping), custom endpoint path handling (origin-only gets canonical path, custom path used verbatim), HTTP acceptance for custom endpoints, invalid URL rejection, empty/whitespace site rejection, and credentials-in-error safetyOther details
Stacked PRs:
System tests: DataDog/system-tests#7496