use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.
the class Optimizely method getFeatureVariableValueForType.
@VisibleForTesting
String getFeatureVariableValueForType(@Nonnull String featureKey, @Nonnull String variableKey, @Nonnull String userId, @Nonnull Map<String, String> attributes, @Nonnull LiveVariable.VariableType variableType) {
if (featureKey == null) {
logger.warn("The featureKey parameter must be nonnull.");
return null;
} else if (variableKey == null) {
logger.warn("The variableKey parameter must be nonnull.");
return null;
} else if (userId == null) {
logger.warn("The userId parameter must be nonnull.");
return null;
}
FeatureFlag featureFlag = projectConfig.getFeatureKeyMapping().get(featureKey);
if (featureFlag == null) {
logger.info("No feature flag was found for key \"{}\".", featureKey);
return null;
}
LiveVariable variable = featureFlag.getVariableKeyToLiveVariableMap().get(variableKey);
if (variable == null) {
logger.info("No feature variable was found for key \"{}\" in feature flag \"{}\".", variableKey, featureKey);
return null;
} else if (!variable.getType().equals(variableType)) {
logger.info("The feature variable \"" + variableKey + "\" is actually of type \"" + variable.getType().toString() + "\" type. You tried to access it as type \"" + variableType.toString() + "\". Please use the appropriate feature variable accessor.");
return null;
}
String variableValue = variable.getDefaultValue();
FeatureDecision featureDecision = decisionService.getVariationForFeature(featureFlag, userId, attributes);
if (featureDecision.variation != null) {
LiveVariableUsageInstance liveVariableUsageInstance = featureDecision.variation.getVariableIdToLiveVariableUsageInstanceMap().get(variable.getId());
if (liveVariableUsageInstance != null) {
variableValue = liveVariableUsageInstance.getValue();
} else {
variableValue = variable.getDefaultValue();
}
} else {
logger.info("User \"{}\" was not bucketed into any variation for feature flag \"{}\". " + "The default value \"{}\" for \"{}\" is being returned.", userId, featureKey, variableValue, variableKey);
}
return variableValue;
}
use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.
the class Optimizely method isFeatureEnabled.
@Nonnull
private Boolean isFeatureEnabled(@Nonnull ProjectConfig projectConfig, @Nonnull String featureKey, @Nonnull String userId, @Nonnull Map<String, ?> attributes) {
if (featureKey == null) {
logger.warn("The featureKey parameter must be nonnull.");
return false;
} else if (userId == null) {
logger.warn("The userId parameter must be nonnull.");
return false;
}
FeatureFlag featureFlag = projectConfig.getFeatureKeyMapping().get(featureKey);
if (featureFlag == null) {
logger.info("No feature flag was found for key \"{}\".", featureKey);
return false;
}
Map<String, ?> copiedAttributes = copyAttributes(attributes);
FeatureDecision.DecisionSource decisionSource = FeatureDecision.DecisionSource.ROLLOUT;
FeatureDecision featureDecision = decisionService.getVariationForFeature(featureFlag, createUserContext(userId, copiedAttributes), projectConfig).getResult();
Boolean featureEnabled = false;
SourceInfo sourceInfo = new RolloutSourceInfo();
if (featureDecision.decisionSource != null) {
decisionSource = featureDecision.decisionSource;
}
if (featureDecision.variation != null) {
// For rollouts experiments and variations are an implementation detail only.
if (featureDecision.decisionSource.equals(FeatureDecision.DecisionSource.FEATURE_TEST)) {
sourceInfo = new FeatureTestSourceInfo(featureDecision.experiment.getKey(), featureDecision.variation.getKey());
} else {
logger.info("The user \"{}\" is not included in an experiment for feature \"{}\".", userId, featureKey);
}
if (featureDecision.variation.getFeatureEnabled()) {
featureEnabled = true;
}
}
sendImpression(projectConfig, featureDecision.experiment, userId, copiedAttributes, featureDecision.variation, featureKey, decisionSource.toString(), featureEnabled);
DecisionNotification decisionNotification = DecisionNotification.newFeatureDecisionNotificationBuilder().withUserId(userId).withAttributes(copiedAttributes).withFeatureKey(featureKey).withFeatureEnabled(featureEnabled).withSource(decisionSource).withSourceInfo(sourceInfo).build();
notificationCenter.send(decisionNotification);
logger.info("Feature \"{}\" is enabled for user \"{}\"? {}", featureKey, userId, featureEnabled);
return featureEnabled;
}
use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.
the class Optimizely method getFeatureVariableValueForType.
@VisibleForTesting
<T> T getFeatureVariableValueForType(@Nonnull String featureKey, @Nonnull String variableKey, @Nonnull String userId, @Nonnull Map<String, ?> attributes, @Nonnull String variableType) {
if (featureKey == null) {
logger.warn("The featureKey parameter must be nonnull.");
return null;
} else if (variableKey == null) {
logger.warn("The variableKey parameter must be nonnull.");
return null;
} else if (userId == null) {
logger.warn("The userId parameter must be nonnull.");
return null;
}
ProjectConfig projectConfig = getProjectConfig();
if (projectConfig == null) {
logger.error("Optimizely instance is not valid, failing getFeatureVariableValueForType call. type: {}", variableType);
return null;
}
FeatureFlag featureFlag = projectConfig.getFeatureKeyMapping().get(featureKey);
if (featureFlag == null) {
logger.info("No feature flag was found for key \"{}\".", featureKey);
return null;
}
FeatureVariable variable = featureFlag.getVariableKeyToFeatureVariableMap().get(variableKey);
if (variable == null) {
logger.info("No feature variable was found for key \"{}\" in feature flag \"{}\".", variableKey, featureKey);
return null;
} else if (!variable.getType().equals(variableType)) {
logger.info("The feature variable \"" + variableKey + "\" is actually of type \"" + variable.getType().toString() + "\" type. You tried to access it as type \"" + variableType.toString() + "\". Please use the appropriate feature variable accessor.");
return null;
}
String variableValue = variable.getDefaultValue();
Map<String, ?> copiedAttributes = copyAttributes(attributes);
FeatureDecision featureDecision = decisionService.getVariationForFeature(featureFlag, createUserContext(userId, copiedAttributes), projectConfig).getResult();
Boolean featureEnabled = false;
if (featureDecision.variation != null) {
if (featureDecision.variation.getFeatureEnabled()) {
FeatureVariableUsageInstance featureVariableUsageInstance = featureDecision.variation.getVariableIdToFeatureVariableUsageInstanceMap().get(variable.getId());
if (featureVariableUsageInstance != null) {
variableValue = featureVariableUsageInstance.getValue();
logger.info("Got variable value \"{}\" for variable \"{}\" of feature flag \"{}\".", variableValue, variableKey, featureKey);
} else {
variableValue = variable.getDefaultValue();
logger.info("Value is not defined for variable \"{}\". Returning default value \"{}\".", variableKey, variableValue);
}
} else {
logger.info("Feature \"{}\" is not enabled for user \"{}\". " + "Returning the default variable value \"{}\".", featureKey, userId, variableValue);
}
featureEnabled = featureDecision.variation.getFeatureEnabled();
} else {
logger.info("User \"{}\" was not bucketed into any variation for feature flag \"{}\". " + "The default value \"{}\" for \"{}\" is being returned.", userId, featureKey, variableValue, variableKey);
}
Object convertedValue = convertStringToType(variableValue, variableType);
Object notificationValue = convertedValue;
if (convertedValue instanceof OptimizelyJSON) {
notificationValue = ((OptimizelyJSON) convertedValue).toMap();
}
DecisionNotification decisionNotification = DecisionNotification.newFeatureVariableDecisionNotificationBuilder().withUserId(userId).withAttributes(copiedAttributes).withFeatureKey(featureKey).withFeatureEnabled(featureEnabled).withVariableKey(variableKey).withVariableType(variableType).withVariableValue(notificationValue).withFeatureDecision(featureDecision).build();
notificationCenter.send(decisionNotification);
return (T) convertedValue;
}
use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.
the class OptimizelyTest method isFeatureEnabledReturnsFalseAndDispatchesWhenUserIsBucketedIntoAnExperimentVariationToggleOff.
/**
* Verify {@link Optimizely#isFeatureEnabled(String, String)} calls into
* {@link Optimizely#isFeatureEnabled(String, String, Map)} and they both
* return False
* when the user is bucketed an feature test variation that is turned off.
*/
@Test
public void isFeatureEnabledReturnsFalseAndDispatchesWhenUserIsBucketedIntoAnExperimentVariationToggleOff() throws Exception {
assumeTrue(datafileVersion >= Integer.parseInt(ProjectConfig.Version.V4.toString()));
String validFeatureKey = FEATURE_MULTI_VARIATE_FEATURE_KEY;
Optimizely spyOptimizely = optimizelyBuilder.withDecisionService(mockDecisionService).build();
Experiment activatedExperiment = validProjectConfig.getExperimentKeyMapping().get(EXPERIMENT_MULTIVARIATE_EXPERIMENT_KEY);
Variation variation = new Variation("2", "variation_toggled_off", false, null);
FeatureDecision featureDecision = new FeatureDecision(activatedExperiment, variation, FeatureDecision.DecisionSource.FEATURE_TEST);
doReturn(DecisionResponse.responseNoReasons(featureDecision)).when(mockDecisionService).getVariationForFeature(any(FeatureFlag.class), any(OptimizelyUserContext.class), any(ProjectConfig.class));
assertFalse(spyOptimizely.isFeatureEnabled(validFeatureKey, genericUserId));
eventHandler.expectImpression(activatedExperiment.getId(), variation.getId(), genericUserId);
logbackVerifier.expectMessage(Level.INFO, "Feature \"" + validFeatureKey + "\" is enabled for user \"" + genericUserId + "\"? false");
}
use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.
the class OptimizelyTest method isFeatureEnabledReturnsTrueButDoesNotSendWhenUserIsBucketedIntoVariationWithoutExperiment.
/**
* Verify {@link Optimizely#isFeatureEnabled(String, String)} calls into
* {@link Optimizely#isFeatureEnabled(String, String, Map)} and they both
* return True when the user is bucketed into a variation for the feature.
* An impression event should not be dispatched since the user was not bucketed into an Experiment.
*/
@Test
public void isFeatureEnabledReturnsTrueButDoesNotSendWhenUserIsBucketedIntoVariationWithoutExperiment() throws Exception {
assumeTrue(datafileVersion >= Integer.parseInt(ProjectConfig.Version.V4.toString()));
String validFeatureKey = FEATURE_MULTI_VARIATE_FEATURE_KEY;
Optimizely optimizely = optimizelyBuilder.withDecisionService(mockDecisionService).build();
// Should be an experiment from the rollout associated with the feature, but for this test
// it doesn't matter. Just use any valid experiment.
Experiment experiment = validProjectConfig.getRolloutIdMapping().get(ROLLOUT_2_ID).getExperiments().get(0);
Variation variation = new Variation("variationId", "variationKey", true, null);
FeatureDecision featureDecision = new FeatureDecision(experiment, variation, FeatureDecision.DecisionSource.ROLLOUT);
doReturn(DecisionResponse.responseNoReasons(featureDecision)).when(mockDecisionService).getVariationForFeature(eq(FEATURE_FLAG_MULTI_VARIATE_FEATURE), eq(optimizely.createUserContext(genericUserId, Collections.emptyMap())), eq(validProjectConfig));
assertTrue(optimizely.isFeatureEnabled(validFeatureKey, genericUserId));
logbackVerifier.expectMessage(Level.INFO, "The user \"" + genericUserId + "\" is not included in an experiment for feature \"" + validFeatureKey + "\".");
logbackVerifier.expectMessage(Level.INFO, "Feature \"" + validFeatureKey + "\" is enabled for user \"" + genericUserId + "\"? true");
eventHandler.expectImpression("3421010877", "variationId", genericUserId);
verify(mockDecisionService).getVariationForFeature(eq(FEATURE_FLAG_MULTI_VARIATE_FEATURE), eq(optimizely.createUserContext(genericUserId, Collections.emptyMap())), eq(validProjectConfig));
}
Aggregations