-
Notifications
You must be signed in to change notification settings - Fork 52
FFL-908 Implement Flags OpenFeature provider for React Native #1106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/flags
Are you sure you want to change the base?
FFL-908 Implement Flags OpenFeature provider for React Native #1106
Conversation
…-implement-flags-react-native-open-feature-provider
typotter
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing major, but some things to consider. 1 blocker (calling DDFlags.enable in the initialize method)
| <ActivityIndicator /> | ||
| </SafeAreaView> | ||
| }> | ||
| <OpenFeatureProvider suspendUntilReady> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧑🍳
| <Section title={greetingFlag.value.greeting}> | ||
| The title of this section is based on the <Text style={styles.highlight}>{greetingFlag.flagKey}</Text> feature flag.{'\n\n'} | ||
|
|
||
| If it's different from "Default greeting", then it is coming from the feature flag evaluation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
consider adding the details.evaluation_reason here as well.
| import type { FlagsClient } from './FlagsClient'; | ||
|
|
||
| export type DdFlagsType = { | ||
| export interface DdFlagsType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
| export type PrimitiveValue = null | boolean | string | number; | ||
| type JsonObject = { [key: string]: JsonValue }; | ||
| type JsonArray = JsonValue[]; | ||
| /** | ||
| * Represents a JSON node value. | ||
| */ | ||
| export type JsonValue = PrimitiveValue | JsonObject | JsonArray; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧑🍳
| * This is typically a user ID, session ID, or device ID. The targeting key is used | ||
| * by the feature flag service to determine which variation to serve. | ||
| * | ||
| * Pass an empty string if you don't have such an identifier. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a null (or undefined) value for the targetingKey is a valid state. Recommending to pass an empty string is good advice, mind you, so I agree with the suggestion.
The nuance is that the targeting key is only needed if there is experimental/traffic sharding in the matching flag allocation. In the future we may also allow for custom targeting using field(s) from the evaluation context.
| @@ -0,0 +1,86 @@ | |||
| { | |||
| "name": "@datadog/openfeature-react-native", | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "name": "@datadog/openfeature-react-native", | |
| "name": "@datadog/mobile-react-native-openfeature", |
based on the naming pattern of other packages in the repo.
| } | ||
|
|
||
| async initialize(context: OFEvaluationContext = {}): Promise<void> { | ||
| await DdFlags.enable(this.options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think init should enable the DDFlags. We are enabling in the sample app, where the other SDK features are also enabled. Trying to initialize before the module is enabled is an error state in the mobile sdk spec. The doc details how to recover/proceed in such cases.
| private options: DatadogProviderOptions; | ||
| private flagsClient: FlagsClient | undefined; | ||
|
|
||
| constructor(options: DatadogProviderOptions = {}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the android SDK, we wrote a constructor that takes a FlagsClient to wrap instead of passing around the clientName. Not suggesting to change it here, but something to consider
| } | ||
| } | ||
|
|
||
| const toDdContext = (context: OFEvaluationContext): DdEvaluationContext => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth it to add tests for these converters?
| * Controls whether the feature flag evaluation feature is enabled. | ||
| */ | ||
| enabled: boolean; | ||
| export interface FlagsConfiguration { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not a breaking change! (flags not merged to develop yet, right?)
| reason, | ||
| variant, | ||
| flagMetadata: allocationKey ? { allocationKey } : undefined, | ||
| errorCode: errorCode as ErrorCode | undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cast will become unsafe if the DD and OF errorCodes diverge. Consider an explicit converter/map or some other means of type safety
| clientName?: string; | ||
| } | ||
|
|
||
| export class DatadogProvider implements Provider { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there anything to do on shutdown here? The Provider interface also has an onClose method for when the provider is shutdown
| /** | ||
| * An error tha occurs during feature flag evaluation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(while you're here)
| /** | |
| * An error tha occurs during feature flag evaluation. | |
| /** | |
| * An error that occurs during feature flag evaluation. |
| }; | ||
| } | ||
|
|
||
| export type PrimitiveValue = null | boolean | string | number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these types need to be exported from the module also?
|
|
||
| if (!isPrimitiveValue) { | ||
| InternalLog.log( | ||
| `Non-primitive context value under "${key}" is not supported. Omitting this atribute from the evaluation context.`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| `Non-primitive context value under "${key}" is not supported. Omitting this atribute from the evaluation context.`, | |
| `Non-primitive context value under "${key}" is not supported. Omitting this attribute from the evaluation context.`, |
| newContext: OFEvaluationContext | ||
| ): Promise<void> { | ||
| if (!this.flagsClient) { | ||
| throw new Error( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be an OpenFeature ProviderNotReadyError?
What does this PR do?
What's left:
LICENSE-3rdparty.csvMotivation
Datadog Flags SDKs for all platforms are supposed to be consumable through OpenFeature SDKs.
https://datadoghq.atlassian.net/browse/FFL-908
Additional Notes
Anything else we should know when reviewing?
Review checklist (to be filled by reviewers)