From 467dc1d55b2d21384e96aaacfa74664a585ab262 Mon Sep 17 00:00:00 2001 From: Abhijeet <41686026+abhvsn@users.noreply.github.com> Date: Wed, 10 May 2023 17:20:11 +0530 Subject: [PATCH] fix: Email domain hash in analytics event (#23114) ## Description We are solving 2 problems with this PR: 1. For `Installation Setup Complete` event email domain hash was incorrect and earlier we were hashing the instanceId which means if user with same email tries to run 2 different instances hash was different. 2. `IP` is a reserved keyword for tracking events in Mixpanel though this is allowed in Segment. Instead of showing the ip as is, Mixpanel provides derived property. As we want derived props alongwith the ip address we are sharing the IP address in separate keys. Ref: https://help.mixpanel.com/hc/en-us/articles/360001355266-Event-Properties #### PR fixes following issue(s) Fixes https://github.com/appsmithorg/cloud-services/issues/675 #### Type of change - Bug fix (non-breaking change which fixes an issue) #### How Has This Been Tested? - [x] Manual ## Checklist: #### Dev activity - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Test-plan-implementation#speedbreaker-features-to-consider-for-every-change) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans/_edit#areas-of-interest) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed --- .../external/constants/AnalyticsConstants.java | 1 + .../server/services/ce/AnalyticsServiceCEImpl.java | 11 ++++++++--- .../server/solutions/ce/UserSignupCEImpl.java | 7 +++++++ deploy/docker/entrypoint.sh | 7 +++++-- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/AnalyticsConstants.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/AnalyticsConstants.java index 2311563c79..2146e71a41 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/AnalyticsConstants.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/AnalyticsConstants.java @@ -5,5 +5,6 @@ public interface AnalyticsConstants { String SUBSCRIBE_MARKETING = "subscribe-marketing"; String GOAL = "goal"; String IP = "ip"; + String IP_ADDRESS = "ipAddress"; String EMAIL_DOMAIN_HASH = "emailDomainHash"; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCEImpl.java index 18a4da768d..acc9a70403 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/AnalyticsServiceCEImpl.java @@ -32,6 +32,7 @@ import java.util.stream.Collectors; import static com.appsmith.external.constants.AnalyticsConstants.EMAIL_DOMAIN_HASH; import static com.appsmith.external.constants.AnalyticsConstants.GOAL; import static com.appsmith.external.constants.AnalyticsConstants.IP; +import static com.appsmith.external.constants.AnalyticsConstants.IP_ADDRESS; import static com.appsmith.server.constants.ce.FieldNameCE.EMAIL; import static com.appsmith.server.constants.ce.FieldNameCE.NAME; import static com.appsmith.server.constants.ce.FieldNameCE.ROLE; @@ -154,7 +155,8 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE { GOAL, ObjectUtils.defaultIfNull(useCase, ""), EMAIL, ObjectUtils.defaultIfNull(adminEmail, ""), NAME, ObjectUtils.defaultIfNull(adminFullName, ""), - IP, ObjectUtils.defaultIfNull(ip, "unknown") + IP, ObjectUtils.defaultIfNull(ip, "unknown"), + IP_ADDRESS, ObjectUtils.defaultIfNull(ip, "unknown") )) ); analytics.flush(); @@ -225,8 +227,11 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE { )); // For Installation Setup Complete event we are using `instanceId` as tracking id // As this does not satisfy the email validation it's not getting hashed correctly - if (!StringUtils.isEmpty(instanceId) && instanceId.equals(immutableUserId)) { - analyticsProperties.put(EMAIL_DOMAIN_HASH, hash(immutableUserId)); + if (AnalyticsEvents.INSTALLATION_SETUP_COMPLETE.getEventName().equals(event) + && analyticsProperties.containsKey(EMAIL)) { + + String email = analyticsProperties.get(EMAIL) != null ? analyticsProperties.get(EMAIL).toString() : ""; + analyticsProperties.put(EMAIL_DOMAIN_HASH, getEmailDomainHash(email)); } else { analyticsProperties.put(EMAIL_DOMAIN_HASH, emailDomainHash); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java index 3e9d491303..eed8e9ee62 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java @@ -45,6 +45,7 @@ import java.util.Map; import static com.appsmith.external.constants.AnalyticsConstants.DISABLE_TELEMETRY; import static com.appsmith.external.constants.AnalyticsConstants.GOAL; import static com.appsmith.external.constants.AnalyticsConstants.IP; +import static com.appsmith.external.constants.AnalyticsConstants.IP_ADDRESS; import static com.appsmith.external.constants.AnalyticsConstants.SUBSCRIBE_MARKETING; import static com.appsmith.server.constants.Appsmith.DEFAULT_ORIGIN_HEADER; import static com.appsmith.server.constants.EnvVariables.APPSMITH_ADMIN_EMAILS; @@ -246,7 +247,13 @@ public class UserSignupCEImpl implements UserSignupCE { analyticsProps.put(EMAIL, newsletterSignedUpUserEmail); analyticsProps.put(ROLE, ObjectUtils.defaultIfNull(userData.getRole(), "")); analyticsProps.put(GOAL, ObjectUtils.defaultIfNull(userData.getUseCase(), "")); + // ip is a reserved keyword for tracking events in Mixpanel though this is allowed in + // Segment. Instead of showing the ip as is Mixpanel provides derived property. + // As we want derived props alongwith the ip address we are sharing the ip + // address in separate keys + // Ref: https://help.mixpanel.com/hc/en-us/articles/360001355266-Event-Properties analyticsProps.put(IP, ip); + analyticsProps.put(IP_ADDRESS, ip); analyticsProps.put(NAME, ObjectUtils.defaultIfNull(newsletterSignedUpUserName, "")); analyticsService.identifyInstance( diff --git a/deploy/docker/entrypoint.sh b/deploy/docker/entrypoint.sh index 15e2d00a60..1c636e10e5 100755 --- a/deploy/docker/entrypoint.sh +++ b/deploy/docker/entrypoint.sh @@ -1,7 +1,9 @@ #!/usr/bin/env bash set -e - +# ip is a reserved keyword for tracking events in Mixpanel. Instead of showing the ip as is Mixpanel provides derived properties. +# As we want derived props alongwith the ip address we are sharing the ip address in separate keys +# https://help.mixpanel.com/hc/en-us/articles/360001355266-Event-Properties if [[ -n ${APPSMITH_SEGMENT_CE_KEY-} ]]; then ip="$(curl -sS https://api64.ipify.org || echo unknown)" curl \ @@ -11,7 +13,8 @@ if [[ -n ${APPSMITH_SEGMENT_CE_KEY-} ]]; then "userId":"'"$ip"'", "event":"Instance Start", "properties": { - "ip": "'"$ip"'" + "ip": "'"$ip"'", + "ipAddress": "'"$ip"'" } }' \ https://api.segment.io/v1/track \