use of com.optimizely.ab.optimizelydecision.DecisionReasons in project java-sdk by optimizely.
the class DecisionService method getVariationForFeature.
/**
* Get the variation the user is bucketed into for the FeatureFlag
*
* @param featureFlag The feature flag the user wants to access.
* @param user The current OptimizelyuserContext
* @param projectConfig The current projectConfig
* @param options An array of decision options
* @return A {@link DecisionResponse} including a {@link FeatureDecision} and the decision reasons
*/
@Nonnull
public DecisionResponse<FeatureDecision> getVariationForFeature(@Nonnull FeatureFlag featureFlag, @Nonnull OptimizelyUserContext user, @Nonnull ProjectConfig projectConfig, @Nonnull List<OptimizelyDecideOption> options) {
DecisionReasons reasons = DefaultDecisionReasons.newInstance();
DecisionResponse<FeatureDecision> decisionVariationResponse = getVariationFromExperiment(projectConfig, featureFlag, user, options);
reasons.merge(decisionVariationResponse.getReasons());
FeatureDecision decision = decisionVariationResponse.getResult();
if (decision != null) {
return new DecisionResponse(decision, reasons);
}
DecisionResponse<FeatureDecision> decisionFeatureResponse = getVariationForFeatureInRollout(featureFlag, user, projectConfig);
reasons.merge(decisionFeatureResponse.getReasons());
decision = decisionFeatureResponse.getResult();
String message;
if (decision.variation == null) {
message = reasons.addInfo("The user \"%s\" was not bucketed into a rollout for feature flag \"%s\".", user.getUserId(), featureFlag.getKey());
} else {
message = reasons.addInfo("The user \"%s\" was bucketed into a rollout for feature flag \"%s\".", user.getUserId(), featureFlag.getKey());
}
logger.info(message);
return new DecisionResponse(decision, reasons);
}
use of com.optimizely.ab.optimizelydecision.DecisionReasons in project java-sdk by optimizely.
the class DecisionService method getVariationForFeatureInRollout.
/**
* Try to bucket the user into a rollout rule.
* Evaluate the user for rules in priority order by seeing if the user satisfies the audience.
* Fall back onto the everyone else rule if the user is ever excluded from a rule due to traffic allocation.
*
* @param featureFlag The feature flag the user wants to access.
* @param user The current OptimizelyUserContext
* @param projectConfig The current projectConfig
* @return A {@link DecisionResponse} including a {@link FeatureDecision} and the decision reasons
*/
@Nonnull
DecisionResponse<FeatureDecision> getVariationForFeatureInRollout(@Nonnull FeatureFlag featureFlag, @Nonnull OptimizelyUserContext user, @Nonnull ProjectConfig projectConfig) {
DecisionReasons reasons = DefaultDecisionReasons.newInstance();
// use rollout to get variation for feature
if (featureFlag.getRolloutId().isEmpty()) {
String message = reasons.addInfo("The feature flag \"%s\" is not used in a rollout.", featureFlag.getKey());
logger.info(message);
return new DecisionResponse(new FeatureDecision(null, null, null), reasons);
}
Rollout rollout = projectConfig.getRolloutIdMapping().get(featureFlag.getRolloutId());
if (rollout == null) {
String message = reasons.addInfo("The rollout with id \"%s\" was not found in the datafile for feature flag \"%s\".", featureFlag.getRolloutId(), featureFlag.getKey());
logger.error(message);
return new DecisionResponse(new FeatureDecision(null, null, null), reasons);
}
// for all rules before the everyone else rule
int rolloutRulesLength = rollout.getExperiments().size();
if (rolloutRulesLength == 0) {
return new DecisionResponse(new FeatureDecision(null, null, null), reasons);
}
int index = 0;
while (index < rolloutRulesLength) {
DecisionResponse<AbstractMap.SimpleEntry> decisionVariationResponse = getVariationFromDeliveryRule(projectConfig, featureFlag.getKey(), rollout.getExperiments(), index, user);
reasons.merge(decisionVariationResponse.getReasons());
AbstractMap.SimpleEntry<Variation, Boolean> response = decisionVariationResponse.getResult();
Variation variation = response.getKey();
Boolean skipToEveryoneElse = response.getValue();
if (variation != null) {
Experiment rule = rollout.getExperiments().get(index);
FeatureDecision featureDecision = new FeatureDecision(rule, variation, FeatureDecision.DecisionSource.ROLLOUT);
return new DecisionResponse(featureDecision, reasons);
}
// The last rule is special for "Everyone Else"
index = skipToEveryoneElse ? (rolloutRulesLength - 1) : (index + 1);
}
return new DecisionResponse(new FeatureDecision(null, null, null), reasons);
}
use of com.optimizely.ab.optimizelydecision.DecisionReasons in project java-sdk by optimizely.
the class ExperimentUtils method evaluateAudience.
@Nonnull
public static DecisionResponse<Boolean> evaluateAudience(@Nonnull ProjectConfig projectConfig, @Nonnull Experiment experiment, @Nonnull Map<String, ?> attributes, @Nonnull String loggingEntityType, @Nonnull String loggingKey) {
DecisionReasons reasons = DefaultDecisionReasons.newInstance();
List<String> experimentAudienceIds = experiment.getAudienceIds();
// if there are no audiences, ALL users should be part of the experiment
if (experimentAudienceIds.isEmpty()) {
return new DecisionResponse(true, reasons);
}
List<Condition> conditions = new ArrayList<>();
for (String audienceId : experimentAudienceIds) {
AudienceIdCondition condition = new AudienceIdCondition(audienceId);
conditions.add(condition);
}
OrCondition implicitOr = new OrCondition(conditions);
logger.debug("Evaluating audiences for {} \"{}\": {}.", loggingEntityType, loggingKey, conditions);
Boolean result = implicitOr.evaluate(projectConfig, attributes);
String message = reasons.addInfo("Audiences for %s \"%s\" collectively evaluated to %s.", loggingEntityType, loggingKey, result);
logger.info(message);
return new DecisionResponse(result, reasons);
}
use of com.optimizely.ab.optimizelydecision.DecisionReasons in project java-sdk by optimizely.
the class DecisionService method getForcedVariation.
/**
* Gets the forced variation for a given user and experiment.
*
* @param experiment The experiment forced.
* @param userId The user ID to be used for bucketing.
* @return A {@link DecisionResponse} including the {@link Variation} that user is bucketed into (or null)
* and the decision reasons. The variation can be null if the forced variation fails.
*/
@Nonnull
public DecisionResponse<Variation> getForcedVariation(@Nonnull Experiment experiment, @Nonnull String userId) {
DecisionReasons reasons = DefaultDecisionReasons.newInstance();
if (!validateUserId(userId)) {
String message = reasons.addInfo("User ID is invalid");
logger.error(message);
return new DecisionResponse(null, reasons);
}
Map<String, String> experimentToVariation = getForcedVariationMapping().get(userId);
if (experimentToVariation != null) {
String variationId = experimentToVariation.get(experiment.getId());
if (variationId != null) {
Variation variation = experiment.getVariationIdToVariationMap().get(variationId);
if (variation != null) {
String message = reasons.addInfo("Variation \"%s\" is mapped to experiment \"%s\" and user \"%s\" in the forced variation map", variation.getKey(), experiment.getKey(), userId);
logger.debug(message);
return new DecisionResponse(variation, reasons);
}
} else {
logger.debug("No variation for experiment \"{}\" mapped to user \"{}\" in the forced variation map ", experiment.getKey(), userId);
}
}
return new DecisionResponse(null, reasons);
}
use of com.optimizely.ab.optimizelydecision.DecisionReasons in project java-sdk by optimizely.
the class DecisionService method getWhitelistedVariation.
/**
* Get the variation the user has been whitelisted into.
*
* @param experiment {@link Experiment} in which user is to be bucketed.
* @param userId User Identifier
* @return A {@link DecisionResponse} including the {@link Variation} that user is bucketed into (or null)
* and the decision reasons. The variation can be null if the user is not whitelisted into any variation.
*/
@Nonnull
DecisionResponse<Variation> getWhitelistedVariation(@Nonnull Experiment experiment, @Nonnull String userId) {
DecisionReasons reasons = DefaultDecisionReasons.newInstance();
// if a user has a forced variation mapping, return the respective variation
Map<String, String> userIdToVariationKeyMap = experiment.getUserIdToVariationKeyMap();
if (userIdToVariationKeyMap.containsKey(userId)) {
String forcedVariationKey = userIdToVariationKeyMap.get(userId);
Variation forcedVariation = experiment.getVariationKeyToVariationMap().get(forcedVariationKey);
if (forcedVariation != null) {
String message = reasons.addInfo("User \"%s\" is forced in variation \"%s\".", userId, forcedVariationKey);
logger.info(message);
} else {
String message = reasons.addInfo("Variation \"%s\" is not in the datafile. Not activating user \"%s\".", forcedVariationKey, userId);
logger.error(message);
}
return new DecisionResponse(forcedVariation, reasons);
}
return new DecisionResponse(null, reasons);
}
Aggregations