Skip to content

Commit bdb3b4e

Browse files
author
Mike Davis
authored
Refactor EventFactory into static methods. (#311)
* Remove EventFactory from Optimizely constructor. * Remove ClientVersion and ClientEngine from OptimizelyBuilder * Adds ClientEngineInfo for holding global engine value. * Defines new UserEvent, ConversionEvent and ImpressionEvent models * Redefines EventFactory to accept UserEvents via static methods * Defines UserEventFactory to create UserEvents. This change is in preparation for batching event payloads so we first want to extract separate canonical representations of conversions and impressions disjoint from the EventBatch model used for sending to the logging backend.
1 parent 81238f1 commit bdb3b4e

File tree

19 files changed

+1101
-253
lines changed

19 files changed

+1101
-253
lines changed

core-api/src/main/java/com/optimizely/ab/Optimizely.java

Lines changed: 36 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@
2727
import com.optimizely.ab.event.EventHandler;
2828
import com.optimizely.ab.event.LogEvent;
2929
import com.optimizely.ab.event.NoopEventHandler;
30-
import com.optimizely.ab.event.internal.BuildVersionInfo;
31-
import com.optimizely.ab.event.internal.EventFactory;
32-
import com.optimizely.ab.event.internal.payload.EventBatch.ClientEngine;
30+
import com.optimizely.ab.event.internal.*;
31+
import com.optimizely.ab.event.internal.payload.EventBatch;
3332
import com.optimizely.ab.notification.*;
3433
import org.slf4j.Logger;
3534
import org.slf4j.LoggerFactory;
@@ -77,8 +76,6 @@ public class Optimizely implements AutoCloseable {
7776
@VisibleForTesting
7877
final DecisionService decisionService;
7978
@VisibleForTesting
80-
final EventFactory eventFactory;
81-
@VisibleForTesting
8279
final EventHandler eventHandler;
8380
@VisibleForTesting
8481
final ErrorHandler errorHandler;
@@ -92,17 +89,15 @@ public class Optimizely implements AutoCloseable {
9289
private final UserProfileService userProfileService;
9390

9491
private Optimizely(@Nonnull EventHandler eventHandler,
95-
@Nonnull EventFactory eventFactory,
9692
@Nonnull ErrorHandler errorHandler,
9793
@Nonnull DecisionService decisionService,
9894
@Nullable UserProfileService userProfileService,
9995
@Nonnull ProjectConfigManager projectConfigManager,
10096
@Nonnull NotificationCenter notificationCenter
10197
) {
102-
this.decisionService = decisionService;
10398
this.eventHandler = eventHandler;
104-
this.eventFactory = eventFactory;
10599
this.errorHandler = errorHandler;
100+
this.decisionService = decisionService;
106101
this.userProfileService = userProfileService;
107102
this.projectConfigManager = projectConfigManager;
108103
this.notificationCenter = notificationCenter;
@@ -230,36 +225,33 @@ private void sendImpression(@Nonnull ProjectConfig projectConfig,
230225
@Nonnull String userId,
231226
@Nonnull Map<String, ?> filteredAttributes,
232227
@Nonnull Variation variation) {
233-
if (experiment.isRunning()) {
234-
LogEvent impressionEvent = eventFactory.createImpressionEvent(
235-
projectConfig,
236-
experiment,
237-
variation,
238-
userId,
239-
filteredAttributes);
240-
logger.info("Activating user \"{}\" in experiment \"{}\".", userId, experiment.getKey());
228+
if (!experiment.isRunning()) {
229+
logger.info("Experiment has \"Launched\" status so not dispatching event during activation.");
230+
return;
231+
}
241232

242-
if (logger.isDebugEnabled()) {
243-
logger.debug(
244-
"Dispatching impression event to URL {} with params {} and payload \"{}\".",
245-
impressionEvent.getEndpointUrl(), impressionEvent.getRequestParams(), impressionEvent.getBody());
246-
}
233+
logger.info("Activating user \"{}\" in experiment \"{}\".", userId, experiment.getKey());
234+
UserEvent userEvent = UserEventFactory.createImpressionEvent(
235+
projectConfig,
236+
experiment,
237+
variation,
238+
userId,
239+
filteredAttributes);
247240

248-
try {
249-
eventHandler.dispatchEvent(impressionEvent);
250-
} catch (Exception e) {
251-
logger.error("Unexpected exception in event dispatcher", e);
252-
}
241+
LogEvent impressionEvent = EventFactory.createLogEvent(userEvent);
253242

254-
// Kept For backwards compatibility.
255-
// This notification is deprecated and the new DecisionNotifications
256-
// are sent via their respective method calls.
257-
ActivateNotification activateNotification = new ActivateNotification(
258-
experiment, userId, filteredAttributes, variation, impressionEvent);
259-
notificationCenter.send(activateNotification);
260-
} else {
261-
logger.info("Experiment has \"Launched\" status so not dispatching event during activation.");
243+
try {
244+
eventHandler.dispatchEvent(impressionEvent);
245+
} catch (Exception e) {
246+
logger.error("Unexpected exception in event dispatcher", e);
262247
}
248+
249+
// Kept For backwards compatibility.
250+
// This notification is deprecated and the new DecisionNotifications
251+
// are sent via their respective method calls.
252+
ActivateNotification activateNotification = new ActivateNotification(
253+
experiment, userId, filteredAttributes, variation, impressionEvent);
254+
notificationCenter.send(activateNotification);
263255
}
264256

265257
//======== track calls ========//
@@ -309,22 +301,18 @@ public void track(@Nonnull String eventName,
309301
logger.warn("Event tags is null when non-null was expected. Defaulting to an empty event tags map.");
310302
}
311303

312-
// create the conversion event request parameters, then dispatch
313-
LogEvent conversionEvent = eventFactory.createConversionEvent(
304+
UserEvent userEvent = UserEventFactory.createConversionEvent(
314305
projectConfig,
315306
userId,
316307
eventType.getId(),
317308
eventType.getKey(),
318309
copiedAttributes,
319310
eventTags);
320311

312+
// create the conversion event request parameters, then dispatch
313+
LogEvent conversionEvent = EventFactory.createLogEvent(userEvent);
321314
logger.info("Tracking event \"{}\" for user \"{}\".", eventName, userId);
322315

323-
if (logger.isDebugEnabled()) {
324-
logger.debug("Dispatching conversion event to URL {} with params {} and payload \"{}\".",
325-
conversionEvent.getEndpointUrl(), conversionEvent.getRequestParams(), conversionEvent.getBody());
326-
}
327-
328316
try {
329317
eventHandler.dispatchEvent(conversionEvent);
330318
} catch (Exception e) {
@@ -1012,9 +1000,6 @@ public static class Builder {
10121000
private DecisionService decisionService;
10131001
private ErrorHandler errorHandler;
10141002
private EventHandler eventHandler;
1015-
private EventFactory eventFactory;
1016-
private ClientEngine clientEngine;
1017-
private String clientVersion;
10181003
private ProjectConfig projectConfig;
10191004
private ProjectConfigManager projectConfigManager;
10201005
private UserProfileService userProfileService;
@@ -1047,13 +1032,16 @@ public Builder withUserProfileService(UserProfileService userProfileService) {
10471032
return this;
10481033
}
10491034

1050-
public Builder withClientEngine(ClientEngine clientEngine) {
1051-
this.clientEngine = clientEngine;
1035+
@Deprecated
1036+
public Builder withClientEngine(EventBatch.ClientEngine clientEngine) {
1037+
logger.info("Deprecated. In the future, set ClientEngine via ClientEngineInfo#setClientEngine.");
1038+
ClientEngineInfo.setClientEngine(clientEngine);
10521039
return this;
10531040
}
10541041

1042+
@Deprecated
10551043
public Builder withClientVersion(String clientVersion) {
1056-
this.clientVersion = clientVersion;
1044+
logger.info("Explicitly setting the ClientVersion is no longer supported.");
10571045
return this;
10581046
}
10591047

@@ -1090,18 +1078,6 @@ protected Builder withDecisionService(DecisionService decisionService) {
10901078

10911079
public Optimizely build() {
10921080

1093-
if (clientEngine == null) {
1094-
clientEngine = ClientEngine.JAVA_SDK;
1095-
}
1096-
1097-
if (clientVersion == null) {
1098-
clientVersion = BuildVersionInfo.VERSION;
1099-
}
1100-
1101-
if (eventFactory == null) {
1102-
eventFactory = new EventFactory(clientEngine, clientVersion);
1103-
}
1104-
11051081
if (errorHandler == null) {
11061082
errorHandler = new NoOpErrorHandler();
11071083
}
@@ -1141,7 +1117,7 @@ public Optimizely build() {
11411117
notificationCenter = new NotificationCenter();
11421118
}
11431119

1144-
return new Optimizely(eventHandler, eventFactory, errorHandler, decisionService, userProfileService, projectConfigManager, notificationCenter);
1120+
return new Optimizely(eventHandler, errorHandler, decisionService, userProfileService, projectConfigManager, notificationCenter);
11451121
}
11461122
}
11471123
}

core-api/src/main/java/com/optimizely/ab/config/Experiment.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.optimizely.ab.config;
1818

1919
import com.fasterxml.jackson.annotation.*;
20+
import com.optimizely.ab.annotations.VisibleForTesting;
2021
import com.optimizely.ab.config.audience.AudienceIdCondition;
2122
import com.optimizely.ab.config.audience.Condition;
2223

@@ -69,6 +70,11 @@ public String toString() {
6970
}
7071
}
7172

73+
@VisibleForTesting
74+
public Experiment(String id, String key, String layerId) {
75+
this(id, key, null, layerId, Collections.emptyList(), null, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList(), "");
76+
}
77+
7278
@JsonCreator
7379
public Experiment(@JsonProperty("id") String id,
7480
@JsonProperty("key") String key,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
*
3+
* Copyright 2019, Optimizely and contributors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.optimizely.ab.event.internal;
18+
19+
import java.util.UUID;
20+
21+
/**
22+
* BaseEvent provides a GUID implementation along with a system timestamp.
23+
*/
24+
public class BaseEvent {
25+
26+
private final String uuid = UUID.randomUUID().toString();
27+
private final long timestamp = System.currentTimeMillis();
28+
29+
public final String getUUID() {
30+
return uuid;
31+
}
32+
33+
public final long getTimestamp() {
34+
return timestamp;
35+
}
36+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
*
3+
* Copyright 2019, Optimizely and contributors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.optimizely.ab.event.internal;
18+
19+
import com.optimizely.ab.event.internal.payload.EventBatch;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
22+
23+
/**
24+
* ClientEngineInfo is a utility to globally get and set the ClientEngine used in
25+
* event tracking. The ClientEngine defaults to JAVA_SDK but can be overridden at
26+
* runtime.
27+
*/
28+
public class ClientEngineInfo {
29+
private static final Logger logger = LoggerFactory.getLogger(ClientEngineInfo.class);
30+
31+
public static final EventBatch.ClientEngine DEFAULT = EventBatch.ClientEngine.JAVA_SDK;
32+
private static EventBatch.ClientEngine clientEngine = DEFAULT;
33+
34+
public static void setClientEngine(EventBatch.ClientEngine clientEngine) {
35+
if (clientEngine == null) {
36+
logger.warn("ClientEngine cannot be null, defaulting to {}", ClientEngineInfo.clientEngine.getClientEngineValue());
37+
return;
38+
}
39+
40+
logger.info("Setting Optimizely client engine to {}", clientEngine.getClientEngineValue());
41+
ClientEngineInfo.clientEngine = clientEngine;
42+
}
43+
44+
public static EventBatch.ClientEngine getClientEngine() {
45+
return clientEngine;
46+
}
47+
48+
private ClientEngineInfo() {
49+
}
50+
}

0 commit comments

Comments
 (0)