From beb1f63367fb7ba5c040d428b343a04feb8d2d4b Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Mon, 8 Dec 2025 15:04:15 -0500 Subject: [PATCH 01/18] add ffe server sdk landing page and stubs for each language --- .../en/feature_flags/setup/server/_index.md | 140 ++++++++++++++++++ content/en/feature_flags/setup/server/go.md | 25 ++++ content/en/feature_flags/setup/server/java.md | 25 ++++ .../en/feature_flags/setup/server/nodejs.md | 25 ++++ .../en/feature_flags/setup/server/python.md | 25 ++++ content/en/feature_flags/setup/server/ruby.md | 25 ++++ 6 files changed, 265 insertions(+) create mode 100644 content/en/feature_flags/setup/server/_index.md create mode 100644 content/en/feature_flags/setup/server/go.md create mode 100644 content/en/feature_flags/setup/server/java.md create mode 100644 content/en/feature_flags/setup/server/nodejs.md create mode 100644 content/en/feature_flags/setup/server/python.md create mode 100644 content/en/feature_flags/setup/server/ruby.md diff --git a/content/en/feature_flags/setup/server/_index.md b/content/en/feature_flags/setup/server/_index.md new file mode 100644 index 00000000000..a2adf6045a4 --- /dev/null +++ b/content/en/feature_flags/setup/server/_index.md @@ -0,0 +1,140 @@ +--- +title: Server-Side Feature Flags +description: Set up Datadog Feature Flags for server-side applications. +further_reading: +- link: "/feature_flags/setup/" + tag: "Documentation" + text: "Feature Flags Setup" +- link: "/agent/" + tag: "Documentation" + text: "Datadog Agent" +--- + +{{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} +Feature Flags are in Preview. Complete the form to request access. +{{< /callout >}} + +## Overview + +Datadog Feature Flags for server-side applications allow you to remotely control feature availability, run experiments, and roll out new functionality with confidence. Server-side SDKs integrate with the Datadog APM tracer and use Remote Configuration to receive flag updates in real time. + +This guide covers the common setup required for all server-side SDKs, including Agent configuration and application environment variables. + +## Prerequisites + +Before setting up server-side feature flags, ensure you have: + +- **Datadog Agent 7.55 or later** installed and running +- **Datadog API key** configured +- **APM tracing** enabled in your application + +## Agent configuration + +Server-side feature flags use Remote Configuration to deliver flag configurations to your application. Enable Remote Configuration in your Datadog Agent. + +### Configuration file + +Add the following to your `datadog.yaml`: + +{{< code-block lang="yaml" filename="datadog.yaml" >}} +# Enable Remote Configuration +remote_configuration: + enabled: true + +# Your Datadog API key +api_key: +{{< /code-block >}} + +### Environment variables + +Alternatively, configure the Agent using environment variables: + +{{< code-block lang="bash" >}} +# Enable Remote Configuration +DD_REMOTE_CONFIGURATION_ENABLED=true + +# Your Datadog API key +DD_API_KEY= + +# Optional: Configure polling interval (default: 5s) +DD_REMOTE_CONFIGURATION_REFRESH_INTERVAL=5s +{{< /code-block >}} + +### Docker + +When running the Agent in Docker, pass the environment variables: + +{{< code-block lang="bash" >}} +docker run -d \ + -e DD_API_KEY= \ + -e DD_REMOTE_CONFIGURATION_ENABLED=true \ + -v /var/run/docker.sock:/var/run/docker.sock:ro \ + -v /proc/:/host/proc/:ro \ + -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \ + gcr.io/datadoghq/agent:latest +{{< /code-block >}} + +### Kubernetes + +For Kubernetes deployments, add the configuration to your Agent manifest: + +{{< code-block lang="yaml" filename="datadog-agent.yaml" >}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: datadog-agent-config +data: + datadog.yaml: | + remote_configuration: + enabled: true +{{< /code-block >}} + +Or set environment variables in your Agent deployment: + +{{< code-block lang="yaml" >}} +env: + - name: DD_REMOTE_CONFIGURATION_ENABLED + value: "true" + - name: DD_API_KEY + valueFrom: + secretKeyRef: + name: datadog-secrets + key: api-key +{{< /code-block >}} + +## Application configuration + +Configure your application with the standard Datadog environment variables. These are common across all server-side SDKs: + +{{< code-block lang="bash" >}} +# Required: Service identification +DD_SERVICE= +DD_ENV= +DD_VERSION= + +# Agent connection (if not using default localhost:8126) +DD_AGENT_HOST=localhost +DD_TRACE_AGENT_PORT=8126 + +# Enable Remote Configuration in the tracer +DD_REMOTE_CONFIG_ENABLED=true +{{< /code-block >}} + +
Some SDKs require additional experimental flags to enable feature flagging. See the SDK-specific documentation for details.
+ +## Available SDKs + +Select your language or framework to view SDK-specific setup instructions: + +{{< whatsnext desc=" " >}} + {{< nextlink href="/feature_flags/setup/server/go" >}}Go{{< /nextlink >}} + {{< nextlink href="/feature_flags/setup/server/java" >}}Java{{< /nextlink >}} + {{< nextlink href="/feature_flags/setup/server/nodejs" >}}Node.js{{< /nextlink >}} + {{< nextlink href="/feature_flags/setup/server/python" >}}Python{{< /nextlink >}} + {{< nextlink href="/feature_flags/setup/server/ruby" >}}Ruby{{< /nextlink >}} + {{< nextlink href="/feature_flags/setup/server/dotnet" >}}.NET{{< /nextlink >}} +{{< /whatsnext >}} + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} diff --git a/content/en/feature_flags/setup/server/go.md b/content/en/feature_flags/setup/server/go.md new file mode 100644 index 00000000000..522cb56ff81 --- /dev/null +++ b/content/en/feature_flags/setup/server/go.md @@ -0,0 +1,25 @@ +--- +title: Go Feature Flags +description: Set up Datadog Feature Flags for Go applications. +further_reading: +- link: "/feature_flags/setup/server/" + tag: "Documentation" + text: "Server-Side Feature Flags" +- link: "/tracing/trace_collection/dd_libraries/go/" + tag: "Documentation" + text: "Go Tracing" +--- + +{{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} +Feature Flags are in Preview. Complete the form to request access. +{{< /callout >}} + +## Overview + +This page describes how to instrument your Go application with the Datadog Feature Flags SDK. + +Documentation coming soon. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} diff --git a/content/en/feature_flags/setup/server/java.md b/content/en/feature_flags/setup/server/java.md new file mode 100644 index 00000000000..0b8c544158e --- /dev/null +++ b/content/en/feature_flags/setup/server/java.md @@ -0,0 +1,25 @@ +--- +title: Java Feature Flags +description: Set up Datadog Feature Flags for Java applications. +further_reading: +- link: "/feature_flags/setup/server/" + tag: "Documentation" + text: "Server-Side Feature Flags" +- link: "/tracing/trace_collection/dd_libraries/java/" + tag: "Documentation" + text: "Java Tracing" +--- + +{{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} +Feature Flags are in Preview. Complete the form to request access. +{{< /callout >}} + +## Overview + +This page describes how to instrument your Java application with the Datadog Feature Flags SDK. + +Documentation coming soon. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} diff --git a/content/en/feature_flags/setup/server/nodejs.md b/content/en/feature_flags/setup/server/nodejs.md new file mode 100644 index 00000000000..c338238eddc --- /dev/null +++ b/content/en/feature_flags/setup/server/nodejs.md @@ -0,0 +1,25 @@ +--- +title: Node.js Feature Flags +description: Set up Datadog Feature Flags for Node.js applications. +further_reading: +- link: "/feature_flags/setup/server/" + tag: "Documentation" + text: "Server-Side Feature Flags" +- link: "/tracing/trace_collection/dd_libraries/nodejs/" + tag: "Documentation" + text: "Node.js Tracing" +--- + +{{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} +Feature Flags are in Preview. Complete the form to request access. +{{< /callout >}} + +## Overview + +This page describes how to instrument your Node.js application with the Datadog Feature Flags SDK. + +Documentation coming soon. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} diff --git a/content/en/feature_flags/setup/server/python.md b/content/en/feature_flags/setup/server/python.md new file mode 100644 index 00000000000..2849de23ed2 --- /dev/null +++ b/content/en/feature_flags/setup/server/python.md @@ -0,0 +1,25 @@ +--- +title: Python Feature Flags +description: Set up Datadog Feature Flags for Python applications. +further_reading: +- link: "/feature_flags/setup/server/" + tag: "Documentation" + text: "Server-Side Feature Flags" +- link: "/tracing/trace_collection/dd_libraries/python/" + tag: "Documentation" + text: "Python Tracing" +--- + +{{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} +Feature Flags are in Preview. Complete the form to request access. +{{< /callout >}} + +## Overview + +This page describes how to instrument your Python application with the Datadog Feature Flags SDK. + +Documentation coming soon. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} diff --git a/content/en/feature_flags/setup/server/ruby.md b/content/en/feature_flags/setup/server/ruby.md new file mode 100644 index 00000000000..ae006da7a39 --- /dev/null +++ b/content/en/feature_flags/setup/server/ruby.md @@ -0,0 +1,25 @@ +--- +title: Ruby Feature Flags +description: Set up Datadog Feature Flags for Ruby applications. +further_reading: +- link: "/feature_flags/setup/server/" + tag: "Documentation" + text: "Server-Side Feature Flags" +- link: "/tracing/trace_collection/dd_libraries/ruby/" + tag: "Documentation" + text: "Ruby Tracing" +--- + +{{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} +Feature Flags are in Preview. Complete the form to request access. +{{< /callout >}} + +## Overview + +This page describes how to instrument your Ruby application with the Datadog Feature Flags SDK. + +Documentation coming soon. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} From e0de1c9e1d2cc2e90f284ddaf030f9bb18c96f54 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Mon, 8 Dec 2025 15:32:18 -0500 Subject: [PATCH 02/18] add to sidebar --- config/_default/menus/main.en.yaml | 30 +++++++++++++++++++ .../en/feature_flags/setup/server/_index.md | 1 - 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/config/_default/menus/main.en.yaml b/config/_default/menus/main.en.yaml index a421feb89d7..eb24e9a86d0 100644 --- a/config/_default/menus/main.en.yaml +++ b/config/_default/menus/main.en.yaml @@ -5597,6 +5597,36 @@ menu: parent: feature_flags_setup identifier: feature_flags_setup_ios weight: 102 + - name: Server + url: feature_flags/setup/server + parent: feature_flags_setup + identifier: feature_flags_setup_server + weight: 103 + - name: Go + url: feature_flags/setup/server/go + parent: feature_flags_setup_server + identifier: feature_flags_setup_server_go + weight: 10301 + - name: Java + url: feature_flags/setup/server/java + parent: feature_flags_setup_server + identifier: feature_flags_setup_server_java + weight: 10302 + - name: Node.js + url: feature_flags/setup/server/nodejs + parent: feature_flags_setup_server + identifier: feature_flags_setup_server_nodejs + weight: 10303 + - name: Python + url: feature_flags/setup/server/python + parent: feature_flags_setup_server + identifier: feature_flags_setup_server_python + weight: 10304 + - name: Ruby + url: feature_flags/setup/server/ruby + parent: feature_flags_setup_server + identifier: feature_flags_setup_server_ruby + weight: 10305 - name: MCP Server url: feature_flags/feature_flag_mcp_server parent: feature_flags diff --git a/content/en/feature_flags/setup/server/_index.md b/content/en/feature_flags/setup/server/_index.md index a2adf6045a4..f3234235823 100644 --- a/content/en/feature_flags/setup/server/_index.md +++ b/content/en/feature_flags/setup/server/_index.md @@ -132,7 +132,6 @@ Select your language or framework to view SDK-specific setup instructions: {{< nextlink href="/feature_flags/setup/server/nodejs" >}}Node.js{{< /nextlink >}} {{< nextlink href="/feature_flags/setup/server/python" >}}Python{{< /nextlink >}} {{< nextlink href="/feature_flags/setup/server/ruby" >}}Ruby{{< /nextlink >}} - {{< nextlink href="/feature_flags/setup/server/dotnet" >}}.NET{{< /nextlink >}} {{< /whatsnext >}} ## Further reading From dec351be1f172a7b55dfbbc010c2907c5d7bbb00 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Mon, 8 Dec 2025 15:34:53 -0500 Subject: [PATCH 03/18] poll --- content/en/feature_flags/setup/server/_index.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/content/en/feature_flags/setup/server/_index.md b/content/en/feature_flags/setup/server/_index.md index f3234235823..75e5b83fb08 100644 --- a/content/en/feature_flags/setup/server/_index.md +++ b/content/en/feature_flags/setup/server/_index.md @@ -56,8 +56,10 @@ DD_REMOTE_CONFIGURATION_ENABLED=true # Your Datadog API key DD_API_KEY= -# Optional: Configure polling interval (default: 5s) -DD_REMOTE_CONFIGURATION_REFRESH_INTERVAL=5s +# Optional: Configure polling interval (default: 60s) +# This determines the average time between making a flag change in the UI +# and the change becoming available to your application. +DD_REMOTE_CONFIGURATION_REFRESH_INTERVAL=10s {{< /code-block >}} ### Docker From 2b98b97471b54536e70917951f12ab30069af460 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Mon, 8 Dec 2025 15:38:10 -0500 Subject: [PATCH 04/18] simpler setup --- .../en/feature_flags/setup/server/_index.md | 73 ++----------------- 1 file changed, 7 insertions(+), 66 deletions(-) diff --git a/content/en/feature_flags/setup/server/_index.md b/content/en/feature_flags/setup/server/_index.md index 75e5b83fb08..2fc385541d9 100644 --- a/content/en/feature_flags/setup/server/_index.md +++ b/content/en/feature_flags/setup/server/_index.md @@ -5,9 +5,9 @@ further_reading: - link: "/feature_flags/setup/" tag: "Documentation" text: "Feature Flags Setup" -- link: "/agent/" +- link: "/remote_configuration/" tag: "Documentation" - text: "Datadog Agent" + text: "Remote Configuration" --- {{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} @@ -30,79 +30,20 @@ Before setting up server-side feature flags, ensure you have: ## Agent configuration -Server-side feature flags use Remote Configuration to deliver flag configurations to your application. Enable Remote Configuration in your Datadog Agent. +Server-side feature flags use [Remote Configuration][1] to deliver flag configurations to your application. Enable Remote Configuration in your Datadog Agent by setting `DD_REMOTE_CONFIGURATION_ENABLED=true` or adding `remote_configuration.enabled: true` to your `datadog.yaml`. -### Configuration file +See the [Remote Configuration documentation][1] for detailed setup instructions across different deployment environments. -Add the following to your `datadog.yaml`: +### Polling interval -{{< code-block lang="yaml" filename="datadog.yaml" >}} -# Enable Remote Configuration -remote_configuration: - enabled: true - -# Your Datadog API key -api_key: -{{< /code-block >}} - -### Environment variables - -Alternatively, configure the Agent using environment variables: +The Agent polls Datadog for configuration updates at a configurable interval. This interval determines the average time between making a flag change in the UI and the change becoming available to your application. {{< code-block lang="bash" >}} -# Enable Remote Configuration -DD_REMOTE_CONFIGURATION_ENABLED=true - -# Your Datadog API key -DD_API_KEY= - # Optional: Configure polling interval (default: 60s) -# This determines the average time between making a flag change in the UI -# and the change becoming available to your application. DD_REMOTE_CONFIGURATION_REFRESH_INTERVAL=10s {{< /code-block >}} -### Docker - -When running the Agent in Docker, pass the environment variables: - -{{< code-block lang="bash" >}} -docker run -d \ - -e DD_API_KEY= \ - -e DD_REMOTE_CONFIGURATION_ENABLED=true \ - -v /var/run/docker.sock:/var/run/docker.sock:ro \ - -v /proc/:/host/proc/:ro \ - -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \ - gcr.io/datadoghq/agent:latest -{{< /code-block >}} - -### Kubernetes - -For Kubernetes deployments, add the configuration to your Agent manifest: - -{{< code-block lang="yaml" filename="datadog-agent.yaml" >}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: datadog-agent-config -data: - datadog.yaml: | - remote_configuration: - enabled: true -{{< /code-block >}} - -Or set environment variables in your Agent deployment: - -{{< code-block lang="yaml" >}} -env: - - name: DD_REMOTE_CONFIGURATION_ENABLED - value: "true" - - name: DD_API_KEY - valueFrom: - secretKeyRef: - name: datadog-secrets - key: api-key -{{< /code-block >}} +[1]: /remote_configuration ## Application configuration From dd15dbc2d85ec01a56b4393c23283cec90918f49 Mon Sep 17 00:00:00 2001 From: Joe Peeples Date: Tue, 9 Dec 2025 10:12:36 -0500 Subject: [PATCH 05/18] rebuild nav structure also: - rename `setup` to `client` - update links, other URL references --- config/_default/menus/main.en.yaml | 68 +++++++++---------- content/en/feature_flags/_index.md | 7 +- .../feature_flags/{setup => client}/_index.md | 9 ++- .../{setup => client}/android.md | 6 +- .../en/feature_flags/{setup => client}/ios.md | 6 +- .../{setup => }/server/_index.md | 14 ++-- .../en/feature_flags/{setup => }/server/go.md | 2 +- .../feature_flags/{setup => }/server/java.md | 2 +- .../{setup => }/server/nodejs.md | 2 +- .../{setup => }/server/python.md | 2 +- .../feature_flags/{setup => }/server/ruby.md | 2 +- .../feature_flags/feature_flags_setup.html | 8 +-- 12 files changed, 70 insertions(+), 58 deletions(-) rename content/en/feature_flags/{setup => client}/_index.md (76%) rename content/en/feature_flags/{setup => client}/android.md (98%) rename content/en/feature_flags/{setup => client}/ios.md (99%) rename content/en/feature_flags/{setup => }/server/_index.md (85%) rename content/en/feature_flags/{setup => }/server/go.md (94%) rename content/en/feature_flags/{setup => }/server/java.md (94%) rename content/en/feature_flags/{setup => }/server/nodejs.md (94%) rename content/en/feature_flags/{setup => }/server/python.md (94%) rename content/en/feature_flags/{setup => }/server/ruby.md (94%) diff --git a/config/_default/menus/main.en.yaml b/config/_default/menus/main.en.yaml index eb24e9a86d0..b45da123fad 100644 --- a/config/_default/menus/main.en.yaml +++ b/config/_default/menus/main.en.yaml @@ -5582,51 +5582,51 @@ menu: parent: software_delivery_heading identifier: feature_flags weight: 80000 - - name: Setup - url: feature_flags/setup + - name: Client SDKs + url: feature_flags/client parent: feature_flags - identifier: feature_flags_setup + identifier: feature_flags_client weight: 1 - name: Android and Android TV - url: feature_flags/setup/android - parent: feature_flags_setup - identifier: feature_flags_setup_android + url: feature_flags/client/android + parent: feature_flags_client + identifier: feature_flags_client_android weight: 101 - name: iOS and tvOS - url: feature_flags/setup/ios - parent: feature_flags_setup - identifier: feature_flags_setup_ios + url: feature_flags/client/ios + parent: feature_flags_client + identifier: feature_flags_client_ios weight: 102 - - name: Server - url: feature_flags/setup/server - parent: feature_flags_setup - identifier: feature_flags_setup_server - weight: 103 + - name: Server SDKs + url: feature_flags/server + parent: feature_flags + identifier: feature_flags_server + weight: 2 - name: Go - url: feature_flags/setup/server/go - parent: feature_flags_setup_server - identifier: feature_flags_setup_server_go - weight: 10301 + url: feature_flags/server/go + parent: feature_flags_server + identifier: feature_flags_server_go + weight: 201 - name: Java - url: feature_flags/setup/server/java - parent: feature_flags_setup_server - identifier: feature_flags_setup_server_java - weight: 10302 + url: feature_flags/server/java + parent: feature_flags_server + identifier: feature_flags_server_java + weight: 202 - name: Node.js - url: feature_flags/setup/server/nodejs - parent: feature_flags_setup_server - identifier: feature_flags_setup_server_nodejs - weight: 10303 + url: feature_flags/server/nodejs + parent: feature_flags_server + identifier: feature_flags_server_nodejs + weight: 203 - name: Python - url: feature_flags/setup/server/python - parent: feature_flags_setup_server - identifier: feature_flags_setup_server_python - weight: 10304 + url: feature_flags/server/python + parent: feature_flags_server + identifier: feature_flags_server_python + weight: 204 - name: Ruby - url: feature_flags/setup/server/ruby - parent: feature_flags_setup_server - identifier: feature_flags_setup_server_ruby - weight: 10305 + url: feature_flags/server/ruby + parent: feature_flags_server + identifier: feature_flags_server_ruby + weight: 205 - name: MCP Server url: feature_flags/feature_flag_mcp_server parent: feature_flags diff --git a/content/en/feature_flags/_index.md b/content/en/feature_flags/_index.md index b9ae3b306ab..f223d3bf2cc 100644 --- a/content/en/feature_flags/_index.md +++ b/content/en/feature_flags/_index.md @@ -5,9 +5,12 @@ further_reading: - link: "/getting_started/feature_flags/" tag: "Documentation" text: "Getting started with Feature Flags" -- link: "/feature_flags/setup/" +- link: "/feature_flags/client/" tag: "Documentation" - text: "Set up Feature Flags for your applications" + text: "Set up Feature Flags for client-side applications" +- link: "/feature_flags/server/" + tag: "Documentation" + text: "Set up Feature Flags for server-side applications" - link: "/feature_flags/guide/migrate_from_statsig" tag: "Guide" text: "Migrate Your Feature Flags from Statsig" diff --git a/content/en/feature_flags/setup/_index.md b/content/en/feature_flags/client/_index.md similarity index 76% rename from content/en/feature_flags/setup/_index.md rename to content/en/feature_flags/client/_index.md index ebe60724c0b..cf514e4bd94 100644 --- a/content/en/feature_flags/setup/_index.md +++ b/content/en/feature_flags/client/_index.md @@ -1,6 +1,8 @@ --- -title: Set Up Feature Flags -description: Set up Datadog Feature Flags for your mobile applications. +title: Client-Side Feature Flags +description: Set up Datadog Feature Flags for client-side applications. +aliases: + - /feature_flags/setup/ further_reading: - link: "/feature_flags/" tag: "Documentation" @@ -8,6 +10,9 @@ further_reading: - link: "/getting_started/feature_flags/" tag: "Documentation" text: "Getting Started with Feature Flags" +- link: "feature_flags/server/" + tag: "Documentation" + text: "Server-Side Feature Flags" --- {{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} diff --git a/content/en/feature_flags/setup/android.md b/content/en/feature_flags/client/android.md similarity index 98% rename from content/en/feature_flags/setup/android.md rename to content/en/feature_flags/client/android.md index dac6fd1dd0c..8290ba519b1 100644 --- a/content/en/feature_flags/setup/android.md +++ b/content/en/feature_flags/client/android.md @@ -1,10 +1,12 @@ --- title: Android and Android TV Feature Flags description: Set up Datadog Feature Flags for Android and Android TV applications. +aliases: + - /feature_flags/setup/android/ further_reading: -- link: "/feature_flags/setup/" +- link: "/feature_flags/client/" tag: "Documentation" - text: "Feature Flags Setup" + text: "Client-Side Feature Flags" - link: "/real_user_monitoring/android/" tag: "Documentation" text: "Android and Android TV Monitoring" diff --git a/content/en/feature_flags/setup/ios.md b/content/en/feature_flags/client/ios.md similarity index 99% rename from content/en/feature_flags/setup/ios.md rename to content/en/feature_flags/client/ios.md index b1f37d76550..a3fd53e8ba4 100644 --- a/content/en/feature_flags/setup/ios.md +++ b/content/en/feature_flags/client/ios.md @@ -1,10 +1,12 @@ --- title: iOS and tvOS Feature Flags description: Set up Datadog Feature Flags for iOS and tvOS applications. +aliases: + - /feature_flags/setup/ios/ further_reading: -- link: "/feature_flags/setup/" +- link: "/feature_flags/client/" tag: "Documentation" - text: "Feature Flags Setup" + text: "Client-Side Feature Flags" - link: "/real_user_monitoring/ios/" tag: "Documentation" text: "iOS and tvOS Monitoring" diff --git a/content/en/feature_flags/setup/server/_index.md b/content/en/feature_flags/server/_index.md similarity index 85% rename from content/en/feature_flags/setup/server/_index.md rename to content/en/feature_flags/server/_index.md index 2fc385541d9..2c375e74574 100644 --- a/content/en/feature_flags/setup/server/_index.md +++ b/content/en/feature_flags/server/_index.md @@ -2,9 +2,9 @@ title: Server-Side Feature Flags description: Set up Datadog Feature Flags for server-side applications. further_reading: -- link: "/feature_flags/setup/" +- link: "/feature_flags/client/" tag: "Documentation" - text: "Feature Flags Setup" + text: "Client-Side Feature Flags" - link: "/remote_configuration/" tag: "Documentation" text: "Remote Configuration" @@ -70,11 +70,11 @@ DD_REMOTE_CONFIG_ENABLED=true Select your language or framework to view SDK-specific setup instructions: {{< whatsnext desc=" " >}} - {{< nextlink href="/feature_flags/setup/server/go" >}}Go{{< /nextlink >}} - {{< nextlink href="/feature_flags/setup/server/java" >}}Java{{< /nextlink >}} - {{< nextlink href="/feature_flags/setup/server/nodejs" >}}Node.js{{< /nextlink >}} - {{< nextlink href="/feature_flags/setup/server/python" >}}Python{{< /nextlink >}} - {{< nextlink href="/feature_flags/setup/server/ruby" >}}Ruby{{< /nextlink >}} + {{< nextlink href="/feature_flags/server/go" >}}Go{{< /nextlink >}} + {{< nextlink href="/feature_flags/server/java" >}}Java{{< /nextlink >}} + {{< nextlink href="/feature_flags/server/nodejs" >}}Node.js{{< /nextlink >}} + {{< nextlink href="/feature_flags/server/python" >}}Python{{< /nextlink >}} + {{< nextlink href="/feature_flags/server/ruby" >}}Ruby{{< /nextlink >}} {{< /whatsnext >}} ## Further reading diff --git a/content/en/feature_flags/setup/server/go.md b/content/en/feature_flags/server/go.md similarity index 94% rename from content/en/feature_flags/setup/server/go.md rename to content/en/feature_flags/server/go.md index 522cb56ff81..83ab9c090c6 100644 --- a/content/en/feature_flags/setup/server/go.md +++ b/content/en/feature_flags/server/go.md @@ -2,7 +2,7 @@ title: Go Feature Flags description: Set up Datadog Feature Flags for Go applications. further_reading: -- link: "/feature_flags/setup/server/" +- link: "/feature_flags/server/" tag: "Documentation" text: "Server-Side Feature Flags" - link: "/tracing/trace_collection/dd_libraries/go/" diff --git a/content/en/feature_flags/setup/server/java.md b/content/en/feature_flags/server/java.md similarity index 94% rename from content/en/feature_flags/setup/server/java.md rename to content/en/feature_flags/server/java.md index 0b8c544158e..0b416b40626 100644 --- a/content/en/feature_flags/setup/server/java.md +++ b/content/en/feature_flags/server/java.md @@ -2,7 +2,7 @@ title: Java Feature Flags description: Set up Datadog Feature Flags for Java applications. further_reading: -- link: "/feature_flags/setup/server/" +- link: "/feature_flags/server/" tag: "Documentation" text: "Server-Side Feature Flags" - link: "/tracing/trace_collection/dd_libraries/java/" diff --git a/content/en/feature_flags/setup/server/nodejs.md b/content/en/feature_flags/server/nodejs.md similarity index 94% rename from content/en/feature_flags/setup/server/nodejs.md rename to content/en/feature_flags/server/nodejs.md index c338238eddc..82db2d5a098 100644 --- a/content/en/feature_flags/setup/server/nodejs.md +++ b/content/en/feature_flags/server/nodejs.md @@ -2,7 +2,7 @@ title: Node.js Feature Flags description: Set up Datadog Feature Flags for Node.js applications. further_reading: -- link: "/feature_flags/setup/server/" +- link: "/feature_flags/server/" tag: "Documentation" text: "Server-Side Feature Flags" - link: "/tracing/trace_collection/dd_libraries/nodejs/" diff --git a/content/en/feature_flags/setup/server/python.md b/content/en/feature_flags/server/python.md similarity index 94% rename from content/en/feature_flags/setup/server/python.md rename to content/en/feature_flags/server/python.md index 2849de23ed2..f50440ac122 100644 --- a/content/en/feature_flags/setup/server/python.md +++ b/content/en/feature_flags/server/python.md @@ -2,7 +2,7 @@ title: Python Feature Flags description: Set up Datadog Feature Flags for Python applications. further_reading: -- link: "/feature_flags/setup/server/" +- link: "/feature_flags/server/" tag: "Documentation" text: "Server-Side Feature Flags" - link: "/tracing/trace_collection/dd_libraries/python/" diff --git a/content/en/feature_flags/setup/server/ruby.md b/content/en/feature_flags/server/ruby.md similarity index 94% rename from content/en/feature_flags/setup/server/ruby.md rename to content/en/feature_flags/server/ruby.md index ae006da7a39..450cad09baa 100644 --- a/content/en/feature_flags/setup/server/ruby.md +++ b/content/en/feature_flags/server/ruby.md @@ -2,7 +2,7 @@ title: Ruby Feature Flags description: Set up Datadog Feature Flags for Ruby applications. further_reading: -- link: "/feature_flags/setup/server/" +- link: "/feature_flags/server/" tag: "Documentation" text: "Server-Side Feature Flags" - link: "/tracing/trace_collection/dd_libraries/ruby/" diff --git a/layouts/partials/feature_flags/feature_flags_setup.html b/layouts/partials/feature_flags/feature_flags_setup.html index c4f9b4cf6de..0242ff75633 100644 --- a/layouts/partials/feature_flags/feature_flags_setup.html +++ b/layouts/partials/feature_flags/feature_flags_setup.html @@ -3,28 +3,28 @@
- +
{{ partial "img.html" (dict "root" . "src" "integrations_logos/tv_os_large.svg" "class" "img-fluid" "alt" "tvOS" "width" "400") }}
From 41bbb912c0c4b7934acb44b9548eafea4b76fd11 Mon Sep 17 00:00:00 2001 From: Joe Peeples Date: Tue, 9 Dec 2025 11:13:51 -0500 Subject: [PATCH 06/18] add tile layout for server landing page + also renames the tile partial in the client page for consistency --- content/en/feature_flags/client/_index.md | 2 +- content/en/feature_flags/server/_index.md | 16 ++----- ...s_setup.html => feature_flags_client.html} | 0 .../feature_flags/feature_flags_server.html | 43 +++++++++++++++++++ 4 files changed, 47 insertions(+), 14 deletions(-) rename layouts/partials/feature_flags/{feature_flags_setup.html => feature_flags_client.html} (100%) create mode 100644 layouts/partials/feature_flags/feature_flags_server.html diff --git a/content/en/feature_flags/client/_index.md b/content/en/feature_flags/client/_index.md index cf514e4bd94..74d20ac29ab 100644 --- a/content/en/feature_flags/client/_index.md +++ b/content/en/feature_flags/client/_index.md @@ -23,7 +23,7 @@ Feature Flags are in Preview. Complete the form to request access. Set up Datadog Feature Flags for your applications. Follow the platform-specific guides below to integrate feature flags into your application and start collecting feature flag data: -{{< partial name="feature_flags/feature_flags_setup.html" >}} +{{< partial name="feature_flags/feature_flags_client.html" >}} ## Further reading diff --git a/content/en/feature_flags/server/_index.md b/content/en/feature_flags/server/_index.md index 2c375e74574..67c69550648 100644 --- a/content/en/feature_flags/server/_index.md +++ b/content/en/feature_flags/server/_index.md @@ -18,7 +18,9 @@ Feature Flags are in Preview. Complete the form to request access. Datadog Feature Flags for server-side applications allow you to remotely control feature availability, run experiments, and roll out new functionality with confidence. Server-side SDKs integrate with the Datadog APM tracer and use Remote Configuration to receive flag updates in real time. -This guide covers the common setup required for all server-side SDKs, including Agent configuration and application environment variables. +This guide covers the common setup required for all server-side SDKs, including Agent configuration and application environment variables. Select your language or framework to view SDK-specific setup instructions: + +{{< partial name="feature_flags/feature_flags_server.html" >}} ## Prerequisites @@ -65,18 +67,6 @@ DD_REMOTE_CONFIG_ENABLED=true
Some SDKs require additional experimental flags to enable feature flagging. See the SDK-specific documentation for details.
-## Available SDKs - -Select your language or framework to view SDK-specific setup instructions: - -{{< whatsnext desc=" " >}} - {{< nextlink href="/feature_flags/server/go" >}}Go{{< /nextlink >}} - {{< nextlink href="/feature_flags/server/java" >}}Java{{< /nextlink >}} - {{< nextlink href="/feature_flags/server/nodejs" >}}Node.js{{< /nextlink >}} - {{< nextlink href="/feature_flags/server/python" >}}Python{{< /nextlink >}} - {{< nextlink href="/feature_flags/server/ruby" >}}Ruby{{< /nextlink >}} -{{< /whatsnext >}} - ## Further reading {{< partial name="whats-next/whats-next.html" >}} diff --git a/layouts/partials/feature_flags/feature_flags_setup.html b/layouts/partials/feature_flags/feature_flags_client.html similarity index 100% rename from layouts/partials/feature_flags/feature_flags_setup.html rename to layouts/partials/feature_flags/feature_flags_client.html diff --git a/layouts/partials/feature_flags/feature_flags_server.html b/layouts/partials/feature_flags/feature_flags_server.html new file mode 100644 index 00000000000..440b05497be --- /dev/null +++ b/layouts/partials/feature_flags/feature_flags_server.html @@ -0,0 +1,43 @@ +{{ $dot := . }} +
+
From 7f2d4f68d1bcff5a6eae7914f3486f8d72369eb4 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Tue, 9 Dec 2025 17:40:36 -0500 Subject: [PATCH 07/18] add go docs for openfeature implementation (#33234) * add go docs for openfeature implementation * add docs for blocking init, custom timeout, non blocking * no agent version --- content/en/feature_flags/server/go.md | 258 +++++++++++++++++++++++++- 1 file changed, 256 insertions(+), 2 deletions(-) diff --git a/content/en/feature_flags/server/go.md b/content/en/feature_flags/server/go.md index 83ab9c090c6..895a462fb0a 100644 --- a/content/en/feature_flags/server/go.md +++ b/content/en/feature_flags/server/go.md @@ -16,9 +16,263 @@ Feature Flags are in Preview. Complete the form to request access. ## Overview -This page describes how to instrument your Go application with the Datadog Feature Flags SDK. +This page describes how to instrument your Go application with the Datadog Feature Flags SDK. The Go SDK integrates with [OpenFeature][1], an open standard for feature flag management, and uses the Datadog tracer's Remote Configuration to receive flag updates in real time. -Documentation coming soon. +This guide explains how to install and enable the SDK, create an OpenFeature client, and evaluate feature flags in your application. + +## Prerequisites + +Before setting up the Go Feature Flags SDK, ensure you have: + +- **Datadog Agent** with [Remote Configuration][2] enabled +- **Datadog Go tracer** `dd-trace-go` version 2.4.0 or later + +Set the following environment variables: + +{{< code-block lang="bash" >}} +# Required: Enable the feature flags provider +DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true + +# Required: Service identification +DD_SERVICE= +DD_ENV= +{{< /code-block >}} + +## Installation + +Install the Datadog OpenFeature provider package: + +{{< code-block lang="bash" >}} +go get github.com/DataDog/dd-trace-go/v2/openfeature +{{< /code-block >}} + +You also need the OpenFeature Go SDK: + +{{< code-block lang="bash" >}} +go get github.com/open-feature/go-sdk/openfeature +{{< /code-block >}} + +## Initialize the SDK + +Start the Datadog tracer and register the Datadog OpenFeature provider. The tracer must be started first because it enables Remote Configuration, which delivers flag configurations to your application. + +### Blocking initialization + +Use `SetProviderAndWait` to block until the initial flag configuration is received. This ensures flags are ready before your application starts handling requests. + +{{< code-block lang="go" >}} +package main + +import ( + "log" + + "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" + ddopenfeature "github.com/DataDog/dd-trace-go/v2/openfeature" + "github.com/open-feature/go-sdk/openfeature" +) + +func main() { + // Start the Datadog tracer (enables Remote Config) + tracer.Start() + defer tracer.Stop() + + // Create the Datadog OpenFeature provider + provider, err := ddopenfeature.NewDatadogProvider(ddopenfeature.ProviderConfig{}) + if err != nil { + log.Fatalf("Failed to create provider: %v", err) + } + defer provider.Shutdown() + + // Register the provider and wait for initialization (default 30s timeout) + if err := openfeature.SetProviderAndWait(provider); err != nil { + log.Fatalf("Failed to set provider: %v", err) + } + + // Create the OpenFeature client + client := openfeature.NewClient("my-service") + + // Your application code here +} +{{< /code-block >}} + +To specify a custom timeout, use `SetProviderAndWaitWithContext`: + +{{< code-block lang="go" >}} +ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) +defer cancel() + +if err := openfeature.SetProviderAndWaitWithContext(ctx, provider); err != nil { + log.Fatalf("Failed to set provider: %v", err) +} +{{< /code-block >}} + +### Non-blocking initialization + +Use `SetProvider` to register the provider without waiting. Flag evaluations return default values until the configuration is received. + +{{< code-block lang="go" >}} +package main + +import ( + "log" + + "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" + ddopenfeature "github.com/DataDog/dd-trace-go/v2/openfeature" + "github.com/open-feature/go-sdk/openfeature" +) + +func main() { + // Start the Datadog tracer (enables Remote Config) + tracer.Start() + defer tracer.Stop() + + // Create the Datadog OpenFeature provider + provider, err := ddopenfeature.NewDatadogProvider(ddopenfeature.ProviderConfig{}) + if err != nil { + log.Fatalf("Failed to create provider: %v", err) + } + defer provider.Shutdown() + + // Register the provider without waiting + openfeature.SetProvider(provider) + + // Create the OpenFeature client + client := openfeature.NewClient("my-service") + + // Your application code here + // Flag evaluations return defaults until configuration is received +} +{{< /code-block >}} + +## Create a client + +Create an OpenFeature client to evaluate flags. You can create multiple clients with different names for different parts of your application: + +{{< code-block lang="go" >}} +// Create a client for your application +client := openfeature.NewClient("my-service") +{{< /code-block >}} + +## Set the evaluation context + +Define an evaluation context that identifies the user or entity for flag targeting. The evaluation context includes attributes used to determine which flag variations should be returned: + +{{< code-block lang="go" >}} +evalCtx := openfeature.NewEvaluationContext( + "user-123", // Targeting key (typically user ID) + map[string]interface{}{ + "email": "user@example.com", + "country": "US", + "tier": "premium", + "age": 25, + }, +) +{{< /code-block >}} + +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." + +## 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. + +Each flag is identified by a key (a unique string) and can be evaluated with a typed method that returns a value of the expected type. If the flag doesn't exist or cannot be evaluated, the SDK returns the provided default value. + +### Boolean flags + +Use `BooleanValue` for flags that represent on/off or true/false conditions: + +{{< code-block lang="go" >}} +ctx := context.Background() + +enabled, err := client.BooleanValue(ctx, "new-checkout-flow", false, evalCtx) +if err != nil { + log.Printf("Error evaluating flag: %v", err) +} + +if enabled { + showNewCheckout() +} else { + showLegacyCheckout() +} +{{< /code-block >}} + +### String flags + +Use `StringValue` for flags that select between multiple variants or configuration strings: + +{{< code-block lang="go" >}} +theme, err := client.StringValue(ctx, "ui-theme", "light", evalCtx) +if err != nil { + log.Printf("Error evaluating flag: %v", err) +} + +switch theme { +case "dark": + setDarkTheme() +case "light": + setLightTheme() +default: + setLightTheme() +} +{{< /code-block >}} + +### Numeric flags + +For numeric flags, use `IntValue` or `FloatValue`. These are appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: + +{{< code-block lang="go" >}} +maxItems, err := client.IntValue(ctx, "cart-max-items", 20, evalCtx) +if err != nil { + log.Printf("Error evaluating flag: %v", err) +} + +discountRate, err := client.FloatValue(ctx, "discount-rate", 0.0, evalCtx) +if err != nil { + log.Printf("Error evaluating flag: %v", err) +} +{{< /code-block >}} + +### Object flags + +For structured data, use `ObjectValue`. This returns a value that can be type-asserted to maps or other complex types: + +{{< code-block lang="go" >}} +config, err := client.ObjectValue(ctx, "feature-config", map[string]interface{}{ + "maxRetries": 3, + "timeout": 30, +}, evalCtx) +if err != nil { + log.Printf("Error evaluating flag: %v", err) +} + +// Type assert to access the configuration +if configMap, ok := config.(map[string]interface{}); ok { + maxRetries := configMap["maxRetries"] + timeout := configMap["timeout"] + // Use configuration values +} +{{< /code-block >}} + +### Flag evaluation details + +When you need more than just the flag value, use the `*ValueDetails` methods. These return both the evaluated value and metadata explaining the evaluation: + +{{< code-block lang="go" >}} +details, err := client.BooleanValueDetails(ctx, "new-feature", false, evalCtx) +if err != nil { + log.Printf("Error evaluating flag: %v", err) +} + +fmt.Printf("Value: %v\n", details.Value) +fmt.Printf("Variant: %s\n", details.Variant) +fmt.Printf("Reason: %s\n", details.Reason) +fmt.Printf("Error: %v\n", details.Error()) +{{< /code-block >}} + +Flag details help you debug evaluation behavior and understand why a user received a given value. + +[1]: https://openfeature.dev/ +[2]: /agent/remote_config/ ## Further reading From 82837f3e052f2cd8f7ed292c9c2f5b128a924578 Mon Sep 17 00:00:00 2001 From: Greg Huels Date: Wed, 10 Dec 2025 14:20:45 -0600 Subject: [PATCH 08/18] Documentation for dd-trace with feature flagging support (#33165) * Documentation for dd-trace with feature flagging support * Update content/en/feature_flags/setup/nodejs.md Co-authored-by: Leo Romanovsky --------- Co-authored-by: Leo Romanovsky --- content/en/feature_flags/setup/nodejs.md | 199 +++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 content/en/feature_flags/setup/nodejs.md diff --git a/content/en/feature_flags/setup/nodejs.md b/content/en/feature_flags/setup/nodejs.md new file mode 100644 index 00000000000..ca94cfaf90a --- /dev/null +++ b/content/en/feature_flags/setup/nodejs.md @@ -0,0 +1,199 @@ +--- +title: Node.js Feature Flags Support +description: Set up Datadog Feature Flags for Node.js applications. +further_reading: +- link: "/feature_flags/setup/" + tag: "Documentation" + text: "Feature Flags Setup" +- link: "/apm/" + tag: "Documentation" + text: "APM Setup" +--- + +## Installing and initializing + +Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install `dd-trace` and enable remote configuration with the `flaggingProvider` option as shown below. See documentation on `dd-trace` integration for detailed APM installation instructions. + +```shell +npm install dd-trace @openfeature/server-sdk +``` + +```javascript +import { OpenFeature } from '@openfeature/server-sdk' +import tracer from 'dd-trace'; + +tracer.init({ + experimental: { + flaggingProvider: { + enabled: true, + } + } +}); + +OpenFeature.setProvider(tracer.openfeature); +``` + +### Accepting default variant until initialization is complete + +When you call `setProvider` without waiting, the client returns default values until Remote Configuration loads in the background. This approach keeps your application responsive during startup but may serve defaults for early requests. + +```javascript +OpenFeature.setProvider(tracer.openfeature); +const client = OpenFeature.getClient(); + +app.get('/my-endpoint', (req, res) => { + const value = client.getBooleanValue('my-flag', false); + if (value) { + res.send('feature enabled!'); + } else { + res.send('feature disabled!'); + } +}); +``` + +### Waiting for initialization before evaluating a flag + +Use `setProviderAndWait` to ensure the provider fully initializes before evaluating flags. This guarantees that flag evaluations use actual configuration data rather than defaults, at the cost of delaying requests during initialization. + +```javascript +const initializationPromise = OpenFeature.setProviderAndWait(tracer.openfeature); +const client = OpenFeature.getClient(); + +app.get('/my-endpoint', async (req, res) => { + await initializationPromise; + + OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID + }); + + const value = client.getBooleanValue('my-flag', false); + if (value) { + res.send('feature enabled!'); + } else { + res.send('feature disabled!'); + } +}); +``` + +## Set the evaluation context + +Define who or what the flag evaluation applies to using an `EvaluationContext`. The evaluation context can include user or session information used to determine which flag variations should be returned. Call `OpenFeature.setContext` method before evaluating flags to ensure proper targeting. + +## Evaluating flags + +After creating the `OpenFeature` client as described in the previous section, you can start reading flag values throughout your app. Flag evaluation uses locally cached data, so no network requests occur when evaluating flags. + +Each flag is identified by a _key_ (a unique string) and can be evaluated with a _typed getter_ that returns a value of the expected type. If the flag doesn't exist or cannot be evaluated, the SDK returns the provided default value. + +### Boolean flags + +Use `getBooleanValue()` for flags that represent on/off or true/false conditions. Optionally set the context for specific targeting rules. + +```javascript +OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID +}); + +const isNewCheckoutEnabled = client.getBooleanValue( + 'new-checkout-flow', // flag key + false, // default value +); + +if (isNewCheckoutEnabled) { + showNewCheckoutFlow(); +} else { + showLegacyCheckout(); +} +``` + +### String flags + +Use `getStringValue()` for flags that select between multiple variants or configuration strings. For example: + +```javascript +OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID +}); + +const theme = client.getStringValue( + 'ui-theme', // flag key + 'light', // default value +); + +switch (theme) { + case 'light': + setLightTheme(); + break; + case 'dark': + setDarkTheme(); + break; + case 'blue': + setBlueTheme(); + break; + default: + setLightTheme(); +} +``` + +### Number flags + +For number flags, use `getNumberValue()`. This is appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: + +```javascript +OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID +}); + +const maxItems = client.getNumberValue( + 'max-cart-items', // flag key + 20, // default value +); + +const priceMultiplier = client.getNumberValue( + 'pricing-multiplier', // flag key + 1.3, // default value +); +``` + +### Object flags + +For structured JSON data, use `getObjectValue()`. This method returns an `object`, which can represent primitives, arrays, or dictionaries. Object flags are useful for remote configuration scenarios where multiple properties need to be provided together. + +```javascript +OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID +}); + +const defaultConfig = { + color: '#00A3FF', + fontSize: 14, +}; +const config = client.getObjectValue('ui-config', defaultConfig); +``` + +### Flag evaluation details + +When you need more than just the flag value, use the `getDetails` functions. These methods return both the evaluated value and metadata explaining the evaluation: + +* `getBooleanDetails() -> EvaluationDetails` +* `getStringDetails() -> EvaluationDetails` +* `getNumberDetails() -> EvaluationDetails` +* `getObjectDetails() -> EvaluationDetails` + +For example: + +```javascript +const details = client.getStringDetails('paywall-layout', 'control'); + +console.log(details.value); // Evaluated value (for example: "A", "B", or "control") +console.log(details.variant); // Variant name, if applicable +console.log(details.reason); // Description of why this value was chosen (for example: "TARGETING_MATCH") +console.log(details.errorCode); // The error that occurred during evaluation, if any +console.log(details.errorMessage); // A more detailed message of the error that occurred, if any +console.log(details.flagMetadata); // Additional information about the evaluation +``` From d589d53f0649849bd57a854ee58823b59e2ffd43 Mon Sep 17 00:00:00 2001 From: Sameeran Kunche Date: Wed, 10 Dec 2025 12:51:40 -0800 Subject: [PATCH 09/18] Add Ruby feature flags documentation (#33233) * Add Ruby feature flags server documentation - Port content from setup/ruby.md to server/ruby.md - Maintain all Vale linting fixes from previous commits - Include prerequisites, installation, usage examples, and troubleshooting - Support for boolean, string, number, object flags and evaluation context * Update content/en/feature_flags/server/ruby.md Co-authored-by: Leo Romanovsky --------- Co-authored-by: Leo Romanovsky --- content/en/feature_flags/server/ruby.md | 211 +++++++++++++++++++++++- 1 file changed, 210 insertions(+), 1 deletion(-) diff --git a/content/en/feature_flags/server/ruby.md b/content/en/feature_flags/server/ruby.md index 450cad09baa..d5a715383ae 100644 --- a/content/en/feature_flags/server/ruby.md +++ b/content/en/feature_flags/server/ruby.md @@ -18,8 +18,217 @@ Feature Flags are in Preview. Complete the form to request access. This page describes how to instrument your Ruby application with the Datadog Feature Flags SDK. -Documentation coming soon. +## Prerequisites + +Before setting up the Ruby Feature Flags SDK, ensure you have: + +- **Datadog Agent** with [Remote Configuration][1] enabled +- **Datadog Ruby tracer** `datadog` version 2.23.0 or later +- **OpenFeature Ruby SDK** `openfeature-sdk` version 0.4.1 or later +- **Service and environment configured** - Feature flags are targeted by service and environment + +## Installing and initializing + +Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install the required gems and configure remote configuration with OpenFeature support. + +```shell +gem install ddtrace openfeature-sdk +``` + +```ruby +require 'datadog' +require 'open_feature/sdk' +require 'datadog/open_feature/provider' + +# Configure Datadog with feature flagging enabled +Datadog.configure do |config| + config.remote.enabled = true + config.open_feature.enabled = true +end + +# Configure OpenFeature SDK with Datadog provider +OpenFeature::SDK.configure do |config| + config.set_provider(Datadog::OpenFeature::Provider.new) +end + +# Create OpenFeature client +client = OpenFeature::SDK.build_client +``` + +The client returns default values until remote configuration loads in the background. This approach keeps your application responsive during startup but may serve defaults for early requests. + +## Set the evaluation context + +Define an evaluation context that identifies the user or entity for flag targeting. The evaluation context includes attributes used to determine which flag variations should be returned: + +```ruby +context = OpenFeature::SDK::EvaluationContext.new( + targetingKey: 'user-123', # Targeting key (typically user ID) + email: 'user@example.com', + country: 'US', + tier: 'premium', + age: 25 +) +``` + +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." + +## Evaluating flags + +After creating the `OpenFeature` client, you can start reading flag values throughout your app. Flag evaluation uses locally cached data, so no network requests occur when evaluating flags. + +Each flag is identified by a unique string _key_. Flags are evaluated using typed methods that return values matching the expected type. The SDK returns the default value if a flag doesn't exist or cannot be evaluated. + +### Boolean flags + +Use `fetch_boolean_value()` for flags that represent on/off or true/false conditions: + +```ruby +enabled = client.fetch_boolean_value( + flag_key: 'new-checkout-flow', + default_value: false, + evaluation_context: context +) + +if enabled + show_new_checkout +else + show_legacy_checkout +end +``` + +### String flags + +Use `fetch_string_value()` for flags that select between multiple variants or configuration strings: + +```ruby +theme = client.fetch_string_value( + flag_key: 'ui-theme', + default_value: 'light', + evaluation_context: context +) + +case theme +when 'dark' + set_dark_theme +when 'light' + set_light_theme +else + set_light_theme +end +``` + +### Number flags + +For numeric flags, use `fetch_integer_value()` or `fetch_float_value()`. Ruby also provides `fetch_number_value()` which returns the appropriate type based on the default value. These are appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: + +```ruby +max_items = client.fetch_integer_value( + flag_key: 'cart-max-items', + default_value: 20, + evaluation_context: context +) + +discount_rate = client.fetch_float_value( + flag_key: 'discount-rate', + default_value: 0.0, + evaluation_context: context +) + +# Generic number method (type based on default) +batch_size = client.fetch_number_value( + flag_key: 'batch-size', + default_value: 100, # Returns integer + evaluation_context: context +) +``` + +### Object flags + +For structured data, use `fetch_object_value()`. This method returns a hash. Object flags are useful for remote configuration scenarios where multiple properties need to be provided together. + +```ruby +config = client.fetch_object_value( + flag_key: 'feature-config', + default_value: { + 'maxRetries' => 3, + 'timeout' => 30 + }, + evaluation_context: context +) + +max_retries = config['maxRetries'] || 3 +timeout = config['timeout'] || 30 +``` + +### Flag evaluation details + +When you need more than the flag value, use the `fetch__details` methods. These methods return both the evaluated value and metadata explaining the evaluation: + +```ruby +details = client.fetch_boolean_details( + flag_key: 'new-feature', + default_value: false, + evaluation_context: context +) + +puts "Value: #{details.value}" +puts "Variant: #{details.variant}" +puts "Reason: #{details.reason}" +puts "Error Code: #{details.error_code}" +puts "Error Message: #{details.error_message}" +``` + +Flag details help you debug evaluation behavior and understand why a user received a given value. + +## Evaluation without context + +You can evaluate flags without providing an evaluation context. This is useful for global flags that don't require user-specific targeting: + +```ruby +# Global feature flag - no context needed +maintenance_mode = client.fetch_boolean_value( + flag_key: 'maintenance-mode', + default_value: false +) + +if maintenance_mode + halt 503, { error: 'Service temporarily unavailable' }.to_json +end +``` + +## Troubleshooting + +### Feature flags surprisingly always return default values + +If feature flags always return default values: + +1. Verify Remote configuration is enabled in your Datadog Agent configuration +2. Ensure service and environment are configured (either through `DD_SERVICE`/`DD_ENV` environment variables or `config.service`/`config.env` in Ruby) +3. Check that `config.remote.enabled = true` and `config.open_feature.enabled = true` are set in your Ruby application's Datadog configuration +4. Verify the datadog gem version includes OpenFeature support (2.23.0 or later) + +### Remote configuration connection issues + +Check the Datadog tracer logs for Remote configuration status: + +```ruby +# Enable startup and debug logging +Datadog.configure do |config| + config.diagnostics.startup_logs.enabled = true + config.diagnostics.debug = true + config.remote.enabled = true + config.open_feature.enabled = true +end +``` + +Look for messages about: +- Remote Configuration worker starting +- Feature flags configuration being received +- OpenFeature component initialization ## Further reading {{< partial name="whats-next/whats-next.html" >}} + +[1]: /agent/remote_config/ \ No newline at end of file From fdf15c0432a49d469cf4bce8ec7a38d70fb29ed4 Mon Sep 17 00:00:00 2001 From: Oleksii Shmalko Date: Wed, 17 Dec 2025 02:01:22 +0200 Subject: [PATCH 10/18] Add python documentation for OpenFeature implementation (#33247) --- content/en/feature_flags/server/python.md | 226 +++++++++++++++++++++- 1 file changed, 224 insertions(+), 2 deletions(-) diff --git a/content/en/feature_flags/server/python.md b/content/en/feature_flags/server/python.md index f50440ac122..38ede5d4d8e 100644 --- a/content/en/feature_flags/server/python.md +++ b/content/en/feature_flags/server/python.md @@ -16,9 +16,231 @@ Feature Flags are in Preview. Complete the form to request access. ## Overview -This page describes how to instrument your Python application with the Datadog Feature Flags SDK. +This page describes how to instrument your Python application with the Datadog Feature Flags SDK. The Python SDK integrates with [OpenFeature][1], an open standard for feature flag management, and uses the Datadog tracer's Remote Configuration to receive flag updates in real time. -Documentation coming soon. +This guide explains how to install and enable the SDK, create an OpenFeature client, and evaluate feature flags in your application. + +## Prerequisites + +Before setting up the Python Feature Flags SDK, ensure you have: + +- **Datadog Agent** with [Remote Configuration][2] enabled +- **Datadog Python tracer** `ddtrace` version 3.19.0 or later +- **OpenFeature Python SDK** `openfeature-sdk` version 0.5.0 or later + +Set the following environment variables: + +{{< code-block lang="bash" >}} +# Required: Enable the feature flags provider +export DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true + +# Required: Service identification +export DD_SERVICE= +export DD_ENV= +{{< /code-block >}} + +## Installation + +Install the Datadog Python tracer and OpenFeature SDK: + +{{< code-block lang="bash" >}} +pip install ddtrace openfeature-sdk +{{< /code-block >}} + +Or add them to your `requirements.txt`: + +{{< code-block lang="text" filename="requirements.txt" >}} +ddtrace>=3.19.0 +openfeature-sdk>=0.5.0 +{{< /code-block >}} + +## Initialize the SDK + +Register the Datadog OpenFeature provider with the OpenFeature API. The provider connects to the Datadog tracer's Remote Configuration system to receive flag configurations. + +{{< code-block lang="python" >}} +from openfeature import api +from ddtrace.openfeature import DataDogProvider + +# Create and register the Datadog provider +provider = DataDogProvider() +api.set_provider(provider) + +# Create an OpenFeature client +client = api.get_client() + +# Your application code here +{{< /code-block >}} + +## Set the evaluation context + +Define an evaluation context that identifies the user or entity for flag targeting. The evaluation context includes attributes used to determine which flag variations should be returned: + +{{< code-block lang="python" >}} +from openfeature.evaluation_context import EvaluationContext + +eval_ctx = EvaluationContext( + targeting_key="user-123", # Targeting key (typically user ID) + attributes={ + "email": "user@example.com", + "country": "US", + "tier": "premium", + "age": 25 + } +) +{{< /code-block >}} + +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." + +## 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. + +Each flag is identified by a key (a unique string) and can be evaluated with a typed method that returns a value of the expected type. If the flag doesn't exist or cannot be evaluated, the SDK returns the provided default value. + +### Boolean flags + +Use `get_boolean_value` for flags that represent on/off or true/false conditions: + +{{< code-block lang="python" >}} +enabled = client.get_boolean_value("new-checkout-flow", False, eval_ctx) + +if enabled: + show_new_checkout() +else: + show_legacy_checkout() +{{< /code-block >}} + +### String flags + +Use `get_string_value` for flags that select between multiple variants or configuration strings: + +{{< code-block lang="python" >}} +theme = client.get_string_value("ui-theme", "light", eval_ctx) + +if theme == "dark": + set_dark_theme() +elif theme == "light": + set_light_theme() +else: + set_light_theme() +{{< /code-block >}} + +### Numeric flags + +For numeric flags, use `get_integer_value` or `get_float_value`. These are appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: + +{{< code-block lang="python" >}} +max_items = client.get_integer_value("cart-max-items", 20, eval_ctx) + +discount_rate = client.get_float_value("discount-rate", 0.0, eval_ctx) +{{< /code-block >}} + +### Object flags + +For structured data, use `get_object_value`. This returns a dictionary with complex configuration: + +{{< code-block lang="python" >}} +config = client.get_object_value("feature-config", { + "maxRetries": 3, + "timeout": 30 +}, eval_ctx) + +max_retries = config.get("maxRetries", 3) +timeout = config.get("timeout", 30) +{{< /code-block >}} + +### Flag evaluation details + +When you need more than just the flag value, use the `*_details` methods. These return both the evaluated value and metadata explaining the evaluation: + +{{< code-block lang="python" >}} +details = client.get_boolean_details("new-feature", False, eval_ctx) + +print(f"Value: {details.value}") +print(f"Variant: {details.variant}") +print(f"Reason: {details.reason}") +print(f"Error Code: {details.error_code}") +print(f"Error Message: {details.error_message}") +{{< /code-block >}} + +Flag details help you debug evaluation behavior and understand why a user received a given value. + +### Evaluation without context + +You can evaluate flags without providing an evaluation context. This is useful for global flags that don't require user-specific targeting: + +{{< code-block lang="python" >}} +# Global feature flag - no context needed +maintenance_mode = client.get_boolean_value("maintenance-mode", False) + +if maintenance_mode: + return "Service temporarily unavailable" +{{< /code-block >}} + +## Waiting for provider initialization + +By default, the provider initializes asynchronously and flag evaluations return default values until the first Remote Configuration payload is received. If your application requires flags to be ready before handling requests, you can wait for the provider to initialize using event handlers: + +{{< code-block lang="python" >}} +import threading +from openfeature import api +from openfeature.event import ProviderEvent +from ddtrace.openfeature import DataDogProvider + +# Create an event to wait for readiness +ready_event = threading.Event() + +def on_ready(event_details): + ready_event.set() + +# Register event handler +api.add_handler(ProviderEvent.PROVIDER_READY, on_ready) + +# Set provider +provider = DataDogProvider() +api.set_provider(provider) + +# Wait for provider to be ready (with optional timeout) +if ready_event.wait(timeout=30): + print("Provider is ready") +else: + print("Provider initialization timed out") + +# Create client and evaluate flags +client = api.get_client() +{{< /code-block >}} + +**Note:** This requires OpenFeature SDK 0.7.0 or later. Most applications don't need to wait for initialization, as flag evaluations work immediately with default values. + +## Cleanup + +When your application exits, shut down the OpenFeature API to clean up resources: + +{{< code-block lang="python" >}} +api.shutdown() +{{< /code-block >}} + +## Troubleshooting + +### Provider not enabled + +If you see warnings about the provider not being enabled, ensure `DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true` is set in your environment: + +{{< code-block lang="bash" >}} +export DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true +{{< /code-block >}} + +### Remote Configuration not working + +Verify that: +1. Your Datadog Agent is version 7.55 or later +2. Remote Configuration is enabled on the Agent +3. `DD_SERVICE` and `DD_ENV` environment variables are set +4. The tracer can communicate with the Agent + +[1]: https://openfeature.dev/ +[2]: /agent/remote_config/ ## Further reading From e5cc431c19b182e8f64b431422a12004c45e4326 Mon Sep 17 00:00:00 2001 From: Joe Peeples Date: Wed, 17 Dec 2025 10:42:03 -0500 Subject: [PATCH 11/18] consolidate duplicate files Files were in two different paths (older `setup` path and newer `server` path) --- content/en/feature_flags/server/nodejs.md | 191 ++++++++++++++++++++- content/en/feature_flags/setup/nodejs.md | 199 ---------------------- 2 files changed, 190 insertions(+), 200 deletions(-) delete mode 100644 content/en/feature_flags/setup/nodejs.md diff --git a/content/en/feature_flags/server/nodejs.md b/content/en/feature_flags/server/nodejs.md index 82db2d5a098..65ab48e4206 100644 --- a/content/en/feature_flags/server/nodejs.md +++ b/content/en/feature_flags/server/nodejs.md @@ -8,6 +8,9 @@ further_reading: - link: "/tracing/trace_collection/dd_libraries/nodejs/" tag: "Documentation" text: "Node.js Tracing" +- link: "/apm/" + tag: "Documentation" + text: "APM Setup" --- {{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} @@ -18,7 +21,193 @@ Feature Flags are in Preview. Complete the form to request access. This page describes how to instrument your Node.js application with the Datadog Feature Flags SDK. -Documentation coming soon. +## Installing and initializing + +Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install `dd-trace` and enable remote configuration with the `flaggingProvider` option as shown below. See documentation on `dd-trace` integration for detailed APM installation instructions. + +```shell +npm install dd-trace @openfeature/server-sdk +``` + +```javascript +import { OpenFeature } from '@openfeature/server-sdk' +import tracer from 'dd-trace'; + +tracer.init({ + experimental: { + flaggingProvider: { + enabled: true, + } + } +}); + +OpenFeature.setProvider(tracer.openfeature); +``` + +### Accepting default variant until initialization is complete + +When you call `setProvider` without waiting, the client returns default values until Remote Configuration loads in the background. This approach keeps your application responsive during startup but may serve defaults for early requests. + +```javascript +OpenFeature.setProvider(tracer.openfeature); +const client = OpenFeature.getClient(); + +app.get('/my-endpoint', (req, res) => { + const value = client.getBooleanValue('my-flag', false); + if (value) { + res.send('feature enabled!'); + } else { + res.send('feature disabled!'); + } +}); +``` + +### Waiting for initialization before evaluating a flag + +Use `setProviderAndWait` to ensure the provider fully initializes before evaluating flags. This guarantees that flag evaluations use actual configuration data rather than defaults, at the cost of delaying requests during initialization. + +```javascript +const initializationPromise = OpenFeature.setProviderAndWait(tracer.openfeature); +const client = OpenFeature.getClient(); + +app.get('/my-endpoint', async (req, res) => { + await initializationPromise; + + OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID + }); + + const value = client.getBooleanValue('my-flag', false); + if (value) { + res.send('feature enabled!'); + } else { + res.send('feature disabled!'); + } +}); +``` + +## Set the evaluation context + +Define who or what the flag evaluation applies to using an `EvaluationContext`. The evaluation context can include user or session information used to determine which flag variations should be returned. Call `OpenFeature.setContext` method before evaluating flags to ensure proper targeting. + +## Evaluating flags + +After creating the `OpenFeature` client as described in the previous section, you can start reading flag values throughout your app. Flag evaluation uses locally cached data, so no network requests occur when evaluating flags. + +Each flag is identified by a _key_ (a unique string) and can be evaluated with a _typed getter_ that returns a value of the expected type. If the flag doesn't exist or cannot be evaluated, the SDK returns the provided default value. + +### Boolean flags + +Use `getBooleanValue()` for flags that represent on/off or true/false conditions. Optionally set the context for specific targeting rules. + +```javascript +OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID +}); + +const isNewCheckoutEnabled = client.getBooleanValue( + 'new-checkout-flow', // flag key + false, // default value +); + +if (isNewCheckoutEnabled) { + showNewCheckoutFlow(); +} else { + showLegacyCheckout(); +} +``` + +### String flags + +Use `getStringValue()` for flags that select between multiple variants or configuration strings. For example: + +```javascript +OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID +}); + +const theme = client.getStringValue( + 'ui-theme', // flag key + 'light', // default value +); + +switch (theme) { + case 'light': + setLightTheme(); + break; + case 'dark': + setDarkTheme(); + break; + case 'blue': + setBlueTheme(); + break; + default: + setLightTheme(); +} +``` + +### Number flags + +For number flags, use `getNumberValue()`. This is appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: + +```javascript +OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID +}); + +const maxItems = client.getNumberValue( + 'max-cart-items', // flag key + 20, // default value +); + +const priceMultiplier = client.getNumberValue( + 'pricing-multiplier', // flag key + 1.3, // default value +); +``` + +### Object flags + +For structured JSON data, use `getObjectValue()`. This method returns an `object`, which can represent primitives, arrays, or dictionaries. Object flags are useful for remote configuration scenarios where multiple properties need to be provided together. + +```javascript +OpenFeature.setContext({ + userID: req.session?.userID, + companyID: req.session?.companyID +}); + +const defaultConfig = { + color: '#00A3FF', + fontSize: 14, +}; +const config = client.getObjectValue('ui-config', defaultConfig); +``` + +### Flag evaluation details + +When you need more than just the flag value, use the `getDetails` functions. These methods return both the evaluated value and metadata explaining the evaluation: + +* `getBooleanDetails() -> EvaluationDetails` +* `getStringDetails() -> EvaluationDetails` +* `getNumberDetails() -> EvaluationDetails` +* `getObjectDetails() -> EvaluationDetails` + +For example: + +```javascript +const details = client.getStringDetails('paywall-layout', 'control'); + +console.log(details.value); // Evaluated value (for example: "A", "B", or "control") +console.log(details.variant); // Variant name, if applicable +console.log(details.reason); // Description of why this value was chosen (for example: "TARGETING_MATCH") +console.log(details.errorCode); // The error that occurred during evaluation, if any +console.log(details.errorMessage); // A more detailed message of the error that occurred, if any +console.log(details.flagMetadata); // Additional information about the evaluation +``` ## Further reading diff --git a/content/en/feature_flags/setup/nodejs.md b/content/en/feature_flags/setup/nodejs.md deleted file mode 100644 index ca94cfaf90a..00000000000 --- a/content/en/feature_flags/setup/nodejs.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Node.js Feature Flags Support -description: Set up Datadog Feature Flags for Node.js applications. -further_reading: -- link: "/feature_flags/setup/" - tag: "Documentation" - text: "Feature Flags Setup" -- link: "/apm/" - tag: "Documentation" - text: "APM Setup" ---- - -## Installing and initializing - -Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install `dd-trace` and enable remote configuration with the `flaggingProvider` option as shown below. See documentation on `dd-trace` integration for detailed APM installation instructions. - -```shell -npm install dd-trace @openfeature/server-sdk -``` - -```javascript -import { OpenFeature } from '@openfeature/server-sdk' -import tracer from 'dd-trace'; - -tracer.init({ - experimental: { - flaggingProvider: { - enabled: true, - } - } -}); - -OpenFeature.setProvider(tracer.openfeature); -``` - -### Accepting default variant until initialization is complete - -When you call `setProvider` without waiting, the client returns default values until Remote Configuration loads in the background. This approach keeps your application responsive during startup but may serve defaults for early requests. - -```javascript -OpenFeature.setProvider(tracer.openfeature); -const client = OpenFeature.getClient(); - -app.get('/my-endpoint', (req, res) => { - const value = client.getBooleanValue('my-flag', false); - if (value) { - res.send('feature enabled!'); - } else { - res.send('feature disabled!'); - } -}); -``` - -### Waiting for initialization before evaluating a flag - -Use `setProviderAndWait` to ensure the provider fully initializes before evaluating flags. This guarantees that flag evaluations use actual configuration data rather than defaults, at the cost of delaying requests during initialization. - -```javascript -const initializationPromise = OpenFeature.setProviderAndWait(tracer.openfeature); -const client = OpenFeature.getClient(); - -app.get('/my-endpoint', async (req, res) => { - await initializationPromise; - - OpenFeature.setContext({ - userID: req.session?.userID, - companyID: req.session?.companyID - }); - - const value = client.getBooleanValue('my-flag', false); - if (value) { - res.send('feature enabled!'); - } else { - res.send('feature disabled!'); - } -}); -``` - -## Set the evaluation context - -Define who or what the flag evaluation applies to using an `EvaluationContext`. The evaluation context can include user or session information used to determine which flag variations should be returned. Call `OpenFeature.setContext` method before evaluating flags to ensure proper targeting. - -## Evaluating flags - -After creating the `OpenFeature` client as described in the previous section, you can start reading flag values throughout your app. Flag evaluation uses locally cached data, so no network requests occur when evaluating flags. - -Each flag is identified by a _key_ (a unique string) and can be evaluated with a _typed getter_ that returns a value of the expected type. If the flag doesn't exist or cannot be evaluated, the SDK returns the provided default value. - -### Boolean flags - -Use `getBooleanValue()` for flags that represent on/off or true/false conditions. Optionally set the context for specific targeting rules. - -```javascript -OpenFeature.setContext({ - userID: req.session?.userID, - companyID: req.session?.companyID -}); - -const isNewCheckoutEnabled = client.getBooleanValue( - 'new-checkout-flow', // flag key - false, // default value -); - -if (isNewCheckoutEnabled) { - showNewCheckoutFlow(); -} else { - showLegacyCheckout(); -} -``` - -### String flags - -Use `getStringValue()` for flags that select between multiple variants or configuration strings. For example: - -```javascript -OpenFeature.setContext({ - userID: req.session?.userID, - companyID: req.session?.companyID -}); - -const theme = client.getStringValue( - 'ui-theme', // flag key - 'light', // default value -); - -switch (theme) { - case 'light': - setLightTheme(); - break; - case 'dark': - setDarkTheme(); - break; - case 'blue': - setBlueTheme(); - break; - default: - setLightTheme(); -} -``` - -### Number flags - -For number flags, use `getNumberValue()`. This is appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: - -```javascript -OpenFeature.setContext({ - userID: req.session?.userID, - companyID: req.session?.companyID -}); - -const maxItems = client.getNumberValue( - 'max-cart-items', // flag key - 20, // default value -); - -const priceMultiplier = client.getNumberValue( - 'pricing-multiplier', // flag key - 1.3, // default value -); -``` - -### Object flags - -For structured JSON data, use `getObjectValue()`. This method returns an `object`, which can represent primitives, arrays, or dictionaries. Object flags are useful for remote configuration scenarios where multiple properties need to be provided together. - -```javascript -OpenFeature.setContext({ - userID: req.session?.userID, - companyID: req.session?.companyID -}); - -const defaultConfig = { - color: '#00A3FF', - fontSize: 14, -}; -const config = client.getObjectValue('ui-config', defaultConfig); -``` - -### Flag evaluation details - -When you need more than just the flag value, use the `getDetails` functions. These methods return both the evaluated value and metadata explaining the evaluation: - -* `getBooleanDetails() -> EvaluationDetails` -* `getStringDetails() -> EvaluationDetails` -* `getNumberDetails() -> EvaluationDetails` -* `getObjectDetails() -> EvaluationDetails` - -For example: - -```javascript -const details = client.getStringDetails('paywall-layout', 'control'); - -console.log(details.value); // Evaluated value (for example: "A", "B", or "control") -console.log(details.variant); // Variant name, if applicable -console.log(details.reason); // Description of why this value was chosen (for example: "TARGETING_MATCH") -console.log(details.errorCode); // The error that occurred during evaluation, if any -console.log(details.errorMessage); // A more detailed message of the error that occurred, if any -console.log(details.flagMetadata); // Additional information about the evaluation -``` From 30154a0e2fa2402aef2028c02b8046f308c9358c Mon Sep 17 00:00:00 2001 From: Tyler Potter Date: Wed, 17 Dec 2025 10:16:16 -0700 Subject: [PATCH 12/18] Add Java Feature Flags Setup Documentation (#33194) * Add Java Feature Flags setup documentation - Add comprehensive Java SDK onboarding guide - Include installation instructions for Maven and Gradle - Document OpenFeature provider initialization and usage - Add code examples for all flag types (boolean, string, int, double, object) - Document error handling and common error codes - Include best practices and troubleshooting guide - Add Java to feature flags setup page navigation - Document integration with Datadog APM and exposure tracking Related: FFE Server SDK code freeze preparation * fix(docs): Add missing bootstrap JAR and improve Java Feature Flags documentation Critical fixes: - Add missing dd-java-agent-feature-flagging-bootstrap dependency to all examples - Add Building from Source section with detailed instructions - Explain bootstrap module purpose (classloader communication) - Add troubleshooting for ClassNotFoundException Improvements to match Java APM documentation patterns: - Add application server configuration tabs (Spring Boot, Tomcat, JBoss, Jetty, Docker) - Update all code examples to use SLF4J logger instead of System.out/err - Add Compatibility requirements section - Add Getting started section - Update initialization example to show complete application structure Code quality: - Use logger.info/warn/error throughout with parameterized messages - Show proper exception handling with logger - Match actual implementation in ffe-dogfooding repo - Include named client usage ("my-app") The documentation now accurately reflects the required dependencies, follows established Datadog docs patterns, and provides complete setup instructions for the development build. * docs(java): Improve documentation based on review feedback Changes: - Add cross-linking to Configuration section from early warning - Add OpenFeature SDK to compatibility requirements (it is required) - Remove all local build instructions (only reference published X.X.X versions) - Add skip guidance for users with existing agent/remote-config setup - Clarify ProviderNotReadyError is OpenFeature exception (optional handling) - Update exception handling to be optional based on availability requirements - Note that not catching exception may prevent application startup Improvements: - Users with existing APM can skip to provider initialization - Users with existing remote-config can skip agent configuration - Clear guidance on when exception handling is optional vs required - Removed all references to building from source * docs(java): Add event state watching and clarify provider instance sharing Changes: - Add PROVIDER_ERROR and PROVIDER_STALE event listeners to async init example - Note that PROVIDER_CONFIGURATION_CHANGED is optional (depends on provider support) - Update multiple clients section: "organize context and flags" (not just flags) - Clarify that Provider instance is shared globally (client names are organizational only) The Provider constructor doesn't take a name parameter - it's a single shared instance. Named clients are just for organizing your application code, not separate providers. * docs(java): Align flag keys and attributes with mobile SDK conventions Changes: - Update all flag keys to use dot notation (matching Android/iOS): * new-checkout-flow -> checkout.new * ui-theme -> ui.theme * payment-api-endpoint -> payment.api.endpoint * max-retries -> retries.max * discount-rate -> pricing.discount.rate * feature-config -> ui.config * All other flags updated to dot notation - Standardize attribute to use "tier" consistently (not "plan") - Remove "country" attribute from basic example to match mobile simplicity This creates consistency across all SDK documentation and makes it easier for users to migrate between platforms or reference examples. * fix tile image, add page to side nav * headings: sentence-case capitalization * style linter, general style edits * Add Java Feature Flags setup documentation - Add comprehensive Java SDK onboarding guide - Include installation instructions for Maven and Gradle - Document OpenFeature provider initialization and usage - Add code examples for all flag types (boolean, string, int, double, object) - Document error handling and common error codes - Include best practices and troubleshooting guide - Add Java to feature flags setup page navigation - Document integration with Datadog APM and exposure tracking Related: FFE Server SDK code freeze preparation * fix(docs): Add missing bootstrap JAR and improve Java Feature Flags documentation Critical fixes: - Add missing dd-java-agent-feature-flagging-bootstrap dependency to all examples - Add Building from Source section with detailed instructions - Explain bootstrap module purpose (classloader communication) - Add troubleshooting for ClassNotFoundException Improvements to match Java APM documentation patterns: - Add application server configuration tabs (Spring Boot, Tomcat, JBoss, Jetty, Docker) - Update all code examples to use SLF4J logger instead of System.out/err - Add Compatibility requirements section - Add Getting started section - Update initialization example to show complete application structure Code quality: - Use logger.info/warn/error throughout with parameterized messages - Show proper exception handling with logger - Match actual implementation in ffe-dogfooding repo - Include named client usage ("my-app") The documentation now accurately reflects the required dependencies, follows established Datadog docs patterns, and provides complete setup instructions for the development build. * docs(java): Improve documentation based on review feedback Changes: - Add cross-linking to Configuration section from early warning - Add OpenFeature SDK to compatibility requirements (it is required) - Remove all local build instructions (only reference published X.X.X versions) - Add skip guidance for users with existing agent/remote-config setup - Clarify ProviderNotReadyError is OpenFeature exception (optional handling) - Update exception handling to be optional based on availability requirements - Note that not catching exception may prevent application startup Improvements: - Users with existing APM can skip to provider initialization - Users with existing remote-config can skip agent configuration - Clear guidance on when exception handling is optional vs required - Removed all references to building from source * docs(java): Add event state watching and clarify provider instance sharing Changes: - Add PROVIDER_ERROR and PROVIDER_STALE event listeners to async init example - Note that PROVIDER_CONFIGURATION_CHANGED is optional (depends on provider support) - Update multiple clients section: "organize context and flags" (not just flags) - Clarify that Provider instance is shared globally (client names are organizational only) The Provider constructor doesn't take a name parameter - it's a single shared instance. Named clients are just for organizing your application code, not separate providers. * docs(java): Align flag keys and attributes with mobile SDK conventions Changes: - Update all flag keys to use dot notation (matching Android/iOS): * new-checkout-flow -> checkout.new * ui-theme -> ui.theme * payment-api-endpoint -> payment.api.endpoint * max-retries -> retries.max * discount-rate -> pricing.discount.rate * feature-config -> ui.config * All other flags updated to dot notation - Standardize attribute to use "tier" consistently (not "plan") - Remove "country" attribute from basic example to match mobile simplicity This creates consistency across all SDK documentation and makes it easier for users to migrate between platforms or reference examples. * docs(java): Move Java Feature Flags docs to server/ directory - Move java.md from feature_flags/setup/ to feature_flags/setup/server/ - Update frontmatter to reference server-side landing page - Apply style edits from linter (sentence-case headings, consistent capitalization) * extra dev info * various style edits * section collapsing * better sections * reduce expanders --------- Co-authored-by: Joe Peeples --- content/en/feature_flags/server/java.md | 604 +++++++++++++++++- .../feature_flags/feature_flags_client.html | 7 + 2 files changed, 607 insertions(+), 4 deletions(-) diff --git a/content/en/feature_flags/server/java.md b/content/en/feature_flags/server/java.md index 0b416b40626..6f35c688496 100644 --- a/content/en/feature_flags/server/java.md +++ b/content/en/feature_flags/server/java.md @@ -5,20 +5,616 @@ further_reading: - link: "/feature_flags/server/" tag: "Documentation" text: "Server-Side Feature Flags" -- link: "/tracing/trace_collection/dd_libraries/java/" +- link: "/tracing/trace_collection/automatic_instrumentation/dd_libraries/java/" tag: "Documentation" - text: "Java Tracing" + text: "Java APM and Distributed Tracing" --- {{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} Feature Flags are in Preview. Complete the form to request access. {{< /callout >}} +
Java Feature Flags support is experimental and requires enabling an experimental flag in the tracer. See the Configuration section for details.
+ ## Overview -This page describes how to instrument your Java application with the Datadog Feature Flags SDK. +This page describes how to instrument a Java application with the Datadog Feature Flags SDK. Datadog feature flags provide a unified way to remotely control feature availability in your app, experiment safely, and deliver new experiences with confidence. + +The Java SDK integrates feature flags directly into the Datadog APM tracer and implements the [OpenFeature](https://openfeature.dev/) standard for maximum flexibility and compatibility. + +
If you're using Datadog APM and your application already has the Datadog Java tracer and Remote Configuration enabled, skip to Initialize the OpenFeature provider. You only need to add the OpenFeature dependencies and initialize the provider.
+ +## Compatibility requirements + +The Datadog Feature Flags SDK for Java requires: +- **Java 11 or higher** +- **Datadog Java APM Tracer**: Version **1.57.0** or later +- **OpenFeature SDK**: Version **1.18.2** or later +- **Datadog Agent**: Version **7.x or later** with Remote Configuration enabled +- **Datadog API Key**: Required for Remote Configuration + +For a full list of Datadog's Java version and framework support, read [Compatibility Requirements](/tracing/trace_collection/compatibility/java/). + +## Getting started + +Before you begin, make sure you've already [installed and configured the Agent](/tracing/trace_collection/automatic_instrumentation/dd_libraries/java/#install-and-configure-the-agent). + +## Installation + +Feature flagging is integrated into the Datadog Java APM tracer. You need the tracer JAR and the OpenFeature SDK dependencies. + +The `dd-java-agent-feature-flagging-bootstrap` JAR contains shared interfaces that enable the Datadog tracer (running in the bootstrap classloader) to communicate with the OpenFeature provider (running in the application classloader). This is a standard pattern for Java agents. Both JARs are required for feature flags to work. + +{{< tabs >}} +{{% tab "Gradle (Groovy)" %}} +Add the following dependencies to your `build.gradle`: + +{{< code-block lang="groovy" filename="build.gradle" >}} +dependencies { + // Datadog Java tracer (includes feature flagging) + implementation 'com.datadoghq:dd-trace-api:X.X.X' + + // OpenFeature SDK for flag evaluation + implementation 'dev.openfeature:sdk:1.18.2' + + // Datadog OpenFeature Provider + implementation 'com.datadoghq:dd-openfeature:X.X.X' + + // Datadog Feature Flagging Bootstrap (required) + implementation 'com.datadoghq:dd-java-agent-feature-flagging-bootstrap:X.X.X' +} +{{< /code-block >}} +{{% /tab %}} + +{{% tab "Gradle (Kotlin)" %}} +Add the following dependencies to your `build.gradle.kts`: + +{{< code-block lang="kotlin" filename="build.gradle.kts" >}} +dependencies { + // Datadog Java tracer (includes feature flagging) + implementation("com.datadoghq:dd-trace-api:X.X.X") + + // OpenFeature SDK for flag evaluation + implementation("dev.openfeature:sdk:1.18.2") + + // Datadog OpenFeature Provider + implementation("com.datadoghq:dd-openfeature:X.X.X") + + // Datadog Feature Flagging Bootstrap (required) + implementation("com.datadoghq:dd-java-agent-feature-flagging-bootstrap:X.X.X") +} +{{< /code-block >}} +{{% /tab %}} + +{{% tab "Maven" %}} +Add the following dependencies to your `pom.xml`: + +{{< code-block lang="xml" filename="pom.xml" >}} + + + + com.datadoghq + dd-trace-api + X.X.X + + + + + dev.openfeature + sdk + 1.18.2 + + + + + com.datadoghq + dd-openfeature + X.X.X + + + + + com.datadoghq + dd-java-agent-feature-flagging-bootstrap + X.X.X + + +{{< /code-block >}} +{{% /tab %}} +{{< /tabs >}} + +## Configuration + +If your Datadog Agent already has Remote Configuration enabled for other features (like Dynamic Instrumentation or Application Security), you can skip the Agent configuration and go directly to [Application configuration](#application-configuration). + +### Agent configuration + +Configure your Datadog Agent to enable Remote Configuration: + +{{< code-block lang="yaml" filename="datadog.yaml" >}} +# Enable Remote Configuration +remote_configuration: + enabled: true + +# Set your API key +api_key: +{{< /code-block >}} + +### Application configuration + +If your application already runs with `-javaagent:dd-java-agent.jar` and has Remote Configuration enabled (`DD_REMOTE_CONFIG_ENABLED=true`), you only need to add the experimental feature flag (`DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true`). Skip the tracer download and JVM configuration steps. + +Configure your Java application with the required environment variables or system properties: + +{{< tabs >}} +{{% tab "Environment Variables" %}} +{{< code-block lang="bash" >}} +# Required: Enable Remote Configuration in the tracer +export DD_REMOTE_CONFIG_ENABLED=true + +# Required: Enable experimental feature flagging support +export DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true + +# Required: Your Datadog API key +export DD_API_KEY= + +# Required: Service name +export DD_SERVICE= + +# Required: Environment (e.g., prod, staging, dev) +export DD_ENV= + +# Optional: Version +export DD_VERSION= + +# Start your application with the tracer +java -javaagent:path/to/dd-java-agent.jar -jar your-application.jar +{{< /code-block >}} +{{% /tab %}} + +{{% tab "System Properties" %}} +{{< code-block lang="bash" >}} +java -javaagent:path/to/dd-java-agent.jar \ + -Ddd.remote.config.enabled=true \ + -Ddd.experimental.flagging.provider.enabled=true \ + -Ddd.api.key= \ + -Ddd.service= \ + -Ddd.env= \ + -Ddd.version= \ + -jar your-application.jar +{{< /code-block >}} +{{% /tab %}} +{{< /tabs >}} + +The Datadog feature flagging system starts automatically when the tracer is initialized with both Remote Configuration and the experimental flagging provider enabled. No additional initialization code is required in your application. + +
Feature flagging requires both DD_REMOTE_CONFIG_ENABLED=true and DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true. Without the experimental flag, the feature flagging system does not start and the Provider returns the programmatic default.
+ +### Add the Java tracer to the JVM + +For instructions on how to add the `-javaagent` argument to your application server or framework, see [Add the Java Tracer to the JVM](/tracing/trace_collection/automatic_instrumentation/dd_libraries/java/#add-the-java-tracer-to-the-jvm). + +Make sure to include the feature flagging configuration flags: +- `-Ddd.remote.config.enabled=true` +- `-Ddd.experimental.flagging.provider.enabled=true` + +## Initialize the OpenFeature provider + +Initialize the Datadog OpenFeature provider in your application startup code. The provider connects to the feature flagging system running in the Datadog tracer. + +{{< code-block lang="java" >}} +import dev.openfeature.sdk.OpenFeatureAPI; +import dev.openfeature.sdk.Client; +import datadog.trace.api.openfeature.Provider; +import dev.openfeature.sdk.exceptions.ProviderNotReadyError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class App { + private static final Logger logger = LoggerFactory.getLogger(App.class); + private static Client client; + + public static void main(String[] args) throws Exception { + // Initialize the Datadog provider + logger.info("Initializing Datadog OpenFeature Provider..."); + OpenFeatureAPI api = OpenFeatureAPI.getInstance(); + + try { + // Set provider and wait for initial configuration (recommended) + api.setProviderAndWait(new Provider()); + client = api.getClient("my-app"); + logger.info("OpenFeature provider initialized successfully"); + } catch (ProviderNotReadyError e) { + // Optional: Handle gracefully - app will use default flag values + logger.warn("Provider not ready (no tracer/configuration available), continuing with defaults", e); + client = api.getClient("my-app"); + logger.info("App will use default flag values until provider is ready"); + } + + // Your application code here + } +} +{{< /code-block >}} + +Use `setProviderAndWait()` to block until the initial flag configuration is received from Remote Configuration. This ensures flags are ready before the application starts serving traffic. The default timeout is 30 seconds. + +`ProviderNotReadyError` is an OpenFeature SDK exception thrown when the provider times out during initialization. Catching it allows the application to start with default flag values if Remote Configuration is unavailable. If not caught, the exception propagates and may prevent application startup. Handle this based on your availability requirements. + +### Asynchronous initialization + +For non-blocking initialization, use `setProvider()` and listen for provider events: + +{{< code-block lang="java" >}} +import dev.openfeature.sdk.ProviderEvent; + +OpenFeatureAPI api = OpenFeatureAPI.getInstance(); +Client client = api.getClient(); + +// Listen for provider state changes +client.on(ProviderEvent.PROVIDER_READY, (event) -> { + logger.info("Feature flags ready!"); +}); + +client.on(ProviderEvent.PROVIDER_ERROR, (event) -> { + logger.error("Provider error: {}", event.getMessage()); +}); + +client.on(ProviderEvent.PROVIDER_STALE, (event) -> { + logger.warn("Provider configuration is stale"); +}); + +// Set provider asynchronously +api.setProvider(new Provider()); +{{< /code-block >}} + +## Set the evaluation context + +The evaluation context defines the subject (user, device, session) for flag evaluation. It determines which flag variations are returned based on targeting rules. + +{{< code-block lang="java" >}} +import dev.openfeature.sdk.EvaluationContext; +import dev.openfeature.sdk.MutableContext; + +// Create an evaluation context with a targeting key and attributes +EvaluationContext context = new MutableContext("user-123") + .add("email", "user@example.com") + .add("tier", "premium"); + +// Use the context for flag evaluations (see next section) +{{< /code-block >}} + +The `targetingKey` (for example, `user-123`) is the primary identifier used for consistent flag evaluations and percentage-based rollouts. It's typically a user ID, session ID, or device ID. + +## Evaluate flags + +Evaluate feature flags using the OpenFeature client. All flag types are supported: Boolean, string, integer, double, and object. + +{{< tabs >}} +{{% tab "Boolean" %}} +{{< code-block lang="java" >}} +// Simple Boolean evaluation +boolean enabled = client.getBooleanValue("checkout.new", false, context); + +if (enabled) { + // New checkout flow +} else { + // Old checkout flow +} + +// Get detailed evaluation result +import dev.openfeature.sdk.FlagEvaluationDetails; + +FlagEvaluationDetails details = + client.getBooleanDetails("checkout.new", false, context); + +logger.info("Value: {}", details.getValue()); +logger.info("Variant: {}", details.getVariant()); +logger.info("Reason: {}", details.getReason()); +{{< /code-block >}} +{{% /tab %}} + +{{% tab "String" %}} +{{< code-block lang="java" >}} +// Evaluate string flags (e.g., UI themes, API endpoints) +String theme = client.getStringValue("ui.theme", "light", context); + +String apiEndpoint = client.getStringValue( + "payment.api.endpoint", + "https://api.example.com/v1", + context +); +{{< /code-block >}} +{{% /tab %}} + +{{% tab "Number" %}} +{{< code-block lang="java" >}} +// Integer flags (e.g., limits, quotas) +int maxRetries = client.getIntegerValue("retries.max", 3, context); + +// Double flags (e.g., thresholds, rates) +double discountRate = client.getDoubleValue("pricing.discount.rate", 0.0, context); +{{< /code-block >}} +{{% /tab %}} + +{{% tab "Object" %}} +{{< code-block lang="java" >}} +import dev.openfeature.sdk.Value; + +// Evaluate object/JSON flags for complex configuration +Value config = client.getObjectValue("ui.config", new Value(), context); + +// Access structured data +if (config.isStructure()) { + Value timeout = config.asStructure().getValue("timeout"); + Value endpoint = config.asStructure().getValue("endpoint"); +} +{{< /code-block >}} +{{% /tab %}} +{{< /tabs >}} + +## Error handling + +The OpenFeature SDK uses a default value pattern. If evaluation fails for any reason, the default value you provide is returned. + +{{< code-block lang="java" >}} +import dev.openfeature.sdk.ErrorCode; + +// Check evaluation details for errors +FlagEvaluationDetails details = + client.getBooleanDetails("checkout.new", false, context); + +if (details.getErrorCode() != null) { + switch (details.getErrorCode()) { + case FLAG_NOT_FOUND: + logger.warn("Flag does not exist: {}", "checkout.new"); + break; + case PROVIDER_NOT_READY: + logger.warn("Provider not initialized yet"); + break; + case TARGETING_KEY_MISSING: + logger.warn("Evaluation context missing targeting key"); + break; + case TYPE_MISMATCH: + logger.error("Flag value type doesn't match requested type"); + break; + default: + logger.error("Evaluation error for flag: {}", "checkout.new", details.getErrorCode()); + } +} +{{< /code-block >}} + +### Common error codes + +| Error Code | Description | Resolution | +|------------|-------------|------------| +| `PROVIDER_NOT_READY` | Initial configuration not received | Wait for provider initialization or use `setProviderAndWait()` | +| `FLAG_NOT_FOUND` | Flag doesn't exist in configuration | Check flag key or create flag in Datadog UI | +| `TARGETING_KEY_MISSING` | No targeting key in evaluation context | Provide a targeting key when creating context | +| `TYPE_MISMATCH` | Flag value can't be converted to requested type | Use correct evaluation method for flag type | +| `INVALID_CONTEXT` | Evaluation context is null | Provide a valid evaluation context | + +## Advanced configuration + +### Custom initialization timeout + +Configure how long the provider waits for initial configuration: + +{{< code-block lang="java" >}} +import datadog.trace.api.openfeature.Provider; +import java.util.concurrent.TimeUnit; + +Provider.Options options = new Provider.Options() + .initTimeout(10, TimeUnit.SECONDS); + +api.setProviderAndWait(new Provider(options)); +{{< /code-block >}} + +### Configuration change events + +Listen for configuration updates from Remote Configuration: + +{{< code-block lang="java" >}} +import dev.openfeature.sdk.ProviderEvent; + +client.on(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, (event) -> { + logger.info("Flag configuration updated: {}", event.getMessage()); + // Optionally re-evaluate flags or trigger cache refresh +}); +{{< /code-block >}} + +`PROVIDER_CONFIGURATION_CHANGED` is an optional OpenFeature event. Check the Datadog provider documentation to verify this event is supported in your version. + +### Multiple clients + +Use named clients to organize context and flags by domain or team: + +{{< code-block lang="java" >}} +// Named clients share the same provider instance but can have different contexts +Client checkoutClient = api.getClient("checkout"); +Client analyticsClient = api.getClient("analytics"); + +// Each client can have its own evaluation context +EvaluationContext checkoutContext = new MutableContext("session-abc"); +EvaluationContext analyticsContext = new MutableContext("user-123"); + +boolean newCheckout = checkoutClient.getBooleanValue( + "checkout.ui.new", false, checkoutContext +); + +boolean enhancedAnalytics = analyticsClient.getBooleanValue( + "analytics.enhanced", false, analyticsContext +); +{{< /code-block >}} + +The `Provider` instance is shared globally. Client names are for organizational purposes only and don't create separate provider instances. All clients use the same underlying Datadog provider and flag configurations. + +## Best practices + +### Initialize early +Initialize the OpenFeature provider as early as possible in your application lifecycle (for example, in `main()` or application startup). This ensures flags are ready before business logic executes. + +### Use meaningful default values +Always provide sensible default values that maintain safe behavior if flag evaluation fails: + +{{< code-block lang="java" >}} +// Good: Safe default that maintains current behavior +boolean useNewAlgorithm = client.getBooleanValue("algorithm.new", false, context); + +// Good: Conservative default for limits +int rateLimit = client.getIntegerValue("rate.limit", 100, context); +{{< /code-block >}} + +### Create context once +Create the evaluation context once per request/user/session and reuse it for all flag evaluations: + +{{< code-block lang="java" >}} +// In a web filter or request handler +EvaluationContext userContext = new MutableContext(userId) + .add("email", user.getEmail()) + .add("tier", user.getTier()); + +// Reuse context for all flags in this request +boolean featureA = client.getBooleanValue("feature.a", false, userContext); +boolean featureB = client.getBooleanValue("feature.b", false, userContext); +{{< /code-block >}} + +Rebuilding the evaluation context for every flag evaluation adds unnecessary overhead. Create the context once at the start of the request lifecycle, then pass it to all subsequent flag evaluations. + +### Handle initialization failures (optional) +Consider handling initialization failures if your application can function with default flag values: + +{{< code-block lang="java" >}} +try { + api.setProviderAndWait(new Provider()); +} catch (ProviderNotReadyError e) { + // Log error and continue with defaults + logger.warn("Feature flags not ready, using defaults", e); + // Application will use default values for all flags +} +{{< /code-block >}} + +If feature flags are critical for your application to function, let the exception propagate to prevent startup. + +### Use consistent targeting keys +Use consistent, stable identifiers as targeting keys: +- **Good**: User IDs, session IDs, device IDs +- **Avoid**: Timestamps, random values, frequently changing IDs + +### Monitor flag evaluation +Use the detailed evaluation results for logging and debugging: + +{{< code-block lang="java" >}} +FlagEvaluationDetails details = + client.getBooleanDetails("feature.critical", false, context); + +logger.info("Flag: {} | Value: {} | Variant: {} | Reason: {}", + "feature.critical", + details.getValue(), + details.getVariant(), + details.getReason() +); +{{< /code-block >}} + +## Troubleshooting + +### Provider not ready + +**Problem**: `PROVIDER_NOT_READY` errors when evaluating flags + +**Common Causes**: +1. **Experimental flag not enabled**: Feature flagging is disabled by default +2. **Agent not ready**: Application started before Agent was fully initialized +3. **No flags configured**: No flags published to your service/environment combination +4. **Agent Remote Configuration disabled**: Agent not configured for Remote Configuration + +**Solutions**: +1. **Enable experimental feature**: + ```bash + export DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true + ``` +2. **Verify feature flagging system started** in application logs: + ``` + [dd.trace] Feature Flagging system starting + [dd.trace] Feature Flagging system started + ``` +3. **Ensure Agent is ready** before app starts (use health checks in Docker/Kubernetes) +4. **Check EVP Proxy discovered** in logs: + ``` + discovered ... evpProxyEndpoint=evp_proxy/v4/ configEndpoint=v0.7/config + ``` +5. **Wait for Remote Configuration sync** (can take 30-60 seconds after publishing flags) +6. **Verify flags are published** in Datadog UI to the correct service and environment + +### ClassNotFoundException or NoClassDefFoundError + +**Problem**: Application fails to start with `ClassNotFoundException` for Datadog classes like `datadog.trace.api.featureflag.FeatureFlaggingGateway` + +**Cause**: Missing the bootstrap JAR dependency. The bootstrap module contains shared interfaces that allow the Datadog tracer (running in the bootstrap classloader) to communicate with the OpenFeature provider (running in the application classloader). Without it, the two components cannot interact. + +**Solutions**: +1. **Add the bootstrap JAR** to your dependencies: + ```xml + + com.datadoghq + dd-java-agent-feature-flagging-bootstrap + X.X.X + + ``` +2. **Verify both dependencies are included** in your build: + - `dd-openfeature` (the OpenFeature provider) + - `dd-java-agent-feature-flagging-bootstrap` (the bootstrap module) +3. **Check the classpath** includes both JARs in your runtime configuration + +### Feature flagging system not starting + +**Problem**: No "Feature Flagging system starting" messages in logs + +**Cause**: Experimental flag not enabled in tracer + +**Solution**: +Add `-Ddd.experimental.flagging.provider.enabled=true` to your Java command or set `DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true` + +### EVP proxy not available error + +**Problem**: Logs show "EVP Proxy not available" or "agent does not support EVP proxy" + +**Cause**: Application started before Agent was fully initialized + +**Solutions**: +1. **Add Agent health check** in orchestration (Docker Compose, Kubernetes) +2. **Add startup delay** to application +3. **Retry logic**: Implement retry on provider initialization failure +4. **Upgrade Agent**: Ensure using Agent 7.x or later with EVP Proxy support + +### Flags not updating + +**Problem**: Flag configuration changes aren't reflected in the application + +**Solutions**: +1. Check Remote Configuration is enabled on both Agent and application +2. Verify Agent can connect to Datadog backend +3. Check application logs for "No configuration changes" or "Configuration received" +4. Ensure flags are published (not saved as drafts) in the Datadog UI +5. Verify service and environment tags match between app and flag targeting + +### Type mismatch errors + +**Problem**: `TYPE_MISMATCH` errors when evaluating flags + +**Solutions**: +1. Verify the flag type in Datadog UI matches the evaluation method +2. Use correct method: `getBooleanValue()`, `getStringValue()`, `getIntegerValue()`, `getDoubleValue()` +3. Check flag configuration for correct value types + +### No exposures in Datadog + +**Problem**: Flag evaluations aren't appearing in Datadog UI -Documentation coming soon. +**Solutions**: +1. Verify the flag's allocation has `doLog=true` configured +2. Check Datadog Agent is receiving exposure events +3. Verify `DD_API_KEY` is correct +4. Check Agent logs for exposure upload errors ## Further reading diff --git a/layouts/partials/feature_flags/feature_flags_client.html b/layouts/partials/feature_flags/feature_flags_client.html index 0242ff75633..ec36a19a6a6 100644 --- a/layouts/partials/feature_flags/feature_flags_client.html +++ b/layouts/partials/feature_flags/feature_flags_client.html @@ -30,6 +30,13 @@
+
From df185b1986adcaf8f7040afa72e1888750f88acc Mon Sep 17 00:00:00 2001 From: Joe Peeples Date: Wed, 17 Dec 2025 12:21:21 -0500 Subject: [PATCH 13/18] remove Java from client-side tile partial --- layouts/partials/feature_flags/feature_flags_client.html | 7 ------- 1 file changed, 7 deletions(-) diff --git a/layouts/partials/feature_flags/feature_flags_client.html b/layouts/partials/feature_flags/feature_flags_client.html index ec36a19a6a6..0242ff75633 100644 --- a/layouts/partials/feature_flags/feature_flags_client.html +++ b/layouts/partials/feature_flags/feature_flags_client.html @@ -30,13 +30,6 @@ - From 5cd10628b0cbef1548180a96f8fb4140977fdf82 Mon Sep 17 00:00:00 2001 From: Joe Peeples Date: Wed, 17 Dec 2025 12:39:31 -0500 Subject: [PATCH 14/18] Python review edits also applied to other languages with the same text --- content/en/feature_flags/server/go.md | 2 +- content/en/feature_flags/server/python.md | 16 ++++++++-------- content/en/feature_flags/server/ruby.md | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/content/en/feature_flags/server/go.md b/content/en/feature_flags/server/go.md index 895a462fb0a..c62fda55a29 100644 --- a/content/en/feature_flags/server/go.md +++ b/content/en/feature_flags/server/go.md @@ -169,7 +169,7 @@ evalCtx := openfeature.NewEvaluationContext( ) {{< /code-block >}} -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." +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. ## Evaluate flags diff --git a/content/en/feature_flags/server/python.md b/content/en/feature_flags/server/python.md index 38ede5d4d8e..e35fc7ce389 100644 --- a/content/en/feature_flags/server/python.md +++ b/content/en/feature_flags/server/python.md @@ -90,7 +90,7 @@ eval_ctx = EvaluationContext( ) {{< /code-block >}} -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." +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. ## Evaluate flags @@ -211,7 +211,7 @@ else: client = api.get_client() {{< /code-block >}} -**Note:** This requires OpenFeature SDK 0.7.0 or later. Most applications don't need to wait for initialization, as flag evaluations work immediately with default values. +
Waiting for provider initialization requires OpenFeature SDK 0.7.0 or later. Most applications don't need to wait for initialization, as flag evaluations work immediately with default values.
## Cleanup @@ -225,7 +225,7 @@ api.shutdown() ### Provider not enabled -If you see warnings about the provider not being enabled, ensure `DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true` is set in your environment: +If you receive warnings about the provider not being enabled, ensure `DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true` is set in your environment: {{< code-block lang="bash" >}} export DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true @@ -233,11 +233,11 @@ export DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true ### Remote Configuration not working -Verify that: -1. Your Datadog Agent is version 7.55 or later -2. Remote Configuration is enabled on the Agent -3. `DD_SERVICE` and `DD_ENV` environment variables are set -4. The tracer can communicate with the Agent +Verify the following to ensure that Remote Configuration is working: +- Datadog Agent is version 7.55 or later +- Remote Configuration is enabled on the Agent +- `DD_SERVICE` and `DD_ENV` environment variables are set +- The tracer can communicate with the Agent [1]: https://openfeature.dev/ [2]: /agent/remote_config/ diff --git a/content/en/feature_flags/server/ruby.md b/content/en/feature_flags/server/ruby.md index d5a715383ae..3c0f6cf0d86 100644 --- a/content/en/feature_flags/server/ruby.md +++ b/content/en/feature_flags/server/ruby.md @@ -71,7 +71,7 @@ context = OpenFeature::SDK::EvaluationContext.new( ) ``` -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." +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. ## Evaluating flags From 4022d7f8030fab264feb6ebfab961db4b431d770 Mon Sep 17 00:00:00 2001 From: Joe Peeples Date: Wed, 17 Dec 2025 12:56:20 -0500 Subject: [PATCH 15/18] Ruby review edits and other languages with same text --- content/en/feature_flags/server/nodejs.md | 4 ++-- content/en/feature_flags/server/ruby.md | 27 +++++++++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/content/en/feature_flags/server/nodejs.md b/content/en/feature_flags/server/nodejs.md index 65ab48e4206..60df166f31f 100644 --- a/content/en/feature_flags/server/nodejs.md +++ b/content/en/feature_flags/server/nodejs.md @@ -23,7 +23,7 @@ This page describes how to instrument your Node.js application with the Datadog ## Installing and initializing -Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install `dd-trace` and enable remote configuration with the `flaggingProvider` option as shown below. See documentation on `dd-trace` integration for detailed APM installation instructions. +Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install `dd-trace` and enable Remote Configuration with the `flaggingProvider` option as shown below. See documentation on `dd-trace` integration for detailed APM installation instructions. ```shell npm install dd-trace @openfeature/server-sdk @@ -172,7 +172,7 @@ const priceMultiplier = client.getNumberValue( ### Object flags -For structured JSON data, use `getObjectValue()`. This method returns an `object`, which can represent primitives, arrays, or dictionaries. Object flags are useful for remote configuration scenarios where multiple properties need to be provided together. +For structured JSON data, use `getObjectValue()`. This method returns an `object`, which can represent primitives, arrays, or dictionaries. Object flags are useful for Remote Configuration scenarios where multiple properties need to be provided together. ```javascript OpenFeature.setContext({ diff --git a/content/en/feature_flags/server/ruby.md b/content/en/feature_flags/server/ruby.md index 3c0f6cf0d86..907592a1dad 100644 --- a/content/en/feature_flags/server/ruby.md +++ b/content/en/feature_flags/server/ruby.md @@ -8,6 +8,9 @@ further_reading: - link: "/tracing/trace_collection/dd_libraries/ruby/" tag: "Documentation" text: "Ruby Tracing" +- link: "/apm/" + tag: "Documentation" + text: "APM Setup" --- {{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} @@ -29,7 +32,7 @@ Before setting up the Ruby Feature Flags SDK, ensure you have: ## Installing and initializing -Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install the required gems and configure remote configuration with OpenFeature support. +Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install the required gems and configure Remote Configuration with OpenFeature support. ```shell gem install ddtrace openfeature-sdk @@ -55,7 +58,7 @@ end client = OpenFeature::SDK.build_client ``` -The client returns default values until remote configuration loads in the background. This approach keeps your application responsive during startup but may serve defaults for early requests. +The client returns default values until Remote Configuration loads in the background. This approach keeps your application responsive during startup but may serve defaults for early requests. ## Set the evaluation context @@ -120,7 +123,7 @@ end ### Number flags -For numeric flags, use `fetch_integer_value()` or `fetch_float_value()`. Ruby also provides `fetch_number_value()` which returns the appropriate type based on the default value. These are appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: +For numeric flags, use `fetch_integer_value()` or `fetch_float_value()`. Ruby also provides `fetch_number_value()`, which returns the appropriate type based on the default value. These methods are appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: ```ruby max_items = client.fetch_integer_value( @@ -145,7 +148,7 @@ batch_size = client.fetch_number_value( ### Object flags -For structured data, use `fetch_object_value()`. This method returns a hash. Object flags are useful for remote configuration scenarios where multiple properties need to be provided together. +For structured data, use `fetch_object_value()`. This method returns a hash. Object flags are useful for Remote Configuration scenarios where multiple properties need to be provided together. ```ruby config = client.fetch_object_value( @@ -199,18 +202,18 @@ end ## Troubleshooting -### Feature flags surprisingly always return default values +### Feature flags always return default values -If feature flags always return default values: +If feature flags unexpectedly always return default values, check the following: -1. Verify Remote configuration is enabled in your Datadog Agent configuration -2. Ensure service and environment are configured (either through `DD_SERVICE`/`DD_ENV` environment variables or `config.service`/`config.env` in Ruby) -3. Check that `config.remote.enabled = true` and `config.open_feature.enabled = true` are set in your Ruby application's Datadog configuration -4. Verify the datadog gem version includes OpenFeature support (2.23.0 or later) +- Verify Remote Configuration is enabled in your Datadog Agent configuration +- Ensure the service and environment are configured (either through `DD_SERVICE` and `DD_ENV` environment variables or `config.service` and `config.env` in Ruby) +- Check that `config.remote.enabled = true` and `config.open_feature.enabled = true` are set in your Ruby application's Datadog configuration +- Verify the `datadog` gem version includes OpenFeature support (2.23.0 or later) -### Remote configuration connection issues +### Remote Configuration connection issues -Check the Datadog tracer logs for Remote configuration status: +Check the Datadog tracer logs for Remote Configuration status: ```ruby # Enable startup and debug logging From 75ba92033e2884979499cc5092922c682a00c00e Mon Sep 17 00:00:00 2001 From: Joe Peeples Date: Wed, 17 Dec 2025 15:49:55 -0500 Subject: [PATCH 16/18] Go review edits and other languages with same text --- content/en/feature_flags/server/go.md | 2 +- content/en/feature_flags/server/java.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/en/feature_flags/server/go.md b/content/en/feature_flags/server/go.md index c62fda55a29..635e06a24a1 100644 --- a/content/en/feature_flags/server/go.md +++ b/content/en/feature_flags/server/go.md @@ -58,7 +58,7 @@ Start the Datadog tracer and register the Datadog OpenFeature provider. The trac ### Blocking initialization -Use `SetProviderAndWait` to block until the initial flag configuration is received. This ensures flags are ready before your application starts handling requests. +Use `SetProviderAndWait` to block evaluation until the initial flag configuration is received. This ensures flags are ready before your application starts handling requests. {{< code-block lang="go" >}} package main diff --git a/content/en/feature_flags/server/java.md b/content/en/feature_flags/server/java.md index 6f35c688496..2e3412ae6f0 100644 --- a/content/en/feature_flags/server/java.md +++ b/content/en/feature_flags/server/java.md @@ -236,7 +236,7 @@ public class App { } {{< /code-block >}} -Use `setProviderAndWait()` to block until the initial flag configuration is received from Remote Configuration. This ensures flags are ready before the application starts serving traffic. The default timeout is 30 seconds. +Use `setProviderAndWait()` to block evaluation until the initial flag configuration is received from Remote Configuration. This ensures flags are ready before the application starts serving traffic. The default timeout is 30 seconds. `ProviderNotReadyError` is an OpenFeature SDK exception thrown when the provider times out during initialization. Catching it allows the application to start with default flag values if Remote Configuration is unavailable. If not caught, the exception propagates and may prevent application startup. Handle this based on your availability requirements. From a7437e0d29716eefbaeb4bfa1d5594a513cbb91f Mon Sep 17 00:00:00 2001 From: Joe Peeples Date: Wed, 17 Dec 2025 16:01:47 -0500 Subject: [PATCH 17/18] Node.js review edits + other languages --- content/en/feature_flags/server/nodejs.md | 10 +++++----- content/en/feature_flags/server/ruby.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/content/en/feature_flags/server/nodejs.md b/content/en/feature_flags/server/nodejs.md index 60df166f31f..e8162b02e61 100644 --- a/content/en/feature_flags/server/nodejs.md +++ b/content/en/feature_flags/server/nodejs.md @@ -44,7 +44,7 @@ tracer.init({ OpenFeature.setProvider(tracer.openfeature); ``` -### Accepting default variant until initialization is complete +### Accepting default values before initialization When you call `setProvider` without waiting, the client returns default values until Remote Configuration loads in the background. This approach keeps your application responsive during startup but may serve defaults for early requests. @@ -62,7 +62,7 @@ app.get('/my-endpoint', (req, res) => { }); ``` -### Waiting for initialization before evaluating a flag +### Waiting for provider initialization Use `setProviderAndWait` to ensure the provider fully initializes before evaluating flags. This guarantees that flag evaluations use actual configuration data rather than defaults, at the cost of delaying requests during initialization. @@ -89,11 +89,11 @@ app.get('/my-endpoint', async (req, res) => { ## Set the evaluation context -Define who or what the flag evaluation applies to using an `EvaluationContext`. The evaluation context can include user or session information used to determine which flag variations should be returned. Call `OpenFeature.setContext` method before evaluating flags to ensure proper targeting. +Define who or what the flag evaluation applies to using an `EvaluationContext`. The evaluation context can include user or session information used to determine which flag variations should be returned. Call the `OpenFeature.setContext` method before evaluating flags to ensure proper targeting. -## Evaluating flags +## Evaluate flags -After creating the `OpenFeature` client as described in the previous section, you can start reading flag values throughout your app. Flag evaluation uses locally cached data, so no network requests occur when evaluating flags. +After creating the `OpenFeature` client as described in the [Installing and initializing](#installing-and-initializing) section, you can start reading flag values throughout your app. Flag evaluation uses locally cached data, so no network requests occur when evaluating flags. Each flag is identified by a _key_ (a unique string) and can be evaluated with a _typed getter_ that returns a value of the expected type. If the flag doesn't exist or cannot be evaluated, the SDK returns the provided default value. diff --git a/content/en/feature_flags/server/ruby.md b/content/en/feature_flags/server/ruby.md index 907592a1dad..4fa5263d9ea 100644 --- a/content/en/feature_flags/server/ruby.md +++ b/content/en/feature_flags/server/ruby.md @@ -76,7 +76,7 @@ context = OpenFeature::SDK::EvaluationContext.new( 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. -## Evaluating flags +## Evaluate flags After creating the `OpenFeature` client, you can start reading flag values throughout your app. Flag evaluation uses locally cached data, so no network requests occur when evaluating flags. From 273980374a92e9d11c7d183a9578cce757d1da10 Mon Sep 17 00:00:00 2001 From: Joe Peeples Date: Wed, 17 Dec 2025 16:30:17 -0500 Subject: [PATCH 18/18] clean up links --- content/en/feature_flags/server/nodejs.md | 8 +++++--- content/en/feature_flags/server/ruby.md | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/content/en/feature_flags/server/nodejs.md b/content/en/feature_flags/server/nodejs.md index e8162b02e61..00ce3d63719 100644 --- a/content/en/feature_flags/server/nodejs.md +++ b/content/en/feature_flags/server/nodejs.md @@ -8,9 +8,9 @@ further_reading: - link: "/tracing/trace_collection/dd_libraries/nodejs/" tag: "Documentation" text: "Node.js Tracing" -- link: "/apm/" +- link: "/tracing/" tag: "Documentation" - text: "APM Setup" + text: "Learn about Application Performance Monitoring (APM)" --- {{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} @@ -23,7 +23,7 @@ This page describes how to instrument your Node.js application with the Datadog ## Installing and initializing -Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install `dd-trace` and enable Remote Configuration with the `flaggingProvider` option as shown below. See documentation on `dd-trace` integration for detailed APM installation instructions. +Feature Flagging is provided by Application Performance Monitoring (APM). To integrate APM into your application with feature flagging support, install `dd-trace` and enable Remote Configuration with the `flaggingProvider` option as shown below. See [Tracing Node.js Applications][1] for detailed APM installation instructions. ```shell npm install dd-trace @openfeature/server-sdk @@ -212,3 +212,5 @@ console.log(details.flagMetadata); // Additional information about the evaluatio ## Further reading {{< partial name="whats-next/whats-next.html" >}} + +[1]: /tracing/trace_collection/automatic_instrumentation/dd_libraries/nodejs/ \ No newline at end of file diff --git a/content/en/feature_flags/server/ruby.md b/content/en/feature_flags/server/ruby.md index 4fa5263d9ea..f9e040a258b 100644 --- a/content/en/feature_flags/server/ruby.md +++ b/content/en/feature_flags/server/ruby.md @@ -5,12 +5,12 @@ further_reading: - link: "/feature_flags/server/" tag: "Documentation" text: "Server-Side Feature Flags" -- link: "/tracing/trace_collection/dd_libraries/ruby/" +- link: "/tracing/trace_collection/automatic_instrumentation/dd_libraries/ruby/" tag: "Documentation" text: "Ruby Tracing" -- link: "/apm/" +- link: "/tracing/" tag: "Documentation" - text: "APM Setup" + text: "Learn about Application Performance Monitoring (APM)" --- {{< callout url="http://datadoghq.com/product-preview/feature-flags/" >}} @@ -32,7 +32,7 @@ Before setting up the Ruby Feature Flags SDK, ensure you have: ## Installing and initializing -Feature Flagging is provided by APM. To integrate APM into your application with feature flagging support, install the required gems and configure Remote Configuration with OpenFeature support. +Feature Flagging is provided by Application Performance Monitoring (APM). To integrate APM into your application with feature flagging support, install the required gems and configure Remote Configuration with OpenFeature support. ```shell gem install ddtrace openfeature-sdk