Calendar time = event.getTime(); UserInfo user = event.getUser(); appName = ((ApplicationEvent) event).getApplicationName(); Experiment.ID expId = null; if (event instanceof ExperimentEvent) { expLabel = ((ExperimentEvent) event).getExperiment().getLabel(); expId = ((ExperimentEvent) event).getExperiment().getID(); bucketLabel = ((BucketEvent) event).getBucket().getLabel(); String after = null; if (event instanceof ChangeEvent) { property = ((ChangeEvent) event).getPropertyName(); before = ((ChangeEvent) event).getBefore(); after = ((ChangeEvent) event).getAfter(); } else if (event instanceof BucketCreateEvent) { property = "allocation"; after = String.valueOf(((BucketCreateEvent) event).getBucket().getAllocationPercent());
/** * {@inheritDoc} */ @Override public String getSubject(EventLogEvent event) { EventLogEventType type = event.getType(); String subject; switch (type) { case BUCKET_CHANGED: case BUCKET_CREATED: subject = "Experiment Bucket Update"; break; case EXPERIMENT_CHANGED: subject = "Experiment Changed"; break; case EXPERIMENT_CREATED: subject = "Experiment Created"; break; case SIMPLE_EVENT: default: throw new IllegalArgumentException("Can not handle EventType: " + type.toString()); } return subject; }
/** * {@inheritDoc} */ @Override public void erasePageData(Application.Name applicationName, Experiment.ID experimentID, UserInfo user) { pagesRepository.erasePageData(applicationName, experimentID); Experiment experiment = experiments.getExperiment(experimentID); if (experiment != null) { eventLog.postEvent(new ExperimentChangeEvent(user, experiment, "pages", "all pages", null)); } }
/** * This method finds the right attributes to set. The set fields can be found * in the {@link TextTemplates}. * * @param buckEvent an {@link BucketChangeEvent} that represents the changes * @return the message for the email */ private String getBucketChangedMessage(BucketChangeEvent buckEvent) { ST template = new ST(BUCKET_CHANGE); Map<String, String> variables = new HashMap<>(); Bucket buck = buckEvent.getBucket(); ExperimentBase exp = buckEvent.getExperiment(); put(variables, EXPERIMENT_LABEL, exp.getLabel()); put(variables, BUCKET_NAME, buck.getLabel().toString()); put(variables, APPLICATION_NAME, String.valueOf(exp.getApplicationName())); put(variables, USER_NAME, getUserRepresentation(buckEvent.getUser())); put(variables, FIELD_NAME, buckEvent.getPropertyName()); if (buckEvent.getPropertyName() != null && "allocation".equalsIgnoreCase(buckEvent.getPropertyName())) { put(variables, FIELD_BEFORE, String.valueOf(((double) Math.round(Double.parseDouble(buckEvent.getBefore()) * 10000d) / 10000d) * 100).concat("%")); put(variables, FIELD_AFTER, String.valueOf(((double) Math.round(Double.parseDouble(buckEvent.getAfter()) * 10000d) / 10000d) * 100).concat("%")); } else { put(variables, FIELD_BEFORE, buckEvent.getBefore()); put(variables, FIELD_AFTER, buckEvent.getAfter()); } return replaceVariablesInTemplate(variables, template); }
/** * This method finds the right attributes to set. The set fields can be found * in the {@link TextTemplates}. * * @param expEvent an {@link ExperimentChangeEvent} that represents the changes * @return the message for the email */ private String getExperimentChangedMessage(ExperimentChangeEvent expEvent) { ST template = new ST(EXPERIMENT_CHANGED); Map<String, String> variables = new HashMap<>(); ExperimentBase exp = expEvent.getExperiment(); put(variables, EXPERIMENT_LABEL, exp.getLabel()); put(variables, EXPERIMENT_ID, String.valueOf(exp.getID())); put(variables, APPLICATION_NAME, String.valueOf(exp.getApplicationName())); put(variables, USER_NAME, getUserRepresentation(expEvent.getUser())); put(variables, FIELD_NAME, expEvent.getPropertyName()); if (expEvent.getPropertyName() != null && "sampling_percent".equalsIgnoreCase(expEvent.getPropertyName())) { put(variables, FIELD_BEFORE, String.valueOf(((double) Math.round(Double.parseDouble(expEvent.getBefore()) * 10000d) / 10000d) * 100).concat("%")); put(variables, FIELD_AFTER, String.valueOf(((double) Math.round(Double.parseDouble(expEvent.getAfter()) * 10000d) / 10000d) * 100).concat("%")); } else { put(variables, FIELD_BEFORE, expEvent.getBefore()); put(variables, FIELD_AFTER, expEvent.getAfter()); } return replaceVariablesInTemplate(variables, template); }
/** * This method finds the right attributes to set. The set fields can be found * in the {@link TextTemplates}. * * @param buckEvent an {@link BucketCreateEvent} that represents the changes * @return the message for the email */ private String getBucketCreatedMessage(BucketCreateEvent buckEvent) { ST template = new ST(BUCKET_CREATED); Map<String, String> variables = new HashMap<>(); Bucket buck = buckEvent.getBucket(); ExperimentBase exp = buckEvent.getExperiment(); put(variables, EXPERIMENT_LABEL, exp.getLabel()); put(variables, BUCKET_NAME, buck.getLabel().toString()); put(variables, APPLICATION_NAME, String.valueOf(exp.getApplicationName())); put(variables, USER_NAME, getUserRepresentation(buckEvent.getUser())); return replaceVariablesInTemplate(variables, template); }
/** * The addressors for a given experiment are the administrators of the application the * experiment belongs to. * * @param event the {@link ExperimentEvent} to be processed * @return a list of the email-addresses of the addressors */ private Collection<? extends String> getExperimentAddressor(ExperimentEvent event) { Set<String> adressors; ExperimentBase exp = event.getExperiment(); if (exp != null) { adressors = getAdminEmails(exp.getApplicationName()); } else { throw new EventLogException("An ExperimentEvent was recorded without having an Experiment!"); } return adressors; }
/** * This method finds the right attributes to set. The set fields can be found * in the {@link TextTemplates}. * * @param expEvent an {@link ExperimentCreateEvent} that represents the created experiment * @return the message for the email */ private String getExperimentCreatedMessage(ExperimentCreateEvent expEvent) { ST template = new ST(EXPERIMENT_CREATED); Map<String, String> variables = new HashMap<>(); ExperimentBase exp = expEvent.getExperiment(); put(variables, EXPERIMENT_LABEL, exp.getLabel()); put(variables, EXPERIMENT_ID, String.valueOf(exp.getID())); put(variables, APPLICATION_NAME, String.valueOf(exp.getApplicationName())); put(variables, USER_NAME, getUserRepresentation(expEvent.getUser())); return replaceVariablesInTemplate(variables, template); }
@Override public void deleteUserRole(UserInfo.Username userID, Application.Name applicationName, UserInfo admin) { authorizationRepository.deleteUserRole(userID, applicationName); UserInfo user = getUserInfo(userID); eventLog.postEvent(new AuthorizationChangeEvent(admin, applicationName, user, "", "")); }
eventLog.postEvent(new ExperimentCreateEvent(user, newExperiment));
/** * {@inheritDoc} */ @Override public Bucket createBucket(Experiment.ID experimentID, Bucket newBucket, UserInfo user) { Experiment experiment = experiments.getExperiment(experimentID); if (experiment == null) { throw new ExperimentNotFoundException(experimentID); } validateExperimentState(experiment); checkBucketConstraint(experiment, newBucket); LOGGER.debug("Add Bucket: adding new bucket to running experiment" + experiment.getID()); cassandraRepository.createBucket(newBucket); try { databaseRepository.createBucket(newBucket); } catch (RepositoryException e) { cassandraRepository.deleteBucket(newBucket.getExperimentID(), newBucket.getLabel()); throw e; } //if we just created an experiment in a running experiment, update the remaining allocation percentages if (!Experiment.State.DRAFT.equals(experiment.getState())) { eventLog.postEvent(new BucketCreateEvent(user, experiment, newBucket)); BucketList updates = buckets.adjustAllocationPercentages(experiment, newBucket); buckets.updateBucketAllocBatch(experimentID, updates); } return getBucket(experimentID, newBucket.getLabel()); }
eventLog.postEvent(new BucketDeleteEvent(user, experiment, bucket));
/** * {@inheritDoc} */ @Override public void updateExperimentState(final Experiment experiment, final Experiment.State state) { try { cassandraRepository.updateExperimentState(experiment, state); // To maintain consistency, revert the changes made in cassandra in case the mysql update fails try { databaseRepository.updateExperimentState(experiment, state); } catch (Exception exception) { cassandraRepository.updateExperimentState(experiment, experiment.getState()); throw exception; } eventLog.postEvent(new ExperimentChangeEvent(experiment, "state", experiment.getState().toString(), state.toString())); } catch (Exception exception) { LOGGER.error("Updating experiment state for experiment:{} failed with error:", experiment, exception); throw exception; } LOGGER.info("event=EXPERIMENT_METADATA_CHANGE, message=EXPERIMENT_STATE_UPDATED, applicationName={}, configuration=[experimentName={}, oldState={}, newState={}]", experiment.getApplicationName(), experiment.getLabel(), experiment.getState(), state); } }
@Override public void assignUserToSuperAdminRole(final UserInfo candidateUserInfo, final UserInfo assigningUserInfo) { LOGGER.debug("Assigning super admin role to user={} by user={} ", candidateUserInfo, assigningUserInfo); UserRoleList userRoleList = getUserRoleList(candidateUserInfo.getUsername()); LOGGER.debug("User role list {}", userRoleList); boolean isSuperAdmin = userRoleList.getRoleList().stream().anyMatch((UserRole ur) -> ur.getRole().equals(Role.SUPERADMIN)); Preconditions.checkArgument(!isSuperAdmin, "User %s is already a superadmin", candidateUserInfo.getUsername()); authorizationRepository.assignUserToSuperAdminRole(candidateUserInfo); eventLog.postEvent(new AuthorizationChangeEvent(assigningUserInfo, null, candidateUserInfo, null, Role.SUPERADMIN.toString())); }
/** * {@inheritDoc} */ @Override public Set<String> getAddressees(EventLogEvent event) { Set<String> addressants = new HashSet<>(); EventLogEventType type = event.getType(); switch (type) { case BUCKET_CHANGED: case BUCKET_CREATED: case EXPERIMENT_CHANGED: case EXPERIMENT_CREATED: addressants.addAll(getExperimentAddressor((ExperimentEvent) event)); break; case SIMPLE_EVENT: default: throw new IllegalArgumentException("Can not handle EventType: " + type.toString()); } return addressants; }
/** * {@inheritDoc} */ @Override public void deletePage(Experiment.ID experimentID, Page.Name pageName, UserInfo user) { Application.Name applicationName = getApplicationNameForModifyingPages(experimentID); pagesRepository.deletePage(applicationName, experimentID, pageName); Experiment experiment = experiments.getExperiment(experimentID); if (experiment != null) { eventLog.postEvent(new ExperimentChangeEvent(user, experiment, "pages", pageName.toString(), null)); } LOGGER.info("event=EXPERIMENT_METADATA_CHANGE, message=PAGE_REMOVED, applicationName={}, experimentName={}, configuration=[pageName={}, userName={}]", experiment.getApplicationName(), experiment.getLabel(), pageName, user.getUsername()); }
@Override public void removeUserFromSuperAdminRole(final UserInfo candidateUserInfo, final UserInfo assigningUserInfo) { LOGGER.debug("Removing user={} from superadmin by assigningUser={}", candidateUserInfo, assigningUserInfo); List<UserRole> allSuperAdmins = getSuperAdminRoleList(); LOGGER.debug("Current superadmins {}", allSuperAdmins); Preconditions.checkArgument(allSuperAdmins.size() > 1, "Cannot delete. SuperAdmins less than 1"); boolean isSuperAdmin = allSuperAdmins.stream().anyMatch((UserRole ur) -> ur.getRole().equals(Role.SUPERADMIN) && ur.getUserID().equals(candidateUserInfo.getUsername())); Preconditions.checkArgument(isSuperAdmin, "User %s is not a superadmin", candidateUserInfo.getUsername()); authorizationRepository.removeUserFromSuperAdminRole(candidateUserInfo); eventLog.postEvent(new AuthorizationChangeEvent(assigningUserInfo, null, candidateUserInfo, Role.SUPERADMIN.toString(), null)); }
/** * {@inheritDoc} */ @Override public String getMessage(EventLogEvent event) { EventLogEventType type = event.getType(); String message = ""; switch (type) { case BUCKET_CHANGED: message = getBucketChangedMessage((BucketChangeEvent) event); break; case BUCKET_CREATED: message = getBucketCreatedMessage((BucketCreateEvent) event); break; case EXPERIMENT_CHANGED: message = getExperimentChangedMessage((ExperimentChangeEvent) event); break; case EXPERIMENT_CREATED: message = getExperimentCreatedMessage((ExperimentCreateEvent) event); break; case SIMPLE_EVENT: default: throw new IllegalArgumentException("Can not handle EventType: " + type.toString()); } return message; }
/** * {@inheritDoc} */ @Override public void postPages(Experiment.ID experimentID, ExperimentPageList experimentPageList, UserInfo user) { Application.Name applicationName = getApplicationNameForModifyingPages(experimentID); pagesRepository.postPages(applicationName, experimentID, experimentPageList); Experiment experiment = experiments.getExperiment(experimentID); if (experiment != null) { List<String> pageNames = new ArrayList<>(); for (ExperimentPage experimentPage : experimentPageList.getPages()) { pageNames.add(experimentPage.getName().toString()); } String pageString = StringUtils.join(pageNames, ", "); eventLog.postEvent(new ExperimentChangeEvent(user, experiment, "pages", null, pageString)); LOGGER.info("event=EXPERIMENT_METADATA_CHANGE, message=PAGES_ADDED, applicationName={}, experimentName={}, configuration=[pages={}]", experiment.getApplicationName(), experiment.getLabel(), pageString); } }
/** * {@inheritDoc} */ @Override public void deleteExclusion(Experiment.ID expID_1, Experiment.ID expID_2, UserInfo user) { Experiment exp_1 = experiments.getExperiment(expID_1); Experiment exp_2 = experiments.getExperiment(expID_2); // Check that expID_1 is a valid experiment if (exp_1 == null) { throw new ExperimentNotFoundException(expID_1); } // Check that expID_2 is a valid experiment if (exp_2 == null) { throw new ExperimentNotFoundException(expID_2); } mutexRepository.deleteExclusion(expID_1, expID_2); eventLog.postEvent(new ExperimentChangeEvent(user, exp_1, "mutex", exp_2.getLabel().toString(), null)); LOGGER.info("event=EXPERIMENT_METADATA_CHANGE, message=MUTUAL_EXCLUSION_DELETED, applicationName={}, configuration=[experiment1={}, experiment2={}]", exp_1.getApplicationName(), exp_1.getLabel(), exp_2.getLabel()); }