From 66e1d89aeff0005644ea3bcd3f5c3e849297f5ae Mon Sep 17 00:00:00 2001 From: gagik Date: Wed, 7 May 2025 17:09:53 +0200 Subject: [PATCH 1/9] chore(logging): move device_id into Segment identity traits --- .../logging/src/analytics-helpers.spec.ts | 30 ++++++++++++-- packages/logging/src/analytics-helpers.ts | 27 +++++++------ .../logging/src/logging-and-telemetry.spec.ts | 40 +++++-------------- packages/logging/src/logging-and-telemetry.ts | 2 +- 4 files changed, 52 insertions(+), 47 deletions(-) diff --git a/packages/logging/src/analytics-helpers.spec.ts b/packages/logging/src/analytics-helpers.spec.ts index 5030e46f0a..c87ff0f28b 100644 --- a/packages/logging/src/analytics-helpers.spec.ts +++ b/packages/logging/src/analytics-helpers.spec.ts @@ -40,7 +40,11 @@ describe('analytics helpers', function () { toggleable.identify({ userId: 'me', - traits: { platform: '1234', session_id: 'abc' }, + traits: { + platform: '1234', + session_id: 'abc', + device_id: 'test-device-id', + }, timestamp, }); toggleable.track({ @@ -80,7 +84,11 @@ describe('analytics helpers', function () { 'identify', { userId: 'me', - traits: { platform: '1234', session_id: 'abc' }, + traits: { + platform: '1234', + session_id: 'abc', + device_id: 'test-device-id', + }, timestamp, }, ], @@ -124,7 +132,14 @@ describe('analytics helpers', function () { describe('ThrottledAnalytics', function () { const metadataPath = os.tmpdir(); const userId = 'u-' + Date.now(); - const iEvt = { userId, traits: { platform: 'what', session_id: 'abc' } }; + const iEvt = { + userId, + traits: { + platform: 'what', + session_id: 'abc', + device_id: 'test-device-id', + }, + }; const tEvt = { userId, event: 'hi', @@ -252,7 +267,14 @@ describe('analytics helpers', function () { describe('SampledAnalytics', function () { const userId = `u-${Date.now()}`; - const iEvt = { userId, traits: { platform: 'what', session_id: 'abc' } }; + const iEvt = { + userId, + traits: { + platform: 'what', + session_id: 'abc', + device_id: 'test-device-id', + }, + }; const tEvt = { userId, event: 'hi', diff --git a/packages/logging/src/analytics-helpers.ts b/packages/logging/src/analytics-helpers.ts index 3123111c00..17cf707ce3 100644 --- a/packages/logging/src/analytics-helpers.ts +++ b/packages/logging/src/analytics-helpers.ts @@ -1,20 +1,18 @@ import fs from 'fs'; import path from 'path'; +import type { IdentifyParams as SegmentIdentity } from '@segment/analytics-node'; -export type MongoshAnalyticsIdentity = - | { - deviceId?: string; - userId: string; - anonymousId?: never; - } - | { - deviceId?: string; - userId?: never; - anonymousId: string; - }; +export type MongoshAnalyticsIdentity = Omit< + SegmentIdentity, + 'context' | 'traits' | 'timestamp' +>; export type AnalyticsIdentifyMessage = MongoshAnalyticsIdentity & { - traits: { platform: string; session_id: string }; + traits: { + platform: string; + session_id: string; + device_id: string; + }; timestamp?: Date; }; @@ -275,7 +273,10 @@ export class ThrottledAnalytics implements MongoshAnalytics { if (this.currentUserId) { throw new Error('Identify can only be called once per user session'); } - this.currentUserId = message.userId ?? message.anonymousId; + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.currentUserId = message.userId ?? message.anonymousId!; + this.restorePromise = this.restoreThrottleState().then((enabled) => { if (!enabled) { this.trackQueue.disable(); diff --git a/packages/logging/src/logging-and-telemetry.spec.ts b/packages/logging/src/logging-and-telemetry.spec.ts index 7581f3a604..f06ff22f97 100644 --- a/packages/logging/src/logging-and-telemetry.spec.ts +++ b/packages/logging/src/logging-and-telemetry.spec.ts @@ -19,6 +19,7 @@ describe('MongoshLoggingAndTelemetry', function () { const userId = '53defe995fa47e6c13102d9d'; const logId = '5fb3c20ee1507e894e5340f3'; + const deviceId = 'test-device'; let logger: MongoLogWriter; @@ -39,7 +40,6 @@ describe('MongoshLoggingAndTelemetry', function () { const testLoggingArguments: Omit = { analytics, - deviceId: 'test-device', userTraits: { platform: process.platform, arch: process.arch, @@ -54,6 +54,7 @@ describe('MongoshLoggingAndTelemetry', function () { loggingAndTelemetry = setupLoggingAndTelemetry({ ...testLoggingArguments, + deviceId, bus, }); @@ -117,8 +118,8 @@ describe('MongoshLoggingAndTelemetry', function () { 'identify', { anonymousId: userId, - deviceId: 'test-device', traits: { + device_id: deviceId, arch: process.arch, platform: process.platform, session_id: logId, @@ -129,7 +130,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: userId, - deviceId: 'test-device', event: 'New Connection', properties: { mongosh_version: '1.0.0', @@ -178,8 +178,8 @@ describe('MongoshLoggingAndTelemetry', function () { 'identify', { anonymousId: userId, - deviceId: 'test-device', traits: { + device_id: deviceId, arch: process.arch, platform: process.platform, session_id: logId, @@ -190,7 +190,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: userId, - deviceId: 'test-device', event: 'New Connection', properties: { mongosh_version: '1.0.0', @@ -235,9 +234,9 @@ describe('MongoshLoggingAndTelemetry', function () { [ 'identify', { - deviceId: 'unknown', anonymousId: userId, traits: { + device_id: 'unknown', platform: process.platform, arch: process.arch, session_id: logId, @@ -272,9 +271,9 @@ describe('MongoshLoggingAndTelemetry', function () { [ 'identify', { - deviceId, anonymousId: userId, traits: { + device_id: deviceId, platform: process.platform, arch: process.arch, session_id: logId, @@ -299,7 +298,7 @@ describe('MongoshLoggingAndTelemetry', function () { ...testLoggingArguments, bus, deviceId: undefined, - }); + }) as LoggingAndTelemetry; loggingAndTelemetry.attachLogger(logger); @@ -310,13 +309,13 @@ describe('MongoshLoggingAndTelemetry', function () { expect(analyticsOutput).to.have.lengthOf(0); resolveTelemetry('1234'); - await (loggingAndTelemetry as LoggingAndTelemetry).setupTelemetryPromise; + await loggingAndTelemetry.setupTelemetryPromise; expect(logOutput).to.have.lengthOf(1); expect(analyticsOutput).to.have.lengthOf(1); // Hash created from machine ID 1234 - expect(analyticsOutput[0][1].deviceId).equals( + expect(loggingAndTelemetry['deviceId']).equals( '8c9f929608f0ef13bfd5a290e0233f283e2cc25ffefc2ad8d9ef0650eb224a52' ); }); @@ -719,8 +718,8 @@ describe('MongoshLoggingAndTelemetry', function () { 'identify', { anonymousId: userId, - deviceId: 'test-device', traits: { + device_id: deviceId, platform: process.platform, arch: process.arch, session_id: logId, @@ -731,8 +730,8 @@ describe('MongoshLoggingAndTelemetry', function () { 'identify', { anonymousId: userId, - deviceId: 'test-device', traits: { + device_id: deviceId, platform: process.platform, arch: process.arch, session_id: logId, @@ -743,7 +742,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: userId, - deviceId: 'test-device', event: 'Startup Time', properties: { is_interactive: true, @@ -759,7 +757,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'Error', properties: { mongosh_version: '1.0.0', @@ -775,7 +772,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'Error', properties: { mongosh_version: '1.0.0', @@ -791,7 +787,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'Use', properties: { mongosh_version: '1.0.0', @@ -803,7 +798,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'Show', properties: { mongosh_version: '1.0.0', @@ -823,7 +817,6 @@ describe('MongoshLoggingAndTelemetry', function () { shell: true, }, anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', }, ], [ @@ -836,7 +829,6 @@ describe('MongoshLoggingAndTelemetry', function () { nested: false, }, anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', }, ], [ @@ -848,7 +840,6 @@ describe('MongoshLoggingAndTelemetry', function () { session_id: logId, }, anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', }, ], [ @@ -860,7 +851,6 @@ describe('MongoshLoggingAndTelemetry', function () { session_id: logId, }, anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', }, ], [ @@ -873,14 +863,12 @@ describe('MongoshLoggingAndTelemetry', function () { shell: true, }, anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', }, ], [ 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'Snippet Install', properties: { mongosh_version: '1.0.0', @@ -976,7 +964,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'Deprecated Method', properties: { mongosh_version: '1.0.0', @@ -990,7 +977,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'Deprecated Method', properties: { mongosh_version: '1.0.0', @@ -1004,7 +990,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'Deprecated Method', properties: { mongosh_version: '1.0.0', @@ -1018,7 +1003,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'API Call', properties: { mongosh_version: '1.0.0', @@ -1033,7 +1017,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: '53defe995fa47e6c13102d9d', - deviceId: 'test-device', event: 'API Call', properties: { mongosh_version: '1.0.0', @@ -1188,7 +1171,6 @@ describe('MongoshLoggingAndTelemetry', function () { 'track', { anonymousId: undefined, - deviceId: 'test-device', event: 'New Connection', properties: { mongosh_version: '1.0.0', diff --git a/packages/logging/src/logging-and-telemetry.ts b/packages/logging/src/logging-and-telemetry.ts index 6007ff8ee8..b381c99722 100644 --- a/packages/logging/src/logging-and-telemetry.ts +++ b/packages/logging/src/logging-and-telemetry.ts @@ -267,6 +267,7 @@ export class LoggingAndTelemetry implements MongoshLoggingAndTelemetry { const getUserTraits = (): AnalyticsIdentifyMessage['traits'] => ({ ...this.userTraits, + device_id: this.deviceId ?? 'unknown', session_id: this.log.logId, }); @@ -277,7 +278,6 @@ export class LoggingAndTelemetry implements MongoshLoggingAndTelemetry { const getTelemetryUserIdentity = (): MongoshAnalyticsIdentity => { return { - deviceId: this.deviceId, anonymousId: this.busEventState.telemetryAnonymousId ?? (this.busEventState.userId as string), From 009a9b41df9a661561ffa3f6f55c7b7de99d9bc8 Mon Sep 17 00:00:00 2001 From: gagik Date: Mon, 2 Jun 2025 11:22:56 +0200 Subject: [PATCH 2/9] fix: pick the fields instead of omitting --- packages/logging/src/analytics-helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/logging/src/analytics-helpers.ts b/packages/logging/src/analytics-helpers.ts index 17cf707ce3..8f5e321146 100644 --- a/packages/logging/src/analytics-helpers.ts +++ b/packages/logging/src/analytics-helpers.ts @@ -2,9 +2,9 @@ import fs from 'fs'; import path from 'path'; import type { IdentifyParams as SegmentIdentity } from '@segment/analytics-node'; -export type MongoshAnalyticsIdentity = Omit< +export type MongoshAnalyticsIdentity = Pick< SegmentIdentity, - 'context' | 'traits' | 'timestamp' + 'userId' | 'anonymousId' >; export type AnalyticsIdentifyMessage = MongoshAnalyticsIdentity & { From de74a6f8476eb1cbac01358fc031d54ccba2b3bc Mon Sep 17 00:00:00 2001 From: gagik Date: Mon, 2 Jun 2025 11:30:22 +0200 Subject: [PATCH 3/9] fix: tie it to the identify function --- packages/logging/src/analytics-helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/logging/src/analytics-helpers.ts b/packages/logging/src/analytics-helpers.ts index 8f5e321146..58172a693d 100644 --- a/packages/logging/src/analytics-helpers.ts +++ b/packages/logging/src/analytics-helpers.ts @@ -1,9 +1,9 @@ import fs from 'fs'; import path from 'path'; -import type { IdentifyParams as SegmentIdentity } from '@segment/analytics-node'; +import type { Analytics as SegmentAnalytics } from '@segment/analytics-node'; export type MongoshAnalyticsIdentity = Pick< - SegmentIdentity, + Parameters[0], 'userId' | 'anonymousId' >; From 03d85fee27987827495b0d209e4f25c85b4753ce Mon Sep 17 00:00:00 2001 From: gagik Date: Mon, 2 Jun 2025 11:31:55 +0200 Subject: [PATCH 4/9] fix: import identify params instead --- packages/logging/src/analytics-helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/logging/src/analytics-helpers.ts b/packages/logging/src/analytics-helpers.ts index 58172a693d..2312fc9699 100644 --- a/packages/logging/src/analytics-helpers.ts +++ b/packages/logging/src/analytics-helpers.ts @@ -1,9 +1,9 @@ import fs from 'fs'; import path from 'path'; -import type { Analytics as SegmentAnalytics } from '@segment/analytics-node'; +import type { IdentifyParams as SegmentIndetifyParams } from '@segment/analytics-node'; export type MongoshAnalyticsIdentity = Pick< - Parameters[0], + SegmentIndetifyParams, 'userId' | 'anonymousId' >; From 542c93f3d46b9fca01cc6d0533ffd1f5e3a5ca1b Mon Sep 17 00:00:00 2001 From: gagik Date: Mon, 2 Jun 2025 11:44:06 +0200 Subject: [PATCH 5/9] fix: use SegmentIndetifyParams directly --- packages/logging/src/analytics-helpers.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/logging/src/analytics-helpers.ts b/packages/logging/src/analytics-helpers.ts index 2312fc9699..294e5d7700 100644 --- a/packages/logging/src/analytics-helpers.ts +++ b/packages/logging/src/analytics-helpers.ts @@ -2,18 +2,15 @@ import fs from 'fs'; import path from 'path'; import type { IdentifyParams as SegmentIndetifyParams } from '@segment/analytics-node'; -export type MongoshAnalyticsIdentity = Pick< - SegmentIndetifyParams, - 'userId' | 'anonymousId' ->; +export type MongoshAnalyticsIdentity = SegmentIndetifyParams; export type AnalyticsIdentifyMessage = MongoshAnalyticsIdentity & { traits: { platform: string; session_id: string; device_id: string; - }; - timestamp?: Date; + } & SegmentIndetifyParams['traits']; + timestamp?: Date & SegmentIndetifyParams['timestamp']; }; export type AnalyticsTrackMessage = MongoshAnalyticsIdentity & { From 0f9985a5506ee4d441e959689778e7a3247baff0 Mon Sep 17 00:00:00 2001 From: gagik Date: Mon, 2 Jun 2025 11:53:18 +0200 Subject: [PATCH 6/9] fix: support timestamps like in segment --- packages/logging/src/analytics-helpers.ts | 30 +++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/logging/src/analytics-helpers.ts b/packages/logging/src/analytics-helpers.ts index 294e5d7700..0c6da91ba1 100644 --- a/packages/logging/src/analytics-helpers.ts +++ b/packages/logging/src/analytics-helpers.ts @@ -1,16 +1,23 @@ import fs from 'fs'; import path from 'path'; -import type { IdentifyParams as SegmentIndetifyParams } from '@segment/analytics-node'; +import type { + IdentifyParams as SegmentIdentifyParams, + TrackParams as SegmentTrackParams, +} from '@segment/analytics-node'; -export type MongoshAnalyticsIdentity = SegmentIndetifyParams; +type Timestamp = SegmentTrackParams['timestamp']; + +export type MongoshAnalyticsIdentity = SegmentIdentifyParams & { + anonymousId: string; +}; export type AnalyticsIdentifyMessage = MongoshAnalyticsIdentity & { traits: { platform: string; session_id: string; device_id: string; - } & SegmentIndetifyParams['traits']; - timestamp?: Date & SegmentIndetifyParams['timestamp']; + } & SegmentIdentifyParams['traits']; + timestamp?: SegmentIdentifyParams['timestamp']; }; export type AnalyticsTrackMessage = MongoshAnalyticsIdentity & { @@ -20,7 +27,7 @@ export type AnalyticsTrackMessage = MongoshAnalyticsIdentity & { session_id: string; [key: string]: any; }; - timestamp?: Date; + timestamp?: Timestamp; }; /** @@ -88,10 +95,14 @@ type AnalyticsEventsQueueItem = | ['identify', Parameters] | ['track', Parameters]; -function addTimestamp( +function addTimestamp( message: T -): T & { timestamp: Date } { - return { ...message, timestamp: message.timestamp ?? new Date() }; +): T & { timestamp: Timestamp } { + const timestampDate = + message.timestamp instanceof Date || message.timestamp === undefined + ? message.timestamp + : new Date(message.timestamp); + return { ...message, timestamp: timestampDate }; } /** @@ -271,8 +282,7 @@ export class ThrottledAnalytics implements MongoshAnalytics { throw new Error('Identify can only be called once per user session'); } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.currentUserId = message.userId ?? message.anonymousId!; + this.currentUserId = message.userId ?? message.anonymousId; this.restorePromise = this.restoreThrottleState().then((enabled) => { if (!enabled) { From 5b2d9208259618e434519b274b1474d952e3954f Mon Sep 17 00:00:00 2001 From: gagik Date: Mon, 2 Jun 2025 11:57:58 +0200 Subject: [PATCH 7/9] fix: remove redundant field --- packages/logging/src/analytics-helpers.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/logging/src/analytics-helpers.ts b/packages/logging/src/analytics-helpers.ts index 0c6da91ba1..06f5806ab6 100644 --- a/packages/logging/src/analytics-helpers.ts +++ b/packages/logging/src/analytics-helpers.ts @@ -17,7 +17,6 @@ export type AnalyticsIdentifyMessage = MongoshAnalyticsIdentity & { session_id: string; device_id: string; } & SegmentIdentifyParams['traits']; - timestamp?: SegmentIdentifyParams['timestamp']; }; export type AnalyticsTrackMessage = MongoshAnalyticsIdentity & { From 3788dddde069b15f842868b102f6ed184fd393e4 Mon Sep 17 00:00:00 2001 From: gagik Date: Mon, 2 Jun 2025 12:22:03 +0200 Subject: [PATCH 8/9] fix: allow for userId --- packages/logging/src/analytics-helpers.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/logging/src/analytics-helpers.ts b/packages/logging/src/analytics-helpers.ts index 06f5806ab6..93d9354859 100644 --- a/packages/logging/src/analytics-helpers.ts +++ b/packages/logging/src/analytics-helpers.ts @@ -7,9 +7,7 @@ import type { type Timestamp = SegmentTrackParams['timestamp']; -export type MongoshAnalyticsIdentity = SegmentIdentifyParams & { - anonymousId: string; -}; +export type MongoshAnalyticsIdentity = SegmentIdentifyParams; export type AnalyticsIdentifyMessage = MongoshAnalyticsIdentity & { traits: { @@ -281,7 +279,8 @@ export class ThrottledAnalytics implements MongoshAnalytics { throw new Error('Identify can only be called once per user session'); } - this.currentUserId = message.userId ?? message.anonymousId; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.currentUserId = message.userId ?? message.anonymousId!; this.restorePromise = this.restoreThrottleState().then((enabled) => { if (!enabled) { From b71658173f1fb73c84d5c1956250beab45a930a7 Mon Sep 17 00:00:00 2001 From: gagik Date: Mon, 2 Jun 2025 13:23:32 +0200 Subject: [PATCH 9/9] force evergreen run