Skip to content

Commit 40ead9a

Browse files
author
Vignesh Raja
authored
Add support for numeric metrics (#129)
1 parent ad49a4a commit 40ead9a

File tree

5 files changed

+55
-25
lines changed

5 files changed

+55
-25
lines changed

core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilderV2.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,16 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig,
112112

113113
List<LayerState> layerStates = createLayerStates(projectConfig, experimentVariationMap);
114114

115-
Long eventValue = EventTagUtils.getRevenueValue(eventTags);
116-
List<EventMetric> eventMetrics = Collections.emptyList();
117-
if (eventValue != null) {
118-
eventMetrics = Collections.singletonList(new EventMetric(EventMetric.REVENUE_METRIC_TYPE, eventValue));
115+
List<EventMetric> eventMetrics = new ArrayList<EventMetric>();
116+
117+
Long revenueValue = EventTagUtils.getRevenueValue(eventTags);
118+
if (revenueValue != null) {
119+
eventMetrics.add(new EventMetric(EventMetric.REVENUE_METRIC_TYPE, revenueValue));
120+
}
121+
122+
Double numericMetricValue = EventTagUtils.getNumericValue(eventTags);
123+
if (numericMetricValue != null) {
124+
eventMetrics.add(new EventMetric(EventMetric.NUMERIC_METRIC_TYPE, numericMetricValue));
119125
}
120126

121127
Conversion conversionPayload = new Conversion();

core-api/src/main/java/com/optimizely/ab/event/internal/payload/EventMetric.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
public class EventMetric {
2020

2121
public static final String REVENUE_METRIC_TYPE = "revenue";
22+
public static final String NUMERIC_METRIC_TYPE = "value";
2223

2324
private String name;
24-
private long value;
25+
private Number value;
2526

2627
public EventMetric() { }
2728

28-
public EventMetric(String name, long value) {
29+
public EventMetric(String name, Number value) {
2930
this.name = name;
3031
this.value = value;
3132
}
@@ -38,30 +39,29 @@ public void setName(String name) {
3839
this.name = name;
3940
}
4041

41-
public long getValue() {
42+
public Number getValue() {
4243
return value;
4344
}
4445

45-
public void setValue(long value) {
46+
public void setValue(Number value) {
4647
this.value = value;
4748
}
4849

49-
5050
@Override
51-
public boolean equals(Object other) {
52-
if (!(other instanceof EventMetric))
53-
return false;
51+
public boolean equals(Object obj) {
52+
if (this == obj) return true;
53+
if (obj == null || getClass() != obj.getClass()) return false;
5454

55-
EventMetric otherEventMetric = (EventMetric)other;
55+
EventMetric that = (EventMetric) obj;
5656

57-
return name.equals(otherEventMetric.getName()) && value == otherEventMetric.getValue();
57+
if (!name.equals(that.name)) return false;
58+
return value.equals(that.value);
5859
}
5960

60-
6161
@Override
6262
public int hashCode() {
63-
int result = name != null ? name.hashCode() : 0;
64-
result = 31 * result + (int) (value ^ (value >>> 32));
63+
int result = name.hashCode();
64+
result = 31 * result + value.hashCode();
6565
return result;
6666
}
6767

core-api/src/main/java/com/optimizely/ab/internal/EventTagUtils.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,22 @@ public static Long getRevenueValue(@Nonnull Map<String, ?> eventTags) {
4747
}
4848
return eventValue;
4949
}
50+
51+
/**
52+
* Fetch the numeric metric value from event tags. "value" is a reserved keyword.
53+
*/
54+
public static Double getNumericValue(@Nonnull Map<String, ?> eventTags) {
55+
Double eventValue = null;
56+
if (eventTags.containsKey(ReservedEventKey.VALUE.toString())) {
57+
Object rawValue = eventTags.get(ReservedEventKey.VALUE.toString());
58+
if (rawValue instanceof Number) {
59+
eventValue = ((Number) rawValue).doubleValue();
60+
logger.info("Parsed numeric metric value \"{}\" from event tags.", eventValue);
61+
} else {
62+
logger.warn("Failed to parse numeric metric value \"{}\" from event tags.", rawValue);
63+
}
64+
}
65+
66+
return eventValue;
67+
}
5068
}

core-api/src/main/java/com/optimizely/ab/internal/ReservedEventKey.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
package com.optimizely.ab.internal;
1818

1919
public enum ReservedEventKey {
20-
REVENUE("revenue");
20+
REVENUE("revenue"),
21+
VALUE("value");
2122

2223
private final String key;
2324

core-api/src/test/java/com/optimizely/ab/event/internal/EventBuilderV2Test.java

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

1919
import com.google.gson.Gson;
20+
import com.google.gson.internal.LazilyParsedNumber;
2021
import com.optimizely.ab.bucketing.Bucketer;
2122
import com.optimizely.ab.bucketing.DecisionService;
2223
import com.optimizely.ab.bucketing.UserProfileService;
@@ -314,11 +315,13 @@ public void createConversionEvent() throws Exception {
314315
}
315316

316317
/**
317-
* Verify that eventValue is properly recorded in a conversion request as an {@link EventMetric}
318+
* Verify that "revenue" and "value" are properly recorded in a conversion request as {@link EventMetric} objects.
319+
* "revenue" is fixed-point and "value" is floating-point.
318320
*/
319321
@Test
320-
public void createConversionParamsWithRevenue() throws Exception {
321-
long revenue = 1234L;
322+
public void createConversionParamsWithEventMetrics() throws Exception {
323+
Long revenue = 1234L;
324+
Double value = 13.37;
322325

323326
// use the "valid" project config and its associated experiment, variation, and attributes
324327
Attribute attribute = validProjectConfig.getAttributes().get(0);
@@ -341,6 +344,7 @@ public void createConversionParamsWithRevenue() throws Exception {
341344
Map<String, String> attributeMap = Collections.singletonMap(attribute.getKey(), "value");
342345
Map<String, Object> eventTagMap = new HashMap<String, Object>();
343346
eventTagMap.put(ReservedEventKey.REVENUE.toString(), revenue);
347+
eventTagMap.put(ReservedEventKey.VALUE.toString(), value);
344348
Map<Experiment, Variation> experimentVariationMap = createExperimentVariationMap(
345349
validProjectConfig,
346350
decisionService,
@@ -352,10 +356,11 @@ public void createConversionParamsWithRevenue() throws Exception {
352356
eventTagMap);
353357

354358
Conversion conversion = gson.fromJson(conversionEvent.getBody(), Conversion.class);
355-
356-
// we're not going to verify everything, only revenue
357-
assertThat(conversion.getEventMetrics(),
358-
is(Collections.singletonList(new EventMetric(EventMetric.REVENUE_METRIC_TYPE, revenue))));
359+
List<EventMetric> eventMetrics = Arrays.asList(
360+
new EventMetric(EventMetric.REVENUE_METRIC_TYPE, new LazilyParsedNumber(revenue.toString())),
361+
new EventMetric(EventMetric.NUMERIC_METRIC_TYPE, new LazilyParsedNumber(value.toString())));
362+
// we're not going to verify everything, only the event metrics
363+
assertThat(conversion.getEventMetrics(), is(eventMetrics));
359364
}
360365

361366
/**

0 commit comments

Comments
 (0)