Getting Started with Feature Flag Data in RUM
Overview
Feature flag data gives you greater visibility into your user experience and performance monitoring by allowing you to determine which users are being shown a specific feature and if any change you introduce is impacting your user experience or negatively affecting performance.
By enriching your RUM data with feature flag data, you can be confident that your feature successfully launches without unintentionally causing a bug or performance regression. With this additional layer of insight, you can correlate feature releases with performance, pinpoint issues to specific releases, and troubleshoot faster.
Setup
Feature flag tracking is available in the RUM Browser SDK. To start, set up RUM browser monitoring. You need the Browser RUM SDK version >= 4.25.0.
Before v5.17.0
If you are using a version previous to 5.17.0, initialize the RUM SDK and configure the enableExperimentalFeatures
initialization parameter with ["feature_flags"]
to start collecting feature flag data.
import { datadogRum } from '@datadog/browser-rum';
// Initialize Datadog Browser SDK
datadogRum.init({
...
enableExperimentalFeatures: ["feature_flags"],
...
});
window.DD_RUM.onReady(function() {
window.DD_RUM.init({
...
enableExperimentalFeatures: ["feature_flags"],
...
})
})
window.DD_RUM &&
window.DD_RUM.init({
...
enableExperimentalFeatures: ["feature_flags"],
...
})
Feature flag tracking is available in the RUM Android SDK. To start, set up RUM Android monitoring. You need the Android RUM SDK version >= 1.18.0.
Feature flag tracking is available for your Flutter applications. To start, set up RUM Flutter monitoring. You need the Flutter Plugin version >= 1.3.2.
Feature flag tracking is available in the RUM iOS SDK. To start, set up RUM iOS monitoring. You need the iOS RUM SDK version >= 1.16.0.
Feature flag tracking is available for your React Native applications. To start, set up RUM React Native monitoring. You need the React Native RUM SDK version >= 1.7.0.
Feature flag tracking is available for your Unity applications. To start, set up RUM Unity monitoring.
Integrations
You can start collecting feature flag data with custom feature flag management solutions, or by using one of Datadog’s integration partners.
Datadog supports integrations with:
Amplitude integration
Initialize Amplitude’s SDK and create an exposure listener reporting feature flag evaluations to Datadog using the following snippet of code:
For more information about initializing Amplitude’s SDK, see Amplitude’s JavaScript SDK documentation.
const experiment = Experiment.initialize("CLIENT_DEPLOYMENT_KEY", {
exposureTrackingProvider: {
track(exposure: Exposure) {
// Send the feature flag when Amplitude reports the exposure
datadogRum.addFeatureFlagEvaluation(exposure.flag_key, exposure.variant);
}
}
})
Initialize Amplitude’s SDK and create an inspector reporting feature flag evaluations to Datadog using the snippet of code below.
For more information about initializing Amplitude’s SDK, see Amplitude’s iOS SDK documentation.
class DatadogExposureTrackingProvider : ExposureTrackingProvider {
func track(exposure: Exposure) {
// Send the feature flag when Amplitude reports the exposure
if let variant = exposure.variant {
RUMMonitor.shared().addFeatureFlagEvaluation(name: exposure.flagKey, value: variant)
}
}
}
// In initialization:
ExperimentConfig config = ExperimentConfigBuilder()
.exposureTrackingProvider(DatadogExposureTrackingProvider(analytics))
.build()
Initialize Amplitude’s SDK and create an inspector reporting feature flag evaluations to Datadog using the snippet of code below.
For more information about initializing Amplitude’s SDK, see Amplitude’s Android SDK documentation.
internal class DatadogExposureTrackingProvider : ExposureTrackingProvider {
override fun track(exposure: Exposure) {
// Send the feature flag when Amplitude reports the exposure
GlobalRumMonitor.get().addFeatureFlagEvaluation(
exposure.flagKey,
exposure.variant.orEmpty()
)
}
}
// In initialization:
val config = ExperimentConfig.Builder()
.exposureTrackingProvider(DatadogExposureTrackingProvider())
.build()
Amplitude does not support this integration. Create a ticket with Amplitude to request this feature.
ConfigCat integration
When initializing the ConfigCat Javascript SDK, subscribe to the flagEvaluated
event and report feature flag evaluations to Datadog:
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
setupHooks: (hooks) =>
hooks.on('flagEvaluated', (details) => {
datadogRum.addFeatureFlagEvaluation(details.key, details.value);
})
}
);
For more information about initializing the ConfigCat Javascript SDK, see ConfigCat’s JavaScript SDK documentation.
When initializing the ConfigCat Swift iOS SDK, subscribe to the flagEvaluated
event and report feature flag evaluations to Datadog:
let client = ConfigCatClient.get(sdkKey: "#YOUR-SDK-KEY#") { options in
options.hooks.addOnFlagEvaluated { details in
RUMMonitor.shared().addFeatureFlagEvaluation(featureFlag: details.key, variation: details.value)
}
}
For more information about initializing the ConfigCat Swift (iOS) SDK, see ConfigCat’sSwift iOS SDK documentation.
When initializing the ConfigCat Android SDK, subscribe to the flagEvaluated
event and report feature flag evaluations to Datadog:
ConfigCatClient client = ConfigCatClient.get("#YOUR-SDK-KEY#", options -> {
options.hooks().addOnFlagEvaluated(details -> {
GlobalRumMonitor.get().addFeatureFlagEvaluation(details.key, details.value);
});
});
For more information about initializing the ConfigCat Android SDK, see ConfigCat’s Android SDK documentation.
When initializing the ConfigCat Dart SDK, subscribe to the flagEvaluated
event and report feature flag evaluations to Datadog:
final client = ConfigCatClient.get(
sdkKey: '#YOUR-SDK-KEY#',
options: ConfigCatOptions(
pollingMode: PollingMode.autoPoll(),
hooks: Hooks(
onFlagEvaluated: (details) => {
DatadogSdk.instance.rum?.addFeatureFlagEvaluation(details.key, details.value);
}
)
)
);
For more information about initializing the ConfigCat Dart (Flutter) SDK, see ConfigCat’s Dart SDK documentation.
When initializing the ConfigCat React SDK, subscribe to the flagEvaluated
event and report feature flag evaluations to Datadog:
<ConfigCatProvider
sdkKey="YOUR_SDK_KEY"
pollingMode={PollingMode.AutoPoll}
options={{
setupHooks: (hooks) =>
hooks.on('flagEvaluated', (details) => {
DdRum.addFeatureFlagEvaluation(details.key, details.value);
}),
}}
>
...
</ConfigCatProvider>
For more information about initializing the ConfigCat React SDK, see ConfigCat’s React SDK documentation.
Custom feature flag management
Each time a feature flag is evaluated, add the following function to send the feature flag information to RUM:
datadogRum.addFeatureFlagEvaluation(key, value);
Each time a feature flag is evaluated, add the following function to send the feature flag information to RUM:
RUMMonitor.shared().addFeatureFlagEvaluation(key, value);
Each time a feature flag is evaluated, add the following function to send the feature flag information to RUM:
GlobalRumMonitor.get().addFeatureFlagEvaluation(key, value);
Each time a feature flag is evaluated, add the following function to send the feature flag information to RUM:
DatadogSdk.instance.rum?.addFeatureFlagEvaluation(key, value);
Each time a feature flag is evaluated, add the following function to send the feature flag information to RUM:
DdRum.addFeatureFlagEvaluation(key, value);
DevCycle integration
Initialize DevCycle’s SDK and subscribe to the variableEvaluated
event, choosing to subscribe to all variable evaluations variableEvaluated:*
or particular variable evaluations variableEvaluated:my-variable-key
.
For more information about initializing DevCycle’s SDK, see DevCycle’s JavaScript SDK documentation and for more information about DevCycle’s event system, see DevCycle’s SDK Event Documentation.
const user = { user_id: "<USER_ID>" };
const dvcOptions = { ... };
const dvcClient = initialize("<DVC_CLIENT_SDK_KEY>", user, dvcOptions);
...
dvcClient.subscribe(
"variableEvaluated:*",
(key, variable) => {
// track all variable evaluations
datadogRum.addFeatureFlagEvaluation(key, variable.value);
}
)
...
dvcClient.subscribe(
"variableEvaluated:my-variable-key",
(key, variable) => {
// track a particular variable evaluation
datadogRum.addFeatureFlagEvaluation(key, variable.value);
}
)
DevCycle does not support this integration. Create a ticket with DevCycle to request this feature.
DevCycle does not support this integration. Create a ticket with DevCycle to request this feature.
DevCycle does not support this integration. Create a ticket with DevCycle to request this feature.
DevCycle does not support this integration. Create a ticket with DevCycle to request this feature.
Eppo integration
Initialize Eppo’s SDK and create an assignment logger that additionally reports feature flag evaluations to Datadog using the snippet of code shown below.
For more information about initializing Eppo’s SDK, see Eppo’s JavaScript SDK documentation.
const assignmentLogger: IAssignmentLogger = {
logAssignment(assignment) {
datadogRum.addFeatureFlagEvaluation(assignment.featureFlag, assignment.variation);
},
};
await eppoInit({
apiKey: "<API_KEY>",
assignmentLogger,
});
Initialize Eppo’s SDK and create an assignment logger that additionally reports feature flag evaluations to Datadog using the snippet of code shown below.
For more information about initializing Eppo’s SDK, see Eppo’s iOS SDK documentation.
func IAssignmentLogger(assignment: Assignment) {
RUMMonitor.shared().addFeatureFlagEvaluation(featureFlag: assignment.featureFlag, variation: assignment.variation)
}
let eppoClient = EppoClient(apiKey: "mock-api-key", assignmentLogger: IAssignmentLogger)
Initialize Eppo’s SDK and create an assignment logger that additionally reports feature flag evaluations to Datadog using the snippet of code shown below.
For more information about initializing Eppo’s SDK, see Eppo’s Android SDK documentation.
AssignmentLogger logger = new AssignmentLogger() {
@Override
public void logAssignment(Assignment assignment) {
GlobalRumMonitor.get().addFeatureFlagEvaluation(assignment.getFeatureFlag(), assignment.getVariation());
}
};
EppoClient eppoClient = new EppoClient.Builder()
.apiKey("YOUR_API_KEY")
.assignmentLogger(logger)
.application(application)
.buildAndInit();
Eppo does not support this integration. Contact Eppo to request this feature.
Initialize Eppo’s SDK and create an assignment logger that additionally reports feature flag evaluations to Datadog using the snippet of code shown below.
For more information about initializing Eppo’s SDK, see Eppo’s React native SDK documentation.
const assignmentLogger: IAssignmentLogger = {
logAssignment(assignment) {
DdRum.addFeatureFlagEvaluation(assignment.featureFlag, assignment.variation);
},
};
await eppoInit({
apiKey: "<API_KEY>",
assignmentLogger,
});
Flagsmith Integration
Initialize Flagsmith’s SDK with the datadogRum
option, which reports feature flag evaluations to Datadog using the snippet of code shown below.
Optionally, you can configure the client so that Flagsmith traits are sent to Datadog via datadogRum.setUser()
. For more information about initializing Flagsmith’s SDK, check out Flagsmith’s JavaScript SDK documentation.
// Initialize the Flagsmith SDK
flagsmith.init({
datadogRum: {
client: datadogRum,
trackTraits: true,
},
...
})
Flagsmith does not support this integration. Create a ticket with Flagsmith to request this feature.
Flagsmith does not support this integration. Create a ticket with Flagsmith to request this feature.
Flagsmith does not support this integration. Create a ticket with Flagsmith to request this feature.
Flagsmith does not currently support this integration. Create a ticket with Flagsmith to request this feature.
Kameleoon integration
After creating and initializing the Kameleoon SDK, subscribe to the Evaluation
event using the onEvent
handler.
For more information about the SDK, see Kameleoon JavaScript SDK documentation.
client.onEvent(EventType.Evaluation, ({ featureKey, variation }) => {
datadogRum.addFeatureFlagEvaluation(featureKey, variation.key);
});
After creating and initializing the Kameleoon SDK, subscribe to the Evaluation
event using the onEvent
handler.
Learn more about SDK initialization in the Kameleoon React Native SDK documentation.
const { onEvent } = useInitialize();
onEvent(EventType.Evaluation, ({ featureKey, variation }) => {
datadogRum.addFeatureFlagEvaluation(featureKey, variation.key);
});
LaunchDarkly integration
Initialize LaunchDarkly’s SDK and create an inspector reporting feature flags evaluations to Datadog using the snippet of code shown below.
For more information about initializing LaunchDarkly’s SDK, see LaunchDarkly’s JavaScript SDK documentation.
const client = LDClient.initialize("<CLIENT_SIDE_ID>", "<CONTEXT>", {
inspectors: [
{
type: "flag-used",
name: "dd-inspector",
method: (key: string, detail: LDClient.LDEvaluationDetail) => {
datadogRum.addFeatureFlagEvaluation(key, detail.value);
},
},
],
});
LaunchDarkly does not support this integration. Create a ticket with LaunchDarkly to request this feature.
LaunchDarkly does not support this integration. Create a ticket with LaunchDarkly to request this feature.
LaunchDarkly does not support this integration. Create a ticket with LaunchDarkly to request this feature.
LaunchDarkly does not currently support this integration. Create a ticket with LaunchDarkly to request this feature.
Split Integration
Initialize Split’s SDK and create an impression listener reporting feature flag evaluations to Datadog using the following snippet of code:
For more information about initializing Split’s SDK, see Split’s JavaScript SDK documentation.
const factory = SplitFactory({
core: {
authorizationKey: "<APP_KEY>",
key: "<USER_ID>",
},
impressionListener: {
logImpression(impressionData) {
datadogRum
.addFeatureFlagEvaluation(
impressionData.impression.feature,
impressionData.impression.treatment
);
},
},
});
const client = factory.client();
Initialize Split’s SDK and create an inspector reporting feature flag evaluations to Datadog using the snippet of code below.
For more information about initializing Split’s SDK, see Split’s iOS SDK documentation.
let config = SplitClientConfig()
// Send the feature flag when Split reports the impression
config.impressionListener = { impression in
if let feature = impression.feature,
let treatment = impression.treatment {
RUMMonitor.shared().addFeatureFlagEvaluation(name: feature, value: treatment)
}
}
Initialize Split’s SDK and create an inspector reporting feature flag evaluations to Datadog using the snippet of code below.
For more information about initializing Split’s SDK, see Split’s Android SDK documentation.
internal class DatadogSplitImpressionListener : ImpressionListener {
override fun log(impression: Impression) {
// Send the feature flag when Split reports the impression
GlobalRumMonitor.get().addFeatureFlagEvaluation(
impression.split(),
impression.treatment()
)
}
override fun close() {
}
}
// In initialization:
val apikey = BuildConfig.SPLIT_API_KEY
val config = SplitClientConfig.builder()
.impressionListener(DatadogSplitImpressionListener())
.build()
Initialize Split’s SDK and create an inspector reporting feature flag evaluations to Datadog using the snippet of code below.
For more information about initializing Split’s SDK, see Split’s Flutter plugin documentation.
StreamSubscription<Impression> impressionsStream = _split.impressionsStream().listen((impression) {
// Send the feature flag when Split reports the impression
final split = impression.split;
final treatment = impression.treatment;
if (split != null && treatment != null) {
DatadogSdk.instance.rum?.addFeatureFlagEvaluation(split, treatment);
}
});
Initialize Split’s SDK and create an impression listener reporting feature flag evaluations to Datadog using the following snippet of code:
For more information about initializing Split’s SDK, see Split’s React Native SDK documentation.
const factory = SplitFactory({
core: {
authorizationKey: "<APP_KEY>",
key: "<USER_ID>",
},
impressionListener: {
logImpression(impressionData) {
DdRum
.addFeatureFlagEvaluation(
impressionData.impression.feature,
impressionData.impression.treatment
);
},
},
});
const client = factory.client();
Statsig Integration
Initialize Statsig’s SDK with statsig.initialize
.
Update your Browser RUM SDK version 4.25.0 or above.
Initialize the RUM SDK and configure the enableExperimentalFeatures
initialization parameter with ["feature_flags"]
.
Initialize Statsig’s SDK (>= v4.34.0
) and implement the gateEvaluationCallback
option as shown below:
await statsig.initialize('client-<STATSIG CLIENT KEY>',
{userID: '<USER ID>'},
{
gateEvaluationCallback: (key, value) => {
datadogRum.addFeatureFlagEvaluation(key, value);
}
}
);
Statsig does not support this integration. Contact support@statsig.com to request this feature.
Statsig does not support this integration. Contact support@statsig.com to request this feature.
Statsig does not support this integration. Contact support@statsig.com to request this feature.
Statsig does not currently support this integration. Contact support@statsig.com to request this feature.
Feature flags appear in the context of your RUM Sessions, Views, and Errors as a list.
Search feature flags using the RUM Explorer
Search through all the data collected by RUM in the RUM Explorer to surface trends on feature flags, analyze patterns with greater context, or export them into dashboards and monitors. You can search your Sessions, Views, or Errors in the RUM Explorer, with the @feature_flags.{flag_name}
attribute.
Sessions
Filtering your Sessions with the @feature_flags.{flag_name}
attribute, you can find all sessions in the given time frame where your feature flag was evaluated.
Views
Filtering your Views with the @feature_flags.{flag_name}
attribute, you can find the specific views in the given time frame where your feature flag was evaluated.
Errors
Filtering your Errors with the @feature_flags.{flag_name}
attribute, you can find all the errors in the given time frame that occurred on the View where your feature flag was evaluated
Troubleshooting
Feature flags show up in the context of events where they are evaluated, meaning they should show up on the views that the feature flag code logic is run on.
Depending on how you’ve structured your code and set up your feature flags, you may see unexpected feature flags appear in the context of some events.
For example, to see what Views your feature flag is being evaluated on, you can use the RUM Explorer to make a similar query:
Here are a few examples of reasons why your feature flag is being evaluated on unrelated Views that can help with your investigations:
- A common react component that appears on multiple pages which evaluates feature flags whenever they run.
- A routing issue where components with a feature flag evaluation are rendered before/after URL changes.
When performing your investigations, you can also scope your data for View Name
’s that are relevant to your feature flag.
Feature flag naming
The following special characters are not supported for Feature Flag Tracking: .
, :
, +
, -
, =
, &&
, ||
, >
, <
, !
, (
, )
, {
, }
, [
, ]
, ^
, "
, “
, ”
, ~
, *
, ?
, \
. Datadog recommends avoiding these characters when possible in your feature flag names. If you are required to use one of these characters, replace the character before sending the data to Datadog. For example:
datadogRum.addFeatureFlagEvaluation(key.replace(':', '_'), value);
Further Reading
Additional helpful documentation, links, and articles: