Fixes #5556: Feature flags failing to log correctly (#5715)
## Explanation
Fixes #5556: Feature flags failing to log correctly
### Cause of the bug
The primary cause of the bug was [Google Analytics character
limits](https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.html#logEvent(java.lang.String,android.os.Bundle))
on log event parameter values. Google Analytics (GA), particularly GA 4,
imposes the following limits on log events and their parameters;
- **25 Parameters** - Each app event cannot exceed 25 individual
parameters. This number is inclusive of default GA parameters making the
limit slightly lower than that number.
- **40 Characters** - An event parameter name cannot exceed 40
characters.
- **100 Characters** - Each event parameter can have a value not
exceeding 100 characters. If a key or name exceeds the limit, the event
is dropped and a `firebase_error` parameter is added to the event and a
`firebase_error_value` parameter is added to indicate the name of the
parameter with the invalid value. In the case of exceeding the character
limit, the error code is usually `4` as can be seen from the list of
[GA4 errors](https://firebase.google.com/docs/analytics/errors).
**Note**: These limits only apply for free tier users. Google Analytics
360 users are allowed up to `100 parameters` per event and `500
characters` for event parameter values.
### Fix implemented
To fix this issue, three changes were made to the `EventBundleCreator`;
- **Feature flag names** - A new converter, the
`FeatureFlagNameToIntegerNameConverter` was introduced. This converter
will keep a list of flag names supported by the app and their integer
representations. Each feature flag name should have a unique integer
representation and no two feature flag names should have the same
integer representation, even when one of them is no longer supported.
- **Feature flag sync status** - Each feature flag sync status is parsed
into an integer representation based on the number it has in the
`platform_parameters.proto` that defines the various sync statuses as an
enum. The following are the current sync status and their integer
representations: `SYNC_STATUS_UNSPECIFIED` as `0`,
`NOT_SYNCED_FROM_SERVER` as `1`, and `SYNCED_FROM_SERVER` as `2`.
- **Feature flag enabled state** - Since enabled states are either
`true` or `false`, `true` is converted to `1` and `false` to `0`.
By making these changes, it is possible to theoretically log **36
feature flags** in one event. The breakdown for this is as shown;
**Feature flags with 1 digit** - 1 digit each and a comma seperator =
_**9 maximum feature flags taking 18 characters**_
**Feature flags with 2 digits** - 2 digits each and a comma seperator =
_**27 maximum feature flags taking 81 characters**_
**Total loggable feature flags** = _**9 + 27 = 36 maximum feature flags
taking 99/100 characters**_
### Logs comparison
Previously, the feature flags list used to appear like this;
```json
{
"uuid": null,
"app_session_id": "277ed911-efef-3144-b0fa-d37cdd87ac86",
"feature_flag_names": null,
"feature_flag_enabled_states": "false,false,false,false,false,false,false,false,false,false,true,false,false",
"feature_flag_sync_statuses": null
}
```
With the new implementation, the feature flags list appears like this;
```json
{
"uuid": null,
"app_session_id": "277ed911-efef-3144-b0fa-d37cdd87ac86",
"feature_flag_sync_statuses": "1,1,1,1,1,1,1,1,1,1,1,1,1",
"feature_flag_enabled_states": "0,0,0,0,0,0,0,0,0,0,1,0,1",
"feature_flag_names": "1,2,3,4,5,6,7,8,9,10,11,12,13"
}
```
## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).
---------
Co-authored-by: Adhiambo Peres <[email protected]>