[FeatureFlags] Wait for OpenFeature initial config - #8754
leoromanovsky wants to merge 2 commits into
Conversation
This comment has been minimized.
This comment has been minimized.
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8754) and master. ✅ No regressions detected - check the details below Full Metrics ComparisonFakeDbCommand
HttpMessageHandler
Comparison explanationExecution-time benchmarks measure the whole time it takes to execute a program, and are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are highlighted in **red**. The following thresholds were used for comparing the execution times:
Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard. Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph). Duration chartsFakeDbCommand (.NET Framework 4.8)gantt
title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8754) - mean (75ms) : 70, 80
master - mean (75ms) : 70, 80
section Bailout
This PR (8754) - mean (77ms) : 75, 79
master - mean (78ms) : 75, 81
section CallTarget+Inlining+NGEN
This PR (8754) - mean (1,111ms) : 1041, 1181
master - mean (1,114ms) : 1043, 1185
FakeDbCommand (.NET Core 3.1)gantt
title Execution time (ms) FakeDbCommand (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8754) - mean (112ms) : 109, 116
master - mean (114ms) : 110, 118
section Bailout
This PR (8754) - mean (113ms) : 111, 115
master - mean (116ms) : 112, 119
section CallTarget+Inlining+NGEN
This PR (8754) - mean (790ms) : 769, 810
master - mean (799ms) : 777, 821
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8754) - mean (100ms) : 96, 104
master - mean (101ms) : 97, 105
section Bailout
This PR (8754) - mean (104ms) : 98, 110
master - mean (104ms) : 98, 111
section CallTarget+Inlining+NGEN
This PR (8754) - mean (951ms) : 907, 995
master - mean (949ms) : 911, 986
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8754) - mean (100ms) : 96, 103
master - mean (99ms) : 96, 103
section Bailout
This PR (8754) - mean (100ms) : 97, 102
master - mean (99ms) : 98, 101
section CallTarget+Inlining+NGEN
This PR (8754) - mean (827ms) : 787, 867
master - mean (824ms) : 786, 862
HttpMessageHandler (.NET Framework 4.8)gantt
title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8754) - mean (200ms) : 193, 206
master - mean (200ms) : 194, 206
section Bailout
This PR (8754) - mean (201ms) : 195, 208
master - mean (202ms) : 198, 206
section CallTarget+Inlining+NGEN
This PR (8754) - mean (1,205ms) : 1165, 1246
master - mean (1,205ms) : 1159, 1251
HttpMessageHandler (.NET Core 3.1)gantt
title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8754) - mean (287ms) : 280, 293
master - mean (286ms) : 279, 293
section Bailout
This PR (8754) - mean (287ms) : 280, 294
master - mean (287ms) : 280, 294
section CallTarget+Inlining+NGEN
This PR (8754) - mean (962ms) : 941, 982
master - mean (967ms) : 943, 992
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8754) - mean (279ms) : 273, 285
master - mean (280ms) : 273, 287
section Bailout
This PR (8754) - mean (277ms) : 272, 283
master - mean (280ms) : 274, 286
section CallTarget+Inlining+NGEN
This PR (8754) - mean (1,162ms) : 1115, 1209
master - mean (1,165ms) : 1126, 1203
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8754) - mean (277ms) : 271, 282
master - mean (277ms) : 269, 285
section Bailout
This PR (8754) - mean (278ms) : 273, 283
master - mean (278ms) : 270, 285
section CallTarget+Inlining+NGEN
This PR (8754) - mean (1,040ms) : 996, 1085
master - mean (1,039ms) : 997, 1081
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BenchmarksBenchmark execution time: 2026-06-04 20:32:12 Comparing candidate commit 3389719 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 72 metrics, 0 unstable metrics, 62 known flaky benchmarks, 64 flaky benchmarks without significant changes.
|
| internal static CallTargetReturn<bool> OnMethodEnd<TTarget>(bool returnValue, Exception? exception, in CallTargetState state) | ||
| { | ||
| var featureFlags = TracerManager.Instance.FeatureFlags; | ||
| return new CallTargetReturn<bool>(featureFlags is null || featureFlags.IsReady()); |
There was a problem hiding this comment.
This should be
return new CallTargetReturn<bool>(featureFlags?.IsReady() :: false);
|
|
||
| internal bool IsReady() | ||
| { | ||
| return !_isRemoteConfigurationAvailable || Volatile.Read(ref _evaluator) is not null; |
There was a problem hiding this comment.
This should be
return _isRemoteConfigurationAvailable && Volatile.Read(ref _evaluator) is not null;
|
closing in favor of #9264 |
Motivation
FFL-2468 captures a customer-visible startup race in the .NET OpenFeature provider.
await SetProviderAsync(new DatadogProvider())could report the provider as ready before the first FFE Remote Config payload had installed an evaluator, so an immediate flag evaluation returnedPROVIDER_NOT_READY. This madeDD_TRACE_DEBUG=trueappear necessary because debug logging slowed startup enough for Remote Config to arrive first.Changes
This adds an OpenFeature readiness shim and calltarget hook so the provider can ask the tracer whether Feature Flags are ready.
DatadogProvider.InitializeAsyncnow waits for the initial usable FFE configuration before completing provider initialization. If that first configuration never arrives, initialization fails after 30 seconds with a provider-not-ready timeout instead of completing as ready or blocking forever.The Feature Flags module now exposes readiness based on whether an evaluator has been installed, replays the config callback if the evaluator already exists when the handler is registered, and avoids blocking provider initialization when Remote Config is explicitly unavailable. Later Remote Config updates still flow through the existing configuration-change callback path.
Decisions
The fix treats an awaited
SetProviderAsync(...)as a readiness contract because the OpenFeature SDK documents the returned task as waiting for provider setup and initialization to complete. A caller that intentionally does not await the task can still run async startup, but once the task completes successfully, Datadog should not immediately returnPROVIDER_NOT_READYbecause the initial FFE config has not been applied yet.The timeout is bounded at the provider layer rather than changing evaluation semantics. If there is no evaluator during evaluation, evaluations still report
PROVIDER_NOT_READY; the provider just no longer advertises readiness before the evaluator exists. Generated calltarget metadata was updated for the newIsReadyhook.Validation:
dotnet build tracer/src/Datadog.FeatureFlags.OpenFeature/Datadog.FeatureFlags.OpenFeature.csproj -c Releasedotnet build tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/Datadog.Trace.ClrProfiler.IntegrationTests.csproj -c Release -f net10.0git diff --checkNot run locally:
/shared/bin/monitoring-home; the integration test project build passes.