Search in sources :

Example 61 with Variation

use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.

the class EventBuilderTest method createConversionEvent.

/**
 * Verify {@link com.optimizely.ab.event.internal.payload.EventBatch} event creation
 */
@Test
public void createConversionEvent() throws Exception {
    // use the "valid" project config and its associated experiment, variation, and attributes
    Attribute attribute = validProjectConfig.getAttributes().get(0);
    EventType eventType = validProjectConfig.getEventTypes().get(0);
    String userId = "userId";
    Bucketer mockBucketAlgorithm = mock(Bucketer.class);
    List<Experiment> allExperiments = validProjectConfig.getExperiments();
    List<Experiment> experimentsForEventKey = validProjectConfig.getExperimentsForEventKey(eventType.getKey());
    // call the bucket function.
    for (Experiment experiment : allExperiments) {
        when(mockBucketAlgorithm.bucket(experiment, userId)).thenReturn(experiment.getVariations().get(0));
    }
    DecisionService decisionService = new DecisionService(mockBucketAlgorithm, mock(ErrorHandler.class), validProjectConfig, mock(UserProfileService.class));
    Map<String, String> attributeMap = Collections.singletonMap(attribute.getKey(), AUDIENCE_GRYFFINDOR_VALUE);
    Map<String, Object> eventTagMap = new HashMap<String, Object>();
    eventTagMap.put("boolean_param", false);
    eventTagMap.put("string_param", "123");
    Map<Experiment, Variation> experimentVariationMap = createExperimentVariationMap(validProjectConfig, decisionService, eventType.getKey(), userId, attributeMap);
    LogEvent conversionEvent = builder.createConversionEvent(validProjectConfig, experimentVariationMap, userId, eventType.getId(), eventType.getKey(), attributeMap, eventTagMap);
    List<Decision> expectedDecisions = new ArrayList<Decision>();
    for (Experiment experiment : experimentsForEventKey) {
        if (experiment.isRunning()) {
            Decision layerState = new Decision(experiment.getLayerId(), experiment.getId(), experiment.getVariations().get(0).getId(), false);
            expectedDecisions.add(layerState);
        }
    }
    // verify that the request endpoint is correct
    assertThat(conversionEvent.getEndpointUrl(), is(EventBuilder.EVENT_ENDPOINT));
    EventBatch conversion = gson.fromJson(conversionEvent.getBody(), EventBatch.class);
    // verify payload information
    assertThat(conversion.getVisitors().get(0).getVisitorId(), is(userId));
    assertThat((double) conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getTimestamp(), closeTo((double) System.currentTimeMillis(), 120.0));
    assertThat(conversion.getProjectId(), is(validProjectConfig.getProjectId()));
    assertThat(conversion.getAccountId(), is(validProjectConfig.getAccountId()));
    com.optimizely.ab.event.internal.payload.Attribute feature = new com.optimizely.ab.event.internal.payload.Attribute(attribute.getId(), attribute.getKey(), com.optimizely.ab.event.internal.payload.Attribute.CUSTOM_ATTRIBUTE_TYPE, AUDIENCE_GRYFFINDOR_VALUE);
    List<com.optimizely.ab.event.internal.payload.Attribute> expectedUserFeatures = Collections.singletonList(feature);
    assertEquals(conversion.getVisitors().get(0).getAttributes(), expectedUserFeatures);
    assertThat(conversion.getVisitors().get(0).getSnapshots().get(0).getDecisions(), containsInAnyOrder(expectedDecisions.toArray()));
    assertEquals(conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getEntityId(), eventType.getId());
    assertEquals(conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getKey(), eventType.getKey());
    assertEquals(conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getRevenue(), null);
    assertTrue(conversion.getVisitors().get(0).getAttributes().containsAll(expectedUserFeatures));
    assertTrue(conversion.getVisitors().get(0).getSnapshots().get(0).getEvents().get(0).getTags().equals(eventTagMap));
    assertFalse(conversion.getVisitors().get(0).getSnapshots().get(0).getDecisions().get(0).getIsCampaignHoldback());
    assertEquals(conversion.getAnonymizeIp(), validProjectConfig.getAnonymizeIP());
    assertEquals(conversion.getClientName(), EventBatch.ClientEngine.JAVA_SDK.getClientEngineValue());
    assertEquals(conversion.getClientVersion(), BuildVersionInfo.VERSION);
}
Also used : Attribute(com.optimizely.ab.config.Attribute) EventType(com.optimizely.ab.config.EventType) HashMap(java.util.HashMap) UserProfileService(com.optimizely.ab.bucketing.UserProfileService) ArrayList(java.util.ArrayList) DecisionService(com.optimizely.ab.bucketing.DecisionService) NoOpErrorHandler(com.optimizely.ab.error.NoOpErrorHandler) ErrorHandler(com.optimizely.ab.error.ErrorHandler) LogEvent(com.optimizely.ab.event.LogEvent) Experiment(com.optimizely.ab.config.Experiment) Decision(com.optimizely.ab.event.internal.payload.Decision) Variation(com.optimizely.ab.config.Variation) EventBatch(com.optimizely.ab.event.internal.payload.EventBatch) Bucketer(com.optimizely.ab.bucketing.Bucketer) Test(org.junit.Test)

Example 62 with Variation

use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.

the class GsonHelpers method parseVariations.

private static List<Variation> parseVariations(JsonArray variationJson, JsonDeserializationContext context) {
    List<Variation> variations = new ArrayList<Variation>(variationJson.size());
    for (Object obj : variationJson) {
        JsonObject variationObject = (JsonObject) obj;
        String id = variationObject.get("id").getAsString();
        String key = variationObject.get("key").getAsString();
        Boolean featureEnabled = false;
        if (variationObject.has("featureEnabled"))
            featureEnabled = variationObject.get("featureEnabled").getAsBoolean();
        List<LiveVariableUsageInstance> variableUsageInstances = null;
        // across deserializers.
        if (variationObject.has("variables")) {
            Type liveVariableUsageInstancesType = new TypeToken<List<LiveVariableUsageInstance>>() {
            }.getType();
            variableUsageInstances = context.deserialize(variationObject.getAsJsonArray("variables"), liveVariableUsageInstancesType);
        }
        variations.add(new Variation(id, key, featureEnabled, variableUsageInstances));
    }
    return variations;
}
Also used : LiveVariableUsageInstance(com.optimizely.ab.config.LiveVariableUsageInstance) Type(java.lang.reflect.Type) ArrayList(java.util.ArrayList) JsonObject(com.google.gson.JsonObject) JsonObject(com.google.gson.JsonObject) ArrayList(java.util.ArrayList) List(java.util.List) Variation(com.optimizely.ab.config.Variation)

Example 63 with Variation

use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.

the class GsonHelpers method parseExperiment.

static Experiment parseExperiment(JsonObject experimentJson, String groupId, JsonDeserializationContext context) {
    String id = experimentJson.get("id").getAsString();
    String key = experimentJson.get("key").getAsString();
    JsonElement experimentStatusJson = experimentJson.get("status");
    String status = experimentStatusJson.isJsonNull() ? ExperimentStatus.NOT_STARTED.toString() : experimentStatusJson.getAsString();
    JsonElement layerIdJson = experimentJson.get("layerId");
    String layerId = layerIdJson == null ? null : layerIdJson.getAsString();
    JsonArray audienceIdsJson = experimentJson.getAsJsonArray("audienceIds");
    List<String> audienceIds = new ArrayList<String>(audienceIdsJson.size());
    for (JsonElement audienceIdObj : audienceIdsJson) {
        audienceIds.add(audienceIdObj.getAsString());
    }
    // parse the child objects
    List<Variation> variations = parseVariations(experimentJson.getAsJsonArray("variations"), context);
    Map<String, String> userIdToVariationKeyMap = parseForcedVariations(experimentJson.getAsJsonObject("forcedVariations"));
    List<TrafficAllocation> trafficAllocations = parseTrafficAllocation(experimentJson.getAsJsonArray("trafficAllocation"));
    return new Experiment(id, key, status, layerId, audienceIds, variations, userIdToVariationKeyMap, trafficAllocations, groupId);
}
Also used : JsonArray(com.google.gson.JsonArray) TrafficAllocation(com.optimizely.ab.config.TrafficAllocation) JsonElement(com.google.gson.JsonElement) Experiment(com.optimizely.ab.config.Experiment) ArrayList(java.util.ArrayList) Variation(com.optimizely.ab.config.Variation)

Example 64 with Variation

use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.

the class Bucketer method bucketToVariation.

private Variation bucketToVariation(@Nonnull Experiment experiment, @Nonnull String bucketingId) {
    // "salt" the bucket id using the experiment id
    String experimentId = experiment.getId();
    String experimentKey = experiment.getKey();
    String combinedBucketId = bucketingId + experimentId;
    List<TrafficAllocation> trafficAllocations = experiment.getTrafficAllocation();
    int hashCode = MurmurHash3.murmurhash3_x86_32(combinedBucketId, 0, combinedBucketId.length(), MURMUR_HASH_SEED);
    int bucketValue = generateBucketValue(hashCode);
    logger.debug("Assigned bucket {} to user with bucketingId \"{}\" when bucketing to a variation.", bucketValue, bucketingId);
    String bucketedVariationId = bucketToEntity(bucketValue, trafficAllocations);
    if (bucketedVariationId != null) {
        Variation bucketedVariation = experiment.getVariationIdToVariationMap().get(bucketedVariationId);
        String variationKey = bucketedVariation.getKey();
        logger.info("User with bucketingId \"{}\" is in variation \"{}\" of experiment \"{}\".", bucketingId, variationKey, experimentKey);
        return bucketedVariation;
    }
    // user was not bucketed to a variation
    logger.info("User with bucketingId \"{}\" is not in any variation of experiment \"{}\".", bucketingId, experimentKey);
    return null;
}
Also used : TrafficAllocation(com.optimizely.ab.config.TrafficAllocation) Variation(com.optimizely.ab.config.Variation)

Example 65 with Variation

use of com.optimizely.ab.config.Variation in project java-sdk by optimizely.

the class DecisionService method getVariation.

/**
 * Get a {@link Variation} of an {@link Experiment} for a user to be allocated into.
 *
 * @param experiment The Experiment the user will be bucketed into.
 * @param userId The userId of the user.
 * @param filteredAttributes The user's attributes. This should be filtered to just attributes in the Datafile.
 * @return The {@link Variation} the user is allocated into.
 */
@Nullable
public Variation getVariation(@Nonnull Experiment experiment, @Nonnull String userId, @Nonnull Map<String, String> filteredAttributes) {
    if (!ExperimentUtils.isExperimentActive(experiment)) {
        return null;
    }
    // look for forced bucketing first.
    Variation variation = projectConfig.getForcedVariation(experiment.getKey(), userId);
    // check for whitelisting
    if (variation == null) {
        variation = getWhitelistedVariation(experiment, userId);
    }
    if (variation != null) {
        return variation;
    }
    // fetch the user profile map from the user profile service
    UserProfile userProfile = null;
    if (userProfileService != null) {
        try {
            Map<String, Object> userProfileMap = userProfileService.lookup(userId);
            if (userProfileMap == null) {
                logger.info("We were unable to get a user profile map from the UserProfileService.");
            } else if (UserProfileUtils.isValidUserProfileMap(userProfileMap)) {
                userProfile = UserProfileUtils.convertMapToUserProfile(userProfileMap);
            } else {
                logger.warn("The UserProfileService returned an invalid map.");
            }
        } catch (Exception exception) {
            logger.error(exception.getMessage());
            errorHandler.handleError(new OptimizelyRuntimeException(exception));
        }
    }
    // check if user exists in user profile
    if (userProfile != null) {
        variation = getStoredVariation(experiment, userProfile);
        // return the stored variation if it exists
        if (variation != null) {
            return variation;
        }
    } else {
        // if we could not find a user profile, make a new one
        userProfile = new UserProfile(userId, new HashMap<String, Decision>());
    }
    if (ExperimentUtils.isUserInExperiment(projectConfig, experiment, filteredAttributes)) {
        String bucketingId = userId;
        if (filteredAttributes.containsKey(BUCKETING_ATTRIBUTE)) {
            bucketingId = filteredAttributes.get(BUCKETING_ATTRIBUTE);
        }
        variation = bucketer.bucket(experiment, bucketingId);
        if (variation != null) {
            if (userProfileService != null) {
                saveVariation(experiment, variation, userProfile);
            } else {
                logger.info("This decision will not be saved since the UserProfileService is null.");
            }
        }
        return variation;
    }
    logger.info("User \"{}\" does not meet conditions to be in experiment \"{}\".", userId, experiment.getKey());
    return null;
}
Also used : HashMap(java.util.HashMap) Variation(com.optimizely.ab.config.Variation) OptimizelyRuntimeException(com.optimizely.ab.OptimizelyRuntimeException) OptimizelyRuntimeException(com.optimizely.ab.OptimizelyRuntimeException) Nullable(javax.annotation.Nullable)

Aggregations

Variation (com.optimizely.ab.config.Variation)99 Experiment (com.optimizely.ab.config.Experiment)91 Test (org.junit.Test)81 Matchers.anyString (org.mockito.Matchers.anyString)50 LogEvent (com.optimizely.ab.event.LogEvent)44 HashMap (java.util.HashMap)42 EventBuilder (com.optimizely.ab.event.internal.EventBuilder)25 EventType (com.optimizely.ab.config.EventType)22 Map (java.util.Map)18 ImmutableMap (com.google.common.collect.ImmutableMap)15 EventBuilderTest.createExperimentVariationMap (com.optimizely.ab.event.internal.EventBuilderTest.createExperimentVariationMap)15 Attribute (com.optimizely.ab.config.Attribute)13 EventBatch (com.optimizely.ab.event.internal.payload.EventBatch)12 ArrayList (java.util.ArrayList)10 Bucketer (com.optimizely.ab.bucketing.Bucketer)9 ProjectConfig (com.optimizely.ab.config.ProjectConfig)9 TrafficAllocation (com.optimizely.ab.config.TrafficAllocation)8 Rollout (com.optimizely.ab.config.Rollout)7 NoOpErrorHandler (com.optimizely.ab.error.NoOpErrorHandler)7 SuppressFBWarnings (edu.umd.cs.findbugs.annotations.SuppressFBWarnings)7