diff --git a/package-lock.json b/package-lock.json index 84418a98c..8fbd4790c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5727,6 +5727,12 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/@mongodb-js/device-id": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/device-id/-/device-id-0.2.0.tgz", + "integrity": "sha512-auEMkQc6hpSQSQziK5AbeuJeVnI7OQvWmaoMIWcXrMm+RA6pF0ADXZPS6kBtBIrRhWElV6PVYiq+Gfzsss2RYQ==", + "license": "Apache-2.0" + }, "node_modules/@mongodb-js/devtools-connect": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.4.1.tgz", @@ -29848,6 +29854,7 @@ "version": "3.7.0", "license": "Apache-2.0", "dependencies": { + "@mongodb-js/device-id": "^0.2.0", "@mongodb-js/devtools-connect": "^3.4.1", "@mongosh/errors": "2.4.0", "@mongosh/history": "2.4.6", diff --git a/packages/logging/package.json b/packages/logging/package.json index 68d5eb421..af6aeb91c 100644 --- a/packages/logging/package.json +++ b/packages/logging/package.json @@ -17,6 +17,7 @@ "node": ">=14.15.1" }, "dependencies": { + "@mongodb-js/device-id": "^0.2.0", "@mongodb-js/devtools-connect": "^3.4.1", "@mongosh/errors": "2.4.0", "@mongosh/history": "2.4.6", diff --git a/packages/logging/src/logging-and-telemetry.spec.ts b/packages/logging/src/logging-and-telemetry.spec.ts index 7581f3a60..56c937dff 100644 --- a/packages/logging/src/logging-and-telemetry.spec.ts +++ b/packages/logging/src/logging-and-telemetry.spec.ts @@ -8,9 +8,10 @@ import type { Writable } from 'stream'; import type { MongoshLoggingAndTelemetry } from '.'; import { setupLoggingAndTelemetry } from '.'; import type { LoggingAndTelemetry } from './logging-and-telemetry'; -import { getDeviceId } from './logging-and-telemetry'; import sinon from 'sinon'; import type { MongoshLoggingAndTelemetryArguments } from './types'; +import { getDeviceId } from '@mongodb-js/device-id'; +import { getMachineId } from 'native-machine-id'; describe('MongoshLoggingAndTelemetry', function () { let logOutput: any[]; @@ -264,7 +265,10 @@ describe('MongoshLoggingAndTelemetry', function () { bus.emit('mongosh:new-user', { userId, anonymousId: userId }); - const deviceId = await getDeviceId(); + const deviceId = await getDeviceId({ + getMachineId: () => getMachineId({ raw: true }), + isNodeMachineId: false, + }).value; await (loggingAndTelemetry as LoggingAndTelemetry).setupTelemetryPromise; @@ -1202,13 +1206,4 @@ describe('MongoshLoggingAndTelemetry', function () { ], ]); }); - - describe('getDeviceId()', function () { - it('is consistent on the same machine', async function () { - const idA = await getDeviceId(); - const idB = await getDeviceId(); - - expect(idA).equals(idB); - }); - }); }); diff --git a/packages/logging/src/logging-and-telemetry.ts b/packages/logging/src/logging-and-telemetry.ts index 6007ff8ee..24c4e34fd 100644 --- a/packages/logging/src/logging-and-telemetry.ts +++ b/packages/logging/src/logging-and-telemetry.ts @@ -53,40 +53,7 @@ import type { MongoshLoggingAndTelemetryArguments, MongoshTrackingProperties, } from './types'; -import { createHmac } from 'crypto'; - -/** - * @returns A hashed, unique identifier for the running device or `"unknown"` if not known. - */ -export async function getDeviceId({ - onError, -}: { - onError?: (error: Error) => void; -} = {}): Promise { - try { - // Create a hashed format from the all uppercase version of the machine ID - // to match it exactly with the denisbrodbeck/machineid library that Atlas CLI uses. - const originalId: string = - // eslint-disable-next-line @typescript-eslint/no-var-requires - await require('native-machine-id').getMachineId({ - raw: true, - }); - - if (!originalId) { - return 'unknown'; - } - const hmac = createHmac('sha256', originalId); - - /** This matches the message used to create the hashes in Atlas CLI */ - const DEVICE_ID_HASH_MESSAGE = 'atlascli'; - - hmac.update(DEVICE_ID_HASH_MESSAGE); - return hmac.digest('hex'); - } catch (error) { - onError?.(error as Error); - return 'unknown'; - } -} +import { getDeviceId } from '@mongodb-js/device-id'; export function setupLoggingAndTelemetry( props: MongoshLoggingAndTelemetryArguments @@ -171,15 +138,16 @@ export class LoggingAndTelemetry implements MongoshLoggingAndTelemetry { private async setupTelemetry(): Promise { if (!this.deviceId) { - this.deviceId = await Promise.race([ - getDeviceId({ - onError: (error) => - this.bus.emit('mongosh:error', error, 'telemetry'), - }), - new Promise((resolve) => { - this.resolveDeviceId = resolve; - }), - ]); + // eslint-disable-next-line @typescript-eslint/no-var-requires + const getMachineId = require('native-machine-id').getMachineId; + const { value: deviceId, resolve: resolveDeviceId } = getDeviceId({ + getMachineId: () => getMachineId({ raw: true }), + isNodeMachineId: false, + onError: (error) => this.bus.emit('mongosh:error', error, 'telemetry'), + }); + + this.resolveDeviceId = resolveDeviceId; + this.deviceId = await deviceId; } this.runAndClearPendingTelemetryEvents();