diff --git a/packages/compass-e2e-tests/tests/logging.test.ts b/packages/compass-e2e-tests/tests/logging.test.ts index 09c72c713fa..abc97e277ed 100644 --- a/packages/compass-e2e-tests/tests/logging.test.ts +++ b/packages/compass-e2e-tests/tests/logging.test.ts @@ -149,7 +149,8 @@ describe('Logging and Telemetry integration', function () { attr: (actual: any) => { expect(actual.telemetryCapableEnvironment).to.equal(true); expect(actual.hasAnalytics).to.equal(true); - expect(actual.currentUserId).to.be.a('string'); + expect(actual.currentUserId).to.not.exist; + expect(actual.telemetryAnonymousId).to.be.a('string'); expect(actual.state).to.equal('disabled'); }, }, @@ -176,7 +177,8 @@ describe('Logging and Telemetry integration', function () { attr: (actual: any) => { expect(actual.telemetryCapableEnvironment).to.equal(true); expect(actual.hasAnalytics).to.equal(true); - expect(actual.currentUserId).to.be.a('string'); + expect(actual.currentUserId).to.not.exist; + expect(actual.telemetryAnonymousId).to.be.a('string'); expect(actual.state).to.equal('enabled'); }, }, diff --git a/packages/compass-preferences-model/lib/model.js b/packages/compass-preferences-model/lib/model.js index 6e3525a386a..7bd12075a29 100644 --- a/packages/compass-preferences-model/lib/model.js +++ b/packages/compass-preferences-model/lib/model.js @@ -61,10 +61,21 @@ var preferencesProps = { default: THEMES.LIGHT }, /** - * Stores a unique anonymous user ID (uuid) for the current user + * Stores a unique MongoDB ID for the current user. + * Initially, we used this field as telemetry user identifier, + * but this usage is being deprecated. + * The telemetryAnonymousId should be used instead. * @type {String} */ currentUserId: { + type: 'string', + required: false + }, + /** + * Stores a unique telemetry anonymous ID (uuid) for the current user. + * @type {String} + */ + telemetryAnonymousId: { type: 'string', required: true, default: '' diff --git a/packages/compass-user-model/lib/model.js b/packages/compass-user-model/lib/model.js index bc2d76f30de..2352a8782b6 100644 --- a/packages/compass-user-model/lib/model.js +++ b/packages/compass-user-model/lib/model.js @@ -37,9 +37,9 @@ var User = Model.extend(storageMixin, { } }); -User.getOrCreate = function(userId, done) { +User.getOrCreate = function(id, done) { var user = new User({ - id: userId || uuid.v4(), + id: id || uuid.v4(), createdAt: new Date() }); user.fetch({ diff --git a/packages/compass/src/app/index.js b/packages/compass/src/app/index.js index 713cd635586..6b61ebc6735 100644 --- a/packages/compass/src/app/index.js +++ b/packages/compass/src/app/index.js @@ -279,7 +279,8 @@ var Application = View.extend({ fetchUser: function(done) { debug('preferences fetched, now getting user'); User.getOrCreate( - this.preferences.currentUserId, + // Check if uuid was stored as currentUserId, if not pass telemetryAnonymousId to fetch a user. + this.preferences.currentUserId || this.preferences.telemetryAnonymousId, function(err, user) { if (err) { return done(err); @@ -287,9 +288,12 @@ var Application = View.extend({ this.user.set(user.serialize()); this.user.trigger('sync'); this.preferences.save({ - currentUserId: user.id + telemetryAnonymousId: user.id + }); + ipc.call('compass:usage:identify', { + currentUserId: this.preferences.currentUserId, + telemetryAnonymousId: user.id }); - ipc.call('compass:usage:identify', { currentUserId: user.id }); debug('user fetch successful', user.serialize()); done(null, user); }.bind(this) diff --git a/packages/compass/src/main/telemetry.ts b/packages/compass/src/main/telemetry.ts index db07b338ea2..b3498ad6511 100644 --- a/packages/compass/src/main/telemetry.ts +++ b/packages/compass/src/main/telemetry.ts @@ -3,8 +3,9 @@ import { app } from 'electron'; import { ipcMain } from 'hadron-ipc'; import { createLoggerAndTelemetry } from '@mongodb-js/compass-logging'; import type { CompassApplication } from './application'; +import type { EventEmitter } from 'events'; -const { log, mongoLogId, debug } = +const { log, mongoLogId } = createLoggerAndTelemetry('COMPASS-TELEMETRY'); interface EventInfo { @@ -30,8 +31,9 @@ class CompassTelemetry { private static state: 'enabled' | 'disabled' | 'waiting-for-user-config' = 'waiting-for-user-config'; private static queuedEvents: EventInfo[] = []; // Events that happen before we fetch user preferences - private static currentUserId: string = ''; - private static lastReportedScreen: string = ''; + private static currentUserId?: string; // Deprecated field. Should be used only for old users to keep their analytics in Segment. + private static telemetryAnonymousId = ''; // The randomly generated anonymous user id. + private static lastReportedScreen = ''; private constructor() { // marking constructor as private to disallow usage @@ -46,7 +48,7 @@ class CompassTelemetry { compass_channel: process.env.HADRON_CHANNEL, }; - if (this.state === 'waiting-for-user-config' || !this.currentUserId) { + if (this.state === 'waiting-for-user-config' || !this.telemetryAnonymousId) { this.queuedEvents.push(info); return; } @@ -64,6 +66,7 @@ class CompassTelemetry { this.analytics.track({ userId: this.currentUserId, + anonymousId: this.telemetryAnonymousId, event: info.event, properties: { ...info.properties, ...commonProperties }, }); @@ -78,13 +81,15 @@ class CompassTelemetry { telemetryCapableEnvironment, hasAnalytics: !!this.analytics, currentUserId: this.currentUserId, + telemetryAnonymousId: this.telemetryAnonymousId, state: this.state, queuedEvents: this.queuedEvents.length, } ); - if (this.state === 'enabled' && this.analytics && this.currentUserId) { + if (this.state === 'enabled' && this.analytics && this.telemetryAnonymousId) { this.analytics.identify({ userId: this.currentUserId, + anonymousId: this.telemetryAnonymousId, traits: { platform: process.platform, arch: process.arch, @@ -98,7 +103,7 @@ class CompassTelemetry { } } - private static async _init(app: typeof CompassApplication) { + private static _init(app: typeof CompassApplication) { process.on('compass:track', (meta: EventInfo) => { this._track(meta); }); @@ -109,9 +114,10 @@ class CompassTelemetry { ipcMain.respondTo( 'compass:usage:identify', - (evt, meta: { currentUserId: string }) => { + (evt, meta: { currentUserId?: string, telemetryAnonymousId: string }) => { // This always happens after the first enable/disable call. this.currentUserId = meta.currentUserId; + this.telemetryAnonymousId = meta.telemetryAnonymousId; this.identify(); } ); @@ -153,7 +159,7 @@ class CompassTelemetry { this.analytics = new Analytics(SEGMENT_API_KEY, { host: SEGMENT_HOST }); app.addExitHandler(async () => { - await new Promise((resolve) => this.analytics.flush(resolve)); + await new Promise((resolve) => this.analytics?.flush(resolve)); }); } }