-
Notifications
You must be signed in to change notification settings - Fork 32
chore: switch to @mongodb-js/device-id
#196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a73de1f
22c9991
0681b6f
24c1810
e55ab7a
d2fc72d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,9 +5,8 @@ import logger, { LogId } from "../logger.js"; | |
import { ApiClient } from "../common/atlas/apiClient.js"; | ||
import { MACHINE_METADATA } from "./constants.js"; | ||
import { EventCache } from "./eventCache.js"; | ||
import { createHmac } from "crypto"; | ||
import nodeMachineId from "node-machine-id"; | ||
import { DeferredPromise } from "../helpers/deferred-promise.js"; | ||
import { getDeviceId } from "@mongodb-js/device-id"; | ||
|
||
type EventResult = { | ||
success: boolean; | ||
|
@@ -19,7 +18,8 @@ export const DEVICE_ID_TIMEOUT = 3000; | |
export class Telemetry { | ||
private isBufferingEvents: boolean = true; | ||
/** Resolves when the device ID is retrieved or timeout occurs */ | ||
public deviceIdPromise: DeferredPromise<string> | undefined; | ||
public deviceIdPromise: Promise<string> | undefined; | ||
private deviceIdAbortController = new AbortController(); | ||
private eventCache: EventCache; | ||
private getRawMachineId: () => Promise<string>; | ||
|
||
|
@@ -39,7 +39,6 @@ export class Telemetry { | |
{ | ||
commonProperties = { ...MACHINE_METADATA }, | ||
eventCache = EventCache.getInstance(), | ||
|
||
getRawMachineId = () => nodeMachineId.machineId(true), | ||
}: { | ||
eventCache?: EventCache; | ||
|
@@ -57,50 +56,35 @@ export class Telemetry { | |
if (!this.isTelemetryEnabled()) { | ||
return; | ||
} | ||
this.deviceIdPromise = DeferredPromise.fromPromise(this.getDeviceId(), { | ||
timeout: DEVICE_ID_TIMEOUT, | ||
onTimeout: (resolve) => { | ||
resolve("unknown"); | ||
logger.debug(LogId.telemetryDeviceIdTimeout, "telemetry", "Device ID retrieval timed out"); | ||
this.deviceIdPromise = getDeviceId({ | ||
getMachineId: () => this.getRawMachineId(), | ||
onError: (reason, error) => { | ||
switch (reason) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. honestly seeing this used like this does make me think we should instead throw typed error objects and check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I was debating between the two for a while - ended up going with a |
||
case "resolutionError": | ||
logger.debug(LogId.telemetryDeviceIdFailure, "telemetry", String(error)); | ||
break; | ||
case "timeout": | ||
logger.debug(LogId.telemetryDeviceIdTimeout, "telemetry", "Device ID retrieval timed out"); | ||
break; | ||
case "abort": | ||
// No need to log in the case of aborts | ||
break; | ||
} | ||
}, | ||
abortSignal: this.deviceIdAbortController.signal, | ||
}); | ||
|
||
this.commonProperties.device_id = await this.deviceIdPromise; | ||
|
||
this.isBufferingEvents = false; | ||
} | ||
|
||
public async close(): Promise<void> { | ||
this.deviceIdPromise?.resolve("unknown"); | ||
this.deviceIdAbortController.abort(); | ||
this.isBufferingEvents = false; | ||
await this.emitEvents(this.eventCache.getEvents()); | ||
} | ||
|
||
/** | ||
* @returns A hashed, unique identifier for the running device or `"unknown"` if not known. | ||
*/ | ||
private async getDeviceId(): Promise<string> { | ||
try { | ||
if (this.commonProperties.device_id) { | ||
return this.commonProperties.device_id; | ||
} | ||
|
||
const originalId: string = await this.getRawMachineId(); | ||
|
||
// 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 hmac = createHmac("sha256", originalId.toUpperCase()); | ||
|
||
/** 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) { | ||
logger.debug(LogId.telemetryDeviceIdFailure, "telemetry", String(error)); | ||
return "unknown"; | ||
} | ||
} | ||
|
||
/** | ||
* Emits events through the telemetry pipeline | ||
* @param events - The events to emit | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran into jestjs/jest#15312, possibly because of a TypeScript update, so just going to keep it as a
.cjs
file for the time being