-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Document client assignment request reliability #39560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
a1b96ad
030aba5
ea97412
b220ec9
783375e
added44
dec541c
526cfe1
324773a
c97477d
5e59f39
325c289
b802ff0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -40,8 +40,12 @@ val configuration = Configuration.Builder( | |||||||||
| .build() | ||||||||||
| Datadog.initialize(this, configuration, TrackingConsent.GRANTED) | ||||||||||
|
|
||||||||||
| // 3. Enable Feature Flags | ||||||||||
| Flags.enable() | ||||||||||
| // 3. Enable Feature Flags with a bounded assignment request timeout | ||||||||||
| Flags.enable( | ||||||||||
| FlagsConfiguration.Builder() | ||||||||||
| .assignmentRequestTimeout(1_500L) | ||||||||||
| .build() | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| // 4. Create and set up the OpenFeature provider | ||||||||||
| val provider = FlagsClient.Builder().build().asOpenFeatureProvider() | ||||||||||
|
|
@@ -98,8 +102,13 @@ After initializing Datadog, enable `Flags` to attach it to the current Datadog A | |||||||||
|
|
||||||||||
| {{< code-block lang="kotlin" >}} | ||||||||||
| import com.datadog.android.flags.Flags | ||||||||||
| import com.datadog.android.flags.FlagsConfiguration | ||||||||||
|
|
||||||||||
| val flagsConfiguration = FlagsConfiguration.Builder() | ||||||||||
| .assignmentRequestTimeout(1_500L) | ||||||||||
|
leoromanovsky marked this conversation as resolved.
|
||||||||||
| .build() | ||||||||||
|
|
||||||||||
| Flags.enable() | ||||||||||
| Flags.enable(flagsConfiguration) | ||||||||||
| {{< /code-block >}} | ||||||||||
|
|
||||||||||
| You can also pass a configuration object; see [Advanced configuration](#advanced-configuration). | ||||||||||
|
|
@@ -300,12 +309,47 @@ The `Flags.enable()` API accepts optional configuration with the options listed | |||||||||
|
|
||||||||||
| {{< code-block lang="kotlin" >}} | ||||||||||
| val config = FlagsConfiguration.Builder() | ||||||||||
| // configure options here | ||||||||||
| .assignmentRequestTimeout(1_500L) | ||||||||||
| .assignmentRequestRetryCount(2) | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
as I suggested here, I think it's nice to have this placeholder for the other options, to not imply these are the only ones |
||||||||||
| .build() | ||||||||||
|
|
||||||||||
| Flags.enable(config) | ||||||||||
| {{< /code-block >}} | ||||||||||
|
|
||||||||||
| `assignmentRequestTimeout(timeoutMs)` | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggesting to move this info above the settings it references
Suggested change
|
||||||||||
| : Timeout in milliseconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. Negative values are coerced to `0`. When the HTTP call already has a nonzero timeout, the shorter timeout applies. | ||||||||||
|
|
||||||||||
| `assignmentRequestRetryCount(retryCount)` | ||||||||||
| : Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Values outside the range from `0` to `10` are coerced to the nearest bound. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Canceled calls, HTTP 429, generic I/O errors, permanent protocol errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. The SDK reads `Retry-After` only for HTTP 503. A valid value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does it mean for values outside
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
think this info, previously below, makes sense to fold in here |
||||||||||
|
|
||||||||||
| The SDK manages the configured retry count and creates a new HTTP call for each attempt. The timeout applies to each attempt. Total network duration can reach `(retryCount + 1) * timeoutMs`, plus retry delays. When the timeout is `0`, the HTTP transport supplies the time bound and may allow an unlimited duration. | ||||||||||
|
|
||||||||||
| <div class="alert alert-info">Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.</div> | ||||||||||
|
|
||||||||||
| For lower-level transport control, supply an assignment-only OkHttp call factory. Add OkHttp as a direct application dependency when you use this option: | ||||||||||
|
|
||||||||||
| {{< code-block lang="groovy" filename="build.gradle" >}} | ||||||||||
| dependencies { | ||||||||||
| implementation "com.squareup.okhttp3:okhttp:4.12.0" | ||||||||||
| } | ||||||||||
| {{< /code-block >}} | ||||||||||
|
|
||||||||||
| {{< code-block lang="kotlin" >}} | ||||||||||
| import okhttp3.OkHttpClient | ||||||||||
|
|
||||||||||
| val assignmentClient = OkHttpClient.Builder() | ||||||||||
| // Add assignment-specific proxy, TLS, or interceptors here. | ||||||||||
| .build() | ||||||||||
|
|
||||||||||
| val config = FlagsConfiguration.Builder() | ||||||||||
| .assignmentRequestCallFactory(assignmentClient) | ||||||||||
| .assignmentRequestTimeout(1_500L) | ||||||||||
| .assignmentRequestRetryCount(2) | ||||||||||
| .build() | ||||||||||
| {{< /code-block >}} | ||||||||||
|
|
||||||||||
| The SDK still constructs the URL, method, body, and authentication headers. The scalar timeout and retry policies compose on top of calls created by the supplied factory. When the assignment timeout is positive, the factory must return calls that provide and honor a configurable `Call.timeout()`. A call that returns `Timeout.NONE` fails before execution. Exposure and evaluation uploads continue to use the SDK transport. The application retains ownership of the supplied factory and its resources. | ||||||||||
|
Comment on lines
+329
to
+351
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this content breaks up the Global configuration list and makes it difficult to follow—see the preview link to validate. I suggest moving it to its own section, placed after the list ends, titled "#### Supply a custom assignment transport" |
||||||||||
|
|
||||||||||
| `trackExposures()` | ||||||||||
| : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. If you only need local evaluation without telemetry, you can disable it with: `trackExposures(false)`. | ||||||||||
|
|
||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -86,7 +86,13 @@ final configuration = DatadogConfiguration( | |
| rumConfiguration: DatadogRumConfiguration( | ||
| applicationId: '<RUM_APPLICATION_ID>', | ||
| ), | ||
| )..addPlugin(const DatadogFlagsPluginConfiguration()); | ||
| )..addPlugin( | ||
| const DatadogFlagsPluginConfiguration( | ||
| flagsConfiguration: DatadogFlagsConfiguration( | ||
| assignmentRequestTimeout: Duration(milliseconds: 1500), | ||
|
leoromanovsky marked this conversation as resolved.
|
||
| ), | ||
| ), | ||
| ); | ||
|
|
||
| await DatadogSdk.instance.initialize(configuration, TrackingConsent.granted); | ||
| {{< /code-block >}} | ||
|
|
@@ -126,6 +132,7 @@ final datadogFlags = DatadogFlags.instance; | |
|
|
||
| await datadogFlags.enable( | ||
| configuration: DatadogFlagsConfiguration( | ||
| assignmentRequestTimeout: const Duration(milliseconds: 1500), | ||
| datadogConfig: const DatadogFlagsConfig( | ||
| clientToken: '<CLIENT_TOKEN>', | ||
| env: '<ENV_NAME>', | ||
|
|
@@ -289,13 +296,45 @@ print(details.error?.code); | |
| {{< code-block lang="dart" >}} | ||
| DatadogFlagsConfiguration( | ||
| datadogConfig: datadogConfig, | ||
| assignmentRequestTimeout: const Duration(milliseconds: 1500), | ||
| assignmentRequestRetryCount: 2, | ||
| trackExposures: true, | ||
| trackEvaluations: true, | ||
| evaluationFlushInterval: const Duration(seconds: 10), | ||
| store: myStore, | ||
| ); | ||
| {{< /code-block >}} | ||
|
|
||
| `assignmentRequestTimeout` | ||
| : Timeout for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive duration to enable the timeout; `Duration.zero` leaves it disabled. | ||
|
|
||
| `assignmentRequestRetryCount` | ||
| : Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, generic I/O errors, permanent protocol errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. | ||
|
|
||
| <div class="alert alert-info">Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.</div> | ||
|
|
||
| For lower-level transport control, compose an assignment-only HTTP client: | ||
|
|
||
| {{< code-block lang="dart" >}} | ||
| import 'package:datadog_flags/datadog_flags.dart'; | ||
| import 'package:http/http.dart' as http; | ||
|
leoromanovsky marked this conversation as resolved.
|
||
|
|
||
| final assignmentClient = withAssignmentRequestRetry( | ||
| withAssignmentRequestTimeout( | ||
| http.Client(), | ||
| const Duration(milliseconds: 1500), | ||
| ), | ||
| 2, | ||
| ); | ||
|
|
||
| final config = DatadogFlagsConfiguration( | ||
| datadogConfig: datadogConfig, | ||
| assignmentRequestHttpClient: assignmentClient, | ||
| ); | ||
| {{< /code-block >}} | ||
|
|
||
| A supplied `assignmentRequestHttpClient` is used verbatim and replaces the scalar timeout and retry settings. The helpers buffer the complete response, create a fresh request for each retry, and apply only to assignment requests. The application owns and closes the supplied client after disabling Feature Flags. | ||
|
|
||
|
Comment on lines
+314
to
+337
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same feedback as the android.md page (except the new header on this page should be an H3 instead of H4)—move the alert callout above the settings and the new content into a new "### Supply a custom assignment transport" section |
||
| `trackExposures` | ||
| : When `true` (default), the SDK records exposure events for successful evaluations whose assignments are marked for logging. Set to `false` to disable exposure tracking. | ||
|
|
||
|
|
@@ -326,6 +365,8 @@ final configuration = DatadogConfiguration( | |
| )..addPlugin( | ||
| const DatadogFlagsPluginConfiguration( | ||
| flagsConfiguration: DatadogFlagsConfiguration( | ||
| assignmentRequestTimeout: Duration(milliseconds: 1500), | ||
| assignmentRequestRetryCount: 2, | ||
| trackExposures: true, | ||
| trackEvaluations: true, | ||
| ), | ||
|
|
@@ -391,6 +432,7 @@ Future<void> initializeFlags() async { | |
|
|
||
| await datadogFlags.enable( | ||
| configuration: DatadogFlagsConfiguration( | ||
| assignmentRequestTimeout: const Duration(milliseconds: 1500), | ||
| datadogConfig: const DatadogFlagsConfig( | ||
| clientToken: '<CLIENT_TOKEN>', | ||
| env: '<ENV_NAME>', | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -99,7 +99,9 @@ After initializing Datadog, enable `Flags` to attach it to the current Datadog i | |||||||||
| {{< code-block lang="swift" >}} | ||||||||||
| import DatadogFlags | ||||||||||
|
|
||||||||||
| Flags.enable() | ||||||||||
| var flagsConfiguration = Flags.Configuration() | ||||||||||
| flagsConfiguration.assignmentRequestTimeout = 1.5 | ||||||||||
|
leoromanovsky marked this conversation as resolved.
|
||||||||||
| Flags.enable(with: flagsConfiguration) | ||||||||||
| {{< /code-block >}} | ||||||||||
|
|
||||||||||
| You can also pass a configuration object; see [Advanced configuration](#advanced-configuration). | ||||||||||
|
|
@@ -328,7 +330,9 @@ Datadog.initialize( | |||||||||
| trackingConsent: .granted | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| Flags.enable() | ||||||||||
| var flagsConfiguration = Flags.Configuration() | ||||||||||
| flagsConfiguration.assignmentRequestTimeout = 1.5 | ||||||||||
| Flags.enable(with: flagsConfiguration) | ||||||||||
|
|
||||||||||
| let context = MutableContext(targetingKey: "user-123") | ||||||||||
| let provider = DatadogProvider() | ||||||||||
|
|
@@ -444,9 +448,53 @@ The `Flags.enable()` API accepts optional configuration with options listed belo | |||||||||
|
|
||||||||||
| {{< code-block lang="swift" >}} | ||||||||||
| var config = Flags.Configuration() | ||||||||||
| config.assignmentRequestTimeout = 1.5 | ||||||||||
| config.assignmentRequestRetryCount = 2 | ||||||||||
| Flags.enable(with: config) | ||||||||||
| {{< /code-block >}} | ||||||||||
|
|
||||||||||
| `assignmentRequestTimeout` | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
moving callout from below |
||||||||||
| : Timeout in seconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive, finite value to enable the timeout. A value of `0`, a negative value, or a non-finite value disables it. Values greater than `2_147_483.647` seconds are reduced to this maximum. | ||||||||||
|
|
||||||||||
| `assignmentRequestRetryCount` | ||||||||||
| : Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Values outside the range from `0` to `10` are reduced to the nearest bound. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, unknown URL errors, permanent URL errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. The SDK reads `Retry-After` only for HTTP 503. A valid value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
moving the orphaned text below here |
||||||||||
|
|
||||||||||
| The scalar timeout applies to each attempt. Total duration includes all attempts and all retry delays. | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
suggesting to fold this in to the description above |
||||||||||
|
|
||||||||||
| <div class="alert alert-info">Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.</div> | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
moving this above |
||||||||||
|
|
||||||||||
| For lower-level transport control, compose an assignment-only fetch implementation: | ||||||||||
|
|
||||||||||
| {{< code-block lang="swift" >}} | ||||||||||
| let assignmentFetch = Flags.AssignmentRequestFetch | ||||||||||
| .urlSession() | ||||||||||
| .withTimeout(1.5) | ||||||||||
| .withRetry(2) | ||||||||||
|
|
||||||||||
| var config = Flags.Configuration() | ||||||||||
| config.assignmentRequestFetch = assignmentFetch | ||||||||||
| Flags.enable(with: config) | ||||||||||
| {{< /code-block >}} | ||||||||||
|
|
||||||||||
| The SDK still constructs the URL, body, authentication, and custom headers. A supplied `assignmentRequestFetch` replaces the scalar timeout and retry settings. The SDK accepts at most one completion from the supplied fetch for each request and validates the HTTP response status. The custom transport applies only to assignment requests. The caller retains ownership of a supplied `URLSession` and other custom transport resources. The SDK does not invalidate or close them. | ||||||||||
|
|
||||||||||
| `withTimeout(timeout)` | ||||||||||
| : Adds a timeout that includes the complete response-body download. A positive, finite value enables the timeout. A nonpositive or non-finite value leaves the transport unchanged. Values greater than `2_147_483.647` seconds are reduced to this maximum. | ||||||||||
|
|
||||||||||
| `withRetry(retryCount)` | ||||||||||
| : Adds SDK-managed retries after the initial attempt. Values outside the range from `0` to `10` are reduced to the nearest bound. The retry policy matches `assignmentRequestRetryCount`. The SDK reads `Retry-After` only for HTTP 503. | ||||||||||
|
|
||||||||||
| In the example, `withTimeout` is inside `withRetry`. Therefore, each attempt has its own 1.5-second timeout. Reverse the wrappers to use one 1.5-second timeout for the initial request and all retries: | ||||||||||
|
|
||||||||||
| {{< code-block lang="swift" >}} | ||||||||||
| let assignmentFetch = Flags.AssignmentRequestFetch | ||||||||||
| .urlSession() | ||||||||||
| .withRetry(2) | ||||||||||
| .withTimeout(1.5) | ||||||||||
| {{< /code-block >}} | ||||||||||
|
|
||||||||||
| With this reversed order, one timeout covers all attempts and retry delays. With the original order, total duration includes each attempt timeout and all retry delays. | ||||||||||
|
|
||||||||||
|
Comment on lines
+466
to
+497
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggesting to move this into a new H3 (titled ### Supply a custom assignment transport) after line 525 (customFlagsHeaders entry), before ## Testing (527) |
||||||||||
| `trackExposures` | ||||||||||
| : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. If you only need local evaluation without telemetry, you can disable this option. | ||||||||||
|
|
||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -53,7 +53,7 @@ Create a `DatadogProvider` instance with your Datadog credentials. For live Brow | |||||||||
| {{< site-region region="gov,gov2" >}}<div class="alert alert-danger">Browser Feature Flags are not supported for the selected <a href="/getting_started/site">Datadog site</a> ({{< region-param key="dd_site_name" >}}).</div>{{< /site-region >}} | ||||||||||
|
|
||||||||||
| ```javascript | ||||||||||
| import { DatadogProvider } from '@datadog/openfeature-browser'; | ||||||||||
| import { DatadogProvider, withTimeout } from '@datadog/openfeature-browser'; | ||||||||||
| import { OpenFeature } from '@openfeature/web-sdk'; | ||||||||||
|
|
||||||||||
| const provider = new DatadogProvider({ | ||||||||||
|
|
@@ -65,6 +65,7 @@ const provider = new DatadogProvider({ | |||||||||
| clientToken: '<CLIENT_TOKEN>', | ||||||||||
| site: '{{< region-param key="dd_site" code="true" >}}', | ||||||||||
| env: '<ENV_NAME>', | ||||||||||
| flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500), | ||||||||||
| }); | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
|
|
@@ -170,7 +171,7 @@ console.log(details.errorCode); // Error code, if evaluation failed | |||||||||
| Here's a complete example showing how to set up and use Datadog Feature Flags in a JavaScript application: | ||||||||||
|
|
||||||||||
| ```javascript | ||||||||||
| import { DatadogProvider } from '@datadog/openfeature-browser'; | ||||||||||
| import { DatadogProvider, withTimeout } from '@datadog/openfeature-browser'; | ||||||||||
| import { OpenFeature } from '@openfeature/web-sdk'; | ||||||||||
|
|
||||||||||
| // Initialize the Datadog provider | ||||||||||
|
|
@@ -179,6 +180,7 @@ const provider = new DatadogProvider({ | |||||||||
| clientToken: '<CLIENT_TOKEN>', | ||||||||||
| site: '{{< region-param key="dd_site" code="true" >}}', | ||||||||||
| env: '<ENV_NAME>', | ||||||||||
| flagConfigurationFetch: withTimeout(globalThis.fetch, 1_500), | ||||||||||
| }); | ||||||||||
|
|
||||||||||
| // Set the evaluation context | ||||||||||
|
|
@@ -226,6 +228,30 @@ The web provider also supports these optional settings: | |||||||||
| | `flaggingProxy` | unset | Fetch flags through a proxy instead of `site`. | | ||||||||||
| | `customHeaders` | unset | Add headers to flag-fetch requests. | | ||||||||||
| | `overwriteRequestHeaders` | `false` | Replace default request headers with `customHeaders`. | | ||||||||||
| | `flagConfigurationFetch` | `globalThis.fetch` | Provide a Fetch-compatible implementation for flag configuration requests. | | ||||||||||
|
|
||||||||||
| ### Bound flag configuration requests | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| The browser provider does not add a timeout or retries by default. Use `withTimeout` and `withRetry` to bound each request attempt and retry transient failures: | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
suggesting moving alert from below up here. also updating "bound" to "limit" |
||||||||||
|
|
||||||||||
| {{< code-block lang="javascript" >}} | ||||||||||
| import { DatadogProvider, withRetry, withTimeout } from '@datadog/openfeature-browser'; | ||||||||||
|
|
||||||||||
| const provider = new DatadogProvider({ | ||||||||||
| // Other provider options... | ||||||||||
| flagConfigurationFetch: withRetry(withTimeout(globalThis.fetch, 1_500), 2), | ||||||||||
| }); | ||||||||||
| {{< /code-block >}} | ||||||||||
|
|
||||||||||
| `withTimeout(fetch, timeoutMs)` | ||||||||||
| : Sets the timeout in milliseconds for each request attempt, including the complete response-body download. Set the timeout to `0` to disable the timer. Accepted values are non-negative integers up to `2_147_483_647`. | ||||||||||
|
|
||||||||||
| `withRetry(fetch, retryCount)` | ||||||||||
| : Sets the number of retries after the initial request. Set the retry count to `0` to disable retries. Accepted values are integers from `0` to `10`. Retries cover Fetch `TypeError` failures, timeout errors, HTTP 408, and HTTP 5xx responses. Caller cancellation and HTTP 429 responses are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. Browsers report network, CORS, and CSP failures as `TypeError`, so the wrapper cannot separate these causes. | ||||||||||
|
|
||||||||||
| In the example, `withTimeout` is inside `withRetry`. Therefore, each attempt has its own 1,500-millisecond timeout. | ||||||||||
|
|
||||||||||
| <div class="alert alert-info">The `flagConfigurationFetch` option applies only to flag configuration requests. It does not affect exposure, aggregated flag evaluation, or RUM telemetry requests.</div> | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
suggesting moving this above |
||||||||||
|
|
||||||||||
| ## Override flags in your browser | ||||||||||
|
|
||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,7 +52,9 @@ After initializing Datadog, enable `Flags` to attach it to the current Datadog U | |
| {{< code-block lang="csharp" >}} | ||
| using Datadog.Unity.Flags; | ||
|
|
||
| DdFlags.Enable(); | ||
| DdFlags.Enable(new FlagsConfiguration( | ||
| assignmentRequestTimeoutSeconds: 1, | ||
|
leoromanovsky marked this conversation as resolved.
|
||
| assignmentRequestRetryCount: 0)); | ||
| {{< /code-block >}} | ||
|
|
||
| You can also pass a configuration object; see [Advanced configuration](#advanced-configuration). | ||
|
|
@@ -203,12 +205,35 @@ The `DdFlags.Enable()` API accepts optional configuration with options listed be | |
|
|
||
| {{< code-block lang="csharp" >}} | ||
| DdFlags.Enable(new FlagsConfiguration( | ||
| assignmentRequestTimeoutSeconds: 1, | ||
| assignmentRequestRetryCount: 2, | ||
| trackExposures: true, | ||
| trackEvaluations: true, | ||
| evaluationFlushIntervalSeconds: 10.0f | ||
| )); | ||
| {{< /code-block >}} | ||
|
|
||
| `assignmentRequestTimeoutSeconds` | ||
| : Timeout in seconds for each flag assignment request, including the complete response-body download. The SDK does not add a timeout by default. Set a positive value to enable the timeout; `0` leaves it disabled. | ||
|
|
||
| `assignmentRequestRetryCount` | ||
| : Number of retries after the initial flag assignment request. The default is `0`, so the SDK makes only the initial request unless you opt in to retries. Accepted values are from `0` to `10`. Retries cover selected transient network errors, timeouts, HTTP 408, and HTTP 5xx responses. Cancellation, HTTP 429, generic I/O errors, permanent protocol errors, and TLS failures are not retried. Retries use randomized exponential backoff capped at 30 seconds. For HTTP 503, a valid `Retry-After` value up to 30 seconds is a minimum delay before the backoff. A response that requests a longer delay is not retried. | ||
|
|
||
| <div class="alert alert-info">Assignment request timeout and retry settings apply only to requests that fetch flag assignments. They do not affect exposure, aggregated flag evaluation, or RUM telemetry requests.</div> | ||
|
|
||
| For lower-level transport control, compose an assignment-only transport: | ||
|
|
||
| {{< code-block lang="csharp" >}} | ||
| var assignmentTransport = AssignmentRequestTransports.Default | ||
| .WithTimeout(1) | ||
| .WithRetry(2); | ||
|
|
||
| DdFlags.Enable(new FlagsConfiguration( | ||
| assignmentRequestTransport: assignmentTransport)); | ||
| {{< /code-block >}} | ||
|
|
||
| A supplied `assignmentRequestTransport` is used verbatim and replaces the scalar timeout and retry settings. The helpers use fully buffered immutable responses, create a fresh native request for each retry, and apply only to assignment requests. The SDK owns its native requests; the application retains ownership of a custom transport and its resources. | ||
|
|
||
|
Comment on lines
+222
to
+236
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same feedback as the android.md page (except the new header on this page should be an H3 instead of H4)—move the alert callout above the settings and the new content into a new "### Supply a custom assignment transport" section |
||
| `trackExposures` | ||
| : When `true` (default), the SDK automatically records an _exposure event_ when a flag is evaluated. These events contain metadata about which flag was accessed, which variant was served, and under what context. They are sent to Datadog so you can later analyze feature adoption. Set to `false` to disable exposure tracking. | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.