Skip to content

Changing Fireperf's SDK Floats to Doubles #4874

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

Merged
merged 6 commits into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions firebase-perf/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased
* [changed] Updated javalite, protoc, protobufjavautil to 3.21.11.
* [changed] Updated [perfmon] to use Double precision for sampling.

# 20.3.1
* [changed] Migrated [perfmon] to use standard Firebase executors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,22 +286,22 @@ private boolean isFireperfSdkVersionInList(String versions) {
}

/** Returns what percentage of Traces should be collected, range is [0.00f, 1.00f]. */
public float getTraceSamplingRate() {
public double getTraceSamplingRate() {
// Order of precedence is:
// 1. If the value exists through Firebase Remote Config, cache and return this value.
// 2. If the value exists in device cache, return this value.
// 3. Otherwise, return default value.
TraceSamplingRate config = TraceSamplingRate.getInstance();

// 1. Reads value from Firebase Remote Config, saves this value in cache layer if valid.
Optional<Float> rcValue = getRemoteConfigFloat(config);
Optional<Double> rcValue = getRemoteConfigDouble(config);
if (rcValue.isAvailable() && isSamplingRateValid(rcValue.get())) {
deviceCacheManager.setValue(config.getDeviceCacheFlag(), rcValue.get());
return rcValue.get();
}

// 2. Reads value from cache layer.
Optional<Float> deviceCacheValue = getDeviceCacheFloat(config);
Optional<Double> deviceCacheValue = getDeviceCacheDouble(config);
if (deviceCacheValue.isAvailable() && isSamplingRateValid(deviceCacheValue.get())) {
return deviceCacheValue.get();
}
Expand All @@ -311,22 +311,22 @@ public float getTraceSamplingRate() {
}

/** Returns what percentage of NetworkRequest should be collected, range is [0.00f, 1.00f]. */
public float getNetworkRequestSamplingRate() {
public double getNetworkRequestSamplingRate() {
// Order of precedence is:
// 1. If the value exists through Firebase Remote Config, cache and return this value.
// 2. If the value exists in device cache, return this value.
// 3. Otherwise, return default value.
NetworkRequestSamplingRate config = NetworkRequestSamplingRate.getInstance();

// 1. Reads value from Firebase Remote Config, saves this value in cache layer if valid.
Optional<Float> rcValue = getRemoteConfigFloat(config);
Optional<Double> rcValue = getRemoteConfigDouble(config);
if (rcValue.isAvailable() && isSamplingRateValid(rcValue.get())) {
deviceCacheManager.setValue(config.getDeviceCacheFlag(), rcValue.get());
return rcValue.get();
}

// 2. Reads value from cache layer.
Optional<Float> deviceCacheValue = getDeviceCacheFloat(config);
Optional<Double> deviceCacheValue = getDeviceCacheDouble(config);
if (deviceCacheValue.isAvailable() && isSamplingRateValid(deviceCacheValue.get())) {
return deviceCacheValue.get();
}
Expand All @@ -336,7 +336,7 @@ public float getNetworkRequestSamplingRate() {
}

/** Returns what percentage of Session gauge should be collected, range is [0.00f, 1.00f]. */
public float getSessionsSamplingRate() {
public double getSessionsSamplingRate() {
// Order of precedence is:
// 1. If the value exists in Android Manifest, convert from [0.00f, 100.00f] to [0.00f, 1.00f]
// and return this value.
Expand All @@ -346,24 +346,24 @@ public float getSessionsSamplingRate() {
SessionsSamplingRate config = SessionsSamplingRate.getInstance();

// 1. Reads value in Android Manifest (it is set by developers during build time).
Optional<Float> metadataValue = getMetadataFloat(config);
Optional<Double> metadataValue = getMetadataDouble(config);
if (metadataValue.isAvailable()) {
// Sampling percentage from metadata needs to convert from [0.00f, 100.00f] to [0.00f, 1.00f].
float samplingRate = metadataValue.get() / 100.0f;
double samplingRate = metadataValue.get() / 100;
if (isSamplingRateValid(samplingRate)) {
return samplingRate;
}
}

// 2. Reads value from Firebase Remote Config, saves this value in cache layer if valid.
Optional<Float> rcValue = getRemoteConfigFloat(config);
Optional<Double> rcValue = getRemoteConfigDouble(config);
if (rcValue.isAvailable() && isSamplingRateValid(rcValue.get())) {
deviceCacheManager.setValue(config.getDeviceCacheFlag(), rcValue.get());
return rcValue.get();
}

// 3. Reads value from cache layer.
Optional<Float> deviceCacheValue = getDeviceCacheFloat(config);
Optional<Double> deviceCacheValue = getDeviceCacheDouble(config);
if (deviceCacheValue.isAvailable() && isSamplingRateValid(deviceCacheValue.get())) {
return deviceCacheValue.get();
}
Expand Down Expand Up @@ -732,7 +732,7 @@ public String getAndCacheLogSourceName() {
}

/** Returns what percentage of fragment traces should be collected, range is [0.00f, 1.00f]. */
public float getFragmentSamplingRate() {
public double getFragmentSamplingRate() {
// Order of precedence is:
// 1. If the value exists in Android Manifest, convert from [0.00f, 100.00f] to [0.00f, 1.00f]
// and return this value.
Expand All @@ -742,24 +742,24 @@ public float getFragmentSamplingRate() {
FragmentSamplingRate config = FragmentSamplingRate.getInstance();

// 1. Reads value in Android Manifest (it is set by developers during build time).
Optional<Float> metadataValue = getMetadataFloat(config);
Optional<Double> metadataValue = getMetadataDouble(config);
if (metadataValue.isAvailable()) {
// Sampling percentage from metadata needs to convert from [0.00f, 100.00f] to [0.00f, 1.00f].
float samplingRate = metadataValue.get() / 100.0f;
double samplingRate = metadataValue.get() / 100.0f;
if (isSamplingRateValid(samplingRate)) {
return samplingRate;
}
}

// 2. Reads value from Firebase Remote Config, saves this value in cache layer if valid.
Optional<Float> rcValue = getRemoteConfigFloat(config);
Optional<Double> rcValue = getRemoteConfigDouble(config);
if (rcValue.isAvailable() && isSamplingRateValid(rcValue.get())) {
deviceCacheManager.setValue(config.getDeviceCacheFlag(), rcValue.get());
return rcValue.get();
}

// 3. Reads value from cache layer.
Optional<Float> deviceCacheValue = getDeviceCacheFloat(config);
Optional<Double> deviceCacheValue = getDeviceCacheDouble(config);
if (deviceCacheValue.isAvailable() && isSamplingRateValid(deviceCacheValue.get())) {
return deviceCacheValue.get();
}
Expand Down Expand Up @@ -807,17 +807,17 @@ private Optional<Boolean> getMetadataBoolean(ConfigurationFlag<Boolean> config)
return metadataBundle.getBoolean(config.getMetadataFlag());
}

private Optional<Float> getMetadataFloat(ConfigurationFlag<Float> config) {
return metadataBundle.getFloat(config.getMetadataFlag());
private Optional<Double> getMetadataDouble(ConfigurationFlag<Double> config) {
return metadataBundle.getDouble(config.getMetadataFlag());
}

private Optional<Long> getMetadataLong(ConfigurationFlag<Long> config) {
return metadataBundle.getLong(config.getMetadataFlag());
}

// Helper functions for interaction with Firebase Remote Config.
private Optional<Float> getRemoteConfigFloat(ConfigurationFlag<Float> config) {
return remoteConfigManager.getFloat(config.getRemoteConfigFlag());
private Optional<Double> getRemoteConfigDouble(ConfigurationFlag<Double> config) {
return remoteConfigManager.getDouble(config.getRemoteConfigFlag());
}

private Optional<Long> getRemoteConfigLong(ConfigurationFlag<Long> config) {
Expand All @@ -841,8 +841,8 @@ private Long getRemoteConfigValue(ConfigurationFlag<Long> configFlag) {
}

// Helper functions for interaction with Device Caching layer.
private Optional<Float> getDeviceCacheFloat(ConfigurationFlag<Float> config) {
return deviceCacheManager.getFloat(config.getDeviceCacheFlag());
private Optional<Double> getDeviceCacheDouble(ConfigurationFlag<Double> config) {
return deviceCacheManager.getDouble(config.getDeviceCacheFlag());
}

private Optional<Long> getDeviceCacheLong(ConfigurationFlag<Long> config) {
Expand All @@ -858,7 +858,7 @@ private Optional<String> getDeviceCacheString(ConfigurationFlag<String> config)
}

// Helper functions for config value validation.
private boolean isSamplingRateValid(float samplingRate) {
private boolean isSamplingRateValid(double samplingRate) {
return MIN_SAMPLING_RATE <= samplingRate && samplingRate <= MAX_SAMPLING_RATE;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ protected String getDeviceCacheFlag() {
}
}

protected static final class TraceSamplingRate extends ConfigurationFlag<Float> {
protected static final class TraceSamplingRate extends ConfigurationFlag<Double> {
private static TraceSamplingRate instance;

private TraceSamplingRate() {
Expand All @@ -145,11 +145,11 @@ protected static synchronized TraceSamplingRate getInstance() {
}

@Override
protected Float getDefault() {
protected Double getDefault() {
// Sampling rate range is [0.00f, 1.00f]. By default, sampling rate is 1.00f, which is 100%.
// 0.00f means 0%, Fireperf will not capture any event for trace from the device,
// 1.00f means 100%, Fireperf will capture all events for trace from the device.
return 1.00f;
return 1.0;
}

@Override
Expand All @@ -163,7 +163,7 @@ protected String getDeviceCacheFlag() {
}
}

protected static final class NetworkRequestSamplingRate extends ConfigurationFlag<Float> {
protected static final class NetworkRequestSamplingRate extends ConfigurationFlag<Double> {
private static NetworkRequestSamplingRate instance;

private NetworkRequestSamplingRate() {
Expand All @@ -178,11 +178,11 @@ protected static synchronized NetworkRequestSamplingRate getInstance() {
}

@Override
protected Float getDefault() {
protected Double getDefault() {
// Sampling rate range is [0.00f, 1.00f]. By default, sampling rate is 1.00f, which is 100%.
// 0.00f means 0%, Fireperf will not capture any event for trace from the device,
// 1.00f means 100%, Fireperf will capture all events for trace from the device.
return 1.00f;
return 1.0;
}

@Override
Expand Down Expand Up @@ -534,7 +534,7 @@ protected String getDeviceCacheFlag() {
}
}

protected static final class SessionsSamplingRate extends ConfigurationFlag<Float> {
protected static final class SessionsSamplingRate extends ConfigurationFlag<Double> {
private static SessionsSamplingRate instance;

private SessionsSamplingRate() {
Expand All @@ -549,8 +549,8 @@ public static synchronized SessionsSamplingRate getInstance() {
}

@Override
protected Float getDefault() {
return 0.01f;
protected Double getDefault() {
return 0.01;
}

@Override
Expand Down Expand Up @@ -624,7 +624,7 @@ protected String getDeviceCacheFlag() {
}
}

protected static final class FragmentSamplingRate extends ConfigurationFlag<Float> {
protected static final class FragmentSamplingRate extends ConfigurationFlag<Double> {
private static FragmentSamplingRate instance;

private FragmentSamplingRate() {
Expand All @@ -639,11 +639,11 @@ protected static synchronized FragmentSamplingRate getInstance() {
}

@Override
protected Float getDefault() {
protected Double getDefault() {
// Sampling rate range is [0.00f, 1.00f]. By default, sampling rate is 0.00f, which is 0%.
// 0.00f means 0%, Fireperf will not capture any event for fragment trace from the device,
// 1.00f means 100%, Fireperf will capture all events for fragment trace from the device.
return 0.00f;
return 0.00;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,9 @@ public boolean setValue(String key, String value) {
* Retrieves value stored in caching layer for {@code key}, if caching layer is not initialized,
* or value with the desired type doesn't exist in caching layer, return {@code Optional.empty()}.
*/
public Optional<Float> getFloat(String key) {
public Optional<Double> getDouble(String key) {
if (key == null) {
logger.debug("Key is null when getting float value on device cache.");
logger.debug("Key is null when getting double value on device cache.");
return Optional.absent();
}

Expand All @@ -227,11 +227,19 @@ public Optional<Float> getFloat(String key) {
}

try {
// SharedPreferences does not allow storing a Double directly. We store the double's bits as a
// long so here we convert that back to a double.
// Default value should never be used because key existence is checked above.
return Optional.of(sharedPref.getFloat(key, 0.0f));
} catch (ClassCastException e) {
logger.debug(
"Key %s from sharedPreferences has type other than float: %s", key, e.getMessage());
return Optional.of(Double.longBitsToDouble(sharedPref.getLong(key, 0)));
} catch (ClassCastException unused) {
// In the past, we used to store a Float here instead of a Double. Before the value is
// overwritten for the first time, it will still have a Float and so this may be expected.
try {
return Optional.of(Float.valueOf(sharedPref.getFloat(key, 0.0f)).doubleValue());
} catch (ClassCastException e) {
logger.debug(
"Key %s from sharedPreferences has type other than double: %s", key, e.getMessage());
}
}
return Optional.absent();
}
Expand All @@ -242,18 +250,22 @@ public Optional<Float> getFloat(String key) {
*
* @return whether provided value has been saved to device caching layer.
*/
public boolean setValue(String key, float value) {
public boolean setValue(String key, double value) {
if (key == null) {
logger.debug("Key is null when setting float value on device cache.");
logger.debug("Key is null when setting double value on device cache.");
return false;
}

if (sharedPref == null) {
setContext(getFirebaseApplicationContext());
if (sharedPref == null) {
return false;
}
}
sharedPref.edit().putFloat(key, value).apply();
// SharedPreferences does not allow storing a Double directly. The main way to store it without
// losing precision is to store the double's bits as a long so it can then be converted back to
// a double.
sharedPref.edit().putLong(key, Double.doubleToRawLongBits(value)).apply();
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,23 +139,23 @@ public void setFirebaseRemoteConfigProvider(
}

/**
* Retrieves the double value of the given key from the remote config, converts to float type and
* Retrieves the double value of the given key from the remote config, converts to double type and
* returns this value.
*
* @implNote Triggers a remote config fetch on a background thread if it hasn't yet been fetched.
* @param key The key to fetch the double value for.
* @return The float value of the key or not present.
* @return The double value of the key or not present.
*/
public Optional<Float> getFloat(String key) {
public Optional<Double> getDouble(String key) {
if (key == null) {
logger.debug("The key to get Remote Config float value is null.");
logger.debug("The key to get Remote Config double value is null.");
return Optional.absent();
}

FirebaseRemoteConfigValue rcValue = getRemoteConfigValue(key);
if (rcValue != null) {
try {
return Optional.of(Double.valueOf(rcValue.asDouble()).floatValue());
return Optional.of(rcValue.asDouble());
} catch (IllegalArgumentException e) {
if (!rcValue.asString().isEmpty()) {
logger.debug("Could not parse value: '%s' for key: '%s'.", rcValue.asString(), key);
Expand Down Expand Up @@ -260,8 +260,8 @@ public <T extends Object> T getRemoteConfigValueOrDefault(String key, T defaultV
if (defaultValue instanceof Boolean) {
valueToReturn = rcValue.asBoolean();

} else if (defaultValue instanceof Float) {
valueToReturn = Double.valueOf(rcValue.asDouble()).floatValue();
} else if (defaultValue instanceof Double) {
valueToReturn = rcValue.asDouble();

} else if (defaultValue instanceof Long || defaultValue instanceof Integer) {
valueToReturn = rcValue.asLong();
Expand Down
Loading