فهرست منبع

Merge pull request #4050 from overleaf/ta-set-user-property

Send 'created-at' User Property

GitOrigin-RevId: 2a6c8356f0a64ffbc55eac485bb80c38b326f683
Timothée Alby 5 سال پیش
والد
کامیت
7957c2eae7

+ 26 - 0
services/web/app/src/Features/Analytics/AnalyticsManager.js

@@ -4,6 +4,7 @@ const Queues = require('../../infrastructure/Queues')
 
 
 const analyticsEventsQueue = Queues.getAnalyticsEventsQueue()
 const analyticsEventsQueue = Queues.getAnalyticsEventsQueue()
 const analyticsEditingSessionsQueue = Queues.getAnalyticsEditingSessionsQueue()
 const analyticsEditingSessionsQueue = Queues.getAnalyticsEditingSessionsQueue()
+const analyticsUserPropertiesQueue = Queues.getAnalyticsUserPropertiesQueue()
 
 
 function identifyUser(userId, oldUserId) {
 function identifyUser(userId, oldUserId) {
   if (isAnalyticsDisabled() || isSmokeTestUser(userId)) {
   if (isAnalyticsDisabled() || isSmokeTestUser(userId)) {
@@ -59,6 +60,30 @@ function updateEditingSession(userId, projectId, countryCode) {
     })
     })
 }
 }
 
 
+function setUserProperty(userId, propertyName, propertyValue) {
+  if (isAnalyticsDisabled() || isSmokeTestUser(userId)) {
+    return
+  }
+  Metrics.analyticsQueue.inc({
+    status: 'adding',
+    event_type: 'user-property',
+  })
+  analyticsUserPropertiesQueue
+    .add({ userId, propertyName, propertyValue })
+    .then(() => {
+      Metrics.analyticsQueue.inc({
+        status: 'added',
+        event_type: 'user-property',
+      })
+    })
+    .catch(() => {
+      Metrics.analyticsQueue.inc({
+        status: 'error',
+        event_type: 'user-property',
+      })
+    })
+}
+
 function isSmokeTestUser(userId) {
 function isSmokeTestUser(userId) {
   const smokeTestUserId = Settings.smokeTest && Settings.smokeTest.userId
   const smokeTestUserId = Settings.smokeTest && Settings.smokeTest.userId
   return smokeTestUserId != null && userId.toString() === smokeTestUserId
   return smokeTestUserId != null && userId.toString() === smokeTestUserId
@@ -72,4 +97,5 @@ module.exports = {
   identifyUser,
   identifyUser,
   recordEvent,
   recordEvent,
   updateEditingSession,
   updateEditingSession,
+  setUserProperty,
 }
 }

+ 1 - 0
services/web/app/src/Features/User/UserCreator.js

@@ -81,6 +81,7 @@ async function createNewUser(attributes, options = {}) {
   }
   }
 
 
   Analytics.recordEvent(user._id, 'user-registered')
   Analytics.recordEvent(user._id, 'user-registered')
+  Analytics.setUserProperty(user._id, 'created-at', new Date())
   try {
   try {
     await UserOnboardingEmailQueueManager.scheduleOnboardingEmail(user)
     await UserOnboardingEmailQueueManager.scheduleOnboardingEmail(user)
   } catch (error) {
   } catch (error) {

+ 7 - 0
services/web/app/src/infrastructure/Queues.js

@@ -21,6 +21,12 @@ function getAnalyticsEditingSessionsQueue() {
   }
   }
 }
 }
 
 
+function getAnalyticsUserPropertiesQueue() {
+  if (Settings.analytics.enabled) {
+    return getOrCreateQueue('analytics-user-properties')
+  }
+}
+
 function getOnboardingEmailsQueue() {
 function getOnboardingEmailsQueue() {
   return getOrCreateQueue('emails-onboarding')
   return getOrCreateQueue('emails-onboarding')
 }
 }
@@ -46,5 +52,6 @@ function getOrCreateQueue(queueName, defaultJobOptions) {
 module.exports = {
 module.exports = {
   getAnalyticsEventsQueue,
   getAnalyticsEventsQueue,
   getAnalyticsEditingSessionsQueue,
   getAnalyticsEditingSessionsQueue,
+  getAnalyticsUserPropertiesQueue,
   getOnboardingEmailsQueue,
   getOnboardingEmailsQueue,
 }
 }

+ 7 - 0
services/web/test/unit/src/Analytics/AnalyticsManagerTests.js

@@ -25,6 +25,10 @@ describe('AnalyticsManager', function () {
       add: sinon.stub().resolves(),
       add: sinon.stub().resolves(),
       process: sinon.stub().resolves(),
       process: sinon.stub().resolves(),
     }
     }
+    this.analyticsUserPropertiesQueue = {
+      add: sinon.stub().resolves(),
+      process: sinon.stub().resolves(),
+    }
     const self = this
     const self = this
     this.Queues = {
     this.Queues = {
       getAnalyticsEventsQueue: () => {
       getAnalyticsEventsQueue: () => {
@@ -36,6 +40,9 @@ describe('AnalyticsManager', function () {
       getOnboardingEmailsQueue: () => {
       getOnboardingEmailsQueue: () => {
         return self.onboardingEmailsQueue
         return self.onboardingEmailsQueue
       },
       },
+      getAnalyticsUserPropertiesQueue: () => {
+        return self.analyticsUserPropertiesQueue
+      },
     }
     }
     this.backgroundRequest = sinon.stub().yields()
     this.backgroundRequest = sinon.stub().yields()
     this.request = sinon.stub().yields()
     this.request = sinon.stub().yields()

+ 7 - 1
services/web/test/unit/src/User/UserCreatorTests.js

@@ -43,6 +43,7 @@ describe('UserCreator', function () {
         }),
         }),
         '../Analytics/AnalyticsManager': (this.Analytics = {
         '../Analytics/AnalyticsManager': (this.Analytics = {
           recordEvent: sinon.stub(),
           recordEvent: sinon.stub(),
+          setUserProperty: sinon.stub(),
         }),
         }),
         './UserOnboardingEmailManager': (this.UserOnboardingEmailManager = {
         './UserOnboardingEmailManager': (this.UserOnboardingEmailManager = {
           scheduleOnboardingEmail: sinon.stub(),
           scheduleOnboardingEmail: sinon.stub(),
@@ -261,7 +262,7 @@ describe('UserCreator', function () {
         assert.equal(user.emails[0].samlProviderId, '1')
         assert.equal(user.emails[0].samlProviderId, '1')
       })
       })
 
 
-      it('should fire an analytics event on registration', async function () {
+      it('should fire an analytics event and user property on registration', async function () {
         const user = await this.UserCreator.promises.createNewUser({
         const user = await this.UserCreator.promises.createNewUser({
           email: this.email,
           email: this.email,
         })
         })
@@ -271,6 +272,11 @@ describe('UserCreator', function () {
           user._id,
           user._id,
           'user-registered'
           'user-registered'
         )
         )
+        sinon.assert.calledWith(
+          this.Analytics.setUserProperty,
+          user._id,
+          'created-at'
+        )
       })
       })
 
 
       it('should schedule an onboarding email on registration', async function () {
       it('should schedule an onboarding email on registration', async function () {