Ce produit n'est pas pris en charge par le site Datadog que vous avez sélectionné. ().
Cette page n'est pas encore disponible en français, sa traduction est en cours. Si vous avez des questions ou des retours sur notre projet de traduction actuel, n'hésitez pas à nous contacter.
Overview
This guide walks you through the process of migrating feature flags from LaunchDarkly to Datadog Feature Flags. Follow these general steps:
Datadog Feature Flags are built on the OpenFeature standard, which provides vendor-agnostic feature flag APIs. You need to install both the OpenFeature SDK and the Datadog provider for your platform.
Follow the installation instructions for your platform:
Client-side SDKs
Server-side SDKs
After installation, ensure you have initialized the Datadog provider with your credentials and set up an evaluation context that includes user attributes for targeting.
2. Set up and verify a new flag
Create a flag in Datadog by navigating to Software Delivery > Feature Flags, then clicking Create Flag.
Implement the flag in your application code (see the code examples below these steps).
Test the flag in your local development environment to ensure it works as expected.
Deploy the application to your staging or testing environments and verify the flag’s functionality.
Once verified, deploy the application to your production environment and test the flag again.
Android & Android TV
importcom.datadog.android.flags.FlagsClientimportcom.datadog.android.flags.EvaluationContextvalflagsClient=FlagsClient.getDefault()// Set evaluation context
flagsClient.setEvaluationContext(EvaluationContext(targetingKey="user-123",attributes=mapOf("country"to"US","tier"to"premium")))// Evaluate flag
valshowNewFeature=flagsClient.resolveBooleanValue(flagKey="show-new-feature",defaultValue=false)if(showNewFeature){// Feature is enabled
}
iOS & tvOS
importDatadogFlagsletflagsClient=FlagsClient.shared()// Set evaluation contextflagsClient.setEvaluationContext(FlagsEvaluationContext(targetingKey:"user-123",attributes:["country":.string("US"),"tier":.string("premium")]))// Evaluate flagletshowNewFeature=flagsClient.resolveBooleanValue(flagKey:"show-new-feature",defaultValue:false)ifshowNewFeature{// Feature is enabled}
JavaScript (browser)
constclient=OpenFeature.getClient();// Context is set on the provider, not passed to getBooleanValue
constshowNewFeature=client.getBooleanValue('show-new-feature',false// default value
);if(showNewFeature){// Feature is enabled
}
usingOpenFeature;usingOpenFeature.Model;varclient=Api.Instance.GetClient("my-service");varevalCtx=EvaluationContext.Builder().SetTargetingKey("user-123").Set("country","US").Set("tier","premium").Build();varshowNewFeature=awaitclient.GetBooleanValueAsync("show-new-feature",false,evalCtx);if(showNewFeature){// Feature is enabled}
require'openfeature/sdk'client=OpenFeature::SDK.build_clientcontext=OpenFeature::SDK::EvaluationContext.new(targeting_key:'user-123',country:'US',tier:'premium')show_new_feature=client.fetch_boolean_value(flag_key:'show-new-feature',default_value:false,evaluation_context:context)ifshow_new_feature# Feature is enabledend
3. Identify critical flags in LaunchDarkly
Make a list of all the feature flags currently in use within your application.
Categorize the flags as critical or non-critical based on their importance and impact on your application’s functionality.
Flags that are disabled or are rolled out to 100% can be categorized as non-critical.
4. Remove non-critical flag code
For the non-critical flags identified in the previous step, remove the flag code from your application and from LaunchDarkly. They are no longer relevant.
Test your application thoroughly to ensure that the removal of these flags does not introduce any regressions or unintended behavior.
5. Create fallback values for critical flags
Implement a wrapper function that provides a fallback mechanism to use the LaunchDarkly flag values if the application experiences issues fetching the Datadog flag.
LaunchDarkly and Datadog SDKs use strongly typed methods for flag evaluation (for example, getBooleanValue, getStringValue, getIntegerValue). The examples below demonstrate Boolean flag evaluation. You will need to create similar wrapper functions for each flag type used in your application.
Android & Android TV
FallbackWrapper.kt
importcom.launchdarkly.sdk.LDContextimportcom.launchdarkly.sdk.android.LDClientimportcom.launchdarkly.sdk.android.LDConfigimportcom.datadog.android.flags.Flagsimportcom.datadog.android.flags.FlagsClientimportcom.datadog.android.flags.EvaluationContextclassFallbackWrapper(userId:String,evaluationContext:Map<String,String>){privatevalldClient:LDClientprivatevalddClient:FlagsClientinit{valldConfig=LDConfig.Builder().mobileKey('YOUR_LD_MOBILE_KEY').build()valcb=LDContext.builder(userId)for((key,value)inevaluationContext){cb.set(key,value)}valldContext=cb.build()ldClient=LDClient.init(this@BaseApplication,ldConfig,ldContext,5)valddConfig=Configuration.Builder(clientToken='YOUR_DD_CLIENT_TOKEN',env='DD_ENV',variant='APP_VARIANT_NAME')Flags.enable()ddClient=FlagsClient.Builder().build()ddClient.setEvaluationContext(EvaluationContext(targetingKey=userId,attributes=evaluationContext))}fungetBooleanFlag(flagKey:String,defaultValue:Boolean):Boolean{returntry{ddClient.resolveBooleanValue(flagKey=flagKey,defaultValue=defaultValue)}catch(e:Exception){println("Falling back to LaunchDarkly for flag: $flagKey")ldClient.boolVariation(flagKey,defaultValue)}}}
iOS & tvOS
FallbackWrapper.swift
importFoundationimportLaunchDarklyimportDatadogFlagsimportDatadogCoreclassFallbackWrapper{privateletldClient:LDClientprivateletddClient:FlagsClientinit(userId:String,evaluationContext:[String:AnyValue]=[:]){letldConfig=LDConfig(mobileKey:'YOUR_LD_MOBILE_KEY',autoEnvAttributes:.enabled)varldContext=LDContextBuilder(key:userId)for(key,value)inevaluationContext{ldContext.trySetValue(key,value)}LDClient.start(config:ldConfig,context:ldContext)self.ldClient=LDClient.get()!Datadog.initialize(with:Datadog.Configuration(clientToken:"<client token>",env:"<environment>",service:"<service name>"),trackingConsent:.granted)Flags.enable()self.ddClient=FlagsClient.create()self.ddClient.setEvaluationContext(FlagsEvaluationContext(targetingKey:userId,attributes:evaluationContext))}funcgetBooleanFlag(flagKey:String,defaultValue:Bool)->Bool{do{returnself.ddClient.resolveBooleanValue(flagKey:flagKey,defaultValue:defaultValue)}catch{print("Falling back to LaunchDarkly for flag: \(flagKey)")returnself.ldClient.boolVariation(forKey:flagKey,defaultValue:defaultValue)}}}
JavaScript (browser)
fallback-wrapper.js
import*asldfrom'launchdarkly-js-client-sdk';import{OpenFeature}from'@openfeature/web-sdk';import{DatadogProvider}from'@datadog/openfeature-browser';classFallbackWrapper{privateldClient;privateddClient;asyncinitialize(userId,evaluationContext={}){try{constddProvider=newDatadogProvider({applicationId:'YOUR_APP_ID',clientToken:'YOUR_CLIENT_TOKEN',env:'ENV_NAME',});awaitOpenFeature.setProviderAndWait(ddProvider,{targetingKey:userId,...evaluationContext});this.ddClient=OpenFeature.getClient();}catch(e){console.warn(`Unable to initialize Datadog feature flags client: ${e}. Flag evaluations will fall back to LaunchDarkly.`);}this.ldClient=ld.initialize('YOUR_LD_KEY',{key:userId,...evaluationContext});awaitthis.ldClient.waitForInitialization();}asyncgetBooleanFeatureFlag(flagKey,defaultValue){try{if(!this.ddClient){thrownewError('Datadog feature flags client not initialized');}returnthis.ddClient.getBooleanValue(flagKey,defaultValue);}catch(e){console.warn(`Falling back to LaunchDarkly for flag: ${flagKey});
return this.ldClient.variation(flagKey, defaultValue);
}
}
}
React
FallbackWrapper.jsx
import*asReactfrom'react';import{useLDClient}from'launchdarkly-react-client-sdk';import{useFlag}from'@openfeature/react-sdk';exportfunctionuseFeatureFlagWithFallback(flagKey,defaultValue){constldClient=useLDClient();const{value:ddFlagValue,errorMessage:ddError}=useFlag(flagKey,defaultValue);returnReact.useMemo(()=>{if(ddError){console.warn(`Falling back to LaunchDarkly for flag: ${flagKey}`);returnldClient.variation(flagKey,defaultValue);}returnddFlagValue;},[ddFlagValue,ddError,ldClient]);}
.NET
FallbackWrapper.cs
usingOpenFeature;usingOpenFeature.Model;usingLaunchDarkly.Sdk;usingLaunchDarkly.Sdk.Server;publicclassFallbackWrapper{privatereadonlyLdClientldClient;privatereadonlyIFeatureClientddClient;publicFallbackWrapper(){varconfig=Configuration.Builder("YOUR_LD_KEY").Build();ldClient=newLdClient(config);ddClient=Api.Instance.GetClient("my-service");}publicasyncTask<bool>GetBooleanFlagAsync(stringflagKey,stringuserId,Dictionary<string,string>evaluationContext,booldefaultValue){try{varevalCtx=EvaluationContext.Builder().SetTargetingKey(userId);foreach(varattrinevaluationContext){evalCtx.Set(attr.Key,attr.Value);}returnawaitddClient.GetBooleanValueAsync(flagKey,defaultValue,evalCtx.Build());}catch(Exceptione){Console.WriteLine($"Falling back to LaunchDarkly for flag: {flagKey}");varcb=Context.Builder(userId);foreach(varattrinevaluationContext){cb.Set(attr.Key,attr.Value);}returnldClient.BoolVariation(flagKey,cb.Build(),defaultValue);}}}
Go
fallback_wrapper.go
packagemainimport("context""log"ld"github.com/launchdarkly/go-server-sdk/v6""github.com/launchdarkly/go-sdk-common/v3/ldcontext""github.com/open-feature/go-sdk/openfeature")typeFallbackWrapperstruct{ldClient*ld.LDClientddClient*openfeature.Client}func(fw*FallbackWrapper)GetBooleanFlag(ctxcontext.Context,flagKeystring,userIdstring,evaluationContextmap[string]string,defaultValuebool,)bool{ofContext:=openfeature.NewEvaluationContext(userId,evaluationContext,)ddValue,err:=fw.ddClient.BooleanValue(ctx,flagKey,defaultValue,ofContext)iferr!=nil{log.Printf("Falling back to LaunchDarkly for flag: %s",flagKey)cb:=ldcontext.NewBuilder(userId)fork,v:=rangeevaluationContext{cb.SetString(k,v)}ldValue,_:=fw.ldClient.BoolVariation(flagKey,cb.Build(),defaultValue)returnldValue}returnddValue}
Java
FallbackWrapper.java
importjava.util.Map;importcom.launchdarkly.sdk.ContextBuilder;importcom.launchdarkly.sdk.LDContext;importcom.launchdarkly.sdk.server.LDClient;importdev.openfeature.sdk.Client;importdev.openfeature.sdk.EvaluationContext;importdev.openfeature.sdk.MutableContext;importdev.openfeature.sdk.OpenFeatureAPI;publicclassFallbackWrapper{privatefinalLDClientldClient;privatefinalClientddClient;publicFallbackWrapper(StringldKey){this.ldClient=newLDClient(ldKey);this.ddClient=OpenFeatureAPI.getInstance().getClient();}publicbooleangetBooleanFlag(StringflagKey,StringuserId,Map<String,String>evaluationContext,booleandefaultValue){try{EvaluationContextcontext=newMutableContext(userId);for(Map.Entry<String,String>entry:evaluationContext.entrySet()){context.add(entry.getKey(),entry.getValue());}returnddClient.getBooleanValue(flagKey,defaultValue,context);}catch(Exceptione){System.out.println("Falling back to LaunchDarkly for flag: "+flagKey);ContextBuildercb=LDContext.builder(userId);for(Map.Entry<String,String>entry:evaluationContext.entrySet()){cb.set(entry.getKey(),entry.getValue());}returnldClient.boolVariation(flagKey,cb.build(),defaultValue);}}}
Node.js
fallback-wrapper.js
import*asLaunchDarklyfrom'@launchdarkly/node-server-sdk';import{OpenFeature}from'@openfeature/server-sdk';constldClient=LaunchDarkly.initialize('YOUR_LD_SDK_KEY');exportasyncfunctiongetBooleanFeatureFlag(flagKey,userId,attributes,defaultValue){constddClient=OpenFeature.getClient();try{constddContext={targetingKey:userId,...attributes};returnddClient.getBooleanValue(flagKey,defaultValue,ddContext);}catch(e){console.warn(`Falling back to LaunchDarkly for flag: ${flagKey}`);constldContext={key:userId,...attributes};returnldClient.variation(flagKey,ldContext,defaultValue);}}
Python
fallback_wrapper.py
importldclientfromldclientimportContextfromopenfeatureimportapifromopenfeature.evaluation_contextimportEvaluationContextdefget_boolean_feature_flag(flag_key,user_id,evaluation_context,default_value):ld_client=ldclient.get()dd_client=api.get_client()try:dd_context=EvaluationContext(targeting_key=user_id,attributes=evaluation_context)returndd_client.get_boolean_value(flag_key,default_value,dd_context)exceptExceptionase:print(f"Falling back to LaunchDarkly for flag: {flag_key}")cb=Context.builder(user_id)forkey,valueinevaluation_context.items():cb.set(key,value)returnld_client.variation(flag_key,cb.build(),default_value)
Ruby
fallback_wrapper.rb
require'ldclient-rb'require'openfeature/sdk'classFallbackWrapperdefinitialize(ld_key)@ld_client=LaunchDarkly::LDClient.new(ld_key)@dd_client=OpenFeature::SDK.build_clientenddefget_boolean_flag(flag_key,user_id,evaluation_context,default_value)begincontext_attrs={targeting_key:user_id}context_attrs.merge!(evaluation_context)context=OpenFeature::SDK::EvaluationContext.new(context_attrs)@dd_client.fetch_boolean_value(flag_key:flag_key,default_value:default_value,evaluation_context:context)rescue=>eputs"Falling back to LaunchDarkly for flag: #{flag_key}"ld_context_attrs={key:user_id}ld_context_attrs.merge!(evaluation_context)ld_context=LaunchDarkly::LDContext.create(ld_context_attrs)@ld_client.variation(flag_key,ld_context,default_value)endendend
6. Recreate critical flags in Datadog
Datadog can help with migrating flags. Contact Support for assistance.
In the Datadog UI, recreate the critical flags from LaunchDarkly by navigating to Software Delivery > Feature Flags.
Ensure that the flag configurations - such as rollout percentages, targeting rules, and variations - are accurately replicated in the new service.
For complex targeting rules, use the evaluation context attributes to implement equivalent logic.
7. Switch existing flags to the new application
After you have verified that the Datadog flags are working correctly, switch your application to use the function that checks Datadog for flags instead of the LaunchDarkly ones.
Remove the fallback mechanism and the LaunchDarkly flag code after you have confirmed that the Datadog flags are working as expected in production.
Further reading
Documentation, liens et articles supplémentaires utiles: