diff --git a/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsClient.java b/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsClient.java index b2f89c3..c9a401a 100644 --- a/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsClient.java +++ b/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsClient.java @@ -35,7 +35,8 @@ public class AnalyticsClient { private static final Log LOG = LogFactory.getLog(AnalyticsClient.class); private final ClickstreamContext context; private final Map globalAttributes = new ConcurrentHashMap<>(); - private JSONObject userAttributes; + private JSONObject simpleUserAttributes; + private JSONObject allUserAttributes; private String userId; private String userUniqueId; private final EventRecorder eventRecorder; @@ -51,7 +52,8 @@ public AnalyticsClient(@NonNull final ClickstreamContext context) { eventRecorder = EventRecorder.newInstance(context); userId = PreferencesUtil.getCurrentUserId(context.getSystem().getPreferences()); userUniqueId = PreferencesUtil.getCurrentUserUniqueId(context.getSystem().getPreferences()); - userAttributes = PreferencesUtil.getUserAttribute(context.getSystem().getPreferences()); + allUserAttributes = PreferencesUtil.getUserAttribute(context.getSystem().getPreferences()); + simpleUserAttributes = getSimpleUserAttribute(); } /** @@ -99,7 +101,7 @@ public void deleteGlobalAttribute(String name) { */ public void addUserAttribute(String name, Object value) { if (value != null) { - Event.EventError error = Event.checkUserAttribute(userAttributes.length(), name, value); + Event.EventError error = Event.checkUserAttribute(allUserAttributes.length(), name, value); if (error != null) { final AnalyticsEvent event = createEvent(Event.PresetEvent.CLICKSTREAM_ERROR); event.addAttribute(Event.ReservedAttribute.ERROR_CODE, error.getErrorCode()); @@ -112,12 +114,12 @@ public void addUserAttribute(String name, Object value) { JSONObject attribute = new JSONObject(); attribute.put("value", value); attribute.put("set_timestamp", timeStamp); - userAttributes.put(name, attribute); + allUserAttributes.put(name, attribute); } catch (JSONException exception) { LOG.error("format user attribute, error message:" + exception.getMessage()); } } else { - userAttributes.remove(name); + allUserAttributes.remove(name); } } @@ -131,7 +133,7 @@ public void updateUserId(String userId) { this.userId = userId; PreferencesUtil.setCurrentUserId(context.getSystem().getPreferences(), userId); if (!StringUtil.isNullOrEmpty(userId)) { - userAttributes = new JSONObject(); + allUserAttributes = new JSONObject(); JSONObject userInfo = PreferencesUtil.getNewUserInfo(context.getSystem().getPreferences(), userId); try { userUniqueId = userInfo.getString("user_unique_id"); @@ -146,6 +148,7 @@ public void updateUserId(String userId) { newUserId = null; } addUserAttribute(Event.ReservedAttribute.USER_ID, newUserId); + simpleUserAttributes = getSimpleUserAttribute(); } } @@ -153,7 +156,7 @@ public void updateUserId(String userId) { * update user attribute after user attribute changed. */ public void updateUserAttribute() { - PreferencesUtil.updateUserAttribute(context.getSystem().getPreferences(), userAttributes); + PreferencesUtil.updateUserAttribute(context.getSystem().getPreferences(), allUserAttributes); } /** @@ -181,7 +184,10 @@ public AnalyticsEvent createEvent(String eventType) { private AnalyticsEvent createAnalyticsEvent(String eventType) { long timestamp = System.currentTimeMillis(); - AnalyticsEvent event = new AnalyticsEvent(eventType, globalAttributes, userAttributes, timestamp, userUniqueId); + JSONObject eventUserAttribute = + eventType.equals(Event.PresetEvent.PROFILE_SET) ? allUserAttributes : simpleUserAttributes; + AnalyticsEvent event = + new AnalyticsEvent(eventType, globalAttributes, eventUserAttribute, timestamp, userUniqueId); event.setDeviceId(this.context.getDeviceId()); event.setAppId(context.getClickstreamConfiguration().getAppId()); event.setSdkInfo(context.getSDKInfo()); @@ -235,4 +241,24 @@ public void setSession(Session session) { public ClickstreamConfiguration getClickstreamConfiguration() { return this.context.getClickstreamConfiguration(); } + + /** + * get simple user attribute from allUserAttributes. + * + * @return userAttribute + */ + private JSONObject getSimpleUserAttribute() { + JSONObject userAttribute = new JSONObject(); + try { + userAttribute.put(Event.ReservedAttribute.USER_FIRST_TOUCH_TIMESTAMP, + allUserAttributes.getString(Event.ReservedAttribute.USER_FIRST_TOUCH_TIMESTAMP)); + if (allUserAttributes.has(Event.ReservedAttribute.USER_ID)) { + userAttribute.put(Event.ReservedAttribute.USER_ID, + allUserAttributes.getString(Event.ReservedAttribute.USER_ID)); + } + } catch (final JSONException jsonException) { + LOG.error("Could not create Json object of simpleUserAttribute. error: " + jsonException.getMessage()); + } + return userAttribute; + } } diff --git a/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsClientTest.java b/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsClientTest.java index 8ed5d57..599f783 100644 --- a/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsClientTest.java +++ b/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsClientTest.java @@ -49,7 +49,7 @@ public class AnalyticsClientTest { private AnalyticsClient analyticsClient; private Map globalAttributes; - private JSONObject userAttributes; + private JSONObject allUserAttributes; private String exceedLengthName = "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"; private final String invalidName = "1_goods_expose"; private String exceedLengthValue = ""; @@ -78,7 +78,7 @@ public void setup() throws Exception { analyticsClient = clickstreamManager.getAnalyticsClient(); globalAttributes = (Map) ReflectUtil.getFiled(analyticsClient, "globalAttributes"); - userAttributes = (JSONObject) ReflectUtil.getFiled(analyticsClient, "userAttributes"); + allUserAttributes = (JSONObject) ReflectUtil.getFiled(analyticsClient, "allUserAttributes"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 21; i++) { @@ -201,10 +201,10 @@ public void testAddGlobalAttributeSameNameMultiTimes() { @Test public void testAddUserAttributeWhenSuccess() throws JSONException { analyticsClient.addUserAttribute("_user_age", 18); - Assert.assertTrue(userAttributes.has("_user_age")); - Assert.assertEquals(18, ((JSONObject) userAttributes.get("_user_age")).get("value")); + Assert.assertTrue(allUserAttributes.has("_user_age")); + Assert.assertEquals(18, ((JSONObject) allUserAttributes.get("_user_age")).get("value")); Assert.assertTrue(System.currentTimeMillis() - - (Long) (((JSONObject) userAttributes.get("_user_age")).get("set_timestamp")) < 1000); + (Long) (((JSONObject) allUserAttributes.get("_user_age")).get("set_timestamp")) < 1000); } /** @@ -266,8 +266,8 @@ public void testAddUserAttributeSameNameMultiTimes() throws JSONException { mockAnalyticsClient.addUserAttribute("name", "value" + i); } verify(mockAnalyticsClient, never()).createEvent(anyString()); - Assert.assertEquals(2, userAttributes.length()); - Assert.assertEquals("value100", ((JSONObject) userAttributes.get("name")).get("value")); + Assert.assertEquals(2, allUserAttributes.length()); + Assert.assertEquals("value100", ((JSONObject) allUserAttributes.get("name")).get("value")); } /** @@ -287,9 +287,9 @@ public void testAddGlobalAttributeForNullValue() { @Test public void testAddUserAttributeForNullValue() { analyticsClient.addUserAttribute("UserAge", 20); - Assert.assertTrue(userAttributes.has("UserAge")); + Assert.assertTrue(allUserAttributes.has("UserAge")); analyticsClient.addUserAttribute("UserAge", null); - Assert.assertFalse(userAttributes.has("UserAge")); + Assert.assertFalse(allUserAttributes.has("UserAge")); } /** @@ -316,10 +316,10 @@ public void testAddUserAttributeForNullValueWhenReachedMaxLength() { for (int i = 0; i < 100; i++) { analyticsClient.addUserAttribute("name" + i, "value" + i); } - Assert.assertTrue(userAttributes.has("name0")); + Assert.assertTrue(allUserAttributes.has("name0")); analyticsClient.addUserAttribute("name0", null); - Assert.assertFalse(userAttributes.has("name0")); - Assert.assertEquals(99, userAttributes.length()); + Assert.assertFalse(allUserAttributes.has("name0")); + Assert.assertEquals(99, allUserAttributes.length()); } /** @@ -343,7 +343,7 @@ public void deleteNonExistingUserAttribute() { analyticsClient.addUserAttribute("name" + i, "value" + i); } analyticsClient.addUserAttribute("name1000", null); - Assert.assertEquals(100, userAttributes.length()); + Assert.assertEquals(100, allUserAttributes.length()); } /** @@ -365,7 +365,7 @@ public void testUserAttributeForStorage() throws Exception { ClickstreamManagerFactory.create(context, AWSClickstreamPluginConfiguration .builder().withAppId("demo-app").withEndpoint("http://example.com/collect").build()); JSONObject userAttributesFromStorage = - (JSONObject) ReflectUtil.getFiled(clickstreamManager.getAnalyticsClient(), "userAttributes"); + (JSONObject) ReflectUtil.getFiled(clickstreamManager.getAnalyticsClient(), "allUserAttributes"); Assert.assertEquals(6, userAttributesFromStorage.length()); Assert.assertEquals("carl", ((JSONObject) userAttributesFromStorage.get("user_name")).getString("value")); Assert.assertEquals("10837409", ((JSONObject) userAttributesFromStorage.get("_user_id")).getString("value")); @@ -390,8 +390,8 @@ public void testInitialValueInAnalyticsClient() throws Exception { Assert.assertEquals("", userId); Assert.assertNotNull(userUniqueId); - userAttributes = (JSONObject) ReflectUtil.getFiled(analyticsClient, "userAttributes"); - Assert.assertTrue(userAttributes.has(Event.ReservedAttribute.USER_FIRST_TOUCH_TIMESTAMP)); + allUserAttributes = (JSONObject) ReflectUtil.getFiled(analyticsClient, "allUserAttributes"); + Assert.assertTrue(allUserAttributes.has(Event.ReservedAttribute.USER_FIRST_TOUCH_TIMESTAMP)); } /** @@ -406,8 +406,8 @@ public void testUpdateSameUserIdTwice() throws Exception { analyticsClient.updateUserId(userIdForA); analyticsClient.addUserAttribute("user_age", 12); analyticsClient.updateUserId(userIdForA); - userAttributes = (JSONObject) ReflectUtil.getFiled(analyticsClient, "userAttributes"); - Assert.assertTrue(userAttributes.has("user_age")); + allUserAttributes = (JSONObject) ReflectUtil.getFiled(analyticsClient, "allUserAttributes"); + Assert.assertTrue(allUserAttributes.has("user_age")); Assert.assertEquals(userUniqueId, ReflectUtil.getFiled(analyticsClient, "userUniqueId")); } @@ -424,8 +424,8 @@ public void testUpdateDifferentUserId() throws Exception { analyticsClient.updateUserId(userIdForA); analyticsClient.addUserAttribute("user_age", 12); analyticsClient.updateUserId(userIdForB); - userAttributes = (JSONObject) ReflectUtil.getFiled(analyticsClient, "userAttributes"); - Assert.assertFalse(userAttributes.has("user_age")); + allUserAttributes = (JSONObject) ReflectUtil.getFiled(analyticsClient, "allUserAttributes"); + Assert.assertFalse(allUserAttributes.has("user_age")); Assert.assertNotEquals(userUniqueId, ReflectUtil.getFiled(analyticsClient, "userUniqueId")); } @@ -448,6 +448,26 @@ public void testChangeToOriginUserId() throws Exception { Assert.assertEquals(userUniqueIdForB, ReflectUtil.getFiled(analyticsClient, "userUniqueId")); } + + /** + * test create event without custom user attributes. + * + * @throws JSONException the json exception + */ + @Test + public void testCreateEventWithoutCustomUserAttributes() throws JSONException { + analyticsClient.updateUserId("123"); + analyticsClient.addUserAttribute("userName", "carl"); + analyticsClient.addUserAttribute("userAge", 22); + + AnalyticsEvent testEvent = analyticsClient.createEvent("testEvent"); + JSONObject user = testEvent.toJSONObject().getJSONObject("user"); + Assert.assertTrue(user.has(Event.ReservedAttribute.USER_ID)); + Assert.assertTrue(user.has(Event.ReservedAttribute.USER_FIRST_TOUCH_TIMESTAMP)); + Assert.assertFalse(user.has("userName")); + Assert.assertFalse(user.has("userAge")); + } + /** * tearDown. */ diff --git a/clickstream/src/test/java/software/aws/solution/clickstream/IntegrationTest.java b/clickstream/src/test/java/software/aws/solution/clickstream/IntegrationTest.java index e697d45..5755815 100644 --- a/clickstream/src/test/java/software/aws/solution/clickstream/IntegrationTest.java +++ b/clickstream/src/test/java/software/aws/solution/clickstream/IntegrationTest.java @@ -300,21 +300,14 @@ public void testAddUserAttributes() throws Exception { .add("_user_name", "carl") .build(); ClickstreamAnalytics.addUserAttributes(clickstreamUserAttribute); - ClickstreamEvent event = ClickstreamEvent.builder() - .name("PasswordReset") - .add("Message", "SMS") - .add("Successful", true) - .add("ProcessDuration", 792) - .add("Number", 20.1) - .build(); - ClickstreamAnalytics.recordEvent(event); - assertEquals(3, dbUtil.getTotalNumber()); + assertEquals(2, dbUtil.getTotalNumber()); Cursor cursor = dbUtil.queryAllEvents(); cursor.moveToLast(); String eventString = cursor.getString(2); JSONObject jsonObject = new JSONObject(eventString); - JSONObject attribute = jsonObject.getJSONObject("attributes"); + String eventType = jsonObject.getString("event_type"); + Assert.assertEquals(Event.PresetEvent.PROFILE_SET, eventType); JSONObject user = jsonObject.getJSONObject("user"); Assert.assertEquals("13212", ((JSONObject) user.get(Event.ReservedAttribute.USER_ID)).getString("value")); Assert.assertEquals(21, ((JSONObject) user.get("_user_age")).getInt("value")); @@ -323,9 +316,6 @@ public void testAddUserAttributes() throws Exception { Assert.assertTrue(((JSONObject) user.get("_user_name")).has("set_timestamp")); Assert.assertEquals(timestamp, ((JSONObject) user.get("timestamp")).getLong("value")); - Assert.assertTrue(attribute.getBoolean("Successful")); - Assert.assertEquals("SMS", attribute.getString("Message")); - ClickstreamAnalytics.flushEvents(); Thread.sleep(1000); assertEquals(0, dbUtil.getTotalNumber()); @@ -347,16 +337,8 @@ public void testModifyUserId() throws Exception { .build(); ClickstreamAnalytics.setUserId("13212"); ClickstreamAnalytics.addUserAttributes(clickstreamUserAttribute); - ClickstreamEvent event = ClickstreamEvent.builder() - .name("PasswordReset") - .add("Message", "SMS") - .add("Successful", true) - .add("ProcessDuration", 792) - .add("Number", 20.1) - .build(); ClickstreamAnalytics.setUserId("12345"); - ClickstreamAnalytics.recordEvent(event); - assertEquals(4, dbUtil.getTotalNumber()); + assertEquals(3, dbUtil.getTotalNumber()); Cursor cursor = dbUtil.queryAllEvents(); cursor.moveToLast(); @@ -405,8 +387,8 @@ public void testSetUserIdNull() throws Exception { JSONObject jsonObject = new JSONObject(eventString); JSONObject user = jsonObject.getJSONObject("user"); Assert.assertFalse(user.has(Event.ReservedAttribute.USER_ID)); - Assert.assertEquals(21, ((JSONObject) user.get("_user_age")).get("value")); - Assert.assertEquals("carl", ((JSONObject) user.get("_user_name")).get("value")); + Assert.assertFalse(user.has("_user_age")); + Assert.assertFalse(user.has("_user_name")); ClickstreamAnalytics.flushEvents(); Thread.sleep(1000); @@ -838,7 +820,8 @@ public void tearDown() throws Exception { ClickstreamAnalytics.getClickStreamConfiguration().withCustomDns(null); Map globalAttribute = (Map) ReflectUtil.getFiled(analyticsClient, "globalAttributes"); - ReflectUtil.modifyFiled(analyticsClient, "userAttributes", new JSONObject()); + ReflectUtil.modifyFiled(analyticsClient, "simpleUserAttributes", new JSONObject()); + ReflectUtil.modifyFiled(analyticsClient, "allUserAttributes", new JSONObject()); globalAttribute.clear(); }