-
Notifications
You must be signed in to change notification settings - Fork 33
feat(core): Feature flags interface uses getFeatureFlagResult
#398
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: main
Are you sure you want to change the base?
Conversation
This is a single call which returns information about the flag evaluation:\ 1. The feature flag key 2. Whether or not the flag is enabled for the user 3. The chosen variant (if applicable) 4. The associated payload (if applicable) This is one step in exposing `getFeatureFlagResult` to the public API.
When `defaultValue` is selected over a null value, `$feature_flag_called` reports the default value. I noticed there's a gap in testing for this behavior, so here it is.
| if (payload == null) return null | ||
| return when (payload) { | ||
| is String -> payload | ||
| else -> gson.toJson(payload) |
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.
either we try catch here or the method should be marked as @throws
| public fun serializedPayload(): String? { | ||
| if (payload == null) return null | ||
| return when (payload) { | ||
| is String -> payload |
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.
can it be else? eg Int, etc otherwise we will try to serialize a primitive type
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.
Primitives are also valid JSON so I'm relying on the serializer to do that. Though, I suppose it's my assumption that it'll handle those cases. I'll verify.
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.
yep, i just think that we dont need to pay the price of gson.toJson if we can just add the other cases here since its just a few anyway, but your call since gson.toJson wont fail anyway
| get() = variant ?: enabled | ||
|
|
||
| internal companion object { | ||
| internal val gson: Gson by lazy { Gson() } |
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 sure if an instance per class is ideal here, can we share an instance for all data classes?
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.
Are you talking about propagating the serializer's Gson instance here?
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.
Nope because that one has our own adapters, just creating a gson instance outside somewhere and pass along all flag result instances maybe?
| @@ -1,17 +1,22 @@ | |||
| ## Next | |||
|
|
|||
| - feat: Add `getFeatureFlagResult` to `PostHogFeatureFlagsInterface`, drop `getFeatureFlag`, `getFeatureFlagPayload`. ([#398](https://github.com/PostHog/posthog-android/pull/398)) | |||
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.
will that break public APIs on Android?
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.
asking because it'd break the flutter sdk https://github.com/PostHog/posthog-flutter/blob/main/android/src/main/kotlin/com/posthog/flutter/PosthogFlutterPlugin.kt
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 change only affects the internal API. I was planning on making a separate PR to introduce getFeatureFlagResult to the public API.
When we do this, we'll leave getFeatureFlag and getFeatureFlagPayload available to the public API.
that was intentional afik since users should never call getFeatureFlagPayload directly before calling isFeatureEnabled or getFeatureFlag, I recall asking that once, customers as well, and that was the reasoning, all of our docs also point out that, that you should check if the flag is enabled once and so on, did we change that? |
|
Thanks for the review! You're right that the behavior of The purpose of this method is to simplify the API such that that in either access pattern, the behavior remains the same. |
i also think it makes sense and i wanted to add it back then. |
💡 Motivation and Context
Currently,
getFeatureFlagPayload()doesn't raise a$feature_flag_calledevent, which causes confusion when customers only call this method. This pattern will result in zero analytics about feature flag usage. This PR lays the groundwork for a newgetFeatureFlagResult()API that returns both value and payload atomically, ensuring a single event captures the complete flag access, without needing to call more than one function.Related: PostHog/posthog#43520
Changes
New
FeatureFlagResultclasskey,enabled,variant, andpayloadfieldsvalueproperty (returns variant or enabled boolean)serializedPayload()andgetPayloadAs<T>()for payload convenienceUpdated
PostHogFeatureFlagsInterface:getFeatureFlag()andgetFeatureFlagPayload()with singlegetFeatureFlagResult()methodPostHogRemoteConfig(client-side implementation) to implementgetFeatureFlagResult()PostHogFeatureFlags(server-side implementation) to implementgetFeatureFlagResult()Updated callers:
PostHogandPostHogStatelessclients now delegate togetFeatureFlagResult()internally💚 How did you test it?
📝 Checklist