Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions hugo/config/_default/menus/main.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6743,6 +6743,11 @@ menu:
parent: feature_flags_concepts
identifier: feature_flags_concepts_flag_key_obfuscation
weight: 317
- name: Evaluation Telemetry Opt-Out
url: feature_flags/concepts/evaluation_telemetry_opt_out
parent: feature_flags_concepts
identifier: feature_flags_concepts_evaluation_telemetry_opt_out
weight: 318
- name: Permissions and Access Control
url: feature_flags/concepts/permissions
parent: feature_flags_concepts
Expand Down
54 changes: 54 additions & 0 deletions hugo/content/en/feature_flags/client/android.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,59 @@ OpenFeatureAPI.setEvaluationContext(

<div class="alert alert-info">OpenFeature attributes must use flat <code>Value</code> primitives such as <code>Value.String()</code>, <code>Value.Integer()</code>, <code>Value.Double()</code>, or <code>Value.Boolean()</code>. The targeting key should be consistent for the same user to help ensure consistent flag evaluation across sessions. For anonymous users, use a persistent UUID stored, for example, in <code>SharedPreferences</code>.</div>

## Per-subject evaluation telemetry opt-out

After initializing Datadog and enabling Flags, enable the control when you first create the client. See [availability and shared behavior][4].

### Provider integration

Pass your application's decision as `Value.Boolean`, not a string:

{{< code-block lang="kotlin" >}}
import com.datadog.android.flags.FlagsClient
import com.datadog.android.flags.openfeature.asOpenFeatureProvider
import dev.openfeature.kotlin.sdk.ImmutableContext
import dev.openfeature.kotlin.sdk.OpenFeatureAPI
import dev.openfeature.kotlin.sdk.Value

val provider = FlagsClient.Builder()
.enableEvaluationTelemetryOptOutParameter(true)
.build()
.asOpenFeatureProvider()

val optedOut = true // Your application determines this value.
val initialContext = ImmutableContext(
targetingKey = "user-123",
attributes = mapOf("dd_evaluation_telemetry_opt_out" to Value.Boolean(optedOut))
)
OpenFeatureAPI.setProviderAndWait(provider, initialContext = initialContext)

val enabled = OpenFeatureAPI.getClient().getBooleanValue("new-checkout", false)
{{< /code-block >}}

Use `OpenFeatureAPI.setEvaluationContext()` to update the subject's decision.

### Direct client integration

The native client has string-valued context attributes. Use its typed setter to control telemetry:

{{< code-block lang="kotlin" >}}
import com.datadog.android.flags.FlagsClient
import com.datadog.android.flags.model.EvaluationContext
import com.datadog.android.flags.setEvaluationTelemetryOptOut

val client = FlagsClient.Builder()
.enableEvaluationTelemetryOptOutParameter(true)
.build()

val optedOut = true // Your application determines this value.
client.setEvaluationTelemetryOptOut(optedOut)
client.setEvaluationContext(EvaluationContext(targetingKey = "user-123"))
val enabled = client.getBooleanValue("new-checkout", false)
{{< /code-block >}}

A string `"true"` in the native context does not activate opt-out. Update the typed setter when the subject or preference changes. Reusing an existing client name retains its original configuration.

## Evaluate flags

After setting up your provider and evaluation context, you can read flag values throughout your app. Flag evaluation is _local and instantaneous_—the SDK uses locally cached data, so no network requests occur when evaluating flags. This makes evaluations safe to perform on the main thread.
Expand Down Expand Up @@ -602,3 +655,4 @@ class CheckoutFlagsTest {
[1]: https://openfeature.dev/
[2]: /account_management/api-app-keys/#client-tokens
[3]: https://github.com/open-feature/kotlin-sdk/pull/226
[4]: /feature_flags/concepts/evaluation_telemetry_opt_out/
60 changes: 60 additions & 0 deletions hugo/content/en/feature_flags/client/flutter.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,66 @@ print(details.error?.code);

`FlagDetails.error` is set when the SDK returns the default value because the provider is not ready, the flag is not found, or the assignment value does not match the typed evaluation method. Successful details include the evaluated value plus assignment metadata, such as `variant` and `reason`, when Datadog returned it.

## Per-subject evaluation telemetry opt-out

Enable the control in `DatadogFlagsConfiguration` before initializing the SDK. See [availability and shared behavior][20].

### Flutter plugin

Use this plugin configuration instead of the `addPlugin` call in the SDK initialization example. Do not register the plugin twice:

{{< code-block lang="dart" >}}
configuration.addPlugin(
const DatadogFlagsPluginConfiguration(
flagsConfiguration: DatadogFlagsConfiguration(
enableEvaluationTelemetryOptOutParameter: true,
),
),
);
await DatadogSdk.instance.initialize(configuration, TrackingConsent.granted);

final client = DatadogSdk.instance.flags!.sharedClient();
final optedOut = true; // Your application determines this value.
await client.initialize(FlagsEvaluationContext(
targetingKey: 'user-123',
attributes: {'dd_evaluation_telemetry_opt_out': optedOut},
));

final enabled = client.getBooleanDetails(
key: 'new-checkout',
defaultValue: false,
).value;
{{< /code-block >}}

### Standalone package

For the `datadog_flags` package without the Flutter plugin, pass the same option when enabling Flags:

{{< code-block lang="dart" >}}
await DatadogFlags.instance.enable(
configuration: DatadogFlagsConfiguration(
datadogConfig: datadogConfig,
enableEvaluationTelemetryOptOutParameter: true,
),
);

final client = DatadogFlags.instance.sharedClient();
final optedOut = true; // Your application determines this value.
await client.initialize(FlagsEvaluationContext(
targetingKey: 'user-123',
attributes: {'dd_evaluation_telemetry_opt_out': optedOut},
));

final enabled = client.getBooleanDetails(
key: 'new-checkout',
defaultValue: false,
).value;
{{< /code-block >}}

In both integrations, update the decision with `client.initialize()` and the complete subject context. Keep the initialization error handling described in the setup instructions.

[20]: /feature_flags/concepts/evaluation_telemetry_opt_out/

## Advanced configuration

`DatadogFlagsConfiguration` controls SDK behavior:
Expand Down
53 changes: 53 additions & 0 deletions hugo/content/en/feature_flags/client/ios.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,58 @@ final class FeatureFlagEventObserver {
}
{{< /code-block >}}

## Per-subject evaluation telemetry opt-out

After initializing Datadog and enabling Flags, enable the control when you first create the client or provider. See [availability and shared behavior][3].

### Native client

Pass your application's decision as a typed Boolean in the context:

{{< code-block lang="swift" >}}
import DatadogFlags

let client = FlagsClient.create(
configuration: .init(enableEvaluationTelemetryOptOutParameter: true)
)
let optedOut = true // Your application determines this value.
client.setEvaluationContext(
FlagsEvaluationContext(
targetingKey: "user-123",
attributes: ["dd_evaluation_telemetry_opt_out": .bool(optedOut)]
)
)

let enabled = client.getBooleanValue(key: "new-checkout", defaultValue: false)
{{< /code-block >}}

### Provider integration

Enable the option on `DatadogProvider` and supply the initial context:

{{< code-block lang="swift" >}}
import DatadogOpenFeatureProvider
import OpenFeature

let provider = DatadogProvider(enableEvaluationTelemetryOptOutParameter: true)
let optedOut = true // Your application determines this value.
let context = MutableContext(
targetingKey: "user-123",
structure: MutableStructure(attributes: [
"dd_evaluation_telemetry_opt_out": .boolean(optedOut)
])
)
await OpenFeatureAPI.shared.setProviderAndWait(
provider: provider,
initialContext: context
)

let enabled = OpenFeatureAPI.shared.getClient()
.getBooleanValue(key: "new-checkout", defaultValue: false)
{{< /code-block >}}

Update the context with `setEvaluationContext` for the native client or `setEvaluationContextAndWait` for OpenFeature. Reusing an existing client name retains its original configuration.

## Advanced configuration

The `Flags.enable()` API accepts optional configuration with options listed below.
Expand Down Expand Up @@ -563,3 +615,4 @@ final class CheckoutFlagTests: XCTestCase {
{{< partial name="whats-next/whats-next.html" >}}

[2]: /account_management/api-app-keys/#client-tokens
[3]: /feature_flags/concepts/evaluation_telemetry_opt_out/
26 changes: 26 additions & 0 deletions hugo/content/en/feature_flags/client/javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,31 @@ await OpenFeature.setProviderAndWait(provider, evaluationContext);

Most applications run several asynchronous tasks at startup, such as fetching data from another service or loading configuration. This example shows only feature flag initialization. As a best practice, start all of your startup promises together and await them as a group (for example, with `Promise.all`) right before the results are needed, rather than awaiting each one sequentially. This keeps total startup time close to the slowest task instead of the sum of all of them.

## Per-subject evaluation telemetry opt-out

Enable the control when you create the provider. Pass your application's decision as a Boolean in the evaluation context. See [availability and shared behavior][7].

{{< code-block lang="javascript" >}}
import { DatadogProvider } from '@datadog/openfeature-browser';
import { OpenFeature } from '@openfeature/web-sdk';

const provider = new DatadogProvider({
clientToken: '<CLIENT_TOKEN>',
env: '<ENV_NAME>',
enableEvaluationTelemetryOptOutParameter: true,
});

const optedOut = true; // Your application determines this value.
await OpenFeature.setProviderAndWait(provider, {
targetingKey: 'user-123',
dd_evaluation_telemetry_opt_out: optedOut,
});

const enabled = OpenFeature.getClient().getBooleanValue('new-checkout', false);
{{< /code-block >}}

Use `OpenFeature.setContext()` to update the decision. Keep the subject's targeting key and other required attributes. For application-managed configuration, enable the same option on `DatadogCoreProvider`; Datadog evaluation and RUM tracking hooks honor it. Exposure hooks remain enabled.

## Evaluate flags

After the provider is initialized, you can evaluate flags anywhere in your application. Flag evaluation is _local and instantaneous_—the SDK uses locally cached data, so no network requests occur when evaluating flags.
Expand Down Expand Up @@ -368,3 +393,4 @@ The Web SDK flag shape requires `variants`, `defaultVariant`, and `disabled`. Om
[4]: /feature_flags/implementation_patterns/browser_rules_based_evaluation/
[5]: /feature_flags/concepts/monthly_flag_configuration_requests/
[6]: /feature_flags/implementation_patterns/browser_rules_based_evaluation/#getting-started
[7]: /feature_flags/concepts/evaluation_telemetry_opt_out/
1 change: 1 addition & 0 deletions hugo/content/en/feature_flags/concepts/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Learn how Datadog Feature Flags work and how to configure flags, environments, t
{{< nextlink href="/feature_flags/concepts/environments" >}}Environments{{< /nextlink >}}
{{< nextlink href="/feature_flags/concepts/variants_and_flag_types" >}}Variants and Flag Types{{< /nextlink >}}
{{< nextlink href="/feature_flags/concepts/evaluation_context" >}}Evaluation Context{{< /nextlink >}}
{{< nextlink href="/feature_flags/concepts/evaluation_telemetry_opt_out" >}}Per-Subject Evaluation Telemetry Opt-Out{{< /nextlink >}}
{{< nextlink href="/feature_flags/concepts/evaluation_results" >}}Flag Evaluation Results{{< /nextlink >}}
{{< nextlink href="/feature_flags/concepts/targeting_rules" >}}Targeting Rules and Filters{{< /nextlink >}}
{{< nextlink href="/feature_flags/concepts/targeting_attributes" >}}Targeting Attributes{{< /nextlink >}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
title: Per-Subject Evaluation Telemetry Opt-Out
description: Suppress new feature flag evaluation telemetry for selected users or devices without changing flag results or experiment exposures.
---

## Overview

Per-subject evaluation telemetry opt-out lets your application exclude selected users or devices from feature flag monitoring data. A **subject** is the user, account, or device identified by the evaluation context's targeting key.

This control affects feature flag evaluation reporting, not internal Datadog SDK telemetry.

Your application determines who opts out. For example, combine a user's preference with your own eligibility rules. Pass the resulting Boolean to the SDK. You do not need to send the underlying personal information solely for this decision.

## Availability

The examples describe upcoming SDK support. The options are not yet available in released SDK versions.

| SDK | Configuration and evaluation example |
| --- | --- |
| Browser JavaScript | [Browser example][1] |
| iOS, including the Swift OpenFeature provider | [iOS examples][2] |
| Android | [Android examples][3] |
| Dart and Flutter | [Dart and Flutter examples][4] |
| Go | [Go example][5] |
| Java | [Java example][6] |
| Node.js | [Node.js example][7] |
| Python | [Python example][8] |
| Ruby | [Ruby example][9] |
| PHP OpenFeature provider | [PHP example][10] |
| .NET | [.NET example][11] |

## Enable the control

1. Enable per-subject opt-out when you create the provider or flags client. Support is disabled by default.
2. Set `dd_evaluation_telemetry_opt_out` to Boolean `true` in the subject's evaluation context before evaluating flags.
3. Evaluate flags with the same methods as before.

Use the exact attribute name in every language. Do not rename or capitalize it to match a language's naming conventions. Android's direct `FlagsClient` API uses a typed setter instead of its string-valued context; see the [Android example][3].

| Support enabled | Attribute value | New evaluation telemetry |
| --- | --- | --- |
| No | Any value | Existing behavior |
| Yes | Boolean `true` | Suppressed |
| Yes | Boolean `false` or missing | Existing behavior |
| Yes | String `"true"`, number, null, or another non-Boolean value | Existing behavior |

Existing telemetry settings still apply. An opt-out value of `false` does not enable a telemetry channel that you disabled elsewhere.

### Server environment variable

Enable support before the application starts:

{{< code-block lang="shell" >}}
export DD_FEATURE_FLAGS_EVALUATION_TELEMETRY_PER_SUBJECT_OPT_OUT_ENABLED=true
{{< /code-block >}}

Then create the provider without an explicit opt-out option. The provider reads this setting when it is created. An explicit provider option overrides the environment variable, including an explicit `false`. The default is `false`.

This setting enables the context parameter. It does not opt out every subject. For concurrent server requests, supply each subject's decision in the per-evaluation context, not a shared global context.

## What the control changes

When a subject opts out, the SDK suppresses new evaluation events, evaluation counts or metrics, and automatic flag annotations on traces or RUM views. The affected channels depend on which telemetry the SDK supports and your application enables. These evaluations do not contribute to the affected flag monitoring charts.

The control does not change:

- Flag values, targeting, or application defaults.
- Experiment participation or experiment exposure events.
- Unrelated application, trace, or RUM data.
- Custom OpenFeature hooks or manually added annotations.
- Events already queued or sent, or annotations already recorded.

The opt-out attribute remains available to targeting rules and normal exposure reporting. If you write a targeting rule against it, that rule can change assignments. Suppression itself does not change assignments.

This control is not a general consent system or a deletion mechanism. Assignment requests and exposure events can still contain subject data. Configure other SDK consent controls and experimentation eligibility separately when your policy requires them.

## Update a subject's decision

Your application owns the decision and updates it when the subject or preference changes. Client SDKs use the current evaluation context; server SDKs use the context supplied for each evaluation. Set Boolean `false` to resume normal evaluation telemetry for that subject.

For clients that fetch assignments, switching subjects can leave the previous subject's assignments active until the refresh succeeds. If that previous subject opted out, reporting stays suppressed while those assignments remain active. An allowed new subject does not override the previous subject's decision. Changing the decision for the same subject takes effect locally without waiting for the refresh.

Supply the decision before the first evaluation that must honor it. Keep the subject's targeting key and other required attributes when replacing a client context.

[1]: /feature_flags/client/javascript/#per-subject-evaluation-telemetry-opt-out
[2]: /feature_flags/client/ios/#per-subject-evaluation-telemetry-opt-out
[3]: /feature_flags/client/android/#per-subject-evaluation-telemetry-opt-out
[4]: /feature_flags/client/flutter/#per-subject-evaluation-telemetry-opt-out
[5]: /feature_flags/server/go/#per-subject-evaluation-telemetry-opt-out
[6]: /feature_flags/server/java/#per-subject-evaluation-telemetry-opt-out
[7]: /feature_flags/server/nodejs/#per-subject-evaluation-telemetry-opt-out
[8]: /feature_flags/server/python/#per-subject-evaluation-telemetry-opt-out
[9]: /feature_flags/server/ruby/#per-subject-evaluation-telemetry-opt-out
[10]: /feature_flags/server/php/#per-subject-evaluation-telemetry-opt-out
[11]: /feature_flags/server/dotnet/#per-subject-evaluation-telemetry-opt-out
28 changes: 28 additions & 0 deletions hugo/content/en/feature_flags/server/dotnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,33 @@ var evalCtx = EvaluationContext.Builder()

The targeting key is used for consistent traffic distribution (percentage rollouts). Additional attributes enable targeting rules, such as "enable for users in the US" or "enable for premium tier users" in the example above.

## Per-subject evaluation telemetry opt-out

Configure the provider once. Supply the subject's decision in each evaluation context, not a shared global context. See [availability and shared behavior][10].

{{< code-block lang="csharp" >}}
using Datadog.FeatureFlags.OpenFeature;
using OpenFeature;
using OpenFeature.Model;

var provider = new DatadogProvider(new DatadogProviderOptions
{
EnableEvaluationTelemetryOptOutParameter = true,
});
await Api.Instance.SetProviderAsync(provider);
var client = Api.Instance.GetClient();

// In a request handler:
var optedOut = true; // Your application determines this value for the subject.
var context = EvaluationContext.Builder()
.SetTargetingKey("user-123")
.Set("dd_evaluation_telemetry_opt_out", optedOut)
.Build();
var enabled = await client.GetBooleanValueAsync("new-checkout", false, context);
{{< /code-block >}}

Alternatively, set `DD_FEATURE_FLAGS_EVALUATION_TELEMETRY_PER_SUBJECT_OPT_OUT_ENABLED=true` and use `new DatadogProvider()`. An explicit option overrides the environment variable, including `false`.

## Evaluate flags

After setting up the provider and creating a client, you can evaluate flags throughout your application. Flag evaluation is local and fast—the SDK uses locally cached configuration data, so no network requests occur during evaluation.
Expand Down Expand Up @@ -403,6 +430,7 @@ var enabled = client.GetBooleanValueAsync("flag-key", false, context);
[7]: /feature_flags/concepts/flag_graphs/
[8]: /tracing/trace_collection/automatic_instrumentation/dd_libraries/dotnet-core/
[9]: /feature_flags/concepts/configuration_sources/
[10]: /feature_flags/concepts/evaluation_telemetry_opt_out/

## Further reading

Expand Down
Loading
Loading